Skip to content
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

Pass entity to checkAccess method to allow Symfony Voters check the r… #19

Merged
merged 4 commits into from
Jul 30, 2018
Merged

Pass entity to checkAccess method to allow Symfony Voters check the r… #19

merged 4 commits into from
Jul 30, 2018

Conversation

juanwilde
Copy link
Contributor

In case of getEntity we need to pass the entity to the checkAccess method in order to check some values within Symfony Voters (To check for example y the logged user is the owner of the requested entity

$request = $this->requestFactory->createEntityRequest($httpRequest->query, $resourceName, $id);
$this->listenerManager->onGetEntityRequest($request, $resourceName);
$repository = $this->getRepository($resourceName);
$entity = $repository->fetchOneResource($id, $request->getRelationships());

$this->checkAccess($resourceName, ResourceConfig::ACTION_READ, $entity);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the same applies to update entity right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It is for read, update and delete to check if the entity is owned by the user given in the Token

@@ -600,7 +642,7 @@ private function setupJsonApiBaseUrl(Request $request, $pathPartsCount)
$baseUrl = $request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo();

$baseUrlParts = explode('/', $baseUrl);
for ($i=0; $i<$pathPartsCount; $i++) {
for ($i = 0; $i < $pathPartsCount; $i ++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$i ++ kind of looks wrong

Copy link
Contributor Author

@juanwilde juanwilde Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the PSR-2 code styling. I will remove this kind of styling before pushing changes

}
$data['meta']['totalItems'] = $repository->countResourcesWithFilters(
$request->getRelationships(),
$request->getConstraint()->getFilterCollection()
);

$data['meta']['totalPages'] = (int) (abs($data['meta']['totalItems']-1)/$request->getConstraint()->getPerPage() + 1);
$data['links'] = $this->buildLinks($httpRequest, $request->getConstraint()->getPageNumber(), $data['meta']['totalPages']);
$data['meta']['totalPages'] = (int) (abs($data['meta']['totalItems'] - 1) / $request->getConstraint(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This formatting looks way too forced
Maybe you can move the calculation out to a function and that should fix the formatting also makes it more readable

@moein
Copy link
Contributor

moein commented Jul 23, 2018

Thanks for the PR
I've addressed some issues that imo need to be fixed

@juanwilde
Copy link
Contributor Author

Updated the code by adding logic to update and also delete an entity

@@ -475,12 +476,12 @@ protected function getRepository($resourceName)
}

/**
* @param string $resourceName
* @param string $action
* @param string $resourceName

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This formatting is not respecting the coding style used in the rest of the library

case ResourceConfig::ACTION_READ:
$role = $resourceConfig->getReadRole();
break;
default:
throw new \LogicException('Invalid action passed');
}

$this->denyAccessUnlessGranted($role, null, 'Unable to access this api!');
$this->denyAccessUnlessGranted($role, $entity, 'Unable to access this api!');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@juanwilde Not sure if this is actually going to be a major change or not
If I setup a simple project and say anyone user with ROLE_READ can get any objects and I don't put any voter what does denyAccessUnlessGranted returns?

Copy link
Contributor Author

@juanwilde juanwilde Jul 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see If you don't put any voter the library will work as always since $entity is null by default. The problem is if we always pass null in the entity param, we are not able to check some stuff.. This is a working example of what I mean

    protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
    {
        /** @var User|AnotherUser $user */
        $user = $token->getUser();

        if ($user instanceof Anotheruser) {
            return false;
        }

        if (self::READ === $attribute) {
            if ((null === $subject) || (null !== $subject && $subject->isOwnedBy($user))) {
                return true;
            }
        }

        if (self::CREATE === $attribute) {
            return true;
        }

        if (self::UPDATE === $attribute || self::DELETE === $attribute) {
            if ($subject->isOwnedBy($user)) {
                return true;
            }
        }

        return false;
    }

With your approach the $subject is always null and you can not perform any action like check if the logged user is the owner... Makes sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I tried the following thing. I have 2 entities, one goes throw a Voter and the other one not. The behaviour is the expected. I you try to get one object of the entity that doesn't have Voter, it works as soon as you define the ROLE_READ in the jade.yml. And for the other one, the same but passing throw the voter after.

I mean. With these changes, the library still working fine if you only use jade.yml and the listeners. But if you add a Voter it will work as well.

@moein
Copy link
Contributor

moein commented Jul 25, 2018

@juanwilde Sounds good
Did you run functional test in the bundle?

@juanwilde
Copy link
Contributor Author

Yes. I did it following the package instructions and everythink ok. Just a couple of deprecations notices

1x: The Symfony\Component\ClassLoader\ClassCollectionLoader class is deprecated since Symfony 3.3 and will be removed in 4.0.
    1x in Application::run from Codeception

  1x: The "sensio_framework_extra.routing.loader.annot_class" service is deprecated since version 5.2
    1x in Application::run from Codeception

  1x: The "Sensio\Bundle\FrameworkExtraBundle\Routing\AnnotatedRouteControllerLoader" class is deprecated since version 5.2. Use "Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader" instead.
    1x in Application::run from Codeception

  1x: The "sensio_framework_extra.routing.loader.annot_dir" service is deprecated since version 5.2
    1x in Application::run from Codeception

  1x: The "sensio_framework_extra.routing.loader.annot_file" service is deprecated since version 5.2
    1x in Application::run from Codeception

@moein moein merged commit c50d7d9 into trivago:master Jul 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants