diff --git a/api/auth/groupauth.py b/api/auth/groupauth.py index df66e8241a617372213cff4cb937955aeab31b61..5cea975ed1c640684bd9e26b8ce0b3ef6607fecc 100644 --- a/api/auth/groupauth.py +++ b/api/auth/groupauth.py @@ -11,8 +11,6 @@ def default(handler, group=None): pass elif handler.public_request: handler.abort(400, 'public request is not valid') - elif config.db.users.find_one({'_id': handler.uid}).get('root'): - pass elif method in ['DELETE', 'POST']: handler.abort(403, 'not allowed to perform operation') elif _get_access(handler.uid, group) >= INTEGER_ROLES['admin']: diff --git a/api/auth/userauth.py b/api/auth/userauth.py index 13cc7b3a838a802e2403ecb1786db7f10ef4e19e..c69870faa4df6f0d4fa6bfb20c83fd22a540bfcd 100644 --- a/api/auth/userauth.py +++ b/api/auth/userauth.py @@ -5,6 +5,8 @@ def default(handler, user=None): handler.abort(403, 'public request is not authorized') elif handler.superuser_request and not (method == 'DELETE' and _id == handler.uid): pass + elif handler.user_is_admin and (method == 'DELETE' and not _id == handler.uid): + pass elif method == 'PUT' and handler.uid == _id: if 'root' in payload and payload['root'] != user['root']: handler.abort(400, 'user cannot alter own superuser privilege') @@ -12,11 +14,13 @@ def default(handler, user=None): handler.abort(400, 'user cannot alter own disabled status') else: pass - elif method == 'POST' and not handler.superuser_request: + elif method == 'PUT' and handler.user_is_admin: + pass + elif method == 'POST' and not handler.superuser_request and not handler.user_is_admin: handler.abort(403, 'only superuser are allowed to create users') - elif method == 'POST' and handler.superuser_request: + elif method == 'POST' and (handler.superuser_request or handler.user_is_admin): pass - elif method == 'GET' and _id == handler.uid: + elif method == 'GET': pass else: handler.abort(403, 'not allowed to perform operation') diff --git a/api/jobs/handlers.py b/api/jobs/handlers.py index 2a9b50f3ba15749f309b15b8d3ac8437469a10d7..237b097f0074e732f40068fecea82c980979cce1 100644 --- a/api/jobs/handlers.py +++ b/api/jobs/handlers.py @@ -226,6 +226,12 @@ class RuleHandler(base.RequestHandler): class JobsHandler(base.RequestHandler): """Provide /jobs API routes.""" + def get(self): + """List all jobs.""" + user = config.db.users.find_one({'_id': self.uid}) + if not self.superuser_request and not user.get('root'): + self.abort(403, 'Request requires superuser') + return list(config.db.jobs.find()) def add(self): """Add a job to the queue.""" @@ -282,7 +288,8 @@ class JobsHandler(base.RequestHandler): return { '_id': result } def stats(self): - if not self.superuser_request: + user = config.db.users.find_one({'_id': self.uid}) + if not self.superuser_request and not user.get('root'): self.abort(403, 'Request requires superuser') return Queue.get_statistics() @@ -306,7 +313,8 @@ class JobsHandler(base.RequestHandler): return job def reap_stale(self): - if not self.superuser_request: + user = config.db.users.find_one({'_id': self.uid}) + if not self.superuser_request and not user.get('root'): self.abort(403, 'Request requires superuser') count = Queue.scan_for_orphans() @@ -352,7 +360,7 @@ class JobHandler(base.RequestHandler): mutation = self.request.json # If user is not superuser, can only cancel jobs they spawned - if not self.superuser_request: + if not self.superuser_request and not self.user_is_admin: if j.origin.get('id') != self.uid: raise APIPermissionException('User does not have permission to access job {}'.format(_id)) if mutation != {'state': 'cancelled'}: diff --git a/test/integration_tests/python/test_jobs.py b/test/integration_tests/python/test_jobs.py index b1bee5baa26339b8ab4d52217c146ca87464d5bf..eeb64e44774363bed5908016274a1e1458991969 100644 --- a/test/integration_tests/python/test_jobs.py +++ b/test/integration_tests/python/test_jobs.py @@ -126,8 +126,8 @@ def test_jobs(data_builder, as_user, as_admin, as_root): r = as_root.post('/jobs/' + next_job_id + '/retry') assert r.ok - # get next job - r = as_root.get('/jobs/next', params={'tags': 'test-tag'}) + # get next job as admin + r = as_admin.get('/jobs/next', params={'tags': 'test-tag'}) assert r.ok next_job_id = r.json()['id'] diff --git a/test/integration_tests/python/test_users.py b/test/integration_tests/python/test_users.py index 6137439c0b85dbbb559fc18ab6159016c5d0abd5..18bf61fcfcb803682fa57b044d9671dacb078116 100644 --- a/test/integration_tests/python/test_users.py +++ b/test/integration_tests/python/test_users.py @@ -1,4 +1,4 @@ -def test_users(as_root, as_user, as_public): +def test_users(as_root, as_admin, as_user, as_public): # List users r = as_user.get('/users') assert r.ok @@ -50,6 +50,21 @@ def test_users(as_root, as_user, as_public): r = as_root.get('/users/' + new_user_id) assert r.ok + # Add new user as admin + new_user_id_admin = 'new2@user.com' + r = as_admin.post('/users', json={ + '_id': new_user_id_admin, + 'firstname': 'New2', + 'lastname': 'User2', + }) + assert r.ok + r = as_root.get('/users/' + new_user_id) + assert r.ok + + #Get another user as user + r = as_user.get('/users/' + new_user_id) + assert r.ok + # Try to update non-existent user r = as_root.put('/users/nonexistent@user.com', json={'firstname': 'Realname'}) assert r.status_code == 404 @@ -59,6 +74,11 @@ def test_users(as_root, as_user, as_public): assert r.ok assert r.json()['modified'] == 1 + # Update existing user as admin + r = as_admin.put('/users/' + new_user_id_admin, json={'firstname': 'Realname2'}) + assert r.ok + assert r.json()['modified'] == 1 + # Try to delete non-existent user r = as_root.delete('/users/nonexistent@user.com') assert r.status_code == 404 @@ -67,6 +87,10 @@ def test_users(as_root, as_user, as_public): r = as_root.delete('/users/' + new_user_id) assert r.ok + # Delete user + r = as_admin.delete('/users/' + new_user_id_admin) + assert r.ok + # Test HTTPS enforcement on avatar urls new_user_id = 'new@user.com' r = as_root.post('/users', json={