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.patch import patch_internal
|
||||
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.gcs import GoogleCloudStorageBucket
|
||||
@ -252,32 +253,32 @@ def project_manage_users():
|
||||
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
|
||||
if request.method == 'GET':
|
||||
project_id = request.args['project_id']
|
||||
projects_collection = current_app.data.driver.db['projects']
|
||||
project = projects_collection.find_one({'_id': ObjectId(project_id)})
|
||||
admin_group_id = project['permissions']['groups'][0]['group']
|
||||
users_collection = current_app.data.driver.db['users']
|
||||
|
||||
users = users_collection.find(
|
||||
{'groups': {'$in': [admin_group_id]}},
|
||||
{'username': 1, 'email': 1, 'full_name': 1})
|
||||
users_list = [user for user in users]
|
||||
return jsonify({'_status': 'OK', '_items': users_list})
|
||||
return jsonify({'_status': 'OK', '_items': list(users)})
|
||||
|
||||
# The request is not a form, since it comes from the API sdk
|
||||
data = json.loads(request.data)
|
||||
project_id = data['project_id']
|
||||
target_user_id = data['user_id']
|
||||
project_id = ObjectId(data['project_id'])
|
||||
target_user_id = ObjectId(data['user_id'])
|
||||
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': ObjectId(project_id)})
|
||||
project = projects_collection.find_one({'_id': project_id})
|
||||
|
||||
# Check if the current_user is owner of the project
|
||||
# TODO: check based on permissions
|
||||
if project['user'] != user_id:
|
||||
# Check if the current_user is owner of the project, or removing themselves.
|
||||
remove_self = target_user_id == current_user_id and action == 'remove'
|
||||
if project['user'] != current_user_id and not remove_self:
|
||||
return abort_with_error(403)
|
||||
|
||||
admin_group = get_admin_group(project)
|
||||
@ -285,19 +286,24 @@ def project_manage_users():
|
||||
# Get the user and add the admin group to it
|
||||
if action == 'add':
|
||||
operation = '$addToSet'
|
||||
log.info('project_manage_users: Adding user %s to admin group of project %s',
|
||||
target_user_id, project_id)
|
||||
elif action == 'remove':
|
||||
log.info('project_manage_users: Removing user %s from admin group of project %s',
|
||||
target_user_id, project_id)
|
||||
operation = '$pull'
|
||||
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': ObjectId(target_user_id)},
|
||||
users_collection.update({'_id': target_user_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,
|
||||
'full_name': 1})
|
||||
user.update({'_status': 'OK'})
|
||||
# Return the user in the response.
|
||||
user['_status'] = 'OK'
|
||||
return jsonify(user)
|
||||
|
||||
|
||||
|
@ -533,4 +533,42 @@ class ProjectNodeAccess(AbstractProjectTest):
|
||||
|
||||
db_user = users.find_one(self.other_user_id)
|
||||
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'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user