Shopware 6 Authorize customers - symfony

I would like to create a controller for providing downloadable files to a specific customer group. I need to authenticate the customer and check if they are authorized.
I checked the context and the HTTP header but I was unable to find valuable data about the customer.
What would be an appropriate approach?

I was able to retrive the customer using the SalesChannelContext.
I used
$event->getSalesChannelContext()->getCustomer();

To restrict access to your own route to only logged in customers you can use the #LoginRequired annotations, e.g.:
/**
* #LoginRequired()
* #Route("/account", name="frontend.account.home.page", methods={"GET"})
*/
public function index(Request $request, SalesChannelContext $context, CustomerEntity $customer): Response
Under the hood the annotation will also check the current customer of the SalesChannelContext.
To get the customer group of the current customer, your proposed solution is the way to go:
$salesChannelContext->getCustomer()->getGroup();

Related

how to make a dynamic roles in Symfony

I am a begginer, I would like to know if is possible to transform a roles in dynamic role like the #Route model.
/**
* #IsGranted("ROLE_{dance}_{level}")
* #Route("/{dance}/{level}", name="danceLevel")
*/
I have a project to make a website with some restrictions to accees to the content and I would like to throught by a interface like "easy Admin" to create a new category of dance and level that will be transform in role automaticaly
thanks by advance for your help
The security annotations would be for statically named roles and other permissions (checked by Voters).
You would be able to do more dynamic checks with:
$this->denyAccessUnlessGranted("ROLE_{$dance}_{$level}", $user, 'No access');
It's possible that a Security voter would be able to simplify the checks to what would be a static name and so used in #IsGranted (Or, it could for example, get the current $request, via the RequestStack service, to get dance and level parameters, if required).

Create custom entrypoint without entity

With Api-Platform, exposing Doctrine Entities is quite easy and works very well but I don't see how to create custom entrypoint without entities just to call an external service and get its data or do complex treatments
I saw this post (API Platform - Which approach should I use for creating custom operation without entity) but I don't want to create a POST method just to insert my logic in a data persister.
If i just want to create one entrypoint /getMyCustomData with the GET method and without passing any parameter, what should I do?
I looked at swagger decorators but if I understand, it works on an existing entity.
you can create just a normal controller in Symfony.
/**
* #Route("/getMyCustomData", methods={"GET"}, name="my_api_custom_data")
* #param Request $request
* #return Response
*/
public function getMyCustomDataAction(Request $request): Response
{
/** your code **/
}

Symfony - Acces only to their own customers

I have these entities
User
(ManyToMany)
Customer (OneToOne --> a customer can have a related customer)
My app works. Now I want to manage permissions.
When a user is logged in, I want to show only customers related to him and customers related to children customers.
For example,
Each time I use findAll(), it will find its customers.
Route /user/4/customer/7 : if customer 7 is not related to user, permission denied
I think I have to override Doctrine Repository or use EntityManagerDecorator
I'm just asking for what is the best practice to figure it ?
Thanks !
Basically, operation like searching a specific data should be delegated to the repository. Eventually if you have to search through different data source you could create a service for this specific responibility and inject there needed dependencies. In your case I would say you don't need to ovveride anything just create a UserRepository and write there a function which do what you need.
Check this out:
https://symfony.com/doc/3.3/doctrine/repository.html
Why don't you create your own custom findAll() function in your customerRepository That filters with your user ?
Something like
public function findAllRelatedToUser(User $user)
{
return $this->createQueryBuilder('c')
->innerJoin('c.user', 'u')
->andWhere('u.id = :user_id')
->setParameter('user_id', $user->getId())
->getQuery()
->getResult();
}
Finally I've found a better way.
Doctrine Filters
Listenning request on kernel, if my entity is concerned, apply my filter (adding WHERE id= xx)
I use this :
http://blog.michaelperrin.fr/2014/12/05/doctrine-filters/

Symfony2 best way of removing business logic from controller and correct usage of model

I'm in searching of the best way of removing business logic from controller and correct usage of model(and maybe services).
Some details below.
Actually, my project is more complicated, but as example I will use Simple Blog application.
I have created my application (Simple Blog) in next steps:
created bundle
generated entities(Topic, Post, Comment)
generated controller for each entity, using doctrine:generate:crud
installed FOSUserBundle and generated User entity
So, I have all needed methods and forms in my controllers. But now I have some troubles:
Admin need to be able see all topics and posts, when simple User can only see
topic and posts where he is owner.
Currently there are indexAction, that return findAll common for any user. As solution, I can check in action, if ROLE_USER or ADMIN and return find result for each condition. But this variant keep some logic at action.
I also can generate action for each role, but what happened if roles amount will increase?
What is the best way to solve this problem with result for each role?
I need to edit some parameters before saving.
For example, I have some scheduler, where I create date in some steps, using features of DateTime.
Before saving I need to do some calculations with date.
I can do it in controller using service or simple $request->params edit.
What is the best way to edit some $request parameters before saving?
My questions I have marked with bold.
Thanks a lot for any help!
What I would do is to create a query which fetches the topics. Afterwards I would have a method argument which specifies if the query should select only the topics for a certain user or all topics. Something like this should do the work in your TopicRepository:
public function findTopics($userId = false)
{
$query = $this->createQueryBuilder('topic');
if($userId) {
$query->join('topic.user', 'user')
->where('user.id = :user_id')
->setParameter(':user_id', $userId)
;
}
return $query->getQuery()->getResult();
}
So, whenever you need to get the topics only by a user, you would pass a $userId to the method and it would return the results only for that user. In your controller you'd have something similar to this code (Symfony 2.6+):
$authorizationChecker = $this->get('security.authorization_checker');
if($authorizationChecker->isGranted('ROLE_ADMIN')){
$results = $this->get('doctrine.orm.entity_manager')->getRepository('TopicRepository')->findTopics();
} else {
$results = $this->get('doctrine.orm.entity_manager')->getRepository('TopicRepository')->findTopics($this->getUser()->getId());
}
You can try using Doctrine Events and create a PreUpdate depending on your case. See the documentation for more information. If you have a TopicFormType, you could also try the form events.
You are not supposed to "edit" a $request, which is why you can't directly do that. You can, however, retrieve a value, save it as a $variable and then do whatever you want with it. You can always create a new Request if you really need it. Could you be more specific what you want to do here and why is this necessary?

Symfony2, Sonata, UserBundle : Send email when user is enable on update

I would like to be able to send an email to the user when the admin enable the user in Sonata admin panel.
I have to idea which file i should override or extend.
I suppose it is similar to this subject or this stack-overflow subject:
/**
* {#inheritdoc}
*/
public function create($object)
{
parent::create($object);
// send welcome email to new user
}
I found the create function in the admin bundle but i suppose it would not be overridden only for the UserBundle. If it is indeed the way to go, how could i specify for the UserBundle only?
For the information I can't find any create or update function in UserBundle. Only in the AdminBundle.
I will relate to contract event from my gist:
https://gist.github.com/webdevilopers/4eea317ade72a119a72e
Adapt it to your needs. Guess you can simply rename "Contract" to "User".
Then add the event somewhere in your admin class:
$event = new ContractEvent($contract);
$dispatcher = $this->get('event_dispatcher');
$dispatcher->dispatch(
ContractEvents::CONTRACT_CREATED,
$event
);
See the gist for details how to inject SwiftMailer.
Instead of creating your own event you can choose from the events Sonata Admin offers you:
Admin's documentation - Reference - Events (master)
Pick up the one that suits your needs.

Resources