mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-06-11 14:54:34 -04:00
Adds a new env var to disable local auth entirely when using OIDC authentication Fixes #922 #834
200 lines
7.0 KiB
Python
200 lines
7.0 KiB
Python
"""Tests for auth mode and admin policy helpers used by OIDC integration."""
|
|
|
|
import sqlite3
|
|
|
|
import pytest
|
|
|
|
from shelfmark.core.auth_modes import (
|
|
determine_auth_mode,
|
|
get_auth_check_admin_status,
|
|
get_settings_tab_from_path,
|
|
is_settings_or_onboarding_path,
|
|
load_active_auth_mode,
|
|
requires_admin_for_settings_access,
|
|
should_restrict_settings_to_admin,
|
|
)
|
|
|
|
|
|
class TestDetermineAuthMode:
|
|
def test_returns_oidc_when_fully_configured(self):
|
|
config = {
|
|
"AUTH_METHOD": "oidc",
|
|
"OIDC_DISCOVERY_URL": "https://auth.example.com/.well-known/openid-configuration",
|
|
"OIDC_CLIENT_ID": "shelfmark",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None) == "oidc"
|
|
|
|
def test_returns_none_when_oidc_missing_client_id(self):
|
|
config = {
|
|
"AUTH_METHOD": "oidc",
|
|
"OIDC_DISCOVERY_URL": "https://auth.example.com/.well-known/openid-configuration",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None) == "none"
|
|
|
|
def test_returns_none_when_oidc_missing_discovery_url(self):
|
|
config = {
|
|
"AUTH_METHOD": "oidc",
|
|
"OIDC_CLIENT_ID": "shelfmark",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None) == "none"
|
|
|
|
def test_builtin_still_works(self):
|
|
config = {
|
|
"AUTH_METHOD": "builtin",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None) == "builtin"
|
|
|
|
def test_builtin_requires_local_admin(self):
|
|
config = {
|
|
"AUTH_METHOD": "builtin",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None, has_local_admin=False) == "none"
|
|
|
|
def test_proxy_still_works(self):
|
|
config = {
|
|
"AUTH_METHOD": "proxy",
|
|
"PROXY_AUTH_USER_HEADER": "X-Auth-User",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None) == "proxy"
|
|
|
|
def test_oidc_requires_local_admin(self):
|
|
config = {
|
|
"AUTH_METHOD": "oidc",
|
|
"OIDC_DISCOVERY_URL": "https://auth.example.com/.well-known/openid-configuration",
|
|
"OIDC_CLIENT_ID": "shelfmark",
|
|
}
|
|
assert determine_auth_mode(config, cwa_db_path=None, has_local_admin=False) == "none"
|
|
|
|
@pytest.mark.parametrize(
|
|
("auth_mode", "config"),
|
|
[
|
|
("builtin", {"AUTH_METHOD": "builtin"}),
|
|
(
|
|
"oidc",
|
|
{
|
|
"AUTH_METHOD": "oidc",
|
|
"OIDC_DISCOVERY_URL": "https://auth.example.com/.well-known/openid-configuration",
|
|
"OIDC_CLIENT_ID": "shelfmark",
|
|
},
|
|
),
|
|
],
|
|
)
|
|
def test_disable_local_auth_keeps_configured_mode_without_admin(self, auth_mode, config):
|
|
assert (
|
|
determine_auth_mode(
|
|
config,
|
|
cwa_db_path=None,
|
|
has_local_admin=False,
|
|
disable_local_auth=True,
|
|
)
|
|
== auth_mode
|
|
)
|
|
|
|
def test_load_active_auth_mode_reads_env_backed_cwa_setting(self, monkeypatch, tmp_path):
|
|
from shelfmark.core.config import config as app_config
|
|
|
|
monkeypatch.setenv("CONFIG_DIR", str(tmp_path))
|
|
monkeypatch.setenv("AUTH_METHOD", "cwa")
|
|
app_config.refresh(force=True)
|
|
|
|
cwa_db_path = tmp_path / "app.db"
|
|
conn = sqlite3.connect(cwa_db_path)
|
|
conn.execute("create table user (name text)")
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
try:
|
|
assert load_active_auth_mode(cwa_db_path) == "cwa"
|
|
finally:
|
|
monkeypatch.delenv("AUTH_METHOD", raising=False)
|
|
app_config.refresh(force=True)
|
|
|
|
def test_load_active_auth_mode_reads_env_backed_proxy_setting(self, monkeypatch, tmp_path):
|
|
from shelfmark.core.config import config as app_config
|
|
|
|
monkeypatch.setenv("CONFIG_DIR", str(tmp_path))
|
|
monkeypatch.setenv("AUTH_METHOD", "proxy")
|
|
monkeypatch.setenv("PROXY_AUTH_USER_HEADER", "X-Forwarded-User")
|
|
app_config.refresh(force=True)
|
|
|
|
try:
|
|
assert load_active_auth_mode(cwa_db_path=None) == "proxy"
|
|
finally:
|
|
monkeypatch.delenv("AUTH_METHOD", raising=False)
|
|
monkeypatch.delenv("PROXY_AUTH_USER_HEADER", raising=False)
|
|
app_config.refresh(force=True)
|
|
|
|
|
|
class TestSettingsRestrictionPolicy:
|
|
def test_settings_path_detection(self):
|
|
assert is_settings_or_onboarding_path("/api/settings/downloads")
|
|
assert is_settings_or_onboarding_path("/api/onboarding")
|
|
assert not is_settings_or_onboarding_path("/api/releases")
|
|
|
|
def test_default_is_admin_restricted(self):
|
|
assert should_restrict_settings_to_admin({}) is True
|
|
|
|
def test_restriction_is_always_enabled(self):
|
|
assert should_restrict_settings_to_admin({"RESTRICT_SETTINGS_TO_ADMIN": True}) is True
|
|
assert should_restrict_settings_to_admin({"RESTRICT_SETTINGS_TO_ADMIN": False}) is True
|
|
|
|
def test_extracts_settings_tab_from_path(self):
|
|
assert get_settings_tab_from_path("/api/settings/security") == "security"
|
|
assert get_settings_tab_from_path("/api/settings/users/action/open_users_tab") == "users"
|
|
assert get_settings_tab_from_path("/api/settings") is None
|
|
|
|
def test_security_and_users_tabs_always_require_admin(self):
|
|
users_config = {"RESTRICT_SETTINGS_TO_ADMIN": False}
|
|
assert requires_admin_for_settings_access("/api/settings/security", users_config) is True
|
|
assert requires_admin_for_settings_access("/api/settings/users", users_config) is True
|
|
|
|
def test_other_tabs_also_require_admin(self):
|
|
assert (
|
|
requires_admin_for_settings_access(
|
|
"/api/settings/general",
|
|
{"RESTRICT_SETTINGS_TO_ADMIN": False},
|
|
)
|
|
is True
|
|
)
|
|
assert (
|
|
requires_admin_for_settings_access(
|
|
"/api/settings/general",
|
|
{"RESTRICT_SETTINGS_TO_ADMIN": True},
|
|
)
|
|
is True
|
|
)
|
|
|
|
|
|
class TestAuthCheckAdminStatus:
|
|
def test_authenticated_admin_when_restricted(self):
|
|
result = get_auth_check_admin_status(
|
|
"oidc",
|
|
{"RESTRICT_SETTINGS_TO_ADMIN": True},
|
|
{"user_id": "admin", "is_admin": True},
|
|
)
|
|
assert result is True
|
|
|
|
def test_authenticated_non_admin_when_restricted(self):
|
|
result = get_auth_check_admin_status(
|
|
"oidc",
|
|
{"RESTRICT_SETTINGS_TO_ADMIN": True},
|
|
{"user_id": "user", "is_admin": False},
|
|
)
|
|
assert result is False
|
|
|
|
def test_authenticated_non_admin_user_is_not_admin(self):
|
|
result = get_auth_check_admin_status(
|
|
"proxy",
|
|
{"RESTRICT_SETTINGS_TO_ADMIN": False},
|
|
{"user_id": "user", "is_admin": False},
|
|
)
|
|
assert result is False
|
|
|
|
def test_unauthenticated_is_never_admin(self):
|
|
result = get_auth_check_admin_status(
|
|
"builtin",
|
|
{"RESTRICT_SETTINGS_TO_ADMIN": False},
|
|
{"is_admin": True},
|
|
)
|
|
assert result is False
|