diff --git a/api/dao/hierarchy.py b/api/dao/hierarchy.py index 44dd38865b8cd58bd3401daaf0e96fd2e56fcf95..b197b9c0593788733410fffb73c2b8d323ff037c 100644 --- a/api/dao/hierarchy.py +++ b/api/dao/hierarchy.py @@ -131,6 +131,24 @@ def get_parent_tree(cont_name, _id): return tree +def propagate_group_change(_id, update, oper): + # Apply change to projects + if oper == 'POST': + config.db.projects.update_many({'group': _id}, {'$addToSet': {'permissions': update}}) + elif oper == 'PUT': + config.db.projects.update_many({'group': _id, 'permissions._id' : update['_id']}, {'$set': {'permissions.$.access': update['access']}}) + elif oper == 'DELETE': + config.db.projects.update_many({'group': _id, 'permissions._id' : update}, {'$pull' : {'permissions': {'_id': update}}}) + else: + raise APIStorageException("Cannot propagate {} operation".format(oper)) + + # Apply change to sessions and acquisitions + projects = config.db.projects.find({'group':_id}) + for project in projects: + propagate_changes('projects', project['_id'], {}, {'$set': { + 'permissions': project['permissions'] + }}) + def propagate_changes(cont_name, _id, query, update): """ diff --git a/api/handlers/listhandler.py b/api/handlers/listhandler.py index 515206c219d7f7e73712c9a713351739cdb3046f..8491788024eff811c156b4b1ea7873a57b1f8577 100644 --- a/api/handlers/listhandler.py +++ b/api/handlers/listhandler.py @@ -185,7 +185,7 @@ class ListHandler(base.RequestHandler): query_params = None container = storage.get_container(_id, query_params) if container is not None: - if self.superuser_request: + if self.superuser_request or self.user_is_admin: permchecker = always_ok elif self.public_request: permchecker = listauth.public_request(self, container) @@ -209,32 +209,43 @@ class PermissionsListHandler(ListHandler): def post(self, cont_name, list_name, **kwargs): _id = kwargs.get('cid') result = super(PermissionsListHandler, self).post(cont_name, list_name, **kwargs) - self._propagate_permissions(cont_name, _id, self.request.params.get('propagate')) + + if cont_name == 'groups' and self.request.params.get('propagate') =='true': + self._propagate_group_permission(_id, self.request.json_body, oper='POST') + else: + self._propagate_permissions(cont_name, _id) return result def put(self, cont_name, list_name, **kwargs): _id = kwargs.get('cid') result = super(PermissionsListHandler, self).put(cont_name, list_name, **kwargs) - self._propagate_permissions(cont_name, _id, self.request.params.get('propagate')) + payload = self.request.json_body + payload['_id'] = kwargs.get('_id') + if cont_name == 'groups' and self.request.params.get('propagate') =='true': + self._propagate_group_permission(_id, payload, oper='PUT') + else: + self._propagate_permissions(cont_name, _id) return result def delete(self, cont_name, list_name, **kwargs): _id = kwargs.get('cid') result = super(PermissionsListHandler, self).delete(cont_name, list_name, **kwargs) - self._propagate_permissions(cont_name, _id, self.request.params.get('propagate')) + + if cont_name == 'groups' and self.request.params.get('propagate') =='true': + self._propagate_group_permission(_id, kwargs.get('_id'), oper='DELETE') + else: + self._propagate_permissions(cont_name, _id) return result - def _propagate_permissions(self, cont_name, _id, propagate=False): + def _propagate_permissions(self, cont_name, _id): """ method to propagate permissions from a container/group to its sessions and acquisitions """ - if (cont_name == 'groups' and propagate) or cont_name == 'projects': + + if cont_name == 'projects': try: - if cont_name == 'projects': - oid = bson.ObjectId(_id) - else: - oid = _id + oid = bson.ObjectId(_id) update = {'$set': { 'permissions': config.db[cont_name].find_one({'_id': oid},{'permissions': 1})['permissions'] }} @@ -242,6 +253,15 @@ class PermissionsListHandler(ListHandler): except APIStorageException: self.abort(500, 'permissions not propagated from {} {} down hierarchy'.format(cont_name, _id)) + def _propagate_group_permission(self, _id, update, oper=None): + """ + method to propagate an isolated change to a groups permissions list to its projects + """ + try: + hierarchy.propagate_group_change(_id, update, oper) + except APIStorageException as e: + self.abort(400, e.message) + class NotesListHandler(ListHandler): """ diff --git a/test/integration_tests/python/test_propagation.py b/test/integration_tests/python/test_propagation.py index a2792df99d473b9a39a287994efd8300888a7575..735cdb9bb899b8084e2388b1514493ccf387b105 100644 --- a/test/integration_tests/python/test_propagation.py +++ b/test/integration_tests/python/test_propagation.py @@ -209,7 +209,7 @@ def test_add_and_remove_user_group_permission(data_builder, as_admin): # Add user to group permissions payload = {'_id': user_id, 'access': 'admin'} - r = as_admin.post('/groups/' + group + '/permissions', json=payload, params={'propagate': True}) + r = as_admin.post('/groups/' + group + '/permissions', json=payload, params={'propagate': 'true'}) assert r.ok r = as_admin.get('/groups/' + group) @@ -220,6 +220,7 @@ def test_add_and_remove_user_group_permission(data_builder, as_admin): r = as_admin.get('/projects/' + project) perms = r.json()['permissions'] user = get_user_in_perms(perms, user_id) + assert r.json()['group'] == group assert r.ok and user r = as_admin.get('/sessions/' + session) @@ -234,7 +235,7 @@ def test_add_and_remove_user_group_permission(data_builder, as_admin): # Modify user permissions payload = {'access': 'rw', '_id': user_id} - r = as_admin.put('/groups/' + group + '/permissions/' + user_id, json=payload, params={'propagate': True}) + r = as_admin.put('/groups/' + group + '/permissions/' + user_id, json=payload, params={'propagate': 'true'}) assert r.ok r = as_admin.get('/groups/' + group) @@ -258,7 +259,7 @@ def test_add_and_remove_user_group_permission(data_builder, as_admin): assert r.ok and user and user['access'] == 'rw' # Remove user from project permissions - r = as_admin.delete('/groups/' + group + '/permissions/' + user_id, json=payload, params={'propagate': True}) + r = as_admin.delete('/groups/' + group + '/permissions/' + user_id, json=payload, params={'propagate': 'true'}) assert r.ok r = as_admin.get('/groups/' + group)