동의 게이트와 런타임 안정화

This commit is contained in:
Yun Chan 2026-06-27 17:22:38 +09:00
parent 0eb7d925ed
commit 0ec266a761
34 changed files with 1186 additions and 158 deletions

View file

@ -12,7 +12,9 @@ from fastapi import Response
from starlette.requests import Request
from unittest.mock import AsyncMock, patch
from . import auth_sessions
from .config import Settings, settings
from .deps import Principal, Role
from .routes import auth as auth_routes
from .saml import inflate_redirect_request
@ -94,10 +96,18 @@ class AuthProviderScaffoldTest(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self) -> None:
auth_routes._oauth_states.clear()
auth_routes._saml_states.clear()
auth_sessions._sessions.clear()
auth_sessions._users.clear()
auth_sessions._email_index.clear()
auth_sessions._inactive_emails.clear()
async def asyncTearDown(self) -> None:
auth_routes._oauth_states.clear()
auth_routes._saml_states.clear()
auth_sessions._sessions.clear()
auth_sessions._users.clear()
auth_sessions._email_index.clear()
auth_sessions._inactive_emails.clear()
async def test_auth_config_reports_google_and_saml_provider_status(self) -> None:
with patched_settings(
@ -134,6 +144,60 @@ class AuthProviderScaffoldTest(unittest.IsolatedAsyncioTestCase):
self.assertTrue(config.dev_login_enabled)
async def test_learner_can_accept_and_withdraw_practice_consent(self) -> None:
with patch.object(auth_sessions, "get_pool", side_effect=RuntimeError("no db")):
_, user = await auth_sessions.create_session(
email="learner@hs.ac.kr",
display_name="Learner",
role="learner",
external_id="dev:learner@hs.ac.kr",
)
principal = Principal(
user_id=user.user_id,
role=Role.LEARNER,
cohort_ids=user.cohort_ids,
email=user.email,
display_name=user.display_name,
consent_at=user.consent_at,
)
accepted = await auth_routes.accept_consent(
auth_routes.ConsentRequest(accepted=True),
principal,
)
self.assertIsNotNone(accepted.consent_at)
self.assertEqual(principal.consent_at, accepted.consent_at)
self.assertTrue(await auth_sessions.user_has_consent(user.user_id))
withdrawn = await auth_routes.withdraw_consent(principal)
self.assertIsNone(withdrawn.consent_at)
self.assertIsNone(principal.consent_at)
self.assertFalse(await auth_sessions.user_has_consent(user.user_id))
async def test_consent_rejects_non_learner_and_unaccepted_body(self) -> None:
teacher = Principal(
user_id="00000000-0000-0000-0000-000000000501",
role=Role.TEACHER,
email="teacher@hs.ac.kr",
display_name="Teacher",
)
learner = Principal(
user_id="00000000-0000-0000-0000-000000000502",
role=Role.LEARNER,
email="learner@hs.ac.kr",
display_name="Learner",
)
with self.assertRaises(auth_routes.HTTPException) as teacher_error:
await auth_routes.accept_consent(auth_routes.ConsentRequest(), teacher)
with self.assertRaises(auth_routes.HTTPException) as learner_error:
await auth_routes.accept_consent(auth_routes.ConsentRequest(accepted=False), learner)
self.assertEqual(teacher_error.exception.status_code, 403)
self.assertEqual(learner_error.exception.status_code, 400)
async def test_auth_config_allows_dev_login_from_configured_tailnet_forwarded_host(self) -> None:
request = _request(
[