aboutsummaryrefslogtreecommitdiffstats
path: root/deluge/tests/test_authmanager.py
diff options
context:
space:
mode:
authorLibravatarDaniel Baumann <daniel@debian.org>2025-11-30 18:42:19 +0100
committerLibravatarDaniel Baumann <daniel@debian.org>2025-11-30 18:42:19 +0100
commit5d5f9bd85b94db8d64148435c30f7fb819bcd255 (patch)
treed406aeebcdc5d273c9e30eb08b59d9c498cd991a /deluge/tests/test_authmanager.py
parent3e1888c3d656906263b0cd08875885166efcfb63 (diff)
Merging upstream version 2.2.1~dev0+20250824.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'deluge/tests/test_authmanager.py')
-rw-r--r--deluge/tests/test_authmanager.py106
1 files changed, 102 insertions, 4 deletions
diff --git a/deluge/tests/test_authmanager.py b/deluge/tests/test_authmanager.py
index aa86fdb..7f087e2 100644
--- a/deluge/tests/test_authmanager.py
+++ b/deluge/tests/test_authmanager.py
@@ -4,20 +4,118 @@
# See LICENSE for more details.
#
+import os
+
+import pytest
+
import deluge.component as component
-from deluge.common import get_localhost_auth
+from deluge.common import (
+ AUTH_LEVEL_ADMIN,
+ AUTH_LEVEL_NORMAL,
+ get_localhost_auth,
+)
+from deluge.configmanager import get_config_dir
from deluge.conftest import BaseTestCase
-from deluge.core.authmanager import AUTH_LEVEL_ADMIN, AuthManager
+from deluge.core.authmanager import AuthManager
+from deluge.core.rpcserver import RPCServer
+from deluge.error import AuthenticationRequired, BadLoginError
+
+
+@pytest.fixture
+def add_user_to_authfile():
+ """Add user directly to the auth file."""
+
+ def _add_user(username, password, level):
+ auth_file = get_config_dir('auth')
+ with open(auth_file, 'a') as file:
+ file.write(f'{username}:{password}:{level}\n')
+
+ # Force mtime to workaround Windows not updating for check by __load_auth_file.
+ stat = os.stat(auth_file)
+ os.utime(auth_file, ns=(stat.st_atime_ns, stat.st_mtime_ns + 1000))
+
+ return _add_user
class TestAuthManager(BaseTestCase):
def set_up(self):
self.auth = AuthManager()
+ self.rpcserver = RPCServer(listen=False)
self.auth.start()
def tear_down(self):
# We must ensure that the components in component registry are removed
return component.shutdown()
- def test_authorize(self):
- assert self.auth.authorize(*get_localhost_auth()) == AUTH_LEVEL_ADMIN
+ def test_authorize_localhost(self):
+ username, password = get_localhost_auth()
+ assert username == 'localclient'
+ assert password
+ assert self.auth.authorize(username, password) == AUTH_LEVEL_ADMIN
+
+ @pytest.mark.parametrize('username', ['', None])
+ def test_authorize_no_username_raises(self, username):
+ with pytest.raises(AuthenticationRequired):
+ self.auth.authorize(username, 'password')
+
+ def test_authorize_no_password_raises(self):
+ with pytest.raises(AuthenticationRequired):
+ self.auth.authorize('localclient', '')
+
+ def test_authorize_incorrect_username_raises(self):
+ with pytest.raises(BadLoginError):
+ self.auth.authorize('notuser', 'password')
+
+ def test_authorize_wrong_password_raises(self):
+ username, password = get_localhost_auth()
+ assert username == 'localclient'
+ assert password
+ with pytest.raises(BadLoginError):
+ self.auth.authorize(username, password + 'x')
+
+ def test_create_account(self):
+ self.auth.create_account('test', 'testpass', 'ADMIN')
+ assert self.auth.has_account('test')
+ assert self.auth.authorize('test', 'testpass') == AUTH_LEVEL_ADMIN
+
+ def test_remove_account(self):
+ self.auth.create_account('test', 'testpass', 'ADMIN')
+ assert self.auth.has_account('test')
+
+ self.auth.remove_account('test')
+ assert not self.auth.has_account('test')
+
+ def test_update_account(self):
+ self.auth.create_account('test', 'testpass', 'ADMIN')
+ assert self.auth.has_account('test')
+
+ self.auth.update_account('test', 'testpass', 'NORMAL')
+ assert self.auth.authorize('test', 'testpass') == AUTH_LEVEL_NORMAL
+
+ self.auth.update_account('test', 'newpass', 'ADMIN')
+ assert self.auth.authorize('test', 'newpass') == AUTH_LEVEL_ADMIN
+
+ @pytest.mark.parametrize('password', ['testpass', '$testpa$$', 'test:pass'])
+ def test_password_hashed(self, password):
+ """Test account password is hashed with scrypt method."""
+ self.auth.create_account('test', password, 'ADMIN')
+
+ with open(get_config_dir('auth')) as file:
+ user, result_password, _ = file.readlines()[1].strip().split(':')
+
+ assert user == 'test'
+ assert result_password.startswith('$scrypt$')
+ assert password not in result_password
+
+ @pytest.mark.parametrize('password', ['testpass1', '$testpa$$'])
+ def test_password_plaintext(self, password, add_user_to_authfile):
+ """Test account plaintext password is still accepted."""
+ add_user_to_authfile('test', password, AUTH_LEVEL_ADMIN)
+
+ assert self.auth.authorize('test', password) == AUTH_LEVEL_ADMIN
+
+ def test_load_auth_level_str(self, add_user_to_authfile):
+ """Test load auth config with auth level as string."""
+ add_user_to_authfile('test', 'testpass', 'NORMAL')
+
+ assert self.auth.authorize('test', 'testpass') == AUTH_LEVEL_NORMAL