mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 06:41:43 +00:00
add ability to remove an user
also replace old user by new one before creation
This commit is contained in:
@ -1,164 +0,0 @@
|
||||
import argparse
|
||||
import pytest
|
||||
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest import mock
|
||||
|
||||
from ahriman.application.handlers import CreateUser
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.user import User
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||
"""
|
||||
default arguments for these test cases
|
||||
:param args: command line arguments fixture
|
||||
:return: generated arguments for these test cases
|
||||
"""
|
||||
args.username = "user"
|
||||
args.password = "pa55w0rd"
|
||||
args.role = UserAccess.Read
|
||||
args.as_service = False
|
||||
return args
|
||||
|
||||
|
||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must run command
|
||||
"""
|
||||
args = _default_args(args)
|
||||
get_auth_configuration_mock = mocker.patch("ahriman.application.handlers.CreateUser.get_auth_configuration")
|
||||
create_configuration_mock = mocker.patch("ahriman.application.handlers.CreateUser.create_configuration")
|
||||
create_user = mocker.patch("ahriman.application.handlers.CreateUser.create_user")
|
||||
get_salt_mock = mocker.patch("ahriman.application.handlers.CreateUser.get_salt")
|
||||
|
||||
CreateUser.run(args, "x86_64", configuration, True)
|
||||
get_auth_configuration_mock.assert_called_once()
|
||||
create_configuration_mock.assert_called_once()
|
||||
create_user.assert_called_once()
|
||||
get_salt_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_create_configuration(configuration: Configuration, user: User, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly create configuration file
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
mocker.patch("pathlib.Path.open")
|
||||
set_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
|
||||
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
|
||||
|
||||
CreateUser.create_configuration(configuration, user, "salt", False)
|
||||
write_mock.assert_called_once()
|
||||
set_mock.assert_has_calls([
|
||||
mock.call("auth", "salt", pytest.helpers.anyvar(str)),
|
||||
mock.call(section, user.username, pytest.helpers.anyvar(str))
|
||||
])
|
||||
|
||||
|
||||
def test_create_configuration_not_loaded(configuration: Configuration, user: User, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must do nothing in case if configuration is not loaded
|
||||
"""
|
||||
configuration.path = None
|
||||
mocker.patch("pathlib.Path.open")
|
||||
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
|
||||
|
||||
CreateUser.create_configuration(configuration, user, "salt", False)
|
||||
write_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_create_configuration_user_exists(configuration: Configuration, user: User, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly update configuration file if user already exists
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
configuration.set_option(section, user.username, "")
|
||||
mocker.patch("pathlib.Path.open")
|
||||
mocker.patch("ahriman.core.configuration.Configuration.write")
|
||||
|
||||
CreateUser.create_configuration(configuration, user, "salt", False)
|
||||
generated = User.from_option(user.username, configuration.get(section, user.username))
|
||||
assert generated.check_credentials(user.password, configuration.get("auth", "salt"))
|
||||
|
||||
|
||||
def test_create_configuration_with_plain_password(
|
||||
configuration: Configuration,
|
||||
user: User,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set plain text password and user for the service
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
mocker.patch("pathlib.Path.open")
|
||||
mocker.patch("ahriman.core.configuration.Configuration.write")
|
||||
|
||||
CreateUser.create_configuration(configuration, user, "salt", True)
|
||||
|
||||
generated = User.from_option(user.username, configuration.get(section, user.username))
|
||||
service = User.from_option(configuration.get("web", "username"), configuration.get("web", "password"))
|
||||
assert generated.username == service.username
|
||||
assert generated.check_credentials(service.password, configuration.get("auth", "salt"))
|
||||
|
||||
|
||||
def test_create_user(args: argparse.Namespace, user: User) -> None:
|
||||
"""
|
||||
must create user
|
||||
"""
|
||||
args = _default_args(args)
|
||||
generated = CreateUser.create_user(args)
|
||||
assert generated.username == user.username
|
||||
assert generated.access == user.access
|
||||
|
||||
|
||||
def test_create_user_getpass(args: argparse.Namespace, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create user and get password from command line
|
||||
"""
|
||||
args = _default_args(args)
|
||||
args.password = None
|
||||
|
||||
getpass_mock = mocker.patch("getpass.getpass", return_value="password")
|
||||
generated = CreateUser.create_user(args)
|
||||
|
||||
getpass_mock.assert_called_once()
|
||||
assert generated.password == "password"
|
||||
|
||||
|
||||
def test_get_salt_read(configuration: Configuration) -> None:
|
||||
"""
|
||||
must read salt from configuration
|
||||
"""
|
||||
assert CreateUser.get_salt(configuration) == "salt"
|
||||
|
||||
|
||||
def test_get_salt_generate(configuration: Configuration) -> None:
|
||||
"""
|
||||
must generate salt if it does not exist
|
||||
"""
|
||||
configuration.remove_option("auth", "salt")
|
||||
|
||||
salt = CreateUser.get_salt(configuration, 16)
|
||||
assert salt
|
||||
assert len(salt) == 16
|
||||
|
||||
|
||||
def test_get_auth_configuration() -> None:
|
||||
"""
|
||||
must load empty configuration
|
||||
"""
|
||||
assert CreateUser.get_auth_configuration(Path("path"))
|
||||
|
||||
|
||||
def test_get_auth_configuration_exists(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must load configuration from filesystem
|
||||
"""
|
||||
mocker.patch("pathlib.Path.open")
|
||||
mocker.patch("pathlib.Path.is_file", return_value=True)
|
||||
read_mock = mocker.patch("ahriman.core.configuration.Configuration.read")
|
||||
|
||||
CreateUser.get_auth_configuration(Path("path"))
|
||||
read_mock.assert_called_once()
|
224
tests/ahriman/application/handlers/test_handler_user.py
Normal file
224
tests/ahriman/application/handlers/test_handler_user.py
Normal file
@ -0,0 +1,224 @@
|
||||
import argparse
|
||||
import pytest
|
||||
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest import mock
|
||||
|
||||
from ahriman.application.handlers import User
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.user import User as MUser
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||
"""
|
||||
default arguments for these test cases
|
||||
:param args: command line arguments fixture
|
||||
:return: generated arguments for these test cases
|
||||
"""
|
||||
args.username = "user"
|
||||
args.password = "pa55w0rd"
|
||||
args.access = UserAccess.Read
|
||||
args.as_service = False
|
||||
args.remove = False
|
||||
return args
|
||||
|
||||
|
||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must run command
|
||||
"""
|
||||
args = _default_args(args)
|
||||
get_auth_configuration_mock = mocker.patch("ahriman.application.handlers.User.get_auth_configuration")
|
||||
create_configuration_mock = mocker.patch("ahriman.application.handlers.User.create_configuration")
|
||||
write_configuration_mock = mocker.patch("ahriman.application.handlers.User.write_configuration")
|
||||
create_user = mocker.patch("ahriman.application.handlers.User.create_user")
|
||||
get_salt_mock = mocker.patch("ahriman.application.handlers.User.get_salt")
|
||||
|
||||
User.run(args, "x86_64", configuration, True)
|
||||
get_auth_configuration_mock.assert_called_once()
|
||||
create_configuration_mock.assert_called_once()
|
||||
create_user.assert_called_once()
|
||||
get_salt_mock.assert_called_once()
|
||||
write_configuration_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_run_remove(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must remove user if remove flag supplied
|
||||
"""
|
||||
args = _default_args(args)
|
||||
args.remove = True
|
||||
get_auth_configuration_mock = mocker.patch("ahriman.application.handlers.User.get_auth_configuration")
|
||||
create_configuration_mock = mocker.patch("ahriman.application.handlers.User.create_configuration")
|
||||
write_configuration_mock = mocker.patch("ahriman.application.handlers.User.write_configuration")
|
||||
|
||||
User.run(args, "x86_64", configuration, True)
|
||||
get_auth_configuration_mock.assert_called_once()
|
||||
create_configuration_mock.assert_not_called()
|
||||
write_configuration_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_clear_user(configuration: Configuration, user: MUser) -> None:
|
||||
"""
|
||||
must clear user from configuration
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
configuration.set_option(section, user.username, user.password)
|
||||
|
||||
User.clear_user(configuration, user)
|
||||
assert configuration.get(section, user.username, fallback=None) is None
|
||||
|
||||
|
||||
def test_clear_user_multiple_sections(configuration: Configuration, user: MUser) -> None:
|
||||
"""
|
||||
must clear user from configuration from all sections
|
||||
"""
|
||||
for role in UserAccess:
|
||||
section = Configuration.section_name("auth", role.value)
|
||||
configuration.set_option(section, user.username, user.password)
|
||||
|
||||
User.clear_user(configuration, user)
|
||||
for role in UserAccess:
|
||||
section = Configuration.section_name("auth", role.value)
|
||||
assert configuration.get(section, user.username, fallback=None) is None
|
||||
|
||||
|
||||
def test_create_configuration(configuration: Configuration, user: MUser, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly create configuration file
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
mocker.patch("pathlib.Path.open")
|
||||
set_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
|
||||
|
||||
User.create_configuration(configuration, user, "salt", False)
|
||||
set_mock.assert_has_calls([
|
||||
mock.call("auth", "salt", pytest.helpers.anyvar(str)),
|
||||
mock.call(section, user.username, pytest.helpers.anyvar(str))
|
||||
])
|
||||
|
||||
|
||||
def test_create_configuration_user_exists(configuration: Configuration, user: MUser, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must correctly update configuration file if user already exists
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
configuration.set_option(section, user.username, "")
|
||||
mocker.patch("pathlib.Path.open")
|
||||
|
||||
User.create_configuration(configuration, user, "salt", False)
|
||||
generated = MUser.from_option(user.username, configuration.get(section, user.username))
|
||||
assert generated.check_credentials(user.password, configuration.get("auth", "salt"))
|
||||
|
||||
|
||||
def test_create_configuration_with_plain_password(
|
||||
configuration: Configuration,
|
||||
user: MUser,
|
||||
mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set plain text password and user for the service
|
||||
"""
|
||||
section = Configuration.section_name("auth", user.access.value)
|
||||
mocker.patch("pathlib.Path.open")
|
||||
|
||||
User.create_configuration(configuration, user, "salt", True)
|
||||
|
||||
generated = MUser.from_option(user.username, configuration.get(section, user.username))
|
||||
service = MUser.from_option(configuration.get("web", "username"), configuration.get("web", "password"))
|
||||
assert generated.username == service.username
|
||||
assert generated.check_credentials(service.password, configuration.get("auth", "salt"))
|
||||
|
||||
|
||||
def test_create_user(args: argparse.Namespace, user: MUser) -> None:
|
||||
"""
|
||||
must create user
|
||||
"""
|
||||
args = _default_args(args)
|
||||
generated = User.create_user(args)
|
||||
assert generated.username == user.username
|
||||
assert generated.access == user.access
|
||||
|
||||
|
||||
def test_create_user_getpass(args: argparse.Namespace, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create user and get password from command line
|
||||
"""
|
||||
args = _default_args(args)
|
||||
args.password = None
|
||||
|
||||
getpass_mock = mocker.patch("getpass.getpass", return_value="password")
|
||||
generated = User.create_user(args)
|
||||
|
||||
getpass_mock.assert_called_once()
|
||||
assert generated.password == "password"
|
||||
|
||||
|
||||
def test_get_salt_read(configuration: Configuration) -> None:
|
||||
"""
|
||||
must read salt from configuration
|
||||
"""
|
||||
assert User.get_salt(configuration) == "salt"
|
||||
|
||||
|
||||
def test_get_salt_generate(configuration: Configuration) -> None:
|
||||
"""
|
||||
must generate salt if it does not exist
|
||||
"""
|
||||
configuration.remove_option("auth", "salt")
|
||||
|
||||
salt = User.get_salt(configuration, 16)
|
||||
assert salt
|
||||
assert len(salt) == 16
|
||||
|
||||
|
||||
def test_get_auth_configuration_exists(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must load configuration from filesystem
|
||||
"""
|
||||
mocker.patch("pathlib.Path.open")
|
||||
mocker.patch("pathlib.Path.is_file", return_value=True)
|
||||
read_mock = mocker.patch("ahriman.core.configuration.Configuration.read")
|
||||
|
||||
assert User.get_auth_configuration(Path("path"))
|
||||
read_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_get_auth_configuration_not_exists(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must try to load configuration from filesystem
|
||||
"""
|
||||
mocker.patch("pathlib.Path.open")
|
||||
mocker.patch("pathlib.Path.is_file", return_value=False)
|
||||
read_mock = mocker.patch("ahriman.core.configuration.Configuration.read")
|
||||
|
||||
assert User.get_auth_configuration(Path("path"))
|
||||
read_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_write_configuration(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must write configuration
|
||||
"""
|
||||
mocker.patch("pathlib.Path.open")
|
||||
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
|
||||
chmod_mock = mocker.patch("pathlib.Path.chmod")
|
||||
|
||||
User.write_configuration(configuration)
|
||||
write_mock.assert_called_once()
|
||||
chmod_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_write_configuration_not_loaded(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must do nothing in case if configuration is not loaded
|
||||
"""
|
||||
configuration.path = None
|
||||
mocker.patch("pathlib.Path.open")
|
||||
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
|
||||
chmod_mock = mocker.patch("pathlib.Path.chmod")
|
||||
|
||||
User.write_configuration(configuration)
|
||||
write_mock.assert_not_called()
|
||||
chmod_mock.assert_not_called()
|
@ -84,28 +84,6 @@ def test_subparsers_config(parser: argparse.ArgumentParser) -> None:
|
||||
assert args.unsafe
|
||||
|
||||
|
||||
def test_subparsers_create_user(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
create-user command must imply architecture, lock, no-log, no-report and unsafe
|
||||
"""
|
||||
args = parser.parse_args(["create-user", "username"])
|
||||
assert args.architecture == [""]
|
||||
assert args.lock is None
|
||||
assert args.no_log
|
||||
assert args.no_report
|
||||
assert args.unsafe
|
||||
|
||||
|
||||
def test_subparsers_create_user_option_role(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
create-user command must convert role option to useraccess instance
|
||||
"""
|
||||
args = parser.parse_args(["create-user", "username"])
|
||||
assert isinstance(args.role, UserAccess)
|
||||
args = parser.parse_args(["create-user", "username", "--role", "write"])
|
||||
assert isinstance(args.role, UserAccess)
|
||||
|
||||
|
||||
def test_subparsers_init(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
init command must imply no_report
|
||||
@ -258,6 +236,28 @@ def test_subparsers_update(parser: argparse.ArgumentParser) -> None:
|
||||
assert args.architecture == []
|
||||
|
||||
|
||||
def test_subparsers_user(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
user command must imply architecture, lock, no-log, no-report and unsafe
|
||||
"""
|
||||
args = parser.parse_args(["user", "username"])
|
||||
assert args.architecture == [""]
|
||||
assert args.lock is None
|
||||
assert args.no_log
|
||||
assert args.no_report
|
||||
assert args.unsafe
|
||||
|
||||
|
||||
def test_subparsers_user_option_role(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
user command must convert role option to useraccess instance
|
||||
"""
|
||||
args = parser.parse_args(["user", "username"])
|
||||
assert isinstance(args.access, UserAccess)
|
||||
args = parser.parse_args(["user", "username", "--access", "write"])
|
||||
assert isinstance(args.access, UserAccess)
|
||||
|
||||
|
||||
def test_subparsers_web(parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
web command must imply lock, no_report and parser
|
||||
|
Reference in New Issue
Block a user