def on_module_enabled(courses_custom_module, perms): global custom_module # pylint: disable=global-statement custom_module = courses_custom_module perms.append( roles.Permission(constants.VIEW_ALL_SETTINGS_PERMISSION, 'Can view all course settings')) permissions.SchemaPermissionRegistry.add( constants.SCOPE_COURSE_SETTINGS, permissions.CourseAdminSchemaPermission()) permissions.SchemaPermissionRegistry.add(constants.SCOPE_COURSE_SETTINGS, ViewAllSettingsPermission()) dashboard.DashboardHandler.add_custom_post_action( 'course_availability', CourseSettingsHandler.post_course_availability) dashboard.DashboardHandler.map_post_action_to_permission_checker( 'course_availability', permissions.SchemaPermissionRegistry.build_edit_checker( constants.SCOPE_COURSE_SETTINGS, ['course/course:now_available'])) dashboard.DashboardHandler.add_custom_post_action( 'course_browsability', CourseSettingsHandler.post_course_browsability) dashboard.DashboardHandler.map_post_action_to_permission_checker( 'course_browsability', permissions.SchemaPermissionRegistry.build_edit_checker( constants.SCOPE_COURSE_SETTINGS, ['course/course:browsable'])) dashboard.DashboardHandler.add_custom_get_action( 'edit_html_hook', HtmlHookHandler.get_edit_html_hook) CourseSettingsHandler.register_settings_section('homepage', placement=1000, sub_group_name='pinned') CourseSettingsHandler.register_settings_section('unit', placement=3000, sub_group_name='pinned') CourseSettingsHandler.register_settings_section('registration') CourseSettingsHandler.register_settings_section('assessment') CourseSettingsHandler.register_settings_section('forums') dashboard.DashboardHandler.add_sub_nav_mapping( SETTINGS_TAB_NAME, 'advanced', 'Advanced course settings', action='settings_advanced', contents=_get_settings_advanced, sub_group_name='advanced')
def on_module_enabled(courses_custom_module, module_permissions): global custom_module # pylint: disable=global-statement custom_module = courses_custom_module module_permissions.extend([ roles.Permission( constants.MODIFY_AVAILABILITY_PERMISSION, 'Can set course, unit, or lesson availability and visibility'), ]) dashboard.DashboardHandler.add_sub_nav_mapping( 'publish', 'availability', 'Availability', AvailabilityRESTHandler.ACTION, placement=1000) dashboard.DashboardHandler.add_custom_get_action( AvailabilityRESTHandler.ACTION, AvailabilityRESTHandler.get_form) dashboard.DashboardHandler.map_get_action_to_permission( AvailabilityRESTHandler.ACTION, courses_custom_module, constants.MODIFY_AVAILABILITY_PERMISSION)
def on_module_enabled(courses_custom_module, module_permissions): global custom_module # pylint: disable=global-statement custom_module = courses_custom_module UnitLessonEditor.on_module_enabled() module_permissions.extend([ roles.Permission(constants.COURSE_OUTLINE_REORDER_PERMISSION, 'Can re-order units and lessons'), ]) # Course admins can always edit all fields in units/assessments/links permissions.SchemaPermissionRegistry.add( constants.SCOPE_UNIT, permissions.CourseAdminSchemaPermission()) permissions.SchemaPermissionRegistry.add( constants.SCOPE_ASSESSMENT, permissions.CourseAdminSchemaPermission()) permissions.SchemaPermissionRegistry.add( constants.SCOPE_LINK, permissions.CourseAdminSchemaPermission())
def on_module_enabled(courses_custom_module, course_permissions): global custom_module # pylint: disable=global-statement custom_module = courses_custom_module course_permissions.append( roles.Permission(constants.TEACHING_ASSISTANT_PERMISSION, 'Can modify assessment due dates and scoring.')) permissions.SchemaPermissionRegistry.add( constants.SCOPE_ASSESSMENT, permissions.SimpleSchemaPermission( custom_module, constants.TEACHING_ASSISTANT_PERMISSION, readable_list=[ 'assessment/type', 'assessment/title', 'assessment/description', ], editable_list=[ 'assessment/%s' % resources_display.workflow_key(courses.SINGLE_SUBMISSION_KEY), 'assessment/%s' % resources_display.workflow_key( courses.SUBMISSION_DUE_DATE_KEY), 'assessment/%s' % resources_display.workflow_key(courses.SHOW_FEEDBACK_KEY), 'assessment/%s' % resources_display.workflow_key(courses.GRADER_KEY), 'review_opts/%s' % resources_display.workflow_key(courses.MATCHER_KEY), 'assessment/%s' % resources_display.workflow_key(courses.REVIEW_DUE_DATE_KEY), 'assessment/%s' % resources_display.workflow_key(courses.REVIEW_MIN_COUNT_KEY), 'assessment/%s' % resources_display.workflow_key(courses.REVIEW_WINDOW_MINS_KEY), ]))
def test_editor_hooks(self): module1 = custom_modules.Module('module1', '', [], []) module2 = custom_modules.Module('module2', '', [], []) module3 = custom_modules.Module('module3', '', [], []) module4 = custom_modules.Module('module4', '', [], []) roles.Roles.register_permissions( module1, lambda unused: [ roles.Permission('permissiona', 'a'), roles.Permission('permissionb', 'b') ]) roles.Roles.register_permissions( module2, lambda unused: [ roles.Permission('permissionc', 'c'), roles.Permission('permissiond', 'd') ]) roles.Roles.register_permissions( module4, lambda unused: [ roles.Permission('permissiong', 'g'), roles.Permission('permissiond', 'h') ]) handler = role_editor.RoleRESTHandler() handler.course = self.course datastore_permissions = { module1.name: ['permission', 'permissiona', 'permissionb'], module2.name: ['permissionc', 'permissiond'], module3.name: ['permissione', 'permissionf'] } datastore_dict = { 'name': 'Role Name', 'users': ['*****@*****.**', '*****@*****.**'], 'permissions': datastore_permissions } editor_dict = handler.transform_for_editor_hook(datastore_dict) self.assertEquals(editor_dict['name'], 'Role Name') self.assertEquals(editor_dict['users'], '[email protected], [email protected]') modules = editor_dict['modules'] # Test registered assigned permission permissionc = modules[module2.name][0] self.assertEquals(permissionc['assigned'], True) self.assertEquals(permissionc['name'], 'permissionc') self.assertEquals(permissionc['description'], 'c') # Test unregistered module with assigned permission permissionsf = modules[role_editor.RoleRESTHandler.INACTIVE_MODULES][1] self.assertEquals(permissionsf['assigned'], True) self.assertEquals(permissionsf['name'], 'permissionf') self.assertEquals( permissionsf['description'], 'This permission was set by the module "module3" which is ' 'currently not registered.') # Test registered module with assigned unregistered permission permission = modules[module1.name][2] self.assertEquals(permission['assigned'], True) self.assertEquals(permission['name'], 'permission') self.assertEquals(permission['description'], 'This permission is currently not registered.') # Test registered unassigned permissions permissiong = editor_dict['modules'][module4.name][0] self.assertEquals(permissiong['assigned'], False) self.assertEquals(permissiong['name'], 'permissiong') self.assertEquals(permissiong['description'], 'g') # Call the hook which gets called when saving new_datastore_dict = handler.transform_after_editor_hook( datastore_dict) # If original dict matches new dict then both hooks work correctly self.assertEquals(datastore_dict, new_datastore_dict)
def permissions_callback(unused_app_context): return [ roles.Permission(All_LOCALES_PERMISSION, All_LOCALES_DESCRIPTION), roles.Permission(SEE_DRAFTS_PERMISSION, SEE_DRAFTS_DESCRIPTION) ]
def _permissions_callback(cls): yield roles.Permission(PERMISSION, PERMISSION_DESCRIPTION)
class PermissionsTests(actions.TestBase): """Tests KeyProperty.""" ADMIN_EMAIL = '*****@*****.**' IN_ROLE_EMAIL = '*****@*****.**' NON_ROLE_EMAIL = '*****@*****.**' COURSE_NAME = 'permissions_tests' NAMESPACE = 'ns_%s' % COURSE_NAME MODULE_NAME = 'permissions_tests' PERMISSION_NAME = 'test_permission' PERMISSION = roles.Permission(PERMISSION_NAME, 'Fake perm. for testing') PERMISSION_SCOPE = 'test_scope' ROLE_NAME = 'test_user_role' custom_module = None @classmethod def setUpClass(cls): super(PermissionsTests, cls).setUpClass() cls.custom_module = custom_modules.Module( cls.MODULE_NAME, 'Permissions Tests', [], [], notify_module_enabled=cls.notify_module_enabled) cls.custom_module.enable() @classmethod def tearDownClass(cls): roles.Roles.unregister_permissions(cls.custom_module) permissions.SchemaPermissionRegistry.remove(cls.PERMISSION_SCOPE, cls.PERMISSION_NAME) super(PermissionsTests, cls).tearDownClass() @classmethod def notify_module_enabled(cls): roles.Roles.register_permissions(cls.custom_module, cls.permissions_callback) permissions.SchemaPermissionRegistry.add( cls.PERMISSION_SCOPE, permissions.SimpleSchemaPermission(cls.custom_module, cls.PERMISSION_NAME, readable_list=['a', 'b'], editable_list=['a'])) permissions.SchemaPermissionRegistry.add( cls.PERMISSION_SCOPE, permissions.CourseAdminSchemaPermission()) @classmethod def permissions_callback(cls, app_context): return [cls.PERMISSION] def setUp(self): super(PermissionsTests, self).setUp() self.app_context = actions.simple_add_course(self.COURSE_NAME, self.ADMIN_EMAIL, 'Permissions Tests') self.schema = schema_fields.FieldRegistry('title') self.schema.add_property(schema_fields.SchemaField('a', 'A', 'string')) self.schema.add_property(schema_fields.SchemaField('b', 'B', 'string')) self.schema.add_property(schema_fields.SchemaField('c', 'C', 'string')) self.entity = {'a': 1, 'b': 2, 'c': 3} with common_utils.Namespace(self.NAMESPACE): role_dto = models.RoleDTO( the_id=None, the_dict={ 'name': self.ROLE_NAME, 'permissions': { self.MODULE_NAME: [self.PERMISSION_NAME] }, 'description': 'Role allowing limited schema access.', 'users': [self.IN_ROLE_EMAIL] }) roles.RoleDAO.save(role_dto) def test_admin_has_permissions_with_no_configuration_needed(self): actions.login(self.ADMIN_EMAIL, is_admin=True) self.assertTrue( permissions.can_view(self.app_context, constants.SCOPE_COURSE_SETTINGS)) self.assertTrue( permissions.can_edit(self.app_context, constants.SCOPE_COURSE_SETTINGS)) self.assertTrue( permissions.can_view_property(self.app_context, constants.SCOPE_COURSE_SETTINGS, 'absolutely/anything')) self.assertTrue( permissions.can_edit_property(self.app_context, constants.SCOPE_COURSE_SETTINGS, 'absolutely/anything')) def test_non_admin_has_no_permissions_with_no_configuration_needed(self): actions.login(self.IN_ROLE_EMAIL) self.assertFalse( permissions.can_view(self.app_context, constants.SCOPE_COURSE_SETTINGS)) self.assertFalse( permissions.can_edit(self.app_context, constants.SCOPE_COURSE_SETTINGS)) self.assertFalse( permissions.can_view_property(self.app_context, constants.SCOPE_COURSE_SETTINGS, 'absolutely/anything')) self.assertFalse( permissions.can_edit_property(self.app_context, constants.SCOPE_COURSE_SETTINGS, 'absolutely/anything')) def test_role_permissions(self): with common_utils.Namespace(self.NAMESPACE): # Admin and assistant can read 'a', but student cannot. checker = permissions.SchemaPermissionRegistry.build_view_checker( self.PERMISSION_SCOPE, ['a']) actions.login(self.ADMIN_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.IN_ROLE_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.NON_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) # Admin and assistant can read 'b', but student cannot. checker = permissions.SchemaPermissionRegistry.build_view_checker( self.PERMISSION_SCOPE, ['b']) actions.login(self.ADMIN_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.IN_ROLE_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.NON_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) # Admin can read 'c', but neither assistant nor student may. checker = permissions.SchemaPermissionRegistry.build_view_checker( self.PERMISSION_SCOPE, ['c']) actions.login(self.ADMIN_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.IN_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) actions.login(self.NON_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) # Admin and assistant can write 'a', but student cannot. checker = permissions.SchemaPermissionRegistry.build_edit_checker( self.PERMISSION_SCOPE, ['a']) actions.login(self.ADMIN_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.IN_ROLE_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.NON_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) # Admin can write 'b', but neither assistant nor student may. checker = permissions.SchemaPermissionRegistry.build_edit_checker( self.PERMISSION_SCOPE, ['b']) actions.login(self.ADMIN_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.IN_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) actions.login(self.NON_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) # Admin can write 'c', but neither assistant nor student may. checker = permissions.SchemaPermissionRegistry.build_edit_checker( self.PERMISSION_SCOPE, ['c']) actions.login(self.ADMIN_EMAIL) self.assertTrue(checker(self.app_context)) actions.login(self.IN_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) actions.login(self.NON_ROLE_EMAIL) self.assertFalse(checker(self.app_context)) def test_schema_redaction(self): reg = permissions.SchemaPermissionRegistry with common_utils.Namespace(self.NAMESPACE): # All properties readable/writable for admin actions.login(self.ADMIN_EMAIL) ret = reg.redact_schema_to_permitted_fields( self.app_context, self.PERMISSION_SCOPE, self.schema) a = ret.get_property('a') self.assertNotIn('disabled', a._extra_schema_dict_values) self.assertFalse(a.hidden) b = ret.get_property('b') self.assertNotIn('disabled', b._extra_schema_dict_values) self.assertFalse(b.hidden) c = ret.get_property('c') self.assertNotIn('disabled', c._extra_schema_dict_values) self.assertFalse(c.hidden) # 'a', 'b' readable, 'a' writable, and 'c' removed for assistant. actions.login(self.IN_ROLE_EMAIL) ret = reg.redact_schema_to_permitted_fields( self.app_context, self.PERMISSION_SCOPE, self.schema) a = ret.get_property('a') self.assertNotIn('disabled', a._extra_schema_dict_values) self.assertFalse(a.hidden) b = ret.get_property('b') self.assertTrue(b._extra_schema_dict_values.get('disabled')) self.assertFalse(b.hidden) self.assertIsNone(ret.get_property('c')) # All properties removed for account w/ no access. actions.login(self.NON_ROLE_EMAIL) ret = reg.redact_schema_to_permitted_fields( self.app_context, self.PERMISSION_SCOPE, self.schema) self.assertIsNone(ret.get_property('a')) self.assertIsNone(ret.get_property('b')) self.assertIsNone(ret.get_property('c'))