From 1fb2f5391467aab77918e302af20b2e8fda0705f Mon Sep 17 00:00:00 2001 From: rr- Date: Wed, 6 Apr 2016 17:12:40 +0200 Subject: [PATCH] server/users: make user names case insensitive --- server/szurubooru/api/user_api.py | 18 ++++++++---------- server/szurubooru/tests/api/test_user_api.py | 19 +++++++++++++++++++ server/szurubooru/util/users.py | 5 ++++- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/server/szurubooru/api/user_api.py b/server/szurubooru/api/user_api.py index df309031..b0971e33 100644 --- a/server/szurubooru/api/user_api.py +++ b/server/szurubooru/api/user_api.py @@ -48,12 +48,11 @@ class UserListApi(BaseApi): except KeyError as ex: raise errors.ValidationError('Field %r not found.' % ex.args[0]) - user = users.create_user(name, password, email) - try: - context.session.add(user) - context.session.commit() - except sqlalchemy.exc.IntegrityError: + if users.get_by_name(context.session, name): raise errors.IntegrityError('User %r already exists.' % name) + user = users.create_user(name, password, email) + context.session.add(user) + context.session.commit() return {'user': _serialize_user(context.user, user)} class UserDetailApi(BaseApi): @@ -80,6 +79,9 @@ class UserDetailApi(BaseApi): if 'name' in context.request: auth.verify_privilege(context.user, 'users:edit:%s:name' % infix) + other_user = users.get_by_name(context.session, context.request['name']) + if other_user and other_user.user_id != user.user_id: + raise errors.IntegrityError('User %r already exists.' % user.name) users.update_name(user, context.request['name']) if 'password' in context.request: @@ -96,9 +98,5 @@ class UserDetailApi(BaseApi): # TODO: avatar - try: - context.session.commit() - except sqlalchemy.exc.IntegrityError: - raise errors.IntegrityError('User %r already exists.' % user.name) - + context.session.commit() return {'user': _serialize_user(context.user, user)} diff --git a/server/szurubooru/tests/api/test_user_api.py b/server/szurubooru/tests/api/test_user_api.py index bfa59320..362a0ada 100644 --- a/server/szurubooru/tests/api/test_user_api.py +++ b/server/szurubooru/tests/api/test_user_api.py @@ -145,6 +145,16 @@ class TestCreatingUser(DatabaseTestCase): self.api.post(self.context) self.assertRaises(errors.IntegrityError, self.api.post, self.context) + def test_creating_user_that_already_exists_insensitive(self): + self.context.request = { + 'name': 'chewie', + 'email': 'asd@asd.asd', + 'password': 'oks', + } + self.api.post(self.context) + self.context.name = 'chewie' + self.assertRaises(errors.IntegrityError, self.api.post, self.context) + def test_missing_field(self): for key in ['name', 'email', 'password']: self.context.request = { @@ -272,6 +282,15 @@ class TestUpdatingUser(DatabaseTestCase): self.assertRaises( errors.IntegrityError, self.api.put, self.context, 'me') + def test_user_trying_to_become_someone_else_insensitive(self): + user1 = _create_user('me', 'regular_user') + user2 = _create_user('her', 'regular_user') + self.session.add_all([user1, user2]) + self.context.user = user1 + self.context.request = {'name': 'HER'} + self.assertRaises( + errors.IntegrityError, self.api.put, self.context, 'me') + def test_mods_trying_to_become_admin(self): user1 = _create_user('u1', 'mod') user2 = _create_user('u2', 'mod') diff --git a/server/szurubooru/util/users.py b/server/szurubooru/util/users.py index a51a374a..edaa3ce5 100644 --- a/server/szurubooru/util/users.py +++ b/server/szurubooru/util/users.py @@ -1,5 +1,6 @@ import re from datetime import datetime +from sqlalchemy import func from szurubooru import config, db, errors from szurubooru.util import auth, misc @@ -64,4 +65,6 @@ def reset_password(user): def get_by_name(session, name): ''' Retrieve an user by its name. ''' - return session.query(db.User).filter_by(name=name).first() + return session.query(db.User) \ + .filter(func.lower(db.User.name) == func.lower(name)) \ + .first()