New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrade to Symfony 5 #9
base: master
Are you sure you want to change the base?
Conversation
Hey man, great work on this package. I just finished installing this branch on a fresh symfony 5 installation. It was a pain without documentation, but that's more my fault than yours ;-) There is one main issue I stumbled upon: In Additionally I needed to install guzzle ( Aside from that I'm going to paste the configuration files I changed to make this work: base config code_cloud_shopify:
oauth:
api_key: "%shopify_api_key%" #key
shared_secret: #secret
scope: "write_customers"
redirect_route: admin
webhooks:
- orders/create
- customers/update add into code_cloud_shopify:
resource: "@CodeCloudShopifyBundle/Resources/config/routing.yml"
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
users_in_memory: { memory: null }
codecloud_shopify:
id: CodeCloud\Bundle\ShopifyBundle\Security\ShopifyAdminUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
# main:
# anonymous: true
# lazy: true
# provider: users_in_memory
#
# # activate different ways to authenticate
# # https://symfony.com/doc/current/security.html#firewalls-authentication
#
# # https://symfony.com/doc/current/security/impersonating_user.html
# # switch_user: true
admin:
pattern: ^/admin
provider: codecloud_shopify
guard:
authenticators:
- CodeCloud\Bundle\ShopifyBundle\Security\SessionAuthenticator
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
I added an alias for my StoreManager in CodeCloud\Bundle\ShopifyBundle\Model\ShopifyStoreManagerInterface:
alias: App\Domain\Shopify\StoreManager Add into twig.yaml: twig:
globals:
shopify_api_key: "%shopify_api_key%" This last one is required for the jwt.html.twig. Success! Thanks again |
For anyone reading this issue, here is a reference implementation of StoreManager and a ShopifyStore Entity. You'll need to add the methods StoreManager: <?php
namespace App\Domain\Shopify;
use App\Entity\ShopifyStore;
use App\Repository\ShopifyStoreRepository;
use CodeCloud\Bundle\ShopifyBundle\Model\Session;
use CodeCloud\Bundle\ShopifyBundle\Model\ShopifyStoreManagerInterface;
use Doctrine\ORM\EntityManagerInterface;
class StoreManager implements ShopifyStoreManagerInterface
{
/**
* @var ShopifyStoreRepository
*/
private ShopifyStoreRepository $shopifyStoreRepository;
/**
* @var EntityManagerInterface
*/
private EntityManagerInterface $entityManager;
public function __construct(ShopifyStoreRepository $shopifyStoreRepository, EntityManagerInterface $entityManager)
{
$this->shopifyStoreRepository = $shopifyStoreRepository;
$this->entityManager = $entityManager;
}
public function getAccessToken($storeName): string
{
$store = $this->shopifyStoreRepository->findOneByStoreName($storeName);
if (null === $store) {
throw new \Exception('trying to get access token for unknown store');
}
return $store->getAccessToken();
}
public function storeExists($storeName): bool
{
return $this->shopifyStoreRepository->findOneByStoreName($storeName) !== null;
}
public function preAuthenticateStore($storeName, $nonce)
{
}
public function authenticateStore($storeName, $accessToken, $nonce)
{
$store = $this->shopifyStoreRepository->findOneByStoreName($storeName);
if (null === $store) {
$store = new ShopifyStore();
$store->setStoreName($storeName);
$this->entityManager->persist($store);
}
$store->setAccessToken($accessToken);
$this->entityManager->flush();
}
public function authenticateSession(Session $session)
{
$store = $this->shopifyStoreRepository->findOneByStoreName($session->storeName);
if (null === $store) {
throw new \Exception('tried to authenticate unknown store');
}
$store->setSessionId($session->sessionId);
$this->entityManager->flush();
}
public function findStoreNameBySession(string $sessionId): ?string
{
$store = $this->shopifyStoreRepository->findOneBySessionId($sessionId);
if (null === $store) {
return null;
}
return $store->getStoreName();
}
} ShopifyStore: <?php
namespace App\Entity;
use App\Repository\ShopifyStoreRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=ShopifyStoreRepository::class)
*/
class ShopifyStore
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $storeName;
/**
* @ORM\Column(type="string", length=255)
*/
private $accessToken;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $sessionId;
public function getId(): ?int
{
return $this->id;
}
public function getStoreName(): ?string
{
return $this->storeName;
}
public function setStoreName(string $storeName): self
{
$this->storeName = $storeName;
return $this;
}
public function getAccessToken(): ?string
{
return $this->accessToken;
}
public function setAccessToken(string $accessToken): self
{
$this->accessToken = $accessToken;
return $this;
}
public function getSessionId(): ?string
{
return $this->sessionId;
}
public function setSessionId(?string $sessionId): self
{
$this->sessionId = $sessionId;
return $this;
}
} |
Hey @Dragony, This is awesome, thank you for taking a crack at installing this fresh. You nailed it! |
Hi, great job @Dragony. |
@jmunozco Here is the config on my Shopify App: Be careful though, Shopify changed their policy to not support third party cookies anymore for embedded apps. This extension uses cookies to save the logged in state. Additionally cookies are used for CSRF protection in forms (by symfony). Both of these things will not work in an embedded app. If your app is not embedded you shouldn't have any issues though. |
Thanks @Dragony ! |
@jmunozco With this extension the store name is the username of the user that is logged in. It all boils down to this:
I use this class to get the Shopify Store. It also takes care of some edge cases:
|
Is there a way to call specific API version? I got this |
You can set the API version in the config: parameters:
shopify_api_key: "%env(APP_API_KEY)%"
shopify_shared_secret: "%env(APP_API_SECRET)%"
code_cloud_shopify:
oauth:
api_key: "%shopify_api_key%"
shared_secret: "%shopify_shared_secret%"
# https://shopify.dev/docs/admin-api/access-scopes
#scope: "read_product_listings,read_content,write_script_tags,read_locations,write_products,read_orders,write_inventory,write_shipping"
scope: "write_script_tags,read_locations"
redirect_route: admin
api_version: 2021-01 # <--------
webhooks:
- app/uninstalled
- subscription_billing_attempts/failure
- subscription_billing_attempts/success |
@Dragony @jmunozco Sorry for the delay, I need to wrap this PR up. FYI, this PR already works around the 3rd-party cookie issue by forcing the session id into the url. All you need to do is include a specific parameter in your admin url, like so:
This listener ensures that the parameter stays in the url: https://github.com/Richtermeister/symfony-shopify-bundle/blob/68b63072195b87e2476bb6b112012a094b4707a5/src/EventListener/SessionRoutingListener.php and this session authenticator makes sure to retrieve the right user against it: I'll add a more comprehensive readme asap. |
One more thing... after installing the app in a store (in Shopify), it redirects to |
You can use |
I have to integrate symfony 6 with shopify and the documentation of the shopify page is very scarce and I would like to use this bundle but I would like a clearer example or a project where I can guide me to integrate it. |
This includes auto-wiring, annotation-routing..