Allow a user to remove themselves from any project they're in.
This commit is contained in:
parent
fc4dfd3964
commit
f98b2a09ca
@ -6,6 +6,7 @@ from bson import ObjectId
|
|||||||
from eve.methods.post import post_internal
|
from eve.methods.post import post_internal
|
||||||
from eve.methods.patch import patch_internal
|
from eve.methods.patch import patch_internal
|
||||||
from flask import g, Blueprint, request, abort, current_app
|
from flask import g, Blueprint, request, abort, current_app
|
||||||
|
from werkzeug import exceptions as wz_exceptions
|
||||||
|
|
||||||
from application.utils import remove_private_keys, authorization, jsonify, mongo
|
from application.utils import remove_private_keys, authorization, jsonify, mongo
|
||||||
from application.utils.gcs import GoogleCloudStorageBucket
|
from application.utils.gcs import GoogleCloudStorageBucket
|
||||||
@ -252,32 +253,32 @@ def project_manage_users():
|
|||||||
No changes are done on the project itself.
|
No changes are done on the project itself.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
projects_collection = current_app.data.driver.db['projects']
|
||||||
|
users_collection = current_app.data.driver.db['users']
|
||||||
|
|
||||||
# TODO: check if user is admin of the project before anything
|
# TODO: check if user is admin of the project before anything
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
project_id = request.args['project_id']
|
project_id = request.args['project_id']
|
||||||
projects_collection = current_app.data.driver.db['projects']
|
|
||||||
project = projects_collection.find_one({'_id': ObjectId(project_id)})
|
project = projects_collection.find_one({'_id': ObjectId(project_id)})
|
||||||
admin_group_id = project['permissions']['groups'][0]['group']
|
admin_group_id = project['permissions']['groups'][0]['group']
|
||||||
users_collection = current_app.data.driver.db['users']
|
|
||||||
users = users_collection.find(
|
users = users_collection.find(
|
||||||
{'groups': {'$in': [admin_group_id]}},
|
{'groups': {'$in': [admin_group_id]}},
|
||||||
{'username': 1, 'email': 1, 'full_name': 1})
|
{'username': 1, 'email': 1, 'full_name': 1})
|
||||||
users_list = [user for user in users]
|
return jsonify({'_status': 'OK', '_items': list(users)})
|
||||||
return jsonify({'_status': 'OK', '_items': users_list})
|
|
||||||
|
|
||||||
# The request is not a form, since it comes from the API sdk
|
# The request is not a form, since it comes from the API sdk
|
||||||
data = json.loads(request.data)
|
data = json.loads(request.data)
|
||||||
project_id = data['project_id']
|
project_id = ObjectId(data['project_id'])
|
||||||
target_user_id = data['user_id']
|
target_user_id = ObjectId(data['user_id'])
|
||||||
action = data['action']
|
action = data['action']
|
||||||
user_id = g.current_user['user_id']
|
current_user_id = g.current_user['user_id']
|
||||||
|
|
||||||
projects_collection = current_app.data.driver.db['projects']
|
project = projects_collection.find_one({'_id': project_id})
|
||||||
project = projects_collection.find_one({'_id': ObjectId(project_id)})
|
|
||||||
|
|
||||||
# Check if the current_user is owner of the project
|
# Check if the current_user is owner of the project, or removing themselves.
|
||||||
# TODO: check based on permissions
|
remove_self = target_user_id == current_user_id and action == 'remove'
|
||||||
if project['user'] != user_id:
|
if project['user'] != current_user_id and not remove_self:
|
||||||
return abort_with_error(403)
|
return abort_with_error(403)
|
||||||
|
|
||||||
admin_group = get_admin_group(project)
|
admin_group = get_admin_group(project)
|
||||||
@ -285,19 +286,24 @@ def project_manage_users():
|
|||||||
# Get the user and add the admin group to it
|
# Get the user and add the admin group to it
|
||||||
if action == 'add':
|
if action == 'add':
|
||||||
operation = '$addToSet'
|
operation = '$addToSet'
|
||||||
|
log.info('project_manage_users: Adding user %s to admin group of project %s',
|
||||||
|
target_user_id, project_id)
|
||||||
elif action == 'remove':
|
elif action == 'remove':
|
||||||
|
log.info('project_manage_users: Removing user %s from admin group of project %s',
|
||||||
|
target_user_id, project_id)
|
||||||
operation = '$pull'
|
operation = '$pull'
|
||||||
else:
|
else:
|
||||||
return abort_with_error(403)
|
log.warning('project_manage_users: Unsupported action %r called by user %s',
|
||||||
|
action, current_user_id)
|
||||||
|
raise wz_exceptions.UnprocessableEntity()
|
||||||
|
|
||||||
users_collection = current_app.data.driver.db['users']
|
users_collection.update({'_id': target_user_id},
|
||||||
users_collection.update({'_id': ObjectId(target_user_id)},
|
|
||||||
{operation: {'groups': admin_group['_id']}})
|
{operation: {'groups': admin_group['_id']}})
|
||||||
user = users_collection.find_one({'_id': ObjectId(target_user_id)},
|
|
||||||
|
user = users_collection.find_one({'_id': target_user_id},
|
||||||
{'username': 1, 'email': 1,
|
{'username': 1, 'email': 1,
|
||||||
'full_name': 1})
|
'full_name': 1})
|
||||||
user.update({'_status': 'OK'})
|
user['_status'] = 'OK'
|
||||||
# Return the user in the response.
|
|
||||||
return jsonify(user)
|
return jsonify(user)
|
||||||
|
|
||||||
|
|
||||||
|
@ -533,4 +533,42 @@ class ProjectNodeAccess(AbstractProjectTest):
|
|||||||
|
|
||||||
db_user = users.find_one(self.other_user_id)
|
db_user = users.find_one(self.other_user_id)
|
||||||
self.assertNotIn(admin_group['_id'], db_user['groups'])
|
self.assertNotIn(admin_group['_id'], db_user['groups'])
|
||||||
|
|
||||||
|
def test_remove_self(self):
|
||||||
|
"""Every user should be able to remove themselves from a project,
|
||||||
|
regardless of permissions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from application.modules import projects
|
||||||
|
from application.utils import dumps
|
||||||
|
|
||||||
|
project_mng_user_url = '/p/users'
|
||||||
|
|
||||||
|
# Use our API to add user to group
|
||||||
|
payload = {
|
||||||
|
'project_id': self.project_id,
|
||||||
|
'user_id': self.other_user_id,
|
||||||
|
'action': 'add'}
|
||||||
|
|
||||||
|
resp = self.client.post(project_mng_user_url,
|
||||||
|
data=dumps(payload),
|
||||||
|
content_type='application/json',
|
||||||
|
headers={'Authorization': self.make_header('token')})
|
||||||
|
self.assertEqual(200, resp.status_code, resp.data)
|
||||||
|
|
||||||
|
# Update payload to remove the user we just added, and call it as that user.
|
||||||
|
payload['action'] = 'remove'
|
||||||
|
|
||||||
|
resp = self.client.post(project_mng_user_url,
|
||||||
|
data=dumps(payload),
|
||||||
|
content_type='application/json',
|
||||||
|
headers={'Authorization': self.make_header('other-token')})
|
||||||
|
self.assertEqual(200, resp.status_code, resp.data)
|
||||||
|
|
||||||
|
# Check if the user is now actually removed from the group.
|
||||||
|
with self.app.test_request_context():
|
||||||
|
users = self.app.data.driver.db['users']
|
||||||
|
|
||||||
|
db_user = users.find_one(self.other_user_id)
|
||||||
|
admin_group = projects.get_admin_group(self.project)
|
||||||
self.assertNotIn(admin_group['_id'], db_user['groups'])
|
self.assertNotIn(admin_group['_id'], db_user['groups'])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user