def test_item_need_read(self): class BookResource(PrincipalResource): class Meta: model = self.BOOK permissions = { 'read': ['owns-copy', 'admin'], 'create': 'admin', 'owns-copy': 'owns-copy' } self.api.add_resource(BookResource) self.mock_user = {'id': 1, 'roles': ['admin']} # TODO Bulk inserts # response = self.client.post('/book', data=[ # {'title': 'GoT Vol. {}'.format(i + 1)} for i in range(20) # ]) for i in range(20): self.client.post('/book', data={'title': 'GoT Vol. {}'.format(i + 1)}) self.assertEqual(20, len(self.client.get('/book').json)) self.mock_user = { 'id': 2, 'needs': [ ItemNeed('owns-copy', i, 'book') for i in (1, 4, 6, 8, 11, 15, 19) ] } self.assertEqual(7, len(self.client.get('/book').json)) self.mock_user = { 'id': 3, 'needs': [ItemNeed('owns-copy', i, 'book') for i in (2, 7, 19)] } self.assertEqual([{ '$uri': '/book/2', 'title': 'GoT Vol. 2' }, { '$uri': '/book/7', 'title': 'GoT Vol. 7' }, { '$uri': '/book/19', 'title': 'GoT Vol. 19' }], self.client.get('/book').json) self.assert404(self.client.get('/book/15')) self.assert200(self.client.get('/book/2')) self.assert200(self.client.get('/book/7')) self.assert404(self.client.get('/book/1')) self.assert404(self.client.get('/book/99')) self.mock_user = {'id': 4} self.assertEqual([], self.client.get('/book').json)
def __init__(self, project_id): coordinator_need = ItemNeed('project_coordinator', int(project_id), 'project_role') labeler_need = ItemNeed('data_labeler', int(project_id), 'project_role') super(AddLabelPermission, self).__init__(RoleNeed('admin'), RoleNeed('project_coordinator'), RoleNeed('data_labeler'), coordinator_need, labeler_need)
def __init__(self, project_id): coordinator_need = ItemNeed('project_coordinator', int(project_id), 'project_role') scientist_need = ItemNeed('data_scientist', int(project_id), 'project_role') super(UploadDataPermission, self).__init__(RoleNeed('admin'), RoleNeed('project_coordinator'), RoleNeed('data_scientist'), coordinator_need, scientist_need)
def __init__(self, project_id): coordinator_need = ItemNeed('project_coordinator', int(project_id), 'project_role') labeler_need = ItemNeed('data_labeler', int(project_id), 'project_role') scientist_need = ItemNeed('data_scientist', int(project_id), 'project_role') super(ViewResultsPermission, self).__init__(RoleNeed('admin'), RoleNeed('project_coordinator'), RoleNeed('data_labeler'), RoleNeed('data_scientist'), coordinator_need, labeler_need, scientist_need)
def get_quality_assurance_form_dashboard_menu(form_types): """Retrieves a list of forms that have the verification flag set :param form_type: The form type for the forms to be retrieved """ event = g.event return [ { 'url': url_for('submissions.quality_assurance_dashboard', form_id=form.id), 'text': form.name, 'visible': True } for form in [ f for f in models.Form.query.filter( models.Form.form_type.in_(form_types), models.Form.quality_checks_enabled == True # noqa ).join(models.Form.events).filter( models.Form.events.contains(event)).order_by(models.Form.name) if Permission( ItemNeed('access_resource', f.resource_id, f.resource_type), RoleNeed('admin')).can() ] ]
def generate_sitewide_needs(needs): ''' For a given set of ```ItemNeed``` or ```HybridItemNeed``` instances, generates a tuple of needs that ensures that users with sitewide permissions on an object type can perform the specified operation(s) even if they do not have explicit authorization. Parameters ---------- needs : tuple The existing needs Returns ------- tuple A tuple of the sitewide needs for the given needs ''' sitewide_needs = set() for need in needs: if isinstance(need, HybridItemNeed) or isinstance(need, ItemNeed): # The need is already a site-wide need. if need.type == 'site': continue permission = need.method resource_type = need.type sitewide_needs.add(ItemNeed(permission, None, resource_type)) return sitewide_needs
def test_item_need_update(self): class BookStoreResource(PrincipalResource): class Meta: model = self.BOOK_STORE permissions = {'create': 'admin', 'update': 'update'} self.api.add_resource(BookStoreResource) self.mock_user = {'id': 1, 'roles': ['admin']} # response = self.client.post('/book_store', data=[ # {'name': 'Bar Books'}, # {'name': 'Foomazon'} # ]) response = self.client.post('/book_store', data={'name': 'Bar Books'}) self.assert200(response) response = self.client.post('/book_store', data={'name': 'Foomazon'}) self.assert200(response) self.mock_user = { 'id': 1, 'needs': [ItemNeed('update', 2, 'book_store')] } self.assert403(self.client.patch('/book_store/1', data={'name': 'Foo'})) response = self.client.patch('/book_store/2', data={'name': 'Foo'}) self.assert200(response) self.assertEqual({ '$uri': '/book_store/2', 'name': 'Foo' }, response.json)
def __call__(self, item): """ """ for field in self.fields: item = get_value(item, field.attribute) if item is None: if self.method == 'id': return UserNeed(None) return ItemNeed(self.method, None, self.type) item_id = get_value(item, self.final_field.resource.manager.id_attribute, None) if self.method == 'id': return UserNeed(item_id) return ItemNeed(self.method, item_id, self.type)
def __call__(self, item): if self.method == 'id': return UserNeed( get_value(item, self.resource.manager.id_attribute, None)) return ItemNeed( self.method, get_value(item, self.resource.manager.id_attribute, None), self.type)
def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Default role identity.provides.add(RoleNeed('data_labeler')) # If the user account has the admin flag, make them a global admin if hasattr(current_user, 'admin'): if current_user.admin: identity.provides.add(RoleNeed('admin')) # Get all project roles # If not assigned to a project, treat it as a global role if hasattr(current_user, 'projects'): for project in current_user.projects: if project.project_coordinator: if project.project_id is None: identity.provides.add(RoleNeed('project_coordinator')) else: identity.provides.add( ItemNeed('project_coordinator', project.project_id, 'project_role')) if project.data_labeler: if project.project_id is None: identity.provides.add(RoleNeed('data_labeler')) else: identity.provides.add( ItemNeed('data_labeler', project.project_id, 'project_role')) if project.data_scientist: if project.project_id is None: identity.provides.add(RoleNeed('data_scientist')) else: identity.provides.add( ItemNeed('data_scientist', project.project_id, 'project_role'))
def build_permission(self, resource): # NOTE(stephen): Lazily import ItemNeed since this class can be # referenced from the pipeline where web dependencies are not installed. from flask_principal import ItemNeed resource_id = resource.id if resource else None resource_type = self.resource_type.name.name.lower() # We want to take the Enum NAME, # not the Enum itself permission = self.permission return ItemNeed(permission, resource_id, resource_type)
def __init__(self, file_name): restricted = LabeledClip.query.filter( LabeledClip.file_name == file_name).join( Label, Label.id == LabeledClip.label_id).filter( Label.restricted == True).first() if restricted: audio_file = AudioFile.query.filter( AudioFile.name == file_name).first() station = audio_file.monitoring_station project_need = ItemNeed('project_coordinator', int(station.project_id), 'project_role') else: project_need = UserNeed(current_user.id) super(ListenPermission, self).__init__(RoleNeed('admin'), RoleNeed('project_coordinator'), project_need)
def get_checklist_form_dashboard_menu(**kwargs): """Retrieves a list of forms that have the verification flag set :param form_type: The form type for the forms to be retrieved """ event = g.event return [{ 'url': url_for('dashboard.checklists', form_id=form.id), 'text': form.name, 'visible': True } for form in [ f for f in models.Form.query.filter_by( **kwargs).join(models.Form.events).filter( models.Form.events.contains(event)).order_by(models.Form.name) if Permission( ItemNeed('access_resource', f.resource_id, f.resource_type), RoleNeed('admin')).can() ]]
def _build_resource_specific_needs(resource_type, permission, resource): '''Yields any authorization needs that are specifically related to an individual authorization resource or authorization resource type. ''' # $CycloneIdaiHack(vedant) if resource_type.name == ResourceTypeEnum.ALERT: resource_id = resource.id if resource else None yield ItemNeed(permission.permission, resource_id, 'alert_definitions') if not resource: return if resource.resource_type.name == ResourceTypeEnum.QUERY_POLICY: with Transaction() as transaction: query_policy_entity = transaction.find_by_id( QueryPolicy, resource.id, 'resource_id') query_need = construct_query_need_from_policy(query_policy_entity) yield query_need
def get_form_list_menu(**kwargs): """Retrieves a list of forms that the user has access to and returns it in a format that can be rendered on the menu :param form_type: The form type for the forms to be retrieved """ event = g.event return [{ 'url': url_for('submissions.submission_list', form_id=form.id), 'text': form.name, 'icon': '<i class="glyphicon glyphicon-check"></i>', 'visible': True } for form in [ f for f in models.Form.query.filter_by( **kwargs).join(models.Form.events).filter( models.Form.events.contains(event)).order_by(models.Form.name) if Permission( ItemNeed('access_resource', f.resource_id, f.resource_type), RoleNeed('admin')).can() ]]
def install_default_user_permissions(identity): ''' Add permisisons that the current user should be able to perform regardless of whatever other roles they possess. ''' identity.provides.add(UserNeed(identity.user.id)) # TODO(vedant) - This should not be hardcoded. # Always allow the user to view their profile identity.provides.add(ItemNeed('view_resource', identity.user.id, 'user')) # HACK(vedant) - Fixed as part of a short term solution for T2113 # The long term solution is to define default permissions or a default user group that all new # users should be added to. identity.provides.add(ItemNeed('create_resource', None, 'dashboard')) # Continuation of Work for T2148 but now allowing RO-access to all Potion APIs identity.provides.add(ItemNeed('view_resource', None, 'user')) identity.provides.add(ItemNeed('view_resource', None, 'group')) identity.provides.add(ItemNeed('view_resource', None, 'role')) identity.provides.add(ItemNeed('view_resource', None, 'resource')) identity.provides.add(ItemNeed('view_resource', None, 'configuration'))
def test_relationship(self): "should require update permission on parent resource for updating, read permissions on both" class BookResource(PrincipalResource): class Schema: author = fields.ToOne('user', nullable=True) class Meta: model = self.BOOK permissions = { 'read': ['owns-copy', 'update', 'admin'], 'create': 'writer', 'update': 'user:author', 'owns-copy': 'owns-copy' } class UserResource(PrincipalResource): books = Relation(BookResource) class Meta: model = self.USER permissions = {'create': 'admin'} self.api.add_resource(UserResource) self.api.add_resource(BookResource) self.mock_user = {'id': 1, 'roles': ['admin']} for user in [{ 'name': 'Admin' }, { 'name': 'Author 1' }, { 'name': 'Author 2' }]: response = self.client.post('/user', data=user) self.assert200(response) response = self.client.post('/book', data={'title': 'Foo'}) self.assert403(response) self.mock_user = {'id': 2, 'roles': ['writer']} response = self.client.post('/book', data={ 'author': { '$ref': '/user/2' }, 'title': 'Bar' }) self.assert200(response) self.mock_user = {'id': 3, 'roles': ['writer']} response = self.client.post('/book', data={'title': 'Spying: Novel'}) self.assert200(response) response = self.client.post('/book', data={'title': 'Spied: The Sequel'}) self.assert200(response) response = self.client.post('/book', data={'title': 'Spy: The Prequel'}) self.assert200(response) self.assertJSONEqual( { '$uri': '/book/4', 'author': None, 'title': 'Spy: The Prequel' }, response.json) self.mock_user = {'id': 1, 'roles': ['admin']} self.client.post('/user/3/books', data={'$ref': '/book/2'}) self.client.post('/user/3/books', data={'$ref': '/book/3'}) self.client.post('/user/3/books', data={'$ref': '/book/4'}) self.mock_user = {'id': 3, 'roles': ['writer']} self.assert200(response) response = self.client.get('/user/3/books') self.assert200(response) self.assertEqual(3, len(response.json)) # read -> update -> user:author self.mock_user = {'id': 4, 'needs': [ItemNeed('owns-copy', 3, 'book')]} response = self.client.get('/user/3/books') self.assertEqual(1, len(response.json)) # read -> owns-copy self.assert200(self.client.get('/book/3')) self.assert404(self.client.get('/book/2')) self.mock_user = {'id': 5} response = self.client.get('/user/3/books') self.assertEqual(0, len(response.json)) self.assert404(self.client.get('/book/2'))
def __init__(self, project_id): coordinator_need = ItemNeed('project_coordinator', int(project_id), 'project_role') super(ManageLabelsPermission, self).__init__(RoleNeed('admin'), RoleNeed('project_coordinator'), coordinator_need)
def is_authorized(permission, resource_type, resource_id=None, log_request=True): ''' Determines whether or not the currently loaded user can perform the specified operation on the specified resource. Parameters ---------- permission : string The desired object permission that the user must possess (e.g. 'edit_resource') resource_type : string The type of resource that the operation is being performed on (e.g. 'dashboard') resource_id (optional): int The id of the resource in question (based on the `id` attribute of the `Resource` model). Do not specify if you are attempting to determine whether the user has a sitewide permission for a given resource type. log_request (optional): string Whether or not to log the authorization check. This should generally be true unless the user is simply querying whether or not they have the permission to do so. Returns ------- bool True if the user is authorized and False otherwise ''' # WARNING: Please be careful what changes you make to this function. It is ultimately # the function that decides whether or not to authorize ANY action on the website. permission = str(permission).lower() resource_type = str(resource_type).lower() resource_name = int(resource_id) if resource_id else None resource_specific_need = [ ItemNeed(permission, resource_name, resource_type) ] required_permission = WhitelistedPermission(resource_specific_need) if required_permission.can(): if log_request: g.request_logger.debug( 'User \'%s\' successfully authorized to perform ' '\'%s\' on resource \'%s\' of type \'%s\'.', get_user_string(current_user), permission, resource_id, resource_type, ) return True if log_request: g.request_logger.info( 'User \'%s\' attempted to perform ' '\'%s\' on resource \'%s\' of type \'%s\' but was unauthorized.', get_user_string(current_user), permission, resource_id, resource_type, ) return False
def can_access_resource(resource): perm = Permission( ItemNeed('access_resource', resource.resource_id, resource.resource_type), RoleNeed('admin')) return perm.can()
def require_item_perm(action, item, http_exception=403): perm = Permission(ItemNeed(action, item, 'object'), RoleNeed('admin')) if not perm.can(): abort(http_exception, perm)
def __init__(self, board_name): need = ItemNeed(ACTUALIZAR_CONTENIDO, board_name, 'board') super().__init__(need, AdminRolNeed, ListarArticulosNeed)
def __init__(self, board_name): need = ItemNeed(ENVIAR_CONTENIDO, board_name, 'board') super().__init__(need, AdminRolNeed, EnviarAritulosNeed)
def __init__(self, board_name): need = ItemNeed(PONER_CONTENIDO, board_name, 'board') super().__init__(need, AdminRolNeed, PonerArticulosNeed)