diff --git a/CHANGELOG.md b/CHANGELOG.md index efba27f7a..50bea47b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to * [activity] check ACL on activity list in person context * [list for accompanying course in person] filter list using ACL * [validation] toasts are displayed for errors when modifying accompanying course (generalization required). +* add an endpoint for checking permissions. See https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/232 ## Test releases diff --git a/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php b/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php new file mode 100644 index 000000000..3476c4bbe --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/PermissionApiController.php @@ -0,0 +1,80 @@ +denormalizer = $denormalizer; + $this->security = $security; + } + + /** + * @Route("/api/1.0/main/permissions/info.json", methods={"POST"}) + * + * @throws \Symfony\Component\Serializer\Exception\ExceptionInterface + */ + public function getPermissions(Request $request): JsonResponse + { + $this->denyAccessUnlessGranted('ROLE_USER'); + + $data = json_decode($request->getContent(), true); + + if (null === $data) { + throw new BadRequestHttpException(sprintf( + 'Could not decode json received, or data invalid: %s, %s', + json_last_error(), + json_last_error_msg() + )); + } + + if (!array_key_exists('object', $data)) { + throw new BadRequestHttpException('the object key is not present'); + } + + if (!array_key_exists('class', $data)) { + throw new BadRequestHttpException('the class key is not present'); + } + + if (null !== $data['object']) { + $object = $this->denormalizer->denormalize($data['object'], $data['class'], 'json'); + } else { + $object = null; + } + $roles = []; + + foreach (($data['roles'] ?? []) as $role) { + $roles[$role] = $this->security->isGranted($role, $object); + } + + return $this->json( + ['roles' => $roles], + 200, + [], + ); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/PermissionApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/PermissionApiControllerTest.php new file mode 100644 index 000000000..f267421bf --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Controller/PermissionApiControllerTest.php @@ -0,0 +1,72 @@ +getClientAuthenticated(); + + $client->request( + 'POST', + '/api/1.0/main/permissions/info.json', + [], // parameters + [], // files + [], // server + json_encode([ + 'object' => [ + 'datetime' => '1969-07-09T00:00:00+0100', + ], + 'class' => DateTime::class, + 'roles' => ['FOO_ROLE'], + ]) + ); + + $this->assertResponseIsSuccessful(); + + $data = json_decode($client->getResponse()->getContent(), true); + $this->assertFalse($data['roles']['FOO_ROLE']); + } + + public function testNullObject() + { + $client = $this->getClientAuthenticated(); + + $client->request( + 'POST', + '/api/1.0/main/permissions/info.json', + [], // parameters + [], // files + [], // server + json_encode([ + 'object' => null, + 'class' => null, + 'roles' => ['ROLE_USER', 'ROLE_ADMIN'], + ]) + ); + + $this->assertResponseIsSuccessful(); + + $data = json_decode($client->getResponse()->getContent(), true); + $this->assertTrue($data['roles']['ROLE_USER']); + $this->assertFalse($data['roles']['ROLE_ADMIN']); + } +} diff --git a/src/Bundle/ChillMainBundle/chill.api.specs.yaml b/src/Bundle/ChillMainBundle/chill.api.specs.yaml index 110547201..ff0c844df 100644 --- a/src/Bundle/ChillMainBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillMainBundle/chill.api.specs.yaml @@ -624,3 +624,40 @@ paths: 401: description: "Unauthorized" + /1.0/main/permissions/info.json: + post: + tags: + - permissions + summary: Return info about permissions on entity + responses: + 200: + description: "ok" + 401: + description: "Unauthorized" + 400: + description: "Bad request" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + object: + type: object + class: + type: string + roles: + type: array + items: + type: string + examples: + an-accompanying-period: + value: + object: + type: accompanying_period + id: 1 + class: 'Chill\PersonBundle\Entity\AccompanyingPeriod' + roles: + - 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE' +