From 450a61c1e1bffecefdbc62328d3ea1d1adc78e0f Mon Sep 17 00:00:00 2001 From: rr- Date: Sat, 9 Apr 2016 09:21:56 +0200 Subject: [PATCH] server/users: add user removal --- API.md | 19 +++++- server/szurubooru/api/user_api.py | 16 +++++ server/szurubooru/tests/api/test_user_api.py | 68 +++++++++++++++++++- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/API.md b/API.md index 74de9cc..31e0b49 100644 --- a/API.md +++ b/API.md @@ -17,6 +17,7 @@ - [Creating user](#creating-user) - [Updating user](#updating-user) - [Getting user](#getting-user) + - [Removing user](#removing-user) - [Password reset - step 1: mail request](#password-reset---step-2-confirmation) - [Password reset - step 2: confirmation](#password-reset---step-2-confirmation) @@ -95,6 +96,7 @@ Output: ``` ...where `` is an [user resource](#user) and `query` contains standard [search query](#search). +Errors: if privileges are too low. Searches for users. @@ -143,7 +145,7 @@ Output: ``` ...where `` is an [user resource](#user). Errors: if such user already exists (names are case insensitive), or either of -user name, password and email are invalid. +user name, password and email are invalid, or privileges are too low. Creates a new user using specified parameters. Names and passwords must match `user_name_regex` and `password_regex` from server's configuration, @@ -174,7 +176,7 @@ Output: Errors: if the user does not exist, or the user with new name already exists (names are case insensitive), or either of user name, password, email or rank are invalid, or the user is trying to update their or someone else's rank to -higher than their own. +higher than their own, or privileges are too low. Updates an existing user using specified parameters. Names and passwords must match `user_name_regex` and `password_regex` from server's configuration, @@ -191,11 +193,22 @@ Output: } ``` ...where `` is an [user resource](#user). -Errors: if the user does not exist. +Errors: if the user does not exist or privileges are too low. Retrieves information about an existing user. +### Removing user +Request: `DELETE /user/` +Output: +```json5 +{} +``` +Errors: if the user does not exist or privileges are too low. + +Deletes existing user. + + ### Password reset - step 1: mail request Request: `GET /password-reset/` Output: diff --git a/server/szurubooru/api/user_api.py b/server/szurubooru/api/user_api.py index a634d97..bae3cb6 100644 --- a/server/szurubooru/api/user_api.py +++ b/server/szurubooru/api/user_api.py @@ -111,3 +111,19 @@ class UserDetailApi(BaseApi): context.session.commit() return {'user': _serialize_user(context.user, user)} + + def delete(self, context, user_name): + ''' Delete an existing user. ''' + user = users.get_by_name(context.session, user_name) + if not user: + raise errors.NotFoundError('User %r not found.' % user_name) + + if context.user.user_id == user.user_id: + infix = 'self' + else: + infix = 'any' + + auth.verify_privilege(context.user, 'users:delete:%s' % infix) + context.session.delete(user) + context.session.commit() + return {} diff --git a/server/szurubooru/tests/api/test_user_api.py b/server/szurubooru/tests/api/test_user_api.py index bd69df1..5a5dab8 100644 --- a/server/szurubooru/tests/api/test_user_api.py +++ b/server/szurubooru/tests/api/test_user_api.py @@ -10,8 +10,6 @@ class TestRetrievingUsers(DatabaseTestCase): util.mock_config({ 'privileges': { 'users:list': 'regular_user', - 'users:view': 'regular_user', - 'users:create': 'regular_user', }, 'avatar_thumbnail_size': 200, 'ranks': ['anonymous', 'regular_user', 'mod', 'admin'], @@ -39,6 +37,30 @@ class TestRetrievingUsers(DatabaseTestCase): api_ = api.UserListApi() self.assertRaises(errors.AuthError, api_.get, self.context) + def test_retrieving_non_existing(self): + self.context.user.rank = 'regular_user' + util.mock_params(self.context, {'query': 'asd', 'page': 1}) + api_ = api.UserListApi() + result = api_.get(self.context) + self.assertEqual(result['query'], 'asd') + self.assertEqual(result['page'], 1) + self.assertEqual(result['pageSize'], 100) + self.assertEqual(result['total'], 0) + self.assertEqual([u['name'] for u in result['users']], []) + +class TestRetrievingUser(DatabaseTestCase): + def setUp(self): + super().setUp() + util.mock_config({ + 'privileges': { + 'users:view': 'regular_user', + }, + 'avatar_thumbnail_size': 200, + 'ranks': ['anonymous', 'regular_user', 'mod', 'admin'], + 'rank_names': {}, + }) + util.mock_context(self) + def test_retrieving_single(self): user = util.mock_user('u1', 'regular_user') self.session.add(user) @@ -65,6 +87,48 @@ class TestRetrievingUsers(DatabaseTestCase): api_ = api.UserDetailApi() self.assertRaises(errors.AuthError, api_.get, self.context, '-') +class TestDeletingUser(DatabaseTestCase): + def setUp(self): + super().setUp() + util.mock_config({ + 'privileges': { + 'users:delete:self': 'regular_user', + 'users:delete:any': 'mod', + }, + 'ranks': ['anonymous', 'regular_user', 'mod', 'admin'], + 'rank_names': {}, + }) + util.mock_context(self) + + def test_removing_oneself(self): + user1 = util.mock_user('u1', 'regular_user') + user2 = util.mock_user('u2', 'regular_user') + self.session.add_all([user1, user2]) + self.session.commit() + self.context.user.user_id = user1.user_id + self.context.user.rank = 'regular_user' + api_ = api.UserDetailApi() + self.assertRaises(errors.AuthError, api_.delete, self.context, 'u2') + api_.delete(self.context, 'u1') + self.assertEqual(self.session.query(db.User).filter_by(name='u1').all(), []) + + def test_removing_someone_else(self): + user1 = util.mock_user('u1', 'regular_user') + user2 = util.mock_user('u2', 'regular_user') + self.session.add_all([user1, user2]) + self.session.commit() + self.context.user.rank = 'mod' + api_ = api.UserDetailApi() + api_.delete(self.context, 'u1') + api_.delete(self.context, 'u2') + self.assertEqual(self.session.query(db.User).filter_by(name='u1').all(), []) + self.assertEqual(self.session.query(db.User).filter_by(name='u2').all(), []) + + def test_removing_non_existing(self): + self.context.user.rank = 'regular_user' + api_ = api.UserDetailApi() + self.assertRaises(errors.NotFoundError, api_.delete, self.context, 'bad') + class TestCreatingUser(DatabaseTestCase): def setUp(self): super().setUp()