port part of settings to database (#54)

This commit is contained in:
2022-03-31 01:48:06 +03:00
committed by GitHub
parent fb02e676af
commit 28cc38aaa5
117 changed files with 2768 additions and 1044 deletions

View File

@ -8,6 +8,7 @@ from typing import Any
import ahriman.core.auth.helpers
from ahriman.core.configuration import Configuration
from ahriman.core.database.sqlite import SQLite
from ahriman.core.spawn import Spawn
from ahriman.models.user import User
from ahriman.web.web import setup_service
@ -31,53 +32,60 @@ def request(app: web.Application, path: str, method: str, json: Any = None, data
@pytest.fixture
def application(configuration: Configuration, spawner: Spawn, mocker: MockerFixture) -> web.Application:
def application(configuration: Configuration, spawner: Spawn, database: SQLite,
mocker: MockerFixture) -> web.Application:
"""
application fixture
:param configuration: configuration fixture
:param spawner: spawner fixture
:param database: database fixture
:param mocker: mocker object
:return: application test instance
"""
mocker.patch("ahriman.core.database.sqlite.SQLite.load", return_value=database)
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner)
@pytest.fixture
def application_with_auth(configuration: Configuration, user: User, spawner: Spawn,
def application_with_auth(configuration: Configuration, user: User, spawner: Spawn, database: SQLite,
mocker: MockerFixture) -> web.Application:
"""
application fixture with auth enabled
:param configuration: configuration fixture
:param user: user descriptor fixture
:param spawner: spawner fixture
:param database: database fixture
:param mocker: mocker object
:return: application test instance
"""
configuration.set_option("auth", "target", "configuration")
mocker.patch("ahriman.core.database.sqlite.SQLite.load", return_value=database)
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", True)
application = setup_service("x86_64", configuration, spawner)
generated = User(user.username, user.hash_password(application["validator"].salt), user.access)
application["validator"]._users[generated.username] = generated
generated = user.hash_password(application["validator"].salt)
mocker.patch("ahriman.core.database.sqlite.SQLite.user_get", return_value=generated)
return application
@pytest.fixture
def application_with_debug(configuration: Configuration, user: User, spawner: Spawn,
def application_with_debug(configuration: Configuration, user: User, spawner: Spawn, database: SQLite,
mocker: MockerFixture) -> web.Application:
"""
application fixture with debug enabled
:param configuration: configuration fixture
:param user: user descriptor fixture
:param spawner: spawner fixture
:param database: database fixture
:param mocker: mocker object
:return: application test instance
"""
configuration.set_option("web", "debug", "yes")
mocker.patch("ahriman.core.database.sqlite.SQLite.load", return_value=database)
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner)

View File

@ -2,18 +2,18 @@ import pytest
from ahriman.core.auth.auth import Auth
from ahriman.core.configuration import Configuration
from ahriman.core.database.sqlite import SQLite
from ahriman.models.user import User
from ahriman.web.middlewares.auth_handler import AuthorizationPolicy
@pytest.fixture
def authorization_policy(configuration: Configuration, user: User) -> AuthorizationPolicy:
def authorization_policy(configuration: Configuration, database: SQLite, user: User) -> AuthorizationPolicy:
"""
fixture for authorization policy
:return: authorization policy fixture
"""
configuration.set_option("auth", "target", "configuration")
validator = Auth.load(configuration)
validator = Auth.load(configuration, database)
policy = AuthorizationPolicy(validator)
policy.validator._users = {user.username: user}
return policy

View File

@ -20,11 +20,18 @@ def _identity(username: str) -> str:
return f"{username} {UserIdentity.expire_when(60)}"
async def test_authorized_userid(authorization_policy: AuthorizationPolicy, user: User) -> None:
async def test_authorized_userid(authorization_policy: AuthorizationPolicy, user: User, mocker: MockerFixture) -> None:
"""
must return authorized user id
"""
mocker.patch("ahriman.core.database.sqlite.SQLite.user_get", return_value=user)
assert await authorization_policy.authorized_userid(_identity(user.username)) == user.username
async def test_authorized_userid_unknown(authorization_policy: AuthorizationPolicy, user: User) -> None:
"""
must not allow unknown user id for authorization
"""
assert await authorization_policy.authorized_userid(_identity("somerandomname")) is None
assert await authorization_policy.authorized_userid("somerandomname") is None

View File

@ -2,11 +2,12 @@ import pytest
from aiohttp import web
from asyncio import BaseEventLoop
from aiohttp.test_utils import TestClient
from pytest_mock import MockerFixture
from typing import Any
from unittest.mock import MagicMock
from ahriman.core.auth.oauth import OAuth
from ahriman.web.views.base import BaseView
@ -21,30 +22,46 @@ def base(application: web.Application) -> BaseView:
@pytest.fixture
def client(application: web.Application, loop: BaseEventLoop,
def client(application: web.Application, event_loop: BaseEventLoop,
aiohttp_client: Any, mocker: MockerFixture) -> TestClient:
"""
web client fixture
:param application: application fixture
:param loop: context event loop
:param event_loop: context event loop
:param aiohttp_client: aiohttp client fixture
:param mocker: mocker object
:return: web client test instance
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
return loop.run_until_complete(aiohttp_client(application))
return event_loop.run_until_complete(aiohttp_client(application))
@pytest.fixture
def client_with_auth(application_with_auth: web.Application, loop: BaseEventLoop,
def client_with_auth(application_with_auth: web.Application, event_loop: BaseEventLoop,
aiohttp_client: Any, mocker: MockerFixture) -> TestClient:
"""
web client fixture with full authorization functions
:param application_with_auth: application fixture
:param loop: context event loop
:param event_loop: context event loop
:param aiohttp_client: aiohttp client fixture
:param mocker: mocker object
:return: web client test instance
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
return loop.run_until_complete(aiohttp_client(application_with_auth))
return event_loop.run_until_complete(aiohttp_client(application_with_auth))
@pytest.fixture
def client_with_oauth_auth(application_with_auth: web.Application, event_loop: BaseEventLoop,
aiohttp_client: Any, mocker: MockerFixture) -> TestClient:
"""
web client fixture with full authorization functions
:param application_with_auth: application fixture
:param event_loop: context event loop
:param aiohttp_client: aiohttp client fixture
:param mocker: mocker object
:return: web client test instance
"""
mocker.patch("pathlib.Path.iterdir", return_value=[])
application_with_auth["validator"] = MagicMock(spec=OAuth)
return event_loop.run_until_complete(aiohttp_client(application_with_auth))

View File

@ -1,41 +0,0 @@
import pytest
from aiohttp.test_utils import TestClient
from pytest_mock import MockerFixture
from ahriman.models.user_access import UserAccess
from ahriman.web.views.service.reload_auth import ReloadAuthView
async def test_get_permission() -> None:
"""
must return correct permission for the request
"""
for method in ("POST",):
request = pytest.helpers.request("", "", method)
assert await ReloadAuthView.get_permission(request) == UserAccess.Write
async def test_post(client_with_auth: TestClient, mocker: MockerFixture) -> None:
"""
must call post request correctly
"""
mocker.patch("aiohttp_security.check_permission", return_value=True)
reload_mock = mocker.patch("ahriman.core.configuration.Configuration.reload")
load_mock = mocker.patch("ahriman.core.auth.auth.Auth.load")
response = await client_with_auth.post("/service-api/v1/reload-auth")
assert response.ok
reload_mock.assert_called_once_with()
load_mock.assert_called_once_with(client_with_auth.app["configuration"])
async def test_post_no_auth(client: TestClient, mocker: MockerFixture) -> None:
"""
must call return 500 if no authorization module loaded
"""
reload_mock = mocker.patch("ahriman.core.configuration.Configuration.reload")
response = await client.post("/service-api/v1/reload-auth")
assert response.status == 500
reload_mock.assert_called_once_with()

View File

@ -12,6 +12,13 @@ def test_configuration(base: BaseView) -> None:
assert base.configuration
def test_database(base: BaseView) -> None:
"""
must return database
"""
assert base.database
def test_service(base: BaseView) -> None:
"""
must return service

View File

@ -52,7 +52,7 @@ async def test_get_static(client: TestClient) -> None:
async def test_get_static_with_auth(client_with_auth: TestClient) -> None:
"""
must return static files
must return static files with authorization enabled
"""
response = await client_with_auth.get("/static/favicon.ico")
assert response.ok

View File

@ -27,42 +27,42 @@ async def test_get_default_validator(client_with_auth: TestClient) -> None:
assert get_response.status == 405
async def test_get_redirect_to_oauth(client_with_auth: TestClient) -> None:
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
"""
oauth = client_with_auth.app["validator"] = MagicMock(spec=OAuth)
oauth = client_with_oauth_auth.app["validator"]
oauth.get_oauth_url.return_value = "https://httpbin.org"
get_response = await client_with_auth.get("/user-api/v1/login")
get_response = await client_with_oauth_auth.get("/user-api/v1/login")
assert get_response.ok
oauth.get_oauth_url.assert_called_once_with()
async def test_get_redirect_to_oauth_empty_code(client_with_auth: TestClient) -> None:
async def test_get_redirect_to_oauth_empty_code(client_with_oauth_auth: TestClient) -> None:
"""
must redirect to OAuth service provider in case if empty code is supplied
"""
oauth = client_with_auth.app["validator"] = MagicMock(spec=OAuth)
oauth = client_with_oauth_auth.app["validator"]
oauth.get_oauth_url.return_value = "https://httpbin.org"
get_response = await client_with_auth.get("/user-api/v1/login", params={"code": ""})
get_response = await client_with_oauth_auth.get("/user-api/v1/login", params={"code": ""})
assert get_response.ok
oauth.get_oauth_url.assert_called_once_with()
async def test_get(client_with_auth: TestClient, mocker: MockerFixture) -> None:
async def test_get(client_with_oauth_auth: TestClient, mocker: MockerFixture) -> None:
"""
must login user correctly from OAuth
"""
oauth = client_with_auth.app["validator"] = MagicMock(spec=OAuth)
oauth = client_with_oauth_auth.app["validator"]
oauth.get_oauth_username.return_value = "user"
oauth.known_username.return_value = True
oauth.enabled = False # lol
oauth.max_age = 60
remember_mock = mocker.patch("aiohttp_security.remember")
get_response = await client_with_auth.get("/user-api/v1/login", params={"code": "code"})
get_response = await client_with_oauth_auth.get("/user-api/v1/login", params={"code": "code"})
assert get_response.ok
oauth.get_oauth_username.assert_called_once_with("code")
@ -71,16 +71,16 @@ async def test_get(client_with_auth: TestClient, mocker: MockerFixture) -> None:
pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), pytest.helpers.anyvar(int))
async def test_get_unauthorized(client_with_auth: TestClient, mocker: MockerFixture) -> None:
async def test_get_unauthorized(client_with_oauth_auth: TestClient, mocker: MockerFixture) -> None:
"""
must return unauthorized from OAuth
"""
oauth = client_with_auth.app["validator"] = MagicMock(spec=OAuth)
oauth = client_with_oauth_auth.app["validator"]
oauth.known_username.return_value = False
oauth.max_age = 60
remember_mock = mocker.patch("aiohttp_security.remember")
get_response = await client_with_auth.get("/user-api/v1/login", params={"code": "code"})
get_response = await client_with_oauth_auth.get("/user-api/v1/login", params={"code": "code"})
assert get_response.status == 401
remember_mock.assert_not_called()