feat: add OIDC sign-in, roles, sessions and client address rule
Authorization-code flow with PKCE through an idp adapter (with a fake), ID token validation, identity and roles resolved from the directory with a short cache, refusal of unknown, disabled and locked accounts with one generic page, sessions that end when the account becomes unavailable, sign-out that ends the server-side session, role decorators and the trusted-proxy client address rule. Adds the OIDC_* and PUBLIC_BASE_URL configuration. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
This commit is contained in:
@@ -72,7 +72,8 @@ def test_settings_defaults():
|
||||
assert settings.SESSION_SAVE_EVERY_REQUEST is True
|
||||
|
||||
|
||||
def _client_with_session(created_at):
|
||||
def _client_with_session(created_at, adapters):
|
||||
adapters.directory.add_user("alice")
|
||||
store = SessionStore()
|
||||
request = RequestFactory().get("/")
|
||||
request.session = store
|
||||
@@ -84,16 +85,17 @@ def _client_with_session(created_at):
|
||||
return client, store.session_key
|
||||
|
||||
|
||||
def test_absolute_limit_removes_session_and_clears_cookie():
|
||||
def test_absolute_limit_removes_session_and_clears_cookie(adapters):
|
||||
assert any(m.endswith("AbsoluteSessionLimitMiddleware") for m in settings.MIDDLEWARE)
|
||||
client, key = _client_with_session(time.time() - settings.SESSION_ABSOLUTE_SECONDS - 5)
|
||||
too_old = time.time() - settings.SESSION_ABSOLUTE_SECONDS - 5
|
||||
client, key = _client_with_session(too_old, adapters)
|
||||
response = client.get("/healthz")
|
||||
assert not UserSession.objects.filter(session_key=key).exists()
|
||||
assert response.cookies[settings.SESSION_COOKIE_NAME].value == ""
|
||||
|
||||
|
||||
def test_session_within_limits_survives_a_request():
|
||||
client, key = _client_with_session(time.time() - 60)
|
||||
def test_session_within_limits_survives_a_request(adapters):
|
||||
client, key = _client_with_session(time.time() - 60, adapters)
|
||||
client.get("/healthz")
|
||||
assert UserSession.objects.filter(session_key=key).exists()
|
||||
|
||||
@@ -104,8 +106,8 @@ def test_middleware_callable_directly():
|
||||
assert current_user(request) is not None
|
||||
|
||||
|
||||
def test_request_renews_expire_date_to_one_hour_ahead():
|
||||
client, key = _client_with_session(time.time() - 60)
|
||||
def test_request_renews_expire_date_to_one_hour_ahead(adapters):
|
||||
client, key = _client_with_session(time.time() - 60, adapters)
|
||||
UserSession.objects.filter(session_key=key).update(
|
||||
expire_date=timezone.now() + timedelta(minutes=5)
|
||||
)
|
||||
@@ -114,8 +116,8 @@ def test_request_renews_expire_date_to_one_hour_ahead():
|
||||
assert timedelta(minutes=59) < remaining <= timedelta(hours=1)
|
||||
|
||||
|
||||
def test_request_with_idle_expired_session_has_no_session_and_clears_cookie():
|
||||
client, key = _client_with_session(time.time() - 60)
|
||||
def test_request_with_idle_expired_session_has_no_session_and_clears_cookie(adapters):
|
||||
client, key = _client_with_session(time.time() - 60, adapters)
|
||||
UserSession.objects.filter(session_key=key).update(
|
||||
expire_date=timezone.now() - timedelta(seconds=1)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user