{"action":"created","comment":{"url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/comments/198987080","pull_request_review_id":133014852,"id":198987080,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5ODk4NzA4MA==","diff_hunk":"@@ -155,3 +182,176 @@ def test_has_permission(self, enforce_scopes, authentication_class, jwt_filters,\n             permissions.JwtHasContentOrgFilterForRequestedCourse().has_permission(request, view),\n             expected_result,\n         )\n+\n+\n+@ddt.ddt\n+class JwtHasUserFilterForRequestedUserTests(TestCase):\n+    \"\"\" Tests for JwtHasUserFilterForRequestedUserTests permission class. \"\"\"\n+\n+    def _create_request(self, user_filters, requested_username):\n+        url = '/?username={}'.format(requested_username)\n+        request = RequestFactory().get(url)\n+        request.user = UserFactory(username='this_user')\n+        request.auth = generate_jwt(request.user, filters=user_filters)\n+        return request\n+\n+    @ddt.data(\n+        # no user filters\n+        ([], 'this_user', True),\n+        ([], 'another_user', True),\n+\n+        # accessing self\n+        (['user:me'], 'this_user', True),\n+        (['user:this_user'], 'this_user', True),\n+\n+        # accessing another\n+        (['user:me'], 'another_user', False),\n+        (['user:this_user'], 'another_user', False),\n+        (['user:another_user'], 'another_user', True),\n+    )\n+    @ddt.unpack\n+    def test_has_permission(self, user_filters, requested_username, expected_result):\n+        request = self._create_request(user_filters, requested_username)\n+        self.assertEqual(\n+            permissions.JwtHasUserFilterForRequestedUser().has_permission(request, None),\n+            expected_result,\n+        )\n+\n+\n+@ddt.ddt\n+class JwtRestrictionApplicationOrUserAccessTests(TestCase):\n+    ExpectedLog = namedtuple('ExpectedLog', 'method, text, param')\n+\n+    IsUserInUrlLog = ExpectedLog('info', 'IsUserInUrl', None)\n+    JwtIsUnrestrictedLog = ExpectedLog('debug', 'JwtRestrictedApplication', False)\n+    JwtIsRestrictedLog = ExpectedLog('debug', 'JwtRestrictedApplication', True)\n+    JwtHasScopeLog = ExpectedLog('warning', 'JwtHasScope', None)","path":"edx_rest_framework_extensions/tests/test_permissions.py","position":259,"original_position":259,"commit_id":"306bd4b7b54c5b5887b0df5e0b4d77473e177525","original_commit_id":"306bd4b7b54c5b5887b0df5e0b4d77473e177525","user":{"login":"robrap","id":14576445,"node_id":"MDQ6VXNlcjE0NTc2NDQ1","avatar_url":"https://avatars2.githubusercontent.com/u/14576445?v=4","gravatar_id":"","url":"https://api.github.com/users/robrap","html_url":"https://github.com/robrap","followers_url":"https://api.github.com/users/robrap/followers","following_url":"https://api.github.com/users/robrap/following{/other_user}","gists_url":"https://api.github.com/users/robrap/gists{/gist_id}","starred_url":"https://api.github.com/users/robrap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robrap/subscriptions","organizations_url":"https://api.github.com/users/robrap/orgs","repos_url":"https://api.github.com/users/robrap/repos","events_url":"https://api.github.com/users/robrap/events{/privacy}","received_events_url":"https://api.github.com/users/robrap/received_events","type":"User","site_admin":false},"body":"Nit: might be more clear to name this something like `MissingScopeForJwtHasScopeLog`.  Other expected logs might be the same.  It would make the tests more clear why they are failing when this name is the only indication.","created_at":"2018-06-28T21:11:15Z","updated_at":"2018-06-28T21:35:21Z","html_url":"https://github.com/edx/edx-drf-extensions/pull/36#discussion_r198987080","pull_request_url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/comments/198987080"},"html":{"href":"https://github.com/edx/edx-drf-extensions/pull/36#discussion_r198987080"},"pull_request":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36"}}},"pull_request":{"url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36","id":197625472,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3NjI1NDcy","html_url":"https://github.com/edx/edx-drf-extensions/pull/36","diff_url":"https://github.com/edx/edx-drf-extensions/pull/36.diff","patch_url":"https://github.com/edx/edx-drf-extensions/pull/36.patch","issue_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues/36","number":36,"state":"closed","locked":false,"title":"Update Permissions and JWT handling for OAuth Scopes","user":{"login":"nasthagiri","id":6772826,"node_id":"MDQ6VXNlcjY3NzI4MjY=","avatar_url":"https://avatars1.githubusercontent.com/u/6772826?v=4","gravatar_id":"","url":"https://api.github.com/users/nasthagiri","html_url":"https://github.com/nasthagiri","followers_url":"https://api.github.com/users/nasthagiri/followers","following_url":"https://api.github.com/users/nasthagiri/following{/other_user}","gists_url":"https://api.github.com/users/nasthagiri/gists{/gist_id}","starred_url":"https://api.github.com/users/nasthagiri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nasthagiri/subscriptions","organizations_url":"https://api.github.com/users/nasthagiri/orgs","repos_url":"https://api.github.com/users/nasthagiri/repos","events_url":"https://api.github.com/users/nasthagiri/events{/privacy}","received_events_url":"https://api.github.com/users/nasthagiri/received_events","type":"User","site_admin":false},"body":"In addition to minor improvements, this PR does the following:\r\n\r\n- Adds a design pattern for centrally managing token versions and updates in jwt_decoder.py via `JwtTokenVersion` and `_upgrade_token`.\r\n- Updates the `EnsureJWTAuthSettingsMiddleware` so it no longer adds `required_scopes` to Views.\r\nInstead, the `JwtHasScope` Permission will fail if the view doesn't have `required_scopes`.\r\n- Adds a `JwtHasUserFilterForRequestedUser` Permission to verify the `user:me` filter.\r\n- Adds a `JWT_RESTRICTED_APPLICATION_OR_USER_ACCESS` Permission constant that encapsulates checking for Jwt related permissions for APIs that have course-related and user-related data.\r\n","created_at":"2018-06-27T06:11:24Z","updated_at":"2018-06-28T21:35:21Z","closed_at":"2018-06-28T21:22:53Z","merged_at":"2018-06-28T21:22:53Z","merge_commit_sha":"3b5c7b0bcaf4daca1daa80b0eca4631c74c867fd","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36/commits","review_comments_url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36/comments","review_comment_url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues/36/comments","statuses_url":"https://api.github.com/repos/edx/edx-drf-extensions/statuses/306bd4b7b54c5b5887b0df5e0b4d77473e177525","head":{"label":"edx:arch/api-scopes","ref":"arch/api-scopes","sha":"306bd4b7b54c5b5887b0df5e0b4d77473e177525","user":{"login":"edx","id":3179841,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNzk4NDE=","avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":53665596,"node_id":"MDEwOlJlcG9zaXRvcnk1MzY2NTU5Ng==","name":"edx-drf-extensions","full_name":"edx/edx-drf-extensions","owner":{"login":"edx","id":3179841,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNzk4NDE=","avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-drf-extensions","description":"edX extensions for Django REST Framework","fork":false,"url":"https://api.github.com/repos/edx/edx-drf-extensions","forks_url":"https://api.github.com/repos/edx/edx-drf-extensions/forks","keys_url":"https://api.github.com/repos/edx/edx-drf-extensions/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-drf-extensions/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-drf-extensions/teams","hooks_url":"https://api.github.com/repos/edx/edx-drf-extensions/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-drf-extensions/events","assignees_url":"https://api.github.com/repos/edx/edx-drf-extensions/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-drf-extensions/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-drf-extensions/tags","blobs_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-drf-extensions/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-drf-extensions/languages","stargazers_url":"https://api.github.com/repos/edx/edx-drf-extensions/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-drf-extensions/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-drf-extensions/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-drf-extensions/subscription","commits_url":"https://api.github.com/repos/edx/edx-drf-extensions/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-drf-extensions/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-drf-extensions/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-drf-extensions/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-drf-extensions/merges","archive_url":"https://api.github.com/repos/edx/edx-drf-extensions/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-drf-extensions/downloads","issues_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-drf-extensions/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-drf-extensions/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-drf-extensions/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-drf-extensions/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-drf-extensions/deployments","created_at":"2016-03-11T12:28:52Z","updated_at":"2018-06-28T21:22:54Z","pushed_at":"2018-06-28T21:24:22Z","git_url":"git://github.com/edx/edx-drf-extensions.git","ssh_url":"git@github.com:edx/edx-drf-extensions.git","clone_url":"https://github.com/edx/edx-drf-extensions.git","svn_url":"https://github.com/edx/edx-drf-extensions","homepage":"http://edx-drf-extensions.readthedocs.org","size":98,"stargazers_count":3,"watchers_count":3,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"gpl-3.0","name":"GNU General Public License v3.0","spdx_id":"GPL-3.0","url":"https://api.github.com/licenses/gpl-3.0","node_id":"MDc6TGljZW5zZTk="},"forks":4,"open_issues":2,"watchers":3,"default_branch":"master"}},"base":{"label":"edx:master","ref":"master","sha":"1ac5339b31d00954954c8ab055e6a2d53a38c21e","user":{"login":"edx","id":3179841,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNzk4NDE=","avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":53665596,"node_id":"MDEwOlJlcG9zaXRvcnk1MzY2NTU5Ng==","name":"edx-drf-extensions","full_name":"edx/edx-drf-extensions","owner":{"login":"edx","id":3179841,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNzk4NDE=","avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-drf-extensions","description":"edX extensions for Django REST Framework","fork":false,"url":"https://api.github.com/repos/edx/edx-drf-extensions","forks_url":"https://api.github.com/repos/edx/edx-drf-extensions/forks","keys_url":"https://api.github.com/repos/edx/edx-drf-extensions/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-drf-extensions/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-drf-extensions/teams","hooks_url":"https://api.github.com/repos/edx/edx-drf-extensions/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-drf-extensions/events","assignees_url":"https://api.github.com/repos/edx/edx-drf-extensions/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-drf-extensions/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-drf-extensions/tags","blobs_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-drf-extensions/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-drf-extensions/languages","stargazers_url":"https://api.github.com/repos/edx/edx-drf-extensions/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-drf-extensions/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-drf-extensions/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-drf-extensions/subscription","commits_url":"https://api.github.com/repos/edx/edx-drf-extensions/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-drf-extensions/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-drf-extensions/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-drf-extensions/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-drf-extensions/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-drf-extensions/merges","archive_url":"https://api.github.com/repos/edx/edx-drf-extensions/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-drf-extensions/downloads","issues_url":"https://api.github.com/repos/edx/edx-drf-extensions/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-drf-extensions/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-drf-extensions/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-drf-extensions/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-drf-extensions/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-drf-extensions/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-drf-extensions/deployments","created_at":"2016-03-11T12:28:52Z","updated_at":"2018-06-28T21:22:54Z","pushed_at":"2018-06-28T21:24:22Z","git_url":"git://github.com/edx/edx-drf-extensions.git","ssh_url":"git@github.com:edx/edx-drf-extensions.git","clone_url":"https://github.com/edx/edx-drf-extensions.git","svn_url":"https://github.com/edx/edx-drf-extensions","homepage":"http://edx-drf-extensions.readthedocs.org","size":98,"stargazers_count":3,"watchers_count":3,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"gpl-3.0","name":"GNU General Public License v3.0","spdx_id":"GPL-3.0","url":"https://api.github.com/licenses/gpl-3.0","node_id":"MDc6TGljZW5zZTk="},"forks":4,"open_issues":2,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36"},"html":{"href":"https://github.com/edx/edx-drf-extensions/pull/36"},"issue":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/issues/36"},"comments":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/issues/36/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/pulls/36/commits"},"statuses":{"href":"https://api.github.com/repos/edx/edx-drf-extensions/statuses/306bd4b7b54c5b5887b0df5e0b4d77473e177525"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"robrap"}}