Compare commits

..

2 Commits

Author SHA1 Message Date
e40b773029 test: add tests to check args list
Some parsers are shared between different subcommands. It causes errors
when wwe add new arguments to one of them. This commit adds some tests
to cover those cases (except for well-known differencies)
2023-12-27 15:01:07 +02:00
ee3ccf70ac refactor: use AppKey's instead of string identifiers for web application 2023-12-27 13:53:23 +02:00
19 changed files with 275 additions and 65 deletions

View File

@ -30,6 +30,14 @@ ahriman.web.cors module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.web.keys module
-----------------------
.. automodule:: ahriman.web.keys
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.routes module ahriman.web.routes module
------------------------- -------------------------

View File

@ -31,8 +31,8 @@ _shtab_ahriman_repo_check_option_strings=('-h' '--help' '--changes' '--no-change
_shtab_ahriman_check_option_strings=('-h' '--help' '--changes' '--no-changes' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_check_option_strings=('-h' '--help' '--changes' '--no-changes' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_repo_create_keyring_option_strings=('-h' '--help') _shtab_ahriman_repo_create_keyring_option_strings=('-h' '--help')
_shtab_ahriman_repo_create_mirrorlist_option_strings=('-h' '--help') _shtab_ahriman_repo_create_mirrorlist_option_strings=('-h' '--help')
_shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--local' '--no-local' '--manual' '--no-manual' '--partitions' '--no-partitions' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--increment' '--no-increment' '--local' '--no-local' '--manual' '--no-manual' '--partitions' '--no-partitions' '-u' '--username' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--local' '--no-local' '--manual' '--no-manual' '--partitions' '--no-partitions' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '--dry-run' '--increment' '--no-increment' '--local' '--no-local' '--manual' '--no-manual' '--partitions' '--no-partitions' '-u' '--username' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username') _shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username')
_shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username') _shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '--increment' '--no-increment' '-e' '--exit-code' '-s' '--status' '-u' '--username')
_shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run') _shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run')
@ -273,6 +273,8 @@ _shtab_ahriman_repo_daemon___no_changes_nargs=0
_shtab_ahriman_repo_daemon___dependencies_nargs=0 _shtab_ahriman_repo_daemon___dependencies_nargs=0
_shtab_ahriman_repo_daemon___no_dependencies_nargs=0 _shtab_ahriman_repo_daemon___no_dependencies_nargs=0
_shtab_ahriman_repo_daemon___dry_run_nargs=0 _shtab_ahriman_repo_daemon___dry_run_nargs=0
_shtab_ahriman_repo_daemon___increment_nargs=0
_shtab_ahriman_repo_daemon___no_increment_nargs=0
_shtab_ahriman_repo_daemon___local_nargs=0 _shtab_ahriman_repo_daemon___local_nargs=0
_shtab_ahriman_repo_daemon___no_local_nargs=0 _shtab_ahriman_repo_daemon___no_local_nargs=0
_shtab_ahriman_repo_daemon___manual_nargs=0 _shtab_ahriman_repo_daemon___manual_nargs=0
@ -292,6 +294,8 @@ _shtab_ahriman_daemon___no_changes_nargs=0
_shtab_ahriman_daemon___dependencies_nargs=0 _shtab_ahriman_daemon___dependencies_nargs=0
_shtab_ahriman_daemon___no_dependencies_nargs=0 _shtab_ahriman_daemon___no_dependencies_nargs=0
_shtab_ahriman_daemon___dry_run_nargs=0 _shtab_ahriman_daemon___dry_run_nargs=0
_shtab_ahriman_daemon___increment_nargs=0
_shtab_ahriman_daemon___no_increment_nargs=0
_shtab_ahriman_daemon___local_nargs=0 _shtab_ahriman_daemon___local_nargs=0
_shtab_ahriman_daemon___no_local_nargs=0 _shtab_ahriman_daemon___no_local_nargs=0
_shtab_ahriman_daemon___manual_nargs=0 _shtab_ahriman_daemon___manual_nargs=0

View File

@ -1,4 +1,4 @@
.TH AHRIMAN "1" "2023\-12\-26" "ahriman" "Generated Python Manual" .TH AHRIMAN "1" "2023\-12\-27" "ahriman" "Generated Python Manual"
.SH NAME .SH NAME
ahriman ahriman
.SH SYNOPSIS .SH SYNOPSIS
@ -484,8 +484,9 @@ create package which contains list of available mirrors as set by configuration.
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR .SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-changes | \-\-no\-changes] usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-changes | \-\-no\-changes]
[\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-\-local | \-\-no\-local] [\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-\-increment | \-\-no\-increment]
[\-\-manual | \-\-no\-manual] [\-\-partitions | \-\-no\-partitions] [\-\-vcs | \-\-no\-vcs] [\-y] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-\-partitions | \-\-no\-partitions]
[\-u USERNAME] [\-\-vcs | \-\-no\-vcs] [\-y]
start process which periodically will run update process start process which periodically will run update process
@ -510,6 +511,10 @@ process missing package dependencies
\fB\-\-dry\-run\fR \fB\-\-dry\-run\fR
just perform check for updates, same as check command just perform check for updates, same as check command
.TP
\fB\-\-increment\fR, \fB\-\-no\-increment\fR
increment package release (pkgrel) on duplicate
.TP .TP
\fB\-\-local\fR, \fB\-\-no\-local\fR \fB\-\-local\fR, \fB\-\-no\-local\fR
enable or disable checking of local packages for updates enable or disable checking of local packages for updates
@ -522,6 +527,10 @@ include or exclude manual updates
\fB\-\-partitions\fR, \fB\-\-no\-partitions\fR \fB\-\-partitions\fR, \fB\-\-no\-partitions\fR
instead of updating whole repository, split updates into chunks instead of updating whole repository, split updates into chunks
.TP
\fB\-u\fR \fI\,USERNAME\/\fR, \fB\-\-username\fR \fI\,USERNAME\/\fR
build as user
.TP .TP
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR \fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
fetch actual version of VCS packages fetch actual version of VCS packages

View File

@ -155,9 +155,11 @@ _shtab_ahriman_daemon_options=(
{--changes,--no-changes}"[calculate changes from the latest known commit if available. Only applicable in dry run mode (default\: True)]:changes:" {--changes,--no-changes}"[calculate changes from the latest known commit if available. Only applicable in dry run mode (default\: True)]:changes:"
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: True)]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: True)]:dependencies:"
"--dry-run[just perform check for updates, same as check command (default\: False)]" "--dry-run[just perform check for updates, same as check command (default\: False)]"
{--increment,--no-increment}"[increment package release (pkgrel) on duplicate (default\: True)]:increment:"
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:" {--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:"
{--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:" {--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:"
{--partitions,--no-partitions}"[instead of updating whole repository, split updates into chunks (default\: True)]:partitions:" {--partitions,--no-partitions}"[instead of updating whole repository, split updates into chunks (default\: True)]:partitions:"
{-u,--username}"[build as user (default\: None)]:username:"
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
) )
@ -363,9 +365,11 @@ _shtab_ahriman_repo_daemon_options=(
{--changes,--no-changes}"[calculate changes from the latest known commit if available. Only applicable in dry run mode (default\: True)]:changes:" {--changes,--no-changes}"[calculate changes from the latest known commit if available. Only applicable in dry run mode (default\: True)]:changes:"
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: True)]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: True)]:dependencies:"
"--dry-run[just perform check for updates, same as check command (default\: False)]" "--dry-run[just perform check for updates, same as check command (default\: False)]"
{--increment,--no-increment}"[increment package release (pkgrel) on duplicate (default\: True)]:increment:"
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:" {--local,--no-local}"[enable or disable checking of local packages for updates (default\: True)]:local:"
{--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:" {--manual,--no-manual}"[include or exclude manual updates (default\: True)]:manual:"
{--partitions,--no-partitions}"[instead of updating whole repository, split updates into chunks (default\: True)]:partitions:" {--partitions,--no-partitions}"[instead of updating whole repository, split updates into chunks (default\: True)]:partitions:"
{-u,--username}"[build as user (default\: None)]:username:"
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: True)]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
) )

View File

@ -317,7 +317,8 @@ def _set_package_changes_remove_parser(root: SubParserAction) -> argparse.Argume
description="remove the package changes stored remotely", description="remove the package changes stored remotely",
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("package", help="package base") parser.add_argument("package", help="package base")
parser.set_defaults(handler=handlers.Change, action=Action.Remove, lock=None, quiet=True, report=False, unsafe=True) parser.set_defaults(handler=handlers.Change, action=Action.Remove, exit_code=False, lock=None, quiet=True,
report=False, unsafe=True)
return parser return parser
@ -428,8 +429,8 @@ def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
"it must end with ()") "it must end with ()")
parser.add_argument("patch", help="path to file which contains function or variable value. If not set, " parser.add_argument("patch", help="path to file which contains function or variable value. If not set, "
"the value will be read from stdin", type=Path, nargs="?") "the value will be read from stdin", type=Path, nargs="?")
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture="", lock=None, report=False, parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture="", exit_code=False, lock=None,
repository="") report=False, repository="")
return parser return parser
@ -471,8 +472,8 @@ def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
"to remove only specified PKGBUILD variables. In case if not set, " "to remove only specified PKGBUILD variables. In case if not set, "
"it will remove all patches related to the package", "it will remove all patches related to the package",
action="append") action="append")
parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture="", lock=None, report=False, parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture="", exit_code=False, lock=None,
repository="") report=False, repository="")
return parser return parser
@ -496,8 +497,8 @@ def _set_patch_set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("package", help="path to directory with changed files for patch addition/update", type=Path) parser.add_argument("package", help="path to directory with changed files for patch addition/update", type=Path)
parser.add_argument("-t", "--track", help="files which has to be tracked", action="append", parser.add_argument("-t", "--track", help="files which has to be tracked", action="append",
default=["*.diff", "*.patch"]) default=["*.diff", "*.patch"])
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture="", lock=None, report=False, parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture="", exit_code=False, lock=None,
repository="", variable=None) report=False, repository="", variable=None)
return parser return parser
@ -542,8 +543,8 @@ def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, " parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
"-yy to force refresh even if up to date", "-yy to force refresh even if up to date",
action="count", default=False) action="count", default=False)
parser.set_defaults(handler=handlers.Update, dependencies=False, dry_run=True, aur=True, local=True, manual=False, parser.set_defaults(handler=handlers.Update, aur=True, dependencies=False, dry_run=True, increment=False,
username=None) local=True, manual=False, username=None)
return parser return parser
@ -1073,8 +1074,8 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
"which is in particular must be used for OAuth2 authorization type.") "which is in particular must be used for OAuth2 authorization type.")
parser.add_argument("-R", "--role", help="user access level", parser.add_argument("-R", "--role", help="user access level",
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read) type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture="", lock=None, quiet=True, parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture="", exit_code=False, lock=None,
report=False, repository="") quiet=True, report=False, repository="")
return parser return parser
@ -1113,8 +1114,8 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="remove user from the user mapping and update the configuration", description="remove user from the user mapping and update the configuration",
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("username", help="username for web service") parser.add_argument("username", help="username for web service")
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture="", lock=None, quiet=True, parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture="", exit_code=False, lock=None,
report=False, repository="") quiet=True, report=False, repository="")
return parser return parser

View File

@ -22,6 +22,7 @@ import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.application.handlers.update import Update
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
@ -43,8 +44,6 @@ class Daemon(Handler):
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
""" """
from ahriman.application.handlers import Update
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh) application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
if args.partitions: if args.partitions:
iterator = UpdatesIterator(application, args.interval) iterator = UpdatesIterator(application, args.interval)

View File

@ -23,7 +23,7 @@ from aiohttp.web import Application
from typing import Any from typing import Any
from ahriman import __version__ from ahriman import __version__
from ahriman.core.configuration import Configuration from ahriman.web.keys import ConfigurationKey
__all__ = ["setup_apispec"] __all__ = ["setup_apispec"]
@ -89,7 +89,7 @@ def _servers(application: Application) -> list[dict[str, Any]]:
Returns: Returns:
list[dict[str, Any]]: list (actually only one) of defined web urls list[dict[str, Any]]: list (actually only one) of defined web urls
""" """
configuration: Configuration = application["configuration"] configuration = application[ConfigurationKey]
address = configuration.get("web", "address", fallback=None) address = configuration.get("web", "address", fallback=None)
if not address: if not address:
host = configuration.get("web", "host") host = configuration.get("web", "host")

40
src/ahriman/web/keys.py Normal file
View File

@ -0,0 +1,40 @@
#
# Copyright (c) 2021-2023 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/>.
#
from aiohttp.web import AppKey
from ahriman.core.auth import Auth
from ahriman.core.configuration import Configuration
from ahriman.core.spawn import Spawn
from ahriman.core.status.watcher import Watcher
from ahriman.models.repository_id import RepositoryId
__all__ = [
"AuthKey",
"ConfigurationKey",
"SpawnKey",
"WatcherKey",
]
AuthKey = AppKey("validator", Auth)
ConfigurationKey = AppKey("configuration", Configuration)
SpawnKey = AppKey("spawn", Spawn)
WatcherKey = AppKey("watcher", dict[RepositoryId, Watcher])

View File

@ -154,7 +154,7 @@ def setup_auth(application: Application, configuration: Configuration, validator
setup_session(application, storage) setup_session(application, storage)
authorization_policy = _AuthorizationPolicy(validator) authorization_policy = _AuthorizationPolicy(validator)
identity_policy = application["identity"] = aiohttp_security.SessionIdentityPolicy() identity_policy = aiohttp_security.SessionIdentityPolicy()
aiohttp_security.setup(application, identity_policy, authorization_policy) aiohttp_security.setup(application, identity_policy, authorization_policy)
application.middlewares.append(_auth_handler(validator.allow_read_only)) application.middlewares.append(_auth_handler(validator.allow_read_only))

View File

@ -29,6 +29,7 @@ from ahriman.core.spawn import Spawn
from ahriman.core.status.watcher import Watcher from ahriman.core.status.watcher import Watcher
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.keys import AuthKey, ConfigurationKey, SpawnKey, WatcherKey
T = TypeVar("T", str, list[str]) T = TypeVar("T", str, list[str])
@ -54,8 +55,7 @@ class BaseView(View, CorsViewMixin):
Returns: Returns:
Configuration: configuration instance Configuration: configuration instance
""" """
configuration: Configuration = self.request.app["configuration"] return self.request.app[ConfigurationKey]
return configuration
@property @property
def services(self) -> dict[RepositoryId, Watcher]: def services(self) -> dict[RepositoryId, Watcher]:
@ -65,8 +65,7 @@ class BaseView(View, CorsViewMixin):
Returns: Returns:
dict[RepositoryId, Watcher]: map of loaded watchers per known repository dict[RepositoryId, Watcher]: map of loaded watchers per known repository
""" """
watchers: dict[RepositoryId, Watcher] = self.request.app["watcher"] return self.request.app[WatcherKey]
return watchers
@property @property
def sign(self) -> GPG: def sign(self) -> GPG:
@ -86,8 +85,7 @@ class BaseView(View, CorsViewMixin):
Returns: Returns:
Spawn: external process spawner instance Spawn: external process spawner instance
""" """
spawner: Spawn = self.request.app["spawn"] return self.request.app[SpawnKey]
return spawner
@property @property
def validator(self) -> Auth: def validator(self) -> Auth:
@ -97,8 +95,7 @@ class BaseView(View, CorsViewMixin):
Returns: Returns:
Auth: authorization service instance Auth: authorization service instance
""" """
validator: Auth = self.request.app["validator"] return self.request.app[AuthKey]
return validator
@classmethod @classmethod
async def get_permission(cls, request: Request) -> UserAccess: async def get_permission(cls, request: Request) -> UserAccess:

View File

@ -34,6 +34,7 @@ from ahriman.core.status.watcher import Watcher
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.web.apispec import setup_apispec from ahriman.web.apispec import setup_apispec
from ahriman.web.cors import setup_cors from ahriman.web.cors import setup_cors
from ahriman.web.keys import AuthKey, ConfigurationKey, SpawnKey, WatcherKey
from ahriman.web.middlewares.exception_handler import exception_handler from ahriman.web.middlewares.exception_handler import exception_handler
from ahriman.web.routes import setup_routes from ahriman.web.routes import setup_routes
@ -97,7 +98,7 @@ async def _on_startup(application: Application) -> None:
application.logger.info("server started") application.logger.info("server started")
try: try:
for watcher in application["watcher"].values(): for watcher in application[WatcherKey].values():
watcher.load() watcher.load()
except Exception: except Exception:
message = "could not load packages" message = "could not load packages"
@ -114,7 +115,7 @@ def run_server(application: Application) -> None:
""" """
application.logger.info("start server") application.logger.info("start server")
configuration: Configuration = application["configuration"] configuration = application[ConfigurationKey]
host = configuration.get("web", "host") host = configuration.get("web", "host")
port = configuration.getint("web", "port") port = configuration.getint("web", "port")
unix_socket = _create_socket(configuration, application) unix_socket = _create_socket(configuration, application)
@ -156,7 +157,7 @@ def setup_server(configuration: Configuration, spawner: Spawn, repositories: lis
aiohttp_jinja2.setup(application, trim_blocks=True, lstrip_blocks=True, autoescape=True, loader=loader) aiohttp_jinja2.setup(application, trim_blocks=True, lstrip_blocks=True, autoescape=True, loader=loader)
application.logger.info("setup configuration") application.logger.info("setup configuration")
application["configuration"] = configuration application[ConfigurationKey] = configuration
application.logger.info("setup watchers") application.logger.info("setup watchers")
if not repositories: if not repositories:
@ -166,13 +167,13 @@ def setup_server(configuration: Configuration, spawner: Spawn, repositories: lis
for repository_id in repositories: for repository_id in repositories:
application.logger.info("load repository %s", repository_id) application.logger.info("load repository %s", repository_id)
watchers[repository_id] = Watcher(repository_id, database) watchers[repository_id] = Watcher(repository_id, database)
application["watcher"] = watchers application[WatcherKey] = watchers
application.logger.info("setup process spawner") application.logger.info("setup process spawner")
application["spawn"] = spawner application[SpawnKey] = spawner
application.logger.info("setup authorization") application.logger.info("setup authorization")
validator = application["validator"] = Auth.load(configuration, database) validator = application[AuthKey] = Auth.load(configuration, database)
if validator.enabled: if validator.enabled:
from ahriman.web.middlewares.auth_handler import setup_auth from ahriman.web.middlewares.auth_handler import setup_auth
setup_auth(application, configuration, validator) setup_auth(application, configuration, validator)

View File

@ -272,11 +272,12 @@ def test_subparsers_package_add_option_variable_multiple(parser: argparse.Argume
def test_subparsers_package_changes(parser: argparse.ArgumentParser) -> None: def test_subparsers_package_changes(parser: argparse.ArgumentParser) -> None:
""" """
package-changes command must imply action, lock, quiet, report and unsafe package-changes command must imply action, exit code, lock, quiet, report and unsafe
""" """
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-changes", "ahriman"]) args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-changes", "ahriman"])
assert args.action == Action.List assert args.action == Action.List
assert args.architecture == "x86_64" assert args.architecture == "x86_64"
assert not args.exit_code
assert args.lock is None assert args.lock is None
assert args.quiet assert args.quiet
assert not args.report assert not args.report
@ -298,6 +299,15 @@ def test_subparsers_package_changes_remove(parser: argparse.ArgumentParser) -> N
assert args.unsafe assert args.unsafe
def test_subparsers_package_changes_remove_package_changes(parser: argparse.ArgumentParser) -> None:
"""
package-changes-remove must have same keys as package-changes
"""
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-changes-remove", "ahriman"])
reference_args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-changes", "ahriman"])
assert dir(args) == dir(reference_args)
def test_subparsers_package_remove_option_architecture(parser: argparse.ArgumentParser) -> None: def test_subparsers_package_remove_option_architecture(parser: argparse.ArgumentParser) -> None:
""" """
package-remove command must correctly parse architecture list package-remove command must correctly parse architecture list
@ -369,13 +379,24 @@ def test_subparsers_package_status_update_option_status(parser: argparse.Argumen
assert isinstance(args.status, BuildStatusEnum) assert isinstance(args.status, BuildStatusEnum)
def test_subparsers_package_status_update_package_status_remove(parser: argparse.ArgumentParser) -> None:
"""
package-status-update must have same keys as package-status-remove
"""
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
reference_args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-remove", "ahriman"])
del args.status
assert dir(args) == dir(reference_args)
def test_subparsers_patch_add(parser: argparse.ArgumentParser) -> None: def test_subparsers_patch_add(parser: argparse.ArgumentParser) -> None:
""" """
patch-add command must imply action, architecture list, lock, report and repository patch-add command must imply action, architecture list, exit code, lock, report and repository
""" """
args = parser.parse_args(["patch-add", "ahriman", "version"]) args = parser.parse_args(["patch-add", "ahriman", "version"])
assert args.action == Action.Update assert args.action == Action.Update
assert args.architecture == "" assert args.architecture == ""
assert not args.exit_code
assert args.lock is None assert args.lock is None
assert not args.report assert not args.report
assert args.repository == "" assert args.repository == ""
@ -442,13 +463,24 @@ def test_subparsers_patch_list_option_variable_multiple(parser: argparse.Argumen
assert args.variable == ["var1", "var2"] assert args.variable == ["var1", "var2"]
def test_subparsers_patch_list_patch_add(parser: argparse.ArgumentParser) -> None:
"""
patch-list must have same keys as patch-add
"""
args = parser.parse_args(["patch-list", "ahriman"])
reference_args = parser.parse_args(["patch-add", "ahriman", "version"])
del reference_args.patch
assert dir(args) == dir(reference_args)
def test_subparsers_patch_remove(parser: argparse.ArgumentParser) -> None: def test_subparsers_patch_remove(parser: argparse.ArgumentParser) -> None:
""" """
patch-remove command must imply action, architecture list, lock, report and repository patch-remove command must imply action, architecture list, exit code, lock, report and repository
""" """
args = parser.parse_args(["patch-remove", "ahriman"]) args = parser.parse_args(["patch-remove", "ahriman"])
assert args.action == Action.Remove assert args.action == Action.Remove
assert args.architecture == "" assert args.architecture == ""
assert not args.exit_code
assert args.lock is None assert args.lock is None
assert not args.report assert not args.report
assert args.repository == "" assert args.repository == ""
@ -486,13 +518,24 @@ def test_subparsers_patch_remove_option_variable_multiple(parser: argparse.Argum
assert args.variable == ["var1", "var2"] assert args.variable == ["var1", "var2"]
def test_subparsers_patch_remove_patch_add(parser: argparse.ArgumentParser) -> None:
"""
patch-remove must have same keys as patch-add
"""
args = parser.parse_args(["patch-remove", "ahriman"])
reference_args = parser.parse_args(["patch-add", "ahriman", "version"])
del reference_args.patch
assert dir(args) == dir(reference_args)
def test_subparsers_patch_set_add(parser: argparse.ArgumentParser) -> None: def test_subparsers_patch_set_add(parser: argparse.ArgumentParser) -> None:
""" """
patch-set-add command must imply action, architecture list, lock, report, repository and variable patch-set-add command must imply action, architecture list, exit code, lock, report, repository and variable
""" """
args = parser.parse_args(["patch-set-add", "ahriman"]) args = parser.parse_args(["patch-set-add", "ahriman"])
assert args.action == Action.Update assert args.action == Action.Update
assert args.architecture == "" assert args.architecture == ""
assert not args.exit_code
assert args.lock is None assert args.lock is None
assert not args.report assert not args.report
assert args.repository == "" assert args.repository == ""
@ -531,6 +574,16 @@ def test_subparsers_patch_set_add_option_track(parser: argparse.ArgumentParser)
assert args.track == ["*.diff", "*.patch", "*.py"] assert args.track == ["*.diff", "*.patch", "*.py"]
def test_subparsers_patch_set_add_patch_add(parser: argparse.ArgumentParser) -> None:
"""
patch-set-add must have same keys as patch-add
"""
args = parser.parse_args(["patch-set-add", "ahriman"])
reference_args = parser.parse_args(["patch-add", "ahriman", "version"])
del reference_args.patch, args.track
assert dir(args) == dir(reference_args)
def test_subparsers_repo_backup(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_backup(parser: argparse.ArgumentParser) -> None:
""" """
repo-backup command must imply architecture list, lock, report, repository and unsafe repo-backup command must imply architecture list, lock, report, repository and unsafe
@ -561,12 +614,14 @@ def test_subparsers_repo_backup_option_repository(parser: argparse.ArgumentParse
def test_subparsers_repo_check(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_check(parser: argparse.ArgumentParser) -> None:
""" """
repo-check command must imply dependencies, dry-run, aur, manual and username repo-check command must imply aur, dependencies, dry-run, increment, local, manual and username
""" """
args = parser.parse_args(["repo-check"]) args = parser.parse_args(["repo-check"])
assert args.aur
assert not args.dependencies assert not args.dependencies
assert args.dry_run assert args.dry_run
assert args.aur assert not args.increment
assert args.local
assert not args.manual assert not args.manual
assert args.username is None assert args.username is None
@ -603,6 +658,15 @@ def test_subparsers_repo_check_option_refresh(parser: argparse.ArgumentParser) -
assert args.refresh == 2 assert args.refresh == 2
def test_subparsers_repo_check_repo_update(parser: argparse.ArgumentParser) -> None:
"""
repo-check must have same keys as repo-update
"""
args = parser.parse_args(["repo-check"])
reference_args = parser.parse_args(["repo-update"])
assert dir(args) == dir(reference_args)
def test_subparsers_repo_create_keyring(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_create_keyring(parser: argparse.ArgumentParser) -> None:
""" """
repo-create-keyring command must imply trigger repo-create-keyring command must imply trigger
@ -631,6 +695,15 @@ def test_subparsers_repo_create_keyring_option_repository(parser: argparse.Argum
assert args.repository == "repo" assert args.repository == "repo"
def test_subparsers_repo_create_keyring_repo_triggers(parser: argparse.ArgumentParser) -> None:
"""
repo-create-keyring must have same keys as repo-triggers
"""
args = parser.parse_args(["repo-create-keyring"])
reference_args = parser.parse_args(["repo-triggers"])
assert dir(args) == dir(reference_args)
def test_subparsers_repo_create_mirrorlist(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_create_mirrorlist(parser: argparse.ArgumentParser) -> None:
""" """
repo-create-mirrorlist command must imply trigger repo-create-mirrorlist command must imply trigger
@ -659,6 +732,15 @@ def test_subparsers_repo_create_mirrorlist_option_repository(parser: argparse.Ar
assert args.repository == "repo" assert args.repository == "repo"
def test_subparsers_repo_create_mirrorlist_repo_triggers(parser: argparse.ArgumentParser) -> None:
"""
repo-create-mirrorlist must have same keys as repo-triggers
"""
args = parser.parse_args(["repo-create-mirrorlist"])
reference_args = parser.parse_args(["repo-triggers"])
assert dir(args) == dir(reference_args)
def test_subparsers_repo_daemon(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_daemon(parser: argparse.ArgumentParser) -> None:
""" """
repo-daemon command must imply exit code and package repo-daemon command must imply exit code and package
@ -690,6 +772,16 @@ def test_subparsers_repo_daemon_option_interval(parser: argparse.ArgumentParser)
assert isinstance(args.interval, int) assert isinstance(args.interval, int)
def test_subparsers_repo_daemon_repo_update(parser: argparse.ArgumentParser) -> None:
"""
repo-create-keyring must have same keys as repo-triggers
"""
args = parser.parse_args(["repo-daemon"])
reference_args = parser.parse_args(["repo-update"])
del args.interval, args.partitions
assert dir(args) == dir(reference_args)
def test_subparsers_repo_rebuild_option_architecture(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_rebuild_option_architecture(parser: argparse.ArgumentParser) -> None:
""" """
repo-rebuild command must correctly parse architecture list repo-rebuild command must correctly parse architecture list
@ -782,6 +874,15 @@ def test_subparsers_repo_report_option_repository(parser: argparse.ArgumentParse
assert args.repository == "repo" assert args.repository == "repo"
def test_subparsers_repo_report_repo_triggers(parser: argparse.ArgumentParser) -> None:
"""
repo-report must have same keys as repo-triggers
"""
args = parser.parse_args(["repo-report"])
reference_args = parser.parse_args(["repo-triggers"])
assert dir(args) == dir(reference_args)
def test_subparsers_repo_restore(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_restore(parser: argparse.ArgumentParser) -> None:
""" """
repo-restore command must imply architecture list, lock, report, repository and unsafe repo-restore command must imply architecture list, lock, report, repository and unsafe
@ -855,6 +956,15 @@ def test_subparsers_repo_status_update_option_status(parser: argparse.ArgumentPa
assert isinstance(args.status, BuildStatusEnum) assert isinstance(args.status, BuildStatusEnum)
def test_subparsers_repo_status_update_package_status_update(parser: argparse.ArgumentParser) -> None:
"""
repo-status-update must have same keys as package-status-update
"""
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "repo-status-update"])
reference_args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
assert dir(args) == dir(reference_args)
def test_subparsers_repo_sync(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_sync(parser: argparse.ArgumentParser) -> None:
""" """
repo-sync command must imply trigger repo-sync command must imply trigger
@ -883,6 +993,15 @@ def test_subparsers_repo_sync_option_repository(parser: argparse.ArgumentParser)
assert args.repository == "repo" assert args.repository == "repo"
def test_subparsers_repo_sync_repo_triggers(parser: argparse.ArgumentParser) -> None:
"""
repo-sync must have same keys as repo-triggers
"""
args = parser.parse_args(["repo-sync"])
reference_args = parser.parse_args(["repo-triggers"])
assert dir(args) == dir(reference_args)
def test_subparsers_repo_tree(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_tree(parser: argparse.ArgumentParser) -> None:
""" """
repo-tree command must imply lock, quiet, report and unsafe repo-tree command must imply lock, quiet, report and unsafe
@ -1203,11 +1322,12 @@ def test_subparsers_service_tree_migrate(parser: argparse.ArgumentParser) -> Non
def test_subparsers_user_add(parser: argparse.ArgumentParser) -> None: def test_subparsers_user_add(parser: argparse.ArgumentParser) -> None:
""" """
user-add command must imply action, architecture, lock, quiet, report and repository user-add command must imply action, architecture, exit code, lock, quiet, report and repository
""" """
args = parser.parse_args(["user-add", "username"]) args = parser.parse_args(["user-add", "username"])
assert args.action == Action.Update assert args.action == Action.Update
assert args.architecture == "" assert args.architecture == ""
assert not args.exit_code
assert args.lock is None assert args.lock is None
assert args.quiet assert args.quiet
assert not args.report assert not args.report
@ -1278,13 +1398,24 @@ def test_subparsers_user_list_option_role(parser: argparse.ArgumentParser) -> No
assert isinstance(args.role, UserAccess) assert isinstance(args.role, UserAccess)
def test_subparsers_user_list_user_add(parser: argparse.ArgumentParser) -> None:
"""
user-list must have same keys as user-add
"""
args = parser.parse_args(["user-list"])
reference_args = parser.parse_args(["user-add", "username"])
del reference_args.key, reference_args.packager, reference_args.password
assert dir(args) == dir(reference_args)
def test_subparsers_user_remove(parser: argparse.ArgumentParser) -> None: def test_subparsers_user_remove(parser: argparse.ArgumentParser) -> None:
""" """
user-remove command must imply action, architecture, lock, quiet, report and repository user-remove command must imply action, architecture, exit code, lock, quiet, report and repository
""" """
args = parser.parse_args(["user-remove", "username"]) args = parser.parse_args(["user-remove", "username"])
assert args.action == Action.Remove assert args.action == Action.Remove
assert args.architecture == "" assert args.architecture == ""
assert not args.exit_code
assert args.lock is None assert args.lock is None
assert args.quiet assert args.quiet
assert not args.report assert not args.report
@ -1307,6 +1438,16 @@ def test_subparsers_user_remove_option_repository(parser: argparse.ArgumentParse
assert args.repository == "" assert args.repository == ""
def test_subparsers_user_remove_user_add(parser: argparse.ArgumentParser) -> None:
"""
user-list must have same keys as user-add
"""
args = parser.parse_args(["user-remove", "username"])
reference_args = parser.parse_args(["user-add", "username"])
del reference_args.key, reference_args.packager, reference_args.password, reference_args.role
assert dir(args) == dir(reference_args)
def test_subparsers_web(parser: argparse.ArgumentParser) -> None: def test_subparsers_web(parser: argparse.ArgumentParser) -> None:
""" """
web command must imply architecture, report, repository and parser web command must imply architecture, report, repository and parser

View File

@ -16,6 +16,7 @@ from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite from ahriman.core.database import SQLite
from ahriman.core.spawn import Spawn from ahriman.core.spawn import Spawn
from ahriman.models.user import User from ahriman.models.user import User
from ahriman.web.keys import AuthKey
from ahriman.web.web import setup_server from ahriman.web.web import setup_server
@ -159,7 +160,7 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
_, repository_id = configuration.check_loaded() _, repository_id = configuration.check_loaded()
application = setup_server(configuration, spawner, [repository_id]) application = setup_server(configuration, spawner, [repository_id])
generated = user.hash_password(application["validator"].salt) generated = user.hash_password(application[AuthKey].salt)
mocker.patch("ahriman.core.database.SQLite.user_get", return_value=generated) mocker.patch("ahriman.core.database.SQLite.user_get", return_value=generated)
return application return application
@ -245,5 +246,5 @@ def client_with_oauth_auth(application_with_auth: Application, event_loop: BaseE
TestClient: web client test instance TestClient: web client test instance
""" """
mocker.patch("pathlib.Path.iterdir", return_value=[]) mocker.patch("pathlib.Path.iterdir", return_value=[])
application_with_auth["validator"] = MagicMock(spec=OAuth) application_with_auth[AuthKey] = MagicMock(spec=OAuth)
return event_loop.run_until_complete(aiohttp_client(application_with_auth)) return event_loop.run_until_complete(aiohttp_client(application_with_auth))

View File

@ -12,6 +12,7 @@ from ahriman.core.configuration import Configuration
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.user import User from ahriman.models.user import User
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.keys import AuthKey
from ahriman.web.middlewares.auth_handler import _AuthorizationPolicy, _auth_handler, _cookie_secret_key, setup_auth from ahriman.web.middlewares.auth_handler import _AuthorizationPolicy, _auth_handler, _cookie_secret_key, setup_auth
@ -192,5 +193,5 @@ def test_setup_auth(application_with_auth: Application, configuration: Configura
""" """
setup_mock = mocker.patch("aiohttp_security.setup") setup_mock = mocker.patch("aiohttp_security.setup")
application = setup_auth(application_with_auth, configuration, auth) application = setup_auth(application_with_auth, configuration, auth)
assert application.get("validator") is not None assert application.get(AuthKey) is not None
setup_mock.assert_called_once_with(application_with_auth, pytest.helpers.anyvar(int), pytest.helpers.anyvar(int)) setup_mock.assert_called_once_with(application_with_auth, pytest.helpers.anyvar(int), pytest.helpers.anyvar(int))

View File

@ -5,6 +5,7 @@ from pytest_mock import MockerFixture
from ahriman import __version__ from ahriman import __version__
from ahriman.web.apispec import _info, _security, _servers, setup_apispec from ahriman.web.apispec import _info, _security, _servers, setup_apispec
from ahriman.web.keys import ConfigurationKey
def test_info() -> None: def test_info() -> None:
@ -36,7 +37,7 @@ def test_servers_address(application: Application) -> None:
""" """
must generate servers definitions with address must generate servers definitions with address
""" """
application["configuration"].set_option("web", "address", "https://example.com") application[ConfigurationKey].set_option("web", "address", "https://example.com")
servers = _servers(application) servers = _servers(application)
assert servers == [{"url": "https://example.com"}] assert servers == [{"url": "https://example.com"}]

View File

View File

@ -10,6 +10,7 @@ from ahriman.core.exceptions import InitializeError
from ahriman.core.log.filtered_access_logger import FilteredAccessLogger from ahriman.core.log.filtered_access_logger import FilteredAccessLogger
from ahriman.core.spawn import Spawn from ahriman.core.spawn import Spawn
from ahriman.core.status.watcher import Watcher from ahriman.core.status.watcher import Watcher
from ahriman.web.keys import ConfigurationKey
from ahriman.web.web import _create_socket, _on_shutdown, _on_startup, run_server, setup_server from ahriman.web.web import _create_socket, _on_shutdown, _on_startup, run_server, setup_server
@ -18,14 +19,14 @@ async def test_create_socket(application: Application, mocker: MockerFixture) ->
must create socket must create socket
""" """
path = "/run/ahriman.sock" path = "/run/ahriman.sock"
application["configuration"].set_option("web", "unix_socket", str(path)) application[ConfigurationKey].set_option("web", "unix_socket", str(path))
current_on_shutdown = len(application.on_shutdown) current_on_shutdown = len(application.on_shutdown)
bind_mock = mocker.patch("socket.socket.bind") bind_mock = mocker.patch("socket.socket.bind")
chmod_mock = mocker.patch("pathlib.Path.chmod") chmod_mock = mocker.patch("pathlib.Path.chmod")
unlink_mock = mocker.patch("pathlib.Path.unlink") unlink_mock = mocker.patch("pathlib.Path.unlink")
sock = _create_socket(application["configuration"], application) sock = _create_socket(application[ConfigurationKey], application)
assert sock.family == socket.AF_UNIX assert sock.family == socket.AF_UNIX
assert sock.type == socket.SOCK_STREAM assert sock.type == socket.SOCK_STREAM
bind_mock.assert_called_once_with(str(path)) bind_mock.assert_called_once_with(str(path))
@ -41,7 +42,7 @@ def test_create_socket_empty(application: Application) -> None:
""" """
must skip socket creation if not set by configuration must skip socket creation if not set by configuration
""" """
assert _create_socket(application["configuration"], application) is None assert _create_socket(application[ConfigurationKey], application) is None
def test_create_socket_safe(application: Application, mocker: MockerFixture) -> None: def test_create_socket_safe(application: Application, mocker: MockerFixture) -> None:
@ -49,14 +50,14 @@ def test_create_socket_safe(application: Application, mocker: MockerFixture) ->
must create socket with default permission set must create socket with default permission set
""" """
path = "/run/ahriman.sock" path = "/run/ahriman.sock"
application["configuration"].set_option("web", "unix_socket", str(path)) application[ConfigurationKey].set_option("web", "unix_socket", str(path))
application["configuration"].set_option("web", "unix_socket_unsafe", "no") application[ConfigurationKey].set_option("web", "unix_socket_unsafe", "no")
mocker.patch("socket.socket.bind") mocker.patch("socket.socket.bind")
mocker.patch("pathlib.Path.unlink") mocker.patch("pathlib.Path.unlink")
chmod_mock = mocker.patch("pathlib.Path.chmod") chmod_mock = mocker.patch("pathlib.Path.chmod")
sock = _create_socket(application["configuration"], application) sock = _create_socket(application[ConfigurationKey], application)
assert sock is not None assert sock is not None
chmod_mock.assert_not_called() chmod_mock.assert_not_called()
@ -97,7 +98,7 @@ def test_run(application: Application, mocker: MockerFixture) -> None:
must run application must run application
""" """
port = 8080 port = 8080
application["configuration"].set_option("web", "port", str(port)) application[ConfigurationKey].set_option("web", "port", str(port))
run_application_mock = mocker.patch("ahriman.web.web.run_app") run_application_mock = mocker.patch("ahriman.web.web.run_app")
run_server(application) run_server(application)
@ -112,7 +113,7 @@ def test_run_with_auth(application_with_auth: Application, mocker: MockerFixture
must run application with enabled authorization must run application with enabled authorization
""" """
port = 8080 port = 8080
application_with_auth["configuration"].set_option("web", "port", str(port)) application_with_auth[ConfigurationKey].set_option("web", "port", str(port))
run_application_mock = mocker.patch("ahriman.web.web.run_app") run_application_mock = mocker.patch("ahriman.web.web.run_app")
run_server(application_with_auth) run_server(application_with_auth)
@ -127,12 +128,12 @@ def test_run_with_socket(application: Application, mocker: MockerFixture) -> Non
must run application must run application
""" """
port = 8080 port = 8080
application["configuration"].set_option("web", "port", str(port)) application[ConfigurationKey].set_option("web", "port", str(port))
socket_mock = mocker.patch("ahriman.web.web._create_socket", return_value=42) socket_mock = mocker.patch("ahriman.web.web._create_socket", return_value=42)
run_application_mock = mocker.patch("ahriman.web.web.run_app") run_application_mock = mocker.patch("ahriman.web.web.run_app")
run_server(application) run_server(application)
socket_mock.assert_called_once_with(application["configuration"], application) socket_mock.assert_called_once_with(application[ConfigurationKey], application)
run_application_mock.assert_called_once_with( run_application_mock.assert_called_once_with(
application, host="127.0.0.1", port=port, sock=42, handle_signals=True, application, host="127.0.0.1", port=port, sock=42, handle_signals=True,
access_log=pytest.helpers.anyvar(int), access_log_class=FilteredAccessLogger access_log=pytest.helpers.anyvar(int), access_log_class=FilteredAccessLogger

View File

@ -9,6 +9,7 @@ from unittest.mock import AsyncMock
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.keys import WatcherKey
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView
@ -172,9 +173,9 @@ def test_service(base: BaseView) -> None:
must return service for repository must return service for repository
""" """
repository_id = RepositoryId("i686", "repo") repository_id = RepositoryId("i686", "repo")
base.request.app["watcher"] = { base.request.app[WatcherKey] = {
repository_id: watcher repository_id: watcher
for watcher in base.request.app["watcher"].values() for watcher in base.request.app[WatcherKey].values()
} }
assert base.service(repository_id) == base.services[repository_id] assert base.service(repository_id) == base.services[repository_id]

View File

@ -5,6 +5,7 @@ from pytest_mock import MockerFixture
from ahriman.models.user import User from ahriman.models.user import User
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.keys import AuthKey
from ahriman.web.views.v1.user.login import LoginView from ahriman.web.views.v1.user.login import LoginView
@ -45,7 +46,7 @@ async def test_get_redirect_to_oauth(client_with_oauth_auth: TestClient) -> None
""" """
must redirect to OAuth service provider in case if no code is supplied must redirect to OAuth service provider in case if no code is supplied
""" """
oauth = client_with_oauth_auth.app["validator"] oauth = client_with_oauth_auth.app[AuthKey]
oauth.get_oauth_url.return_value = "http://localhost" oauth.get_oauth_url.return_value = "http://localhost"
request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring") request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring")
@ -60,7 +61,7 @@ async def test_get_redirect_to_oauth_empty_code(client_with_oauth_auth: TestClie
""" """
must redirect to OAuth service provider in case if empty code is supplied must redirect to OAuth service provider in case if empty code is supplied
""" """
oauth = client_with_oauth_auth.app["validator"] oauth = client_with_oauth_auth.app[AuthKey]
oauth.get_oauth_url.return_value = "http://localhost" oauth.get_oauth_url.return_value = "http://localhost"
request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring") request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring")
@ -75,7 +76,7 @@ async def test_get(client_with_oauth_auth: TestClient, mocker: MockerFixture) ->
""" """
must log in user correctly from OAuth must log in user correctly from OAuth
""" """
oauth = client_with_oauth_auth.app["validator"] oauth = client_with_oauth_auth.app[AuthKey]
oauth.get_oauth_username.return_value = "user" oauth.get_oauth_username.return_value = "user"
oauth.known_username.return_value = True oauth.known_username.return_value = True
oauth.enabled = False # lol oauth.enabled = False # lol
@ -98,7 +99,7 @@ async def test_get_unauthorized(client_with_oauth_auth: TestClient, mocker: Mock
""" """
must return unauthorized from OAuth must return unauthorized from OAuth
""" """
oauth = client_with_oauth_auth.app["validator"] oauth = client_with_oauth_auth.app[AuthKey]
oauth.known_username.return_value = False oauth.known_username.return_value = False
oauth.max_age = 60 oauth.max_age = 60
remember_mock = mocker.patch("aiohttp_security.remember") remember_mock = mocker.patch("aiohttp_security.remember")