From 5a561f81d4bf37ce209f6ef139eedf69ae9cb740 Mon Sep 17 00:00:00 2001 From: Clinton Blackburn Date: Mon, 1 Dec 2014 15:01:23 -0500 Subject: [PATCH] Added OAuth2 Permissions Scope Handler This scope offers a simple claim, administrator, that is true iff the user is a superuser. --- lms/djangoapps/oauth2_handler/handlers.py | 25 +++++++++++++++++------ lms/djangoapps/oauth2_handler/tests.py | 22 +++++++++++++++++++- requirements/edx/github.txt | 2 +- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lms/djangoapps/oauth2_handler/handlers.py b/lms/djangoapps/oauth2_handler/handlers.py index 60591ec62e..b44ab7403f 100644 --- a/lms/djangoapps/oauth2_handler/handlers.py +++ b/lms/djangoapps/oauth2_handler/handlers.py @@ -34,6 +34,21 @@ class OpenIDHandler(object): return value +class PermissionsHandler(object): + """ Permissions scope handler """ + + def scope_permissions(self, _data): + return ['administrator'] + + def claim_administrator(self, data): + """ + Return boolean indicating user's administrator status. + + For our purposes an administrator is any user with is_staff set to True. + """ + return data['user'].is_staff + + class ProfileHandler(object): """ Basic OpenID Connect `profile` scope handler with `locale` claim. """ @@ -193,8 +208,9 @@ class CourseAccessHandler(object): return course_ids -class IDTokenHandler(OpenIDHandler, ProfileHandler, CourseAccessHandler): +class IDTokenHandler(OpenIDHandler, ProfileHandler, CourseAccessHandler, PermissionsHandler): """ Configure the ID Token handler for the LMS. """ + def claim_instructor_courses(self, data): # Don't return list of courses unless they are requested as essential. if data.get('essential'): @@ -210,16 +226,13 @@ class IDTokenHandler(OpenIDHandler, ProfileHandler, CourseAccessHandler): return None -class UserInfoHandler(OpenIDHandler, ProfileHandler, CourseAccessHandler): +class UserInfoHandler(OpenIDHandler, ProfileHandler, CourseAccessHandler, PermissionsHandler): """ Configure the UserInfo handler for the LMS. """ pass def _get_all_courses(): - """ - Utitilty function to list all available courses. - - """ + """ Utility function to list all available courses. """ ms_courses = modulestore().get_courses() courses = [c for c in ms_courses if isinstance(c, CourseDescriptor)] diff --git a/lms/djangoapps/oauth2_handler/tests.py b/lms/djangoapps/oauth2_handler/tests.py index 033c29dbb5..4493cceaa9 100644 --- a/lms/djangoapps/oauth2_handler/tests.py +++ b/lms/djangoapps/oauth2_handler/tests.py @@ -98,7 +98,7 @@ class IDTokenTest(BaseTestMixin, IDTokenTestCase): scopes, claims = self.get_id_token_values('openid course_instructor') self.assertIn('course_instructor', scopes) - self.assertNotIn('instructor_courses', claims) # should not return courses in id_token + self.assertNotIn('instructor_courses', claims) # should not return courses in id_token def test_course_staff_courses_with_claims(self): CourseStaffRole(self.course_key).add_users(self.user) @@ -121,6 +121,16 @@ class IDTokenTest(BaseTestMixin, IDTokenTestCase): self.assertIn(course_id, claims['staff_courses']) self.assertNotIn(nonexistent_course_id, claims['staff_courses']) + def test_permissions_scope(self): + scopes, claims = self.get_id_token_values('openid profile permissions') + self.assertIn('permissions', scopes) + self.assertFalse(claims['administrator']) + + self.user.is_staff = True + self.user.save() + _scopes, claims = self.get_id_token_values('openid profile permissions') + self.assertTrue(claims['administrator']) + class UserInfoTest(BaseTestMixin, UserInfoTestCase): def token_for_scope(self, scope): @@ -185,3 +195,13 @@ class UserInfoTest(BaseTestMixin, UserInfoTestCase): courses = claims['instructor_courses'] self.assertIn(self.course_id, courses) self.assertEqual(len(courses), 1) + + def test_permissions_scope(self): + claims = self.get_with_scope('permissions') + self.assertIn('administrator', claims) + self.assertFalse(claims['administrator']) + + self.user.is_staff = True + self.user.save() + claims = self.get_with_scope('permissions') + self.assertTrue(claims['administrator']) diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index 8fcbca910b..924baa84f6 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -33,5 +33,5 @@ git+https://github.com/edx/edx-ora2.git@release-2014-10-27T19.33#egg=edx-ora2 git+https://github.com/edx/opaque-keys.git@0.1.2#egg=opaque-keys git+https://github.com/edx/ease.git@97de68448e5495385ba043d3091f570a699d5b5f#egg=ease git+https://github.com/edx/i18n-tools.git@56f048af9b6868613c14aeae760548834c495011#egg=i18n-tools -git+https://github.com/edx/edx-oauth2-provider.git@0.3.1#egg=oauth2-provider +git+https://github.com/edx/edx-oauth2-provider.git@0.4.0#egg=oauth2-provider git+https://github.com/edx/edx-val.git@a3c54afe30375f7a5755ba6f6412a91de23c3b86#egg=edx-val