mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
add settings object for auth provider
This commit is contained in:
parent
cb5756ea76
commit
5e24d81415
@ -22,9 +22,9 @@ libalpm and AUR related configuration.
|
||||
|
||||
Base authorization settings.
|
||||
|
||||
* `target` - specifies authorization provider, string, optional, default `disabled`. Allowed values are `disabled`, `configuration`.
|
||||
* `allowed_paths` - URI paths (exact match) which can be accessed without authorization, space separated list of strings, optional.
|
||||
* `allowed_paths_groups` - URI paths prefixes which can be accessed without authorization, space separated list of strings, optional.
|
||||
* `enabled` - enables web services authorization, boolean, optional, default `no`.
|
||||
* `salt` - password hash salt, string, required in case if authorization enabled (automatically generated by `create-user` subcommand).
|
||||
|
||||
## `auth:*` groups
|
||||
|
@ -9,7 +9,7 @@ repositories = core extra community multilib
|
||||
root = /
|
||||
|
||||
[auth]
|
||||
enabled = no
|
||||
target = disabled
|
||||
|
||||
[build]
|
||||
archbuild_flags =
|
||||
|
@ -22,6 +22,7 @@ from __future__ import annotations
|
||||
from typing import Optional, Set, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.auth_settings import AuthSettings
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
@ -38,16 +39,17 @@ class Auth:
|
||||
ALLOWED_PATHS = {"/", "/favicon.ico", "/index.html", "/login", "/logout"}
|
||||
ALLOWED_PATHS_GROUPS: Set[str] = set()
|
||||
|
||||
def __init__(self, configuration: Configuration) -> None:
|
||||
def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Disabled) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param configuration: configuration instance
|
||||
:param provider: authorization type definition
|
||||
"""
|
||||
self.allowed_paths = set(configuration.getlist("auth", "allowed_paths"))
|
||||
self.allowed_paths.update(self.ALLOWED_PATHS)
|
||||
self.allowed_paths_groups = set(configuration.getlist("auth", "allowed_paths_groups"))
|
||||
self.allowed_paths_groups.update(self.ALLOWED_PATHS_GROUPS)
|
||||
self.enabled = configuration.getboolean("auth", "enabled", fallback=False)
|
||||
self.enabled = provider.is_enabled
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Auth], configuration: Configuration) -> Auth:
|
||||
@ -56,7 +58,8 @@ class Auth:
|
||||
:param configuration: configuration instance
|
||||
:return: authorization module according to current settings
|
||||
"""
|
||||
if configuration.getboolean("auth", "enabled", fallback=False):
|
||||
provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled"))
|
||||
if provider == AuthSettings.Configuration:
|
||||
from ahriman.core.auth.mapping_auth import MappingAuth
|
||||
return MappingAuth(configuration)
|
||||
return cls(configuration)
|
||||
|
@ -22,6 +22,7 @@ from typing import Dict, Optional
|
||||
from ahriman.core.auth.auth import Auth
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import DuplicateUser
|
||||
from ahriman.models.auth_settings import AuthSettings
|
||||
from ahriman.models.user import User
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
@ -33,12 +34,13 @@ class MappingAuth(Auth):
|
||||
:ivar _users: map of username to its descriptor
|
||||
"""
|
||||
|
||||
def __init__(self, configuration: Configuration) -> None:
|
||||
def __init__(self, configuration: Configuration, provider: AuthSettings = AuthSettings.Configuration) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param configuration: configuration instance
|
||||
:param provider: authorization type definition
|
||||
"""
|
||||
Auth.__init__(self, configuration)
|
||||
Auth.__init__(self, configuration, provider)
|
||||
self.salt = configuration.get("auth", "salt")
|
||||
self._users = self.get_users(configuration)
|
||||
|
||||
|
58
src/ahriman/models/auth_settings.py
Normal file
58
src/ahriman/models/auth_settings.py
Normal file
@ -0,0 +1,58 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum, auto
|
||||
from typing import Type
|
||||
|
||||
from ahriman.core.exceptions import InvalidOption
|
||||
|
||||
|
||||
class AuthSettings(Enum):
|
||||
"""
|
||||
web authorization type
|
||||
:cvar Disabled: authorization is disabled
|
||||
:cvar Configuration: configuration based authorization
|
||||
"""
|
||||
|
||||
Disabled = auto()
|
||||
Configuration = auto()
|
||||
|
||||
@classmethod
|
||||
def from_option(cls: Type[AuthSettings], value: str) -> AuthSettings:
|
||||
"""
|
||||
construct value from configuration
|
||||
:param value: configuration value
|
||||
:return: parsed value
|
||||
"""
|
||||
if value.lower() in ("disabled", "no"):
|
||||
return cls.Disabled
|
||||
if value.lower() in ("configuration", "mapping"):
|
||||
return cls.Configuration
|
||||
raise InvalidOption(value)
|
||||
|
||||
@property
|
||||
def is_enabled(self) -> bool:
|
||||
"""
|
||||
:return: False in case if authorization is disabled and True otherwise
|
||||
"""
|
||||
if self == AuthSettings.Disabled:
|
||||
return False
|
||||
return True
|
@ -10,5 +10,4 @@ def mapping_auth(configuration: Configuration) -> MappingAuth:
|
||||
auth provider fixture
|
||||
:return: auth service instance
|
||||
"""
|
||||
configuration.set_option("auth", "enabled", "yes")
|
||||
return MappingAuth(configuration)
|
||||
|
@ -9,7 +9,7 @@ def test_load_dummy(configuration: Configuration) -> None:
|
||||
"""
|
||||
must load dummy validator if authorization is not enabled
|
||||
"""
|
||||
configuration.set_option("auth", "enabled", "no")
|
||||
configuration.set_option("auth", "target", "disabled")
|
||||
auth = Auth.load(configuration)
|
||||
assert isinstance(auth, Auth)
|
||||
|
||||
@ -26,7 +26,7 @@ def test_load_mapping(configuration: Configuration) -> None:
|
||||
"""
|
||||
must load mapping validator if option set
|
||||
"""
|
||||
configuration.set_option("auth", "enabled", "yes")
|
||||
configuration.set_option("auth", "target", "configuration")
|
||||
auth = Auth.load(configuration)
|
||||
assert isinstance(auth, MappingAuth)
|
||||
|
||||
|
36
tests/ahriman/models/test_auth_settings.py
Normal file
36
tests/ahriman/models/test_auth_settings.py
Normal file
@ -0,0 +1,36 @@
|
||||
import pytest
|
||||
|
||||
from ahriman.core.exceptions import InvalidOption
|
||||
from ahriman.models.auth_settings import AuthSettings
|
||||
|
||||
|
||||
def test_from_option_invalid() -> None:
|
||||
"""
|
||||
must raise exception on invalid option
|
||||
"""
|
||||
with pytest.raises(InvalidOption, match=".* `invalid`$"):
|
||||
AuthSettings.from_option("invalid")
|
||||
|
||||
|
||||
def test_from_option_valid() -> None:
|
||||
"""
|
||||
must return value from valid options
|
||||
"""
|
||||
assert AuthSettings.from_option("disabled") == AuthSettings.Disabled
|
||||
assert AuthSettings.from_option("DISABLED") == AuthSettings.Disabled
|
||||
assert AuthSettings.from_option("no") == AuthSettings.Disabled
|
||||
assert AuthSettings.from_option("NO") == AuthSettings.Disabled
|
||||
|
||||
assert AuthSettings.from_option("configuration") == AuthSettings.Configuration
|
||||
assert AuthSettings.from_option("ConFigUration") == AuthSettings.Configuration
|
||||
assert AuthSettings.from_option("mapping") == AuthSettings.Configuration
|
||||
assert AuthSettings.from_option("MAPPing") == AuthSettings.Configuration
|
||||
|
||||
|
||||
def test_is_enabled() -> None:
|
||||
"""
|
||||
must mark as disabled authorization for disabled and enabled otherwise
|
||||
"""
|
||||
assert not AuthSettings.Disabled.is_enabled
|
||||
for option in filter(lambda o: o != AuthSettings.Disabled, AuthSettings):
|
||||
assert option.is_enabled
|
@ -32,7 +32,7 @@ def application_with_auth(configuration: Configuration, user: User, mocker: Mock
|
||||
:param mocker: mocker object
|
||||
:return: application test instance
|
||||
"""
|
||||
configuration.set_option("auth", "enabled", "yes")
|
||||
configuration.set_option("auth", "target", "configuration")
|
||||
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", True)
|
||||
mocker.patch("pathlib.Path.mkdir")
|
||||
application = setup_service("x86_64", configuration)
|
||||
|
@ -25,7 +25,7 @@ def authorization_policy(configuration: Configuration, user: User) -> Authorizat
|
||||
fixture for authorization policy
|
||||
:return: authorization policy fixture
|
||||
"""
|
||||
configuration.set_option("auth", "enabled", "yes")
|
||||
configuration.set_option("auth", "target", "configuration")
|
||||
validator = Auth.load(configuration)
|
||||
policy = AuthorizationPolicy(validator)
|
||||
policy.validator._users = {user.username: user}
|
||||
|
Loading…
Reference in New Issue
Block a user