do not invoke configuration write in case if no salt or user was written

This commit is contained in:
2022-11-28 00:02:53 +02:00
parent 41cc58ed31
commit bba58352e0
3 changed files with 70 additions and 19 deletions

View File

@ -760,7 +760,7 @@ def _set_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
Returns:
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("shell", help="envoke python shell",
parser = root.add_parser("shell", help="invoke python shell",
description="drop into python shell while having created application",
formatter_class=_formatter)
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
@ -782,6 +782,9 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser = root.add_parser("user-add", help="create or update user",
description="update user for web services with the given password and role. "
"In case if password was not entered it will be asked interactively",
epilog="In case of first run (i.e. if password salt is not set yet) or if ``as-service`` "
"flag is supplied, this action requires root privileges because it performs write "
"to filesystem configuration.",
formatter_class=_formatter)
parser.add_argument("username", help="username for web service")
parser.add_argument("--as-service", help="add user as service user", action="store_true")
@ -830,7 +833,6 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="remove user from the user mapping and update the configuration",
formatter_class=_formatter)
parser.add_argument("username", help="username for web service")
parser.add_argument("-s", "--secure", help="set file permissions to user-only", action="store_true")
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False, # nosec
password="", quiet=True, unsafe=True)
return parser

View File

@ -21,7 +21,7 @@ import argparse
import getpass
from pathlib import Path
from typing import Type
from typing import Optional, Tuple, Type
from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
@ -55,12 +55,13 @@ class Users(Handler):
database = SQLite.load(configuration)
if args.action == Action.Update:
salt = Users.get_salt(configuration)
old_salt, salt = Users.get_salt(configuration)
user = Users.user_create(args)
auth_configuration = Users.configuration_get(configuration.include)
if old_salt is None or args.as_service:
auth_configuration = Users.configuration_get(configuration.include)
Users.configuration_create(auth_configuration, user, salt, args.as_service, args.secure)
Users.configuration_create(auth_configuration, user, salt, args.as_service, args.secure)
database.user_update(user.hash_password(salt))
elif args.action == Action.List:
users = database.user_list(args.username, args.role)
@ -100,7 +101,7 @@ class Users(Handler):
Returns:
Configuration: configuration instance. In case if there are local settings they will be loaded
"""
target = include_path / "auth.ini"
target = include_path / "00-auth.ini"
configuration = Configuration()
configuration.load(target)
@ -124,7 +125,7 @@ class Users(Handler):
path.chmod(0o600)
@staticmethod
def get_salt(configuration: Configuration, salt_length: int = 20) -> str:
def get_salt(configuration: Configuration, salt_length: int = 20) -> Tuple[Optional[str], str]:
"""
get salt from configuration or create new string
@ -133,11 +134,12 @@ class Users(Handler):
salt_length(int, optional): salt length (Default value = 20)
Returns:
str: current salt
Tuple[Optional[str], str]: tuple containing salt from configuration if any and actual salt which must be
used for password hash
"""
if salt := configuration.get("auth", "salt", fallback=None):
return salt
return User.generate_password(salt_length)
return salt, salt
return None, User.generate_password(salt_length)
@staticmethod
def user_create(args: argparse.Namespace) -> User: