def test_invenio_access_permission_cache_redis(app): """Caching the user using redis.""" cache = RedisCache() InvenioAccess(app, cache=cache) with app.test_request_context(): user_can_all = User(email='*****@*****.**') user_can_open = User(email='*****@*****.**') db.session.add(user_can_all) db.session.add(user_can_open) db.session.add(ActionUsers(action='open', user=user_can_all)) db.session.flush() identity_open = FakeIdentity(UserNeed(user_can_open.id)) permission_open = DynamicPermission(ActionNeed('open')) assert not permission_open.allows(identity_open) assert current_access.get_action_cache('open') == (set( [Need(method='id', value=1)]), set([])) db.session.add(ActionUsers(action='open', user=user_can_open)) db.session.flush() permission_open = DynamicPermission(ActionNeed('open')) assert permission_open.allows(identity_open) assert current_access.get_action_cache('open') == (set( [Need(method='id', value=1), Need(method='id', value=2)]), set([]))
def test_permissions(): """Iterates over all users checking its permissions.""" for i in range(users_number): identity = FakeIdentity(UserNeed(users[i].id)) # Allowed permission permission_allowed_both = DynamicPermission( ActionNeed('action{0}'.format( (i % actions_users_number) + actions_roles_number)), ActionNeed('action{0}'.format(i % actions_roles_number)) ) assert permission_allowed_both.allows(identity) # Not allowed action user permission_not_allowed_user = DynamicPermission( ActionNeed('action{0}'.format( (i + 1) % actions_users_number + actions_roles_number)) ) assert not permission_not_allowed_user.allows(identity) # Not allowed action role permission_not_allowed_role = DynamicPermission( ActionNeed('action{0}'.format( (i + 1) % actions_roles_number)) ) assert not permission_not_allowed_role.allows(identity)
def test_invenio_access_permission_for_users(app): """User can access to an action allowed/denied to the user""" InvenioAccess(app) with app.test_request_context(): db.session.begin(nested=True) user_can_all = User(email='*****@*****.**') user_can_read = User(email='*****@*****.**') user_can_open = User(email='*****@*****.**') db.session.add(user_can_all) db.session.add(user_can_read) db.session.add(user_can_open) db.session.add(ActionUsers(action='open', user=user_can_all)) db.session.add(ActionUsers(action='open', user=user_can_open)) db.session.add(ActionUsers(action='read', user=user_can_all)) db.session.add(ActionUsers(action='read', user=user_can_read)) db.session.commit() permission_open = DynamicPermission(ActionNeed('open')) permission_read = DynamicPermission(ActionNeed('read')) identity_all = FakeIdentity(UserNeed(user_can_all.id)) identity_read = FakeIdentity(UserNeed(user_can_read.id)) identity_open = FakeIdentity(UserNeed(user_can_open.id)) assert permission_open.allows(identity_all) assert permission_read.allows(identity_all) assert permission_open.allows(identity_open) assert not permission_read.allows(identity_open) assert not permission_open.allows(identity_read) assert permission_read.allows(identity_read)
def post(self, id): request_arg = RequestMethod_parser.parse_args() requestMethod = request_arg['requestMethod'] if requestMethod == "PUT": permission = Permission(ActionNeed('修改新闻标签')) if permission.can() is not True: abort_if_unauthorized("修改新闻标签") tag = Tag.query.filter(Tag.id == id).first() abort_if_not_exist(tag, "tag") args = parser_spec.parse_args() name = args['name'] if name != None and name != tag.name: t = Tag.query.filter(Tag.name == name).first() abort_if_exist(t, "tag") tag.name = name db.session.add(tag) db.session.commit() elif requestMethod == "DELETE": permission = Permission(ActionNeed('删除新闻标签')) if permission.can() is not True: abort_if_unauthorized("删除新闻标签") tag = Tag.query.filter(Tag.id == id).first() abort_if_not_exist(tag, "tag") db.session.delete(tag) db.session.commit() else: abort(404, message="api not found")
def test_actions_entrypoint(): """Test if the entrypoint is registering actions properly.""" app = Flask('testapp') ext = InvenioAccess(app) assert len(ext.actions) == 2 assert ActionNeed('open') in ext.actions.values() assert ActionNeed('close') in ext.actions.values()
def post(self, id): request_arg = RequestMethod_parser.parse_args() requestMethod = request_arg['requestMethod'] if requestMethod == "PUT": permission = Permission(ActionNeed('修改新闻属性')) if permission.can() is not True: abort_if_unauthorized("修改新闻属性") category = Category.query.filter(Category.id == id).first() abort_if_not_exist(category, "category") args = parser_spec.parse_args() name = args['name'] if name != None and name != category.name: c = Category.query.filter(Category.name == name).first() abort_if_exist(c, "category") category.name = name db.session.add(category) db.session.commit() elif requestMethod == "DELETE": permission = Permission(ActionNeed('删除新闻属性')) if permission.can() is not True: abort_if_unauthorized("删除新闻属性") id = int(id) category = Category.query.filter(Category.id == id).first() abort_if_not_exist(category, "category") db.session.delete(category) db.session.commit() else: abort(404, message="api not found")
def test_system_roles(access_app): """User can access to an action allowed/denied to their system roles.""" authenticated, anonymous = create_users("authenticated", "anonymous") assign_roles({ authenticated: [any_user, authenticated_user], anonymous: [any_user] }) act_read = ActionNeed("read") act_write = ActionNeed("write") expand(act_write, ("allow", authenticated_user)) expand(act_read, ("allow", any_user)) permission_read, permission_write = create_permissions( {"needs": [act_read]}, {"needs": [act_write]}) assert permission_read.allows(anonymous) assert permission_read.allows(authenticated) assert not permission_write.allows(anonymous) assert permission_write.allows(authenticated) superuser = get_superuser() assert permission_read.allows(superuser) assert permission_write.allows(superuser)
def test_invenio_access_permission_for_system_roles(app): """User can access to an action allowed/denied to their system roles.""" InvenioAccess(app) with app.test_request_context(): db.session.begin(nested=True) user = User(email='*****@*****.**') db.session.add(user) db.session.add(ActionSystemRoles.allow( action=ActionNeed('open'), role=authenticated_user)) db.session.add(ActionSystemRoles.allow( action=ActionNeed('write'), role_name='any_user')) db.session.commit() permission_open = DynamicPermission(ActionNeed('open')) permission_write = DynamicPermission(ActionNeed('write')) identity_anon_user = FakeIdentity(any_user) identity_auth_user = FakeIdentity(authenticated_user, any_user) assert not permission_open.allows(identity_anon_user) assert permission_open.allows(identity_auth_user) assert permission_write.allows(identity_anon_user) assert permission_write.allows(identity_auth_user)
def post(self,id): request_arg=RequestMethod_parser.parse_args() requestMethod=request_arg['requestMethod'] if requestMethod=="PUT": if current_user.is_anonymous==True: abort_if_unauthorized("修改用户") permission=Permission(ActionNeed("修改用户")) permission1=EditUserPermission(EditUserNeed(current_user.id)) if (permission.can()is not True)and (permission1.can()is not True): abort_if_unauthorized("修改用户") user=User.query.filter(User.id==id).first() abort_if_not_exist(user,"user") args=User1_parser.parse_args() # userId=args['userId'] status=args['status'] email=args['email'] phone=args['phone'] passWord=args['passWord'] roleName=args['roleName'] userName=args['userName'] if userName!=None and userName!=user.userName: user1=User.query.filter(User.userName==userName).first() abort_if_exist(user1,"userName") user.userName=userName if status!=None and permission.can(): user.status=status if email!=None: user.email=email if phone!=None: user.phone=phone if passWord!=None: user.passWord=generate_password_hash(passWord) if roleName!=None and permission.can(): try: roleName=list(eval(roleName[0])) except: pass r=list() for name in roleName: role=Role.query.filter(Role.roleName==name).first() abort_if_not_exist(role,"role") r.append(role) user.roles=r if userName!=None: user.userName=userName db.session.add(user) db.session.commit() elif requestMethod=="DELETE": permission=Permission(ActionNeed("删除用户")) if permission.can()is not True: abort_if_unauthorized("删除用户") user=User.query.filter(User.id==id).first() abort_if_not_exist(user,"user") db.session.delete(user) db.session.commit() else: abort(404,message="api not found")
def test_actions(base_app): """Test if the actions are registered properly.""" InvenioAccess(base_app, entry_point_actions=None) with base_app.app_context(): current_access.register_action(ActionNeed('action_a')) assert len(current_access.actions) == 1 current_access.register_action(ActionNeed('action_b')) assert len(current_access.actions) == 2
def test_invenio_access_permission_cache(app): """Caching the user using memory caching.""" cache = SimpleCache() InvenioAccess(app, cache=cache) with app.test_request_context(): user_can_all = User(email='*****@*****.**') user_can_open = User(email='*****@*****.**') user_can_open_1 = User(email='*****@*****.**') db.session.add(user_can_all) db.session.add(user_can_open) db.session.add(user_can_open_1) db.session.add(ActionUsers(action='open', user=user_can_all)) db.session.flush() permission_open = DynamicPermission(ActionNeed('open')) identity_open = FakeIdentity(UserNeed(user_can_open.id)) assert not permission_open.allows(identity_open) assert current_access.get_action_cache('open') == ( set([Need(method='id', value=1)]), set([]) ) db.session.add(ActionUsers(action='open', user=user_can_open)) db.session.flush() permission_open = DynamicPermission(ActionNeed('open')) assert permission_open.allows(identity_open) assert current_access.get_action_cache('open') == ( set([Need(method='id', value=1), Need(method='id', value=2)]), set([]) ) db.session.add(ActionUsers(action='open', argument=1, user=user_can_open_1)) db.session.flush() identity_open_1 = FakeIdentity(UserNeed(user_can_open_1.id)) permission_open_1 = DynamicPermission( ParameterizedActionNeed('open', '1')) assert not permission_open.allows(identity_open_1) assert permission_open_1.allows(identity_open_1) assert current_access.get_action_cache('open::1') == ( set([Need(method='id', value=1), Need(method='id', value=2), Need(method='id', value=3)]), set([]) ) assert current_access.get_action_cache('open') == ( set([Need(method='id', value=1), Need(method='id', value=2)]), set([]) )
def test_entrypoints(): """Test if the entrypoints are registering actions and roles properly.""" app = Flask('testapp') ext = InvenioAccess(app) assert len(ext.actions) == 2 assert ActionNeed('open') in ext.actions.values() assert ActionNeed('close') in ext.actions.values() assert len(ext.system_roles) == 2 assert SystemRoleNeed('any_user') in ext.system_roles.values() assert SystemRoleNeed('authenticated_user') in ext.system_roles.values()
def test_invenio_access_permission_for_users(app): """User can access to an action allowed/denied to the user""" InvenioAccess(app) with app.test_request_context(): db.session.begin(nested=True) superuser = User(email='*****@*****.**') user_can_all = User(email='*****@*****.**') user_can_read = User(email='*****@*****.**') user_can_open = User(email='*****@*****.**') db.session.add(superuser) db.session.add(user_can_all) db.session.add(user_can_read) db.session.add(user_can_open) db.session.add(ActionUsers(action='superuser-access', user=superuser)) db.session.add(ActionUsers(action='open', user=user_can_all)) db.session.add(ActionUsers(action='open', user=user_can_open)) db.session.add(ActionUsers(action='read', user=user_can_all)) db.session.add(ActionUsers(action='read', user=user_can_read)) db.session.add(ActionUsers(action='not_logged', user=user_can_all)) db.session.commit() permission_open = DynamicPermission(ActionNeed('open')) permission_read = DynamicPermission(ActionNeed('read')) permission_not_logged = DynamicPermission(ActionNeed('not_logged')) identity_superuser = FakeIdentity(UserNeed(superuser.id)) identity_all = FakeIdentity(UserNeed(user_can_all.id)) identity_read = FakeIdentity(UserNeed(user_can_read.id)) identity_open = FakeIdentity(UserNeed(user_can_open.id)) identity_unknown = AnonymousIdentity() # global permissions assert permission_open.allows(identity_superuser) assert permission_read.allows(identity_superuser) assert permission_open.allows(identity_all) assert permission_read.allows(identity_all) assert permission_not_logged.allows(identity_all) assert permission_open.allows(identity_open) assert not permission_read.allows(identity_open) assert not permission_not_logged.allows(identity_open) assert not permission_open.allows(identity_read) assert permission_read.allows(identity_read) assert not permission_not_logged.allows(identity_read) assert not permission_open.allows(identity_unknown) assert not permission_read.allows(identity_unknown)
def test_actions(): """Test if the actions are registered properly.""" app = Flask('testapp') Babel(app) Mail(app) InvenioDB(app) InvenioAccounts(app) InvenioAccess(app, entry_point_group=None) with app.app_context(): current_access.register_action(ActionNeed('action_a')) assert len(current_access.actions) == 1 current_access.register_action(ActionNeed('action_b')) assert len(current_access.actions) == 2
def post(self, id): request_arg = RequestMethod_parser.parse_args() requestMethod = request_arg['requestMethod'] if requestMethod == "PUT": permission = Permission(ActionNeed('修改新闻')) if permission.can()is not True: abort_if_unauthorized("修改新闻") news = News.query.filter(News.id == id).first() abort_if_not_exist(news, "news") args = NewsSpec_parser.parse_args() category = args['category'] detail = args['detail'] title = args['title'] editable = args['editable'] tags = args['tags'] try: tags = list(eval(tags[0])) except: pass if category != None: news.category = [] news.addCategory(category) if detail != None: news.detail = detail soup, imgUrlFirst = handle_html(detail) news.img_url = imgUrlFirst outline = soup.get_text()[:80] news.outline = outline if title != None: news.title = title if editable != None: news.editable = editable if tags != None: news.tags = [] for tag in tags: news.addTag(tag) db.session.add(news) db.session.commit() elif requestMethod == "DELETE": permission = Permission(ActionNeed('删除新闻')) if permission.can()is not True: abort_if_unauthorized("删除新闻") news = News.query.filter(News.id == id).first() abort_if_not_exist(news, "news") db.session.delete(news) db.session.commit() else: abort(404, message="api not found")
def files_permission_factory(obj, action=None): """Permission for files are always based on the type of bucket. 1. Community bucket: Read access for everyone 2. Record bucket: Read access only with open and restricted access. 3. Deposit bucket: Read/update with restricted access. 4. Any other bucket is restricted to admins only. """ # Extract bucket id bucket_id = None if isinstance(obj, Bucket): bucket_id = str(obj.id) elif isinstance(obj, ObjectVersion): bucket_id = str(obj.bucket_id) elif isinstance(obj, MultipartObject): bucket_id = str(obj.bucket_id) elif isinstance(obj, FileObject): bucket_id = str(obj.bucket_id) # Retrieve record if bucket_id is not None: # Community bucket if str(bucket_id) == current_app.config['COMMUNITIES_BUCKET_UUID']: return CommunityBucketPermission(action) # Record or deposit bucket rb = RecordsBuckets.query.filter_by(bucket_id=bucket_id).one_or_none() if rb is not None: record = Record.get_record(rb.record_id) if is_record(record): return RecordFilesPermission.create(record, action) elif is_deposit(record): return DepositFilesPermission.create(record, action) return DynamicPermission(ActionNeed('admin-access'))
def community_curation(record, user): """Generate a list of pending and accepted communities with permissions. Return a 2-tuple containing two lists, first for 'pending' and second for 'accepted' communities. Each item in both of the list is another 2-tuple of (Community, bool), describing community itself, and the permission (bool) to curate it. """ irs = InclusionRequest.query.filter_by(id_record=record.id).order_by( InclusionRequest.id_community).all() pending = [ir.community for ir in irs] accepted = [Community.get(c) for c in record.get('communities', [])] # Additionally filter out community IDs that did not resolve (None) accepted = [c for c in accepted if c] # Check for global curation permission (all communites on this record). global_perm = None if user.is_anonymous: global_perm = False elif DynamicPermission(ActionNeed('admin-access')).can(): global_perm = True if global_perm: return (pending, pending, accepted, accepted) else: return ( [c for c in pending if _can_curate(c, user, record)], [c for c in accepted if _can_curate(c, user, record, accepted=True)], pending, accepted, )
def check_and_handle_spam(community=None, deposit=None): """Checks community/deposit metadata for spam.""" try: if current_app.config.get('ZENODO_SPAM_MODEL_LOCATION'): if community: task = check_metadata_for_spam.delay(community_id=community.id) if deposit: task = check_metadata_for_spam.delay(dep_id=str(deposit.id)) spam_proba = task.get( timeout=current_app.config['ZENODO_SPAM_CHECK_TIMEOUT']) else: spam_proba = 0 if spam_proba > current_app.config['ZENODO_SPAM_THRESHOLD']: if not Permission(ActionNeed('admin-access')).can(): has_records = RecordsSearch(index='records').query( Q('query_string', query="owners:{}".format(community.id_user))).count() has_communities = Community.query.filter_by( id_user=community.id_user).count() - 1 if not (has_records or has_communities): current_app.config['ZENODO_SPAM_HANDLING_ACTIONS']( community=community, deposit=deposit) except HTTPException: raise except Exception: current_app.logger.exception(u'Could not check for spam')
def post(self): request_arg=RequestMethod_parser.parse_args() requestMethod=request_arg['requestMethod'] print(requestMethod) if requestMethod=="POST": permission=Permission(ActionNeed('添加角色')) if permission.can()is not True: abort_if_unauthorized("添加角色") args=Role_parser.parse_args() roleName=args['roleName'] try: nodeName=list(eval(args['nodeName'][0])) except: nodeName=args['nodeName'] role1=Role.query.filter(Role.roleName==roleName).first() abort_if_exist(role1,"roleName") role=Role(roleName) db.session.add(role) db.session.commit() for name in nodeName: node=Node.query.filter(Node.nodeName==name).first() abort_if_not_exist(node,"node") role.nodes.append(node) db.session.add(role) db.session.commit() else: abort(404,message="api not found")
def get(self,id): permission=Permission(ActionNeed(('查看权限节点'))) if permission.can() is not True: abort_if_unauthorized("查看权限节点") node=Node.query.filter(Node.id==id).first() abort_if_not_exist(node,"node") return node
def get(self, id): permission = Permission(ActionNeed(('查看新闻'))) if permission.can() is not True: abort_if_unauthorized("查看新闻") silder_show = SilderShow.query.filter(SilderShow.id == id).first() abort_if_not_exist(silder_show, "silder_show") return silder_show
def get(self, id): permission = Permission(ActionNeed(('查看新闻'))) if permission.can() is not True: abort_if_unauthorized("查看新闻") news = News.query.filter(News.id == id).first() abort_if_not_exist(news, "news") return news
def test_factory_for_unknown_obj_returns_superuser_permission(self): unknown_obj = {} permission = FilesPermission.create(unknown_obj, 'bucket-update') assert type(permission) == Permission assert ActionNeed('superuser-access') in permission.explicit_needs
def post(self): request_arg = RequestMethod_parser.parse_args() requestMethod = request_arg['requestMethod'] if requestMethod == "POST": permission = Permission(ActionNeed('添加新闻')) if permission.can()is not True: abort_if_unauthorized("添加新闻") args = News_parser.parse_args() category = args['category'] detail = args['detail'] title = args['title'] tags = args['tags'] try: tags = list(eval(tags[0])) except: pass soup, imgUrlFirst = handle_html(detail) outline = soup.get_text()[:80] news = News(soup.prettify(), title, outline, imgUrlFirst) db.session.add(news) db.session.commit() news.addCategory(category) for tag in tags: t = Tag.query.filter_by(name=tag).first() abort_if_not_exist(t, "tag") news.tags.append(t) db.session.add(news) db.session.commit() else: abort(404, message="api not found")
def test_factory_for_unknown_action_returns_superuser_permission(self): record = {'_deposit': {'owners': [1]}} permission = FilesPermission.create(record, 'unknown') assert type(permission) == Permission assert ActionNeed('superuser-access') in permission.explicit_needs
def test_file_permissions(app, db, record_with_files_creation, user, access_right, expected): """Test file permissions.""" pid, record, record_url = record_with_files_creation # Create test users admin = User(email='*****@*****.**', password='******') owner = User(email='*****@*****.**', password='******') auth = User(email='*****@*****.**', password='******') db.session.add_all([admin, owner, auth]) db.session.add(ActionUsers.allow(ActionNeed('admin-access'), user=admin)) db.session.commit() # Create test record record['access_right'] = access_right record['owners'] = [owner.id] record.commit() db.session.commit() file_url = url_for( 'invenio_records_ui.recid_files', pid_value=pid.pid_value, filename='Test.pdf', ) with app.test_client() as client: if user: # Login as user with client.session_transaction() as sess: sess['user_id'] = User.query.filter_by( email='{}@zenodo.org'.format(user)).one().id sess['_fresh'] = True res = client.get(file_url) assert res.status_code == expected
def test_dynamic_permission_needs_cache_invalidation(app): """Testing DynamicPermission refreshes needs. This is important when protecting a view with @permission.require(http_exception=403) If cache does not get invalidated, the needs will only be refreshed when the Python process restarts. """ cache = SimpleCache() InvenioAccess(app, cache=cache) with app.test_request_context(): user_can_all = User(email='*****@*****.**') user_can_open = User(email='*****@*****.**') db.session.add(user_can_all) db.session.add(user_can_open) db.session.add(ActionUsers(action='open', user=user_can_all)) db.session.flush() permission_open = DynamicPermission(ActionNeed('open')) assert permission_open.needs == set([Need(method='id', value=1)]) db.session.add(ActionUsers(action='open', user=user_can_open)) db.session.flush() assert permission_open.needs == set( [Need(method='id', value=1), Need(method='id', value=2)] )
def post(self): request_arg=RequestMethod_parser.parse_args() requestMethod=request_arg['requestMethod'] if requestMethod=="POST": permission=Permission(ActionNeed('添加用户')) if permission.can()is not True: abort_if_unauthorized("添加用户") args=User_parser.parse_args() try: args['roleName']=list(eval(args['roleName'][0])) except: pass userName=args['userName'] passWord=args['passWord'] email=args['email'] roleName=args['roleName'] phone=args['phone'] user1=User.query.filter(User.userName==userName).first() abort_if_exist(user1,"userName") user=User(userName,passWord,email,phone) for name in roleName: role=Role.query.filter(Role.roleName==name).first() abort_if_not_exist(role,"role") user.roles.append(role) db.session.add(user) db.session.commit() else: abort(404,message="api not found")
def community_curation(record, user): """Generate a list of pending and accepted communities with permissions. Return a 4-tuple of lists (in order): * 'pending' communities, which can be curated by given user * 'accepted' communities, which can be curated by given user * All 'pending' communities * All 'accepted' communities """ irs = ZenodoCommunity.get_irs(record).all() pending = list(set(ir.community for ir in irs)) accepted = [Community.get(c) for c in record.get('communities', [])] # Additionally filter out community IDs that did not resolve (None) accepted = [c for c in accepted if c] # Check for global curation permission (all communites on this record). global_perm = None if user.is_anonymous: global_perm = False elif DynamicPermission(ActionNeed('admin-access')).can(): global_perm = True if global_perm: return (pending, accepted, pending, accepted) else: return ( [c for c in pending if _can_curate(c, user, record)], [ c for c in accepted if _can_curate(c, user, record, accepted=True) ], pending, accepted, )
def on_identity_loaded(sender, identity): try: # Set the identity user object identity.user = current_user # user has the permission of edit himself identity.provides.add(EditUserPermission(current_user.id)) # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) for role in current_user.roles: identity.provides.add(RoleNeed(role.roleName)) # Assuming the User model has a list of nodes, update the # identity with the nodes that the user provides if hasattr(current_user, "roles"): for role in current_user.roles: for node in role.nodes: if (node.status == 1) and (current_user.status == 1) and (role.status == 1): identity.provides.add(ActionNeed(node.nodeName)) except: pass