{"action":"created","issue":{"url":"https://api.github.com/repos/ZF-Commons/zfc-rbac/issues/281","labels_url":"https://api.github.com/repos/ZF-Commons/zfc-rbac/issues/281/labels{/name}","comments_url":"https://api.github.com/repos/ZF-Commons/zfc-rbac/issues/281/comments","events_url":"https://api.github.com/repos/ZF-Commons/zfc-rbac/issues/281/events","html_url":"https://github.com/ZF-Commons/zfc-rbac/issues/281","id":53306781,"number":281,"title":"[DOC] Adding contextualized permission","user":{"login":"bakura10","id":1198915,"avatar_url":"https://avatars.githubusercontent.com/u/1198915?v=3","gravatar_id":"","url":"https://api.github.com/users/bakura10","html_url":"https://github.com/bakura10","followers_url":"https://api.github.com/users/bakura10/followers","following_url":"https://api.github.com/users/bakura10/following{/other_user}","gists_url":"https://api.github.com/users/bakura10/gists{/gist_id}","starred_url":"https://api.github.com/users/bakura10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bakura10/subscriptions","organizations_url":"https://api.github.com/users/bakura10/orgs","repos_url":"https://api.github.com/users/bakura10/repos","events_url":"https://api.github.com/users/bakura10/events{/privacy}","received_events_url":"https://api.github.com/users/bakura10/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-01-03T15:31:01Z","updated_at":"2015-01-03T16:12:54Z","closed_at":null,"body":"Hi everyone :),\r\n\r\nIn my application, I have a permission called \"project.read\". However, a project owner can invite many other users to have access to the project. Therefore, the assertion becomes quite complicated:\r\n\r\n```php\r\n\tclass ProjectReadAssertion implements AssertionInterface\r\n\t{\r\n\t\tprivate $teamService;\r\n\t\t\r\n\t\tpublic function __construct(TeamService $teamService)\r\n\t\t{\r\n\t\t\t$this->teamService = $teamService;\r\n\t\t}\r\n\t\t\r\n\t\tpublic function isGranted(AuthorizationService $auth, $context)\r\n\t\t{\r\n\t\t\tif ($context->getOwner() === $auth->getIdentity()) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif ($teamService->projectHasMember($context, $auth->getIdentity())) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn $auth->isGranted('project.read_others');\r\n\t\t}\r\n\t}\r\n```\r\n\r\nThis is complicated because it requires an injection of another service, it requires an additional DB call... It would actually be better to simply create a new permission each time a project is created (\"project.read_1\"), and assign/remove it each time a team member is removed. This way, instead of asking for the generic \"project.read\" permission, would ask for \"project.read_1\". The assertion would therefore be written like:\r\n\r\n```php\r\n\tclass ProjectReadAssertion implements AssertionInterface\r\n\t{\r\n\t\tpublic function isGranted(AuthorizationService $auth, $context)\r\n\t\t{\r\n                        $assertion = 'project.read_' . $context->getId();\r\n\r\n\t\t\tif ($auth->isGranted($assertion)) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn $auth->isGranted('project.read_others');\r\n\t\t}\r\n\t}\r\n```\r\n\r\nAnd the ProjectService/TeamService would be responsible for adding/removing the permission based on user actions.\r\n\r\nHow anyone did tackle this problem (especially at larger scale)? This seems a common problem, so I'd like to add a doc about it.\r\n\r\nping @danizord @ocramius @arekkas "},"comment":{"url":"https://api.github.com/repos/ZF-Commons/zfc-rbac/issues/comments/68599971","html_url":"https://github.com/ZF-Commons/zfc-rbac/issues/281#issuecomment-68599971","issue_url":"https://api.github.com/repos/ZF-Commons/zfc-rbac/issues/281","id":68599971,"user":{"login":"bakura10","id":1198915,"avatar_url":"https://avatars.githubusercontent.com/u/1198915?v=3","gravatar_id":"","url":"https://api.github.com/users/bakura10","html_url":"https://github.com/bakura10","followers_url":"https://api.github.com/users/bakura10/followers","following_url":"https://api.github.com/users/bakura10/following{/other_user}","gists_url":"https://api.github.com/users/bakura10/gists{/gist_id}","starred_url":"https://api.github.com/users/bakura10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bakura10/subscriptions","organizations_url":"https://api.github.com/users/bakura10/orgs","repos_url":"https://api.github.com/users/bakura10/repos","events_url":"https://api.github.com/users/bakura10/events{/privacy}","received_events_url":"https://api.github.com/users/bakura10/received_events","type":"User","site_admin":false},"created_at":"2015-01-03T16:12:54Z","updated_at":"2015-01-03T16:12:54Z","body":"Regarding you saying \"avoiding db lookups\", do you mean sending all the permissions when getting the token, and checking client side in Javascript? The issue is that in my example, if a user is removed from a project (for instance), then if the permission is not validated server side, you could potentially have leaked information (JS still thinks user has permission, but it's not the case)"}}