mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-10-06 07:54:38 +01:00
Patch: Multi-user and OIDC polish (#612)
- Moved backend OIDC functionality to external library Authlib to help maintainability - Separated User settings UI into individual components, allowing for standard settings UI decorator components to be used. - Added full support for reverse proxy and CWA users alongside local and OIDC - Added mapping and syncing functionality for OIDC, CWA and reverse proxy users - Added per-user settings into the app-wide config system. Each config can be declared as user-overrideable, and app-wide functionality can now receive user-specific options via standard config calls. - Added per-user audiobook destination config - Updated login modal UI for simplified login, plus custom labels for OIDC login - Added user visibility in header dropdown - Unified "restrict settings to admin" to use app-wide user roles.
This commit is contained in:
@@ -4,7 +4,7 @@ from shelfmark.download.outputs.booklore import build_booklore_config
|
||||
|
||||
|
||||
class TestBuildBookloreConfigWithOverrides:
|
||||
"""build_booklore_config should accept per-user library/path overrides."""
|
||||
"""build_booklore_config should resolve per-user library/path via config."""
|
||||
|
||||
BASE_SETTINGS = {
|
||||
"BOOKLORE_HOST": "http://booklore:6060",
|
||||
@@ -14,77 +14,62 @@ class TestBuildBookloreConfigWithOverrides:
|
||||
"BOOKLORE_PATH_ID": 10,
|
||||
}
|
||||
|
||||
def test_global_config_no_overrides(self):
|
||||
def test_global_config_without_user_context(self):
|
||||
config = build_booklore_config(self.BASE_SETTINGS)
|
||||
assert config.library_id == 1
|
||||
assert config.path_id == 10
|
||||
|
||||
def test_override_library_and_path(self):
|
||||
overrides = {"booklore_library_id": 2, "booklore_path_id": 20}
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_overrides=overrides)
|
||||
def test_override_library_and_path_with_user_context(self, monkeypatch):
|
||||
def fake_get(key, default=None, user_id=None):
|
||||
if user_id == 7 and key == "BOOKLORE_LIBRARY_ID":
|
||||
return 2
|
||||
if user_id == 7 and key == "BOOKLORE_PATH_ID":
|
||||
return 20
|
||||
return default
|
||||
|
||||
monkeypatch.setattr("shelfmark.download.outputs.booklore.core_config.config.get", fake_get)
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_id=7)
|
||||
assert config.library_id == 2
|
||||
assert config.path_id == 20
|
||||
|
||||
def test_override_library_only(self):
|
||||
overrides = {"booklore_library_id": 3}
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_overrides=overrides)
|
||||
def test_override_library_only(self, monkeypatch):
|
||||
def fake_get(key, default=None, user_id=None):
|
||||
if user_id == 7 and key == "BOOKLORE_LIBRARY_ID":
|
||||
return 3
|
||||
return default
|
||||
|
||||
monkeypatch.setattr("shelfmark.download.outputs.booklore.core_config.config.get", fake_get)
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_id=7)
|
||||
assert config.library_id == 3
|
||||
assert config.path_id == 10 # falls back to global
|
||||
|
||||
def test_override_path_only(self):
|
||||
overrides = {"booklore_path_id": 30}
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_overrides=overrides)
|
||||
def test_override_path_only(self, monkeypatch):
|
||||
def fake_get(key, default=None, user_id=None):
|
||||
if user_id == 7 and key == "BOOKLORE_PATH_ID":
|
||||
return 30
|
||||
return default
|
||||
|
||||
monkeypatch.setattr("shelfmark.download.outputs.booklore.core_config.config.get", fake_get)
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_id=7)
|
||||
assert config.library_id == 1 # falls back to global
|
||||
assert config.path_id == 30
|
||||
|
||||
def test_empty_overrides_uses_global(self):
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_overrides={})
|
||||
def test_none_user_context_uses_global(self):
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_id=None)
|
||||
assert config.library_id == 1
|
||||
assert config.path_id == 10
|
||||
|
||||
def test_none_overrides_uses_global(self):
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_overrides=None)
|
||||
assert config.library_id == 1
|
||||
assert config.path_id == 10
|
||||
def test_auth_fields_remain_global(self, monkeypatch):
|
||||
"""Only Booklore library/path should be resolved with user context."""
|
||||
def fake_get(key, default=None, user_id=None):
|
||||
if user_id == 7 and key == "BOOKLORE_LIBRARY_ID":
|
||||
return 5
|
||||
if user_id == 7 and key == "BOOKLORE_PATH_ID":
|
||||
return 15
|
||||
return default
|
||||
|
||||
def test_auth_fields_not_overridable(self):
|
||||
"""Auth stays global - user overrides should not affect host/user/pass."""
|
||||
overrides = {
|
||||
"booklore_library_id": 5,
|
||||
"BOOKLORE_HOST": "http://evil:6060",
|
||||
"BOOKLORE_USERNAME": "hacker",
|
||||
}
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_overrides=overrides)
|
||||
monkeypatch.setattr("shelfmark.download.outputs.booklore.core_config.config.get", fake_get)
|
||||
config = build_booklore_config(self.BASE_SETTINGS, user_id=7)
|
||||
assert config.base_url == "http://booklore:6060"
|
||||
assert config.username == "admin"
|
||||
assert config.library_id == 5
|
||||
|
||||
|
||||
class TestOutputArgsForBooklore:
|
||||
"""Download tasks should carry per-user booklore settings in output_args."""
|
||||
|
||||
def test_output_args_with_booklore_settings(self):
|
||||
from shelfmark.core.models import DownloadTask
|
||||
|
||||
task = DownloadTask(
|
||||
task_id="test-1",
|
||||
source="direct_download",
|
||||
title="Book1",
|
||||
output_mode="booklore",
|
||||
output_args={"booklore_library_id": 2, "booklore_path_id": 20},
|
||||
user_id=1,
|
||||
)
|
||||
assert task.output_args["booklore_library_id"] == 2
|
||||
assert task.output_args["booklore_path_id"] == 20
|
||||
|
||||
def test_output_args_empty_for_global_booklore(self):
|
||||
from shelfmark.core.models import DownloadTask
|
||||
|
||||
task = DownloadTask(
|
||||
task_id="test-2",
|
||||
source="direct_download",
|
||||
title="Book1",
|
||||
output_mode="booklore",
|
||||
output_args={},
|
||||
)
|
||||
assert task.output_args == {}
|
||||
|
||||
Reference in New Issue
Block a user