mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-28 09:17:17 +00:00
add create user parser
This commit is contained in:
parent
3ee5f7f13e
commit
3e044fd006
@ -30,6 +30,8 @@ from ahriman.models.sign_settings import SignSettings
|
|||||||
|
|
||||||
|
|
||||||
# pylint thinks it is bad idea, but get the fuck off
|
# pylint thinks it is bad idea, but get the fuck off
|
||||||
|
from ahriman.models.user_access import UserAccess
|
||||||
|
|
||||||
SubParserAction = argparse._SubParsersAction # pylint: disable=protected-access
|
SubParserAction = argparse._SubParsersAction # pylint: disable=protected-access
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
_set_check_parser(subparsers)
|
_set_check_parser(subparsers)
|
||||||
_set_clean_parser(subparsers)
|
_set_clean_parser(subparsers)
|
||||||
_set_config_parser(subparsers)
|
_set_config_parser(subparsers)
|
||||||
|
_set_create_user_parser(subparsers)
|
||||||
_set_init_parser(subparsers)
|
_set_init_parser(subparsers)
|
||||||
_set_key_import_parser(subparsers)
|
_set_key_import_parser(subparsers)
|
||||||
_set_rebuild_parser(subparsers)
|
_set_rebuild_parser(subparsers)
|
||||||
@ -138,6 +141,30 @@ def _set_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def _set_create_user_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for create user subcommand
|
||||||
|
:param root: subparsers for the commands
|
||||||
|
:return: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser(
|
||||||
|
"create-user",
|
||||||
|
help="create user for web services",
|
||||||
|
description="create user for web services with password and role. In case if password was not entered it will be asked interactively",
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
|
parser.add_argument("username", help="username for web service")
|
||||||
|
parser.add_argument("-r", "--role", help="user role", type=UserAccess, choices=UserAccess, default=UserAccess.Read)
|
||||||
|
parser.add_argument("-p", "--password", help="user password")
|
||||||
|
parser.set_defaults(
|
||||||
|
handler=handlers.CreateUser,
|
||||||
|
architecture=[""],
|
||||||
|
lock=None,
|
||||||
|
no_log=True,
|
||||||
|
no_report=True,
|
||||||
|
unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def _set_init_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_init_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
"""
|
"""
|
||||||
add parser for init subcommand
|
add parser for init subcommand
|
||||||
|
@ -21,6 +21,7 @@ from ahriman.application.handlers.handler import Handler
|
|||||||
|
|
||||||
from ahriman.application.handlers.add import Add
|
from ahriman.application.handlers.add import Add
|
||||||
from ahriman.application.handlers.clean import Clean
|
from ahriman.application.handlers.clean import Clean
|
||||||
|
from ahriman.application.handlers.create_user import CreateUser
|
||||||
from ahriman.application.handlers.dump import Dump
|
from ahriman.application.handlers.dump import Dump
|
||||||
from ahriman.application.handlers.init import Init
|
from ahriman.application.handlers.init import Init
|
||||||
from ahriman.application.handlers.key_import import KeyImport
|
from ahriman.application.handlers.key_import import KeyImport
|
||||||
|
79
src/ahriman/application/handlers/create_user.py
Normal file
79
src/ahriman/application/handlers/create_user.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
import argparse
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from getpass import getpass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from ahriman.application.handlers.handler import Handler
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.user import User
|
||||||
|
|
||||||
|
|
||||||
|
class CreateUser(Handler):
|
||||||
|
"""
|
||||||
|
create user handler
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration) -> None:
|
||||||
|
"""
|
||||||
|
callback for command line
|
||||||
|
:param args: command line args
|
||||||
|
:param architecture: repository architecture
|
||||||
|
:param configuration: configuration instance
|
||||||
|
"""
|
||||||
|
user = CreateUser.create_user(args, configuration)
|
||||||
|
CreateUser.create_configuration(user, configuration.include)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_configuration(user: User, include_path: Path) -> None:
|
||||||
|
"""
|
||||||
|
put new user to configuration
|
||||||
|
:param user: user descriptor
|
||||||
|
:param include_path: path to directory with configuration includes
|
||||||
|
"""
|
||||||
|
target = include_path / "auth.ini"
|
||||||
|
|
||||||
|
configuration = configparser.ConfigParser()
|
||||||
|
configuration.read(target)
|
||||||
|
|
||||||
|
section = Configuration.section_name("auth", user.access.value)
|
||||||
|
configuration.add_section(section)
|
||||||
|
configuration.set(section, user.username, user.password)
|
||||||
|
|
||||||
|
with target.open("w") as ahriman_configuration:
|
||||||
|
configuration.write(ahriman_configuration)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_user(args: argparse.Namespace, configuration: Configuration) -> User:
|
||||||
|
"""
|
||||||
|
create user descriptor from arguments
|
||||||
|
:param args: command line args
|
||||||
|
:param configuration: configuration instance
|
||||||
|
:return: built user descriptor
|
||||||
|
"""
|
||||||
|
user = User(args.username, args.password, args.role)
|
||||||
|
if user.password is None:
|
||||||
|
user.password = getpass()
|
||||||
|
user.password = user.generate_password(user.password, configuration.get("auth", "salt"))
|
||||||
|
return user
|
@ -49,7 +49,9 @@ class WebClient(Client):
|
|||||||
self.user = User.from_option(
|
self.user = User.from_option(
|
||||||
configuration.get("web", "username", fallback=None),
|
configuration.get("web", "username", fallback=None),
|
||||||
configuration.get("web", "password", fallback=None))
|
configuration.get("web", "password", fallback=None))
|
||||||
|
|
||||||
self.__session = requests.session()
|
self.__session = requests.session()
|
||||||
|
self.login()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _ahriman_url(self) -> str:
|
def _ahriman_url(self) -> str:
|
||||||
|
@ -38,6 +38,8 @@ class User:
|
|||||||
password: str
|
password: str
|
||||||
access: UserAccess
|
access: UserAccess
|
||||||
|
|
||||||
|
_HASHER = sha512_crypt
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_option(cls: Type[User], username: Optional[str], password: Optional[str]) -> Optional[User]:
|
def from_option(cls: Type[User], username: Optional[str], password: Optional[str]) -> Optional[User]:
|
||||||
"""
|
"""
|
||||||
@ -57,9 +59,19 @@ class User:
|
|||||||
:param salt: salt for hashed password
|
:param salt: salt for hashed password
|
||||||
:return: True in case if password matches, False otherwise
|
:return: True in case if password matches, False otherwise
|
||||||
"""
|
"""
|
||||||
verified: bool = sha512_crypt.verify(password + salt, self.password)
|
verified: bool = self._HASHER.verify(password + salt, self.password)
|
||||||
return verified
|
return verified
|
||||||
|
|
||||||
|
def generate_password(self, password: str, salt: str) -> str:
|
||||||
|
"""
|
||||||
|
generate hashed password from plain text
|
||||||
|
:param password: entered password
|
||||||
|
:param salt: salt for hashed password
|
||||||
|
:return: hashed string to store in configuration
|
||||||
|
"""
|
||||||
|
password_hash: str = self._HASHER.hash(password + salt)
|
||||||
|
return password_hash
|
||||||
|
|
||||||
def verify_access(self, required: UserAccess) -> bool:
|
def verify_access(self, required: UserAccess) -> bool:
|
||||||
"""
|
"""
|
||||||
validate if user has access to requested resource
|
validate if user has access to requested resource
|
||||||
|
@ -44,6 +44,7 @@ def client() -> Client:
|
|||||||
def web_client(configuration: Configuration) -> WebClient:
|
def web_client(configuration: Configuration) -> WebClient:
|
||||||
"""
|
"""
|
||||||
fixture for web client
|
fixture for web client
|
||||||
|
:param configuration: configuration fixture
|
||||||
:return: web client test instance
|
:return: web client test instance
|
||||||
"""
|
"""
|
||||||
configuration.set("web", "port", 8080)
|
configuration.set("web", "port", 8080)
|
||||||
|
Loading…
Reference in New Issue
Block a user