aboutsummaryrefslogtreecommitdiff
path: root/server/szurubooru/tests
diff options
context:
space:
mode:
Diffstat (limited to 'server/szurubooru/tests')
-rw-r--r--server/szurubooru/tests/api/test_user_token_creating.py29
-rw-r--r--server/szurubooru/tests/api/test_user_token_deleting.py30
-rw-r--r--server/szurubooru/tests/api/test_user_token_retrieving.py31
-rw-r--r--server/szurubooru/tests/api/test_user_token_updating.py42
-rw-r--r--server/szurubooru/tests/conftest.py25
-rw-r--r--server/szurubooru/tests/func/test_auth.py24
-rw-r--r--server/szurubooru/tests/func/test_user_tokens.py155
-rw-r--r--server/szurubooru/tests/middleware/__init__.py0
-rw-r--r--server/szurubooru/tests/middleware/test_authenticator.py93
-rw-r--r--server/szurubooru/tests/model/test_user_token.py14
10 files changed, 440 insertions, 3 deletions
diff --git a/server/szurubooru/tests/api/test_user_token_creating.py b/server/szurubooru/tests/api/test_user_token_creating.py
new file mode 100644
index 0000000..f550f63
--- /dev/null
+++ b/server/szurubooru/tests/api/test_user_token_creating.py
@@ -0,0 +1,29 @@
+from unittest.mock import patch
+import pytest
+from szurubooru import api
+from szurubooru.func import user_tokens, users
+
+
+@pytest.fixture(autouse=True)
+def inject_config(config_injector):
+ config_injector({'privileges': {'user_tokens:create:self': 'regular'}})
+
+
+def test_creating_user_token(
+ user_token_factory, context_factory, fake_datetime):
+ user_token = user_token_factory()
+ with patch('szurubooru.func.user_tokens.create_user_token'), \
+ patch('szurubooru.func.user_tokens.serialize_user_token'), \
+ patch('szurubooru.func.users.get_user_by_name'), \
+ fake_datetime('1969-02-12'):
+ users.get_user_by_name.return_value = user_token.user
+ user_tokens.serialize_user_token.return_value = 'serialized user token'
+ user_tokens.create_user_token.return_value = user_token
+ result = api.user_token_api.create_user_token(
+ context_factory(user=user_token.user),
+ {
+ 'user_name': user_token.user.name
+ })
+ assert result == 'serialized user token'
+ user_tokens.create_user_token.assert_called_once_with(
+ user_token.user, True)
diff --git a/server/szurubooru/tests/api/test_user_token_deleting.py b/server/szurubooru/tests/api/test_user_token_deleting.py
new file mode 100644
index 0000000..8534152
--- /dev/null
+++ b/server/szurubooru/tests/api/test_user_token_deleting.py
@@ -0,0 +1,30 @@
+from unittest.mock import patch
+import pytest
+from szurubooru import api, db
+from szurubooru.func import user_tokens, users
+
+
+@pytest.fixture(autouse=True)
+def inject_config(config_injector):
+ config_injector({'privileges': {'user_tokens:delete:self': 'regular'}})
+
+
+def test_deleting_user_token(
+ user_token_factory, context_factory, fake_datetime):
+ user_token = user_token_factory()
+ db.session.add(user_token)
+ db.session.commit()
+ with patch('szurubooru.func.user_tokens.get_by_user_and_token'), \
+ patch('szurubooru.func.users.get_user_by_name'), \
+ fake_datetime('1969-02-12'):
+ users.get_user_by_name.return_value = user_token.user
+ user_tokens.get_by_user_and_token.return_value = user_token
+ result = api.user_token_api.delete_user_token(
+ context_factory(user=user_token.user),
+ {
+ 'user_name': user_token.user.name,
+ 'user_token': user_token.token
+ })
+ assert result == {}
+ user_tokens.get_by_user_and_token.assert_called_once_with(
+ user_token.user, user_token.token)
diff --git a/server/szurubooru/tests/api/test_user_token_retrieving.py b/server/szurubooru/tests/api/test_user_token_retrieving.py
new file mode 100644
index 0000000..01b2534
--- /dev/null
+++ b/server/szurubooru/tests/api/test_user_token_retrieving.py
@@ -0,0 +1,31 @@
+from unittest.mock import patch
+import pytest
+from szurubooru import api
+from szurubooru.func import user_tokens, users
+
+
+@pytest.fixture(autouse=True)
+def inject_config(config_injector):
+ config_injector({'privileges': {'user_tokens:list:self': 'regular'}})
+
+
+def test_retrieving_user_tokens(
+ user_token_factory, context_factory, fake_datetime):
+ user_token1 = user_token_factory()
+ user_token2 = user_token_factory(user=user_token1.user)
+ user_token3 = user_token_factory(user=user_token1.user)
+ with patch('szurubooru.func.user_tokens.get_user_tokens'), \
+ patch('szurubooru.func.user_tokens.serialize_user_token'), \
+ patch('szurubooru.func.users.get_user_by_name'), \
+ fake_datetime('1969-02-12'):
+ users.get_user_by_name.return_value = user_token1.user
+ user_tokens.serialize_user_token.return_value = 'serialized user token'
+ user_tokens.get_user_tokens.return_value = [user_token1, user_token2,
+ user_token3]
+ result = api.user_token_api.get_user_tokens(
+ context_factory(user=user_token1.user),
+ {
+ 'user_name': user_token1.user.name
+ })
+ assert result == {'results': ['serialized user token'] * 3}
+ user_tokens.get_user_tokens.assert_called_once_with(user_token1.user)
diff --git a/server/szurubooru/tests/api/test_user_token_updating.py b/server/szurubooru/tests/api/test_user_token_updating.py
new file mode 100644
index 0000000..bf725a3
--- /dev/null
+++ b/server/szurubooru/tests/api/test_user_token_updating.py
@@ -0,0 +1,42 @@
+from unittest.mock import patch
+import pytest
+from szurubooru import api, db
+from szurubooru.func import user_tokens, users
+
+
+@pytest.fixture(autouse=True)
+def inject_config(config_injector):
+ config_injector({'privileges': {'user_tokens:edit:self': 'regular'}})
+
+
+def test_edit_user_token(user_token_factory, context_factory, fake_datetime):
+ user_token = user_token_factory()
+ db.session.add(user_token)
+ db.session.commit()
+ with patch('szurubooru.func.user_tokens.get_by_user_and_token'), \
+ patch('szurubooru.func.user_tokens.update_user_token_enabled'), \
+ patch('szurubooru.func.user_tokens.update_user_token_edit_time'), \
+ patch('szurubooru.func.user_tokens.serialize_user_token'), \
+ patch('szurubooru.func.users.get_user_by_name'), \
+ fake_datetime('1969-02-12'):
+ users.get_user_by_name.return_value = user_token.user
+ user_tokens.serialize_user_token.return_value = 'serialized user token'
+ user_tokens.get_by_user_and_token.return_value = user_token
+ result = api.user_token_api.update_user_token(
+ context_factory(
+ params={
+ 'version': user_token.version,
+ 'enabled': False,
+ },
+ user=user_token.user),
+ {
+ 'user_name': user_token.user.name,
+ 'user_token': user_token.token
+ })
+ assert result == 'serialized user token'
+ user_tokens.get_by_user_and_token.assert_called_once_with(
+ user_token.user, user_token.token)
+ user_tokens.update_user_token_enabled.assert_called_once_with(
+ user_token, False)
+ user_tokens.update_user_token_edit_time.assert_called_once_with(
+ user_token)
diff --git a/server/szurubooru/tests/conftest.py b/server/szurubooru/tests/conftest.py
index db7806e..f6eeee1 100644
--- a/server/szurubooru/tests/conftest.py
+++ b/server/szurubooru/tests/conftest.py
@@ -93,11 +93,11 @@ def session(query_logger): # pylint: disable=unused-argument
@pytest.fixture
def context_factory(session):
- def factory(params=None, files=None, user=None):
+ def factory(params=None, files=None, user=None, headers=None):
ctx = rest.Context(
method=None,
url=None,
- headers={},
+ headers=headers or {},
params=params or {},
files=files or {})
ctx.session = session
@@ -134,6 +134,27 @@ def user_factory():
@pytest.fixture
+def user_token_factory(user_factory):
+ def factory(
+ user=None,
+ token=None,
+ expiration_time=None,
+ enabled=None,
+ creation_time=None):
+ if user is None:
+ user = user_factory()
+ db.session.add(user)
+ user_token = model.UserToken()
+ user_token.user = user
+ user_token.token = token or 'dummy'
+ user_token.expiration_time = expiration_time
+ user_token.enabled = enabled if enabled is not None else True
+ user_token.creation_time = creation_time or datetime(1997, 1, 1)
+ return user_token
+ return factory
+
+
+@pytest.fixture
def tag_category_factory():
def factory(name=None, color='dummy', default=False):
category = model.TagCategory()
diff --git a/server/szurubooru/tests/func/test_auth.py b/server/szurubooru/tests/func/test_auth.py
index 5d0955a..6dc79bb 100644
--- a/server/szurubooru/tests/func/test_auth.py
+++ b/server/szurubooru/tests/func/test_auth.py
@@ -1,5 +1,6 @@
-from szurubooru.func import auth
+from datetime import datetime, timedelta
import pytest
+from szurubooru.func import auth
@pytest.fixture(autouse=True)
@@ -41,3 +42,24 @@ def test_is_valid_password_auto_upgrades_user_password_hash(user_factory):
assert result is True
assert user.password_hash != hash
assert user.password_revision > revision
+
+
+def test_is_valid_token(user_token_factory):
+ user_token = user_token_factory()
+ assert auth.is_valid_token(user_token)
+
+
+def test_expired_token_is_invalid(user_token_factory):
+ past_expiration = (datetime.utcnow() - timedelta(minutes=30))
+ user_token = user_token_factory(expiration_time=past_expiration)
+ assert not auth.is_valid_token(user_token)
+
+
+def test_disabled_token_is_invalid(user_token_factory):
+ user_token = user_token_factory(enabled=False)
+ assert not auth.is_valid_token(user_token)
+
+
+def test_generate_authorization_token():
+ result = auth.generate_authorization_token()
+ assert result != auth.generate_authorization_token()
diff --git a/server/szurubooru/tests/func/test_user_tokens.py b/server/szurubooru/tests/func/test_user_tokens.py
new file mode 100644
index 0000000..8c3577c
--- /dev/null
+++ b/server/szurubooru/tests/func/test_user_tokens.py
@@ -0,0 +1,155 @@
+from datetime import datetime, timedelta
+from unittest.mock import patch
+import pytest
+import pytz
+import random
+import string
+from szurubooru import db, model
+from szurubooru.func import user_tokens, users, auth, util
+
+
+def test_serialize_user_token(user_token_factory):
+ user_token = user_token_factory()
+ db.session.add(user_token)
+ db.session.flush()
+ with patch('szurubooru.func.users.get_avatar_url'):
+ users.get_avatar_url.return_value = 'https://example.com/avatar.png'
+ result = user_tokens.serialize_user_token(user_token, user_token.user)
+ assert result == {
+ 'creationTime': datetime(1997, 1, 1, 0, 0),
+ 'enabled': True,
+ 'expirationTime': None,
+ 'lastEditTime': None,
+ 'lastUsageTime': None,
+ 'note': None,
+ 'token': 'dummy',
+ 'user': {
+ 'avatarUrl': 'https://example.com/avatar.png',
+ 'name': user_token.user.name},
+ 'version': 1
+ }
+
+
+def test_serialize_user_token_none():
+ result = user_tokens.serialize_user_token(None, None)
+ assert result is None
+
+
+def test_get_by_user_and_token(user_token_factory):
+ user_token = user_token_factory()
+ db.session.add(user_token)
+ db.session.flush()
+ db.session.commit()
+ result = user_tokens.get_by_user_and_token(
+ user_token.user, user_token.token)
+ assert result == user_token
+
+
+def test_get_user_tokens(user_token_factory):
+ user_token1 = user_token_factory()
+ user_token2 = user_token_factory(user=user_token1.user)
+ db.session.add(user_token1)
+ db.session.add(user_token2)
+ db.session.flush()
+ db.session.commit()
+ result = user_tokens.get_user_tokens(user_token1.user)
+ assert result == [user_token1, user_token2]
+
+
+def test_create_user_token(user_factory):
+ user = user_factory()
+ db.session.add(user)
+ db.session.flush()
+ db.session.commit()
+ with patch('szurubooru.func.auth.generate_authorization_token'):
+ auth.generate_authorization_token.return_value = 'test'
+ result = user_tokens.create_user_token(user, True)
+ assert result.token == 'test'
+ assert result.user == user
+
+
+def test_update_user_token_enabled(user_token_factory):
+ user_token = user_token_factory()
+ user_tokens.update_user_token_enabled(user_token, False)
+ assert user_token.enabled is False
+ assert user_token.last_edit_time is not None
+
+
+def test_update_user_token_edit_time(user_token_factory):
+ user_token = user_token_factory()
+ assert user_token.last_edit_time is None
+ user_tokens.update_user_token_edit_time(user_token)
+ assert user_token.last_edit_time is not None
+
+
+def test_update_user_token_note(user_token_factory):
+ user_token = user_token_factory()
+ assert user_token.note is None
+ user_tokens.update_user_token_note(user_token, ' Test Note ')
+ assert user_token.note == 'Test Note'
+ assert user_token.last_edit_time is not None
+
+
+def test_update_user_token_note_input_too_long(user_token_factory):
+ user_token = user_token_factory()
+ assert user_token.note is None
+ note_max_length = util.get_column_size(model.UserToken.note) + 1
+ note = ''.join(
+ random.choice(string.ascii_letters) for _ in range(note_max_length))
+ with pytest.raises(user_tokens.InvalidNoteError):
+ user_tokens.update_user_token_note(user_token, note)
+
+
+def test_update_user_token_expiration_time(user_token_factory):
+ user_token = user_token_factory()
+ assert user_token.expiration_time is None
+ expiration_time_str = (
+ (datetime.utcnow() + timedelta(days=1))
+ .replace(tzinfo=pytz.utc)
+ ).isoformat()
+ user_tokens.update_user_token_expiration_time(
+ user_token, expiration_time_str)
+ assert user_token.expiration_time.isoformat() == expiration_time_str
+ assert user_token.last_edit_time is not None
+
+
+def test_update_user_token_expiration_time_in_past(user_token_factory):
+ user_token = user_token_factory()
+ assert user_token.expiration_time is None
+ expiration_time_str = (
+ (datetime.utcnow() - timedelta(days=1))
+ .replace(tzinfo=pytz.utc)
+ ).isoformat()
+ with pytest.raises(
+ user_tokens.InvalidExpirationError,
+ match='Expiration cannot happen in the past'):
+ user_tokens.update_user_token_expiration_time(
+ user_token, expiration_time_str)
+
+
+@pytest.mark.parametrize('expiration_time_str', [
+ datetime.utcnow().isoformat(),
+ (datetime.utcnow() - timedelta(days=1)).ctime(),
+ '1970/01/01 00:00:01.0000Z',
+ '70/01/01 00:00:01.0000Z',
+ ''.join(random.choice(string.ascii_letters) for _ in range(15)),
+ ''.join(random.choice(string.digits) for _ in range(8))
+])
+def test_update_user_token_expiration_time_invalid_format(
+ expiration_time_str, user_token_factory):
+ user_token = user_token_factory()
+ assert user_token.expiration_time is None
+
+ with pytest.raises(
+ user_tokens.InvalidExpirationError,
+ match='Expiration is in an invalid format %s'
+ % expiration_time_str):
+ user_tokens.update_user_token_expiration_time(
+ user_token, expiration_time_str)
+
+
+def test_bump_usage_time(user_token_factory, fake_datetime):
+ user_token = user_token_factory()
+ with fake_datetime('1997-01-01'):
+ user_tokens.bump_usage_time(user_token)
+ assert user_token.last_usage_time == datetime(1997, 1, 1)
diff --git a/server/szurubooru/tests/middleware/__init__.py b/server/szurubooru/tests/middleware/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/server/szurubooru/tests/middleware/__init__.py
diff --git a/server/szurubooru/tests/middleware/test_authenticator.py b/server/szurubooru/tests/middleware/test_authenticator.py
new file mode 100644
index 0000000..be21a93
--- /dev/null
+++ b/server/szurubooru/tests/middleware/test_authenticator.py
@@ -0,0 +1,93 @@
+from unittest.mock import patch
+import pytest
+from szurubooru import db
+from szurubooru.func import auth, users, user_tokens
+from szurubooru.middleware import authenticator
+from szurubooru.rest import errors
+
+
+def test_process_request_no_header(context_factory):
+ ctx = context_factory()
+ authenticator.process_request(ctx)
+ assert ctx.user.name is None
+
+
+def test_process_request_bump_login(context_factory, user_factory):
+ user = user_factory()
+ db.session.add(user)
+ db.session.flush()
+ ctx = context_factory(
+ headers={
+ 'Authorization': 'Basic dGVzdFVzZXI6dGVzdFRva2Vu'
+ },
+ params={
+ 'bump-login': 'true'
+ })
+ with patch('szurubooru.func.auth.is_valid_password'), \
+ patch('szurubooru.func.users.get_user_by_name'):
+ users.get_user_by_name.return_value = user
+ auth.is_valid_password.return_value = True
+ authenticator.process_request(ctx)
+ assert user.last_login_time is not None
+
+
+def test_process_request_bump_login_with_token(
+ context_factory, user_token_factory):
+ user_token = user_token_factory()
+ db.session.add(user_token)
+ db.session.flush()
+ ctx = context_factory(
+ headers={
+ 'Authorization': 'Token dGVzdFVzZXI6dGVzdFRva2Vu'
+ },
+ params={
+ 'bump-login': 'true'
+ })
+ with patch('szurubooru.func.auth.is_valid_token'), \
+ patch('szurubooru.func.users.get_user_by_name'), \
+ patch('szurubooru.func.user_tokens.get_by_user_and_token'):
+ users.get_user_by_name.return_value = user_token.user
+ user_tokens.get_by_user_and_token.return_value = user_token
+ auth.is_valid_token.return_value = True
+ authenticator.process_request(ctx)
+ assert user_token.user.last_login_time is not None
+ assert user_token.last_usage_time is not None
+
+
+def test_process_request_basic_auth_valid(context_factory, user_factory):
+ user = user_factory()
+ ctx = context_factory(
+ headers={
+ 'Authorization': 'Basic dGVzdFVzZXI6dGVzdFBhc3N3b3Jk'
+ })
+ with patch('szurubooru.func.auth.is_valid_password'), \
+ patch('szurubooru.func.users.get_user_by_name'):
+ users.get_user_by_name.return_value = user
+ auth.is_valid_password.return_value = True
+ authenticator.process_request(ctx)
+ assert ctx.user == user
+
+
+def test_process_request_token_auth_valid(context_factory, user_token_factory):
+ user_token = user_token_factory()
+ ctx = context_factory(
+ headers={
+ 'Authorization': 'Token dGVzdFVzZXI6dGVzdFRva2Vu'
+ })
+ with patch('szurubooru.func.auth.is_valid_token'), \
+ patch('szurubooru.func.users.get_user_by_name'), \
+ patch('szurubooru.func.user_tokens.get_by_user_and_token'):
+ users.get_user_by_name.return_value = user_token.user
+ user_tokens.get_by_user_and_token.return_value = user_token
+ auth.is_valid_token.return_value = True
+ authenticator.process_request(ctx)
+ assert ctx.user == user_token.user
+
+
+def test_process_request_bad_header(context_factory):
+ ctx = context_factory(
+ headers={
+ 'Authorization': 'Secret SuperSecretValue'
+ })
+ with pytest.raises(errors.HttpBadRequest):
+ authenticator.process_request(ctx)
diff --git a/server/szurubooru/tests/model/test_user_token.py b/server/szurubooru/tests/model/test_user_token.py
new file mode 100644
index 0000000..0280082
--- /dev/null
+++ b/server/szurubooru/tests/model/test_user_token.py
@@ -0,0 +1,14 @@
+from datetime import datetime
+from szurubooru import db
+
+
+def test_saving_user_token(user_token_factory):
+ user_token = user_token_factory()
+ db.session.add(user_token)
+ db.session.flush()
+ db.session.refresh(user_token)
+ assert not db.session.dirty
+ assert user_token.user is not None
+ assert user_token.token == 'dummy'
+ assert user_token.enabled is True
+ assert user_token.creation_time == datetime(1997, 1, 1)

© 2015 - 2026 Jakob L. Kreuze