add ability to remove an user

also replace old user by new one before creation
This commit is contained in:
2021-09-16 02:36:53 +03:00
parent b561bcc25d
commit 0cf7756ec4
6 changed files with 316 additions and 231 deletions

View File

@ -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()

View 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()

View File

@ -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