Source code for govbr_auth.fake.runtime

"""Canonical framework-independent composition for the local fake provider."""

from collections.abc import Callable
from dataclasses import InitVar, dataclass, field
from datetime import datetime
from typing import Protocol

from cryptography.fernet import Fernet
from pydantic import SecretStr

from govbr_auth.fake.credentials import (
    FakeCredentialAuthenticator,
    FakeLoginCredential,
    InMemoryFakeUserRepository,
    JsonFakeUserRepository,
)
from govbr_auth.fake.http.application import FakeGovHttpApplication
from govbr_auth.fake.models import FakeClient, FakeUser
from govbr_auth.fake.provider import FakeGovBrProvider
from govbr_auth.fake.settings import FakeGovBrSettings
from govbr_auth.fake.signing import FakeSigningKey
from govbr_auth.fake.stores import (
    FakeUserStore,
    InMemoryAuthorizationCodeReplayStore,
)
from govbr_auth.runtime import GovBrProvider, GovBrRuntimeSettings
from govbr_auth.runtime_settings import _is_canonical_path_prefix


class FakeUserRepository(
    FakeCredentialAuthenticator,
    FakeUserStore,
    Protocol,
):
    """Combine the provider's user lookup and login contracts."""


@dataclass(frozen=True, slots=True)
class FakeGovBrEndpoints:
    """Expose the complete endpoint set served by one fake provider."""

    authorize: str
    token: str
    userinfo: str
    jwks: str
    issuer: str


[docs] @dataclass(frozen=True, slots=True) class FakeGovSimulator: """Own one internally consistent fake-provider simulation graph.""" settings: FakeGovBrSettings provider: FakeGovBrProvider credential_authenticator: FakeCredentialAuthenticator = field(repr=False) users: tuple[FakeUser, ...] = field(repr=False) credentials: tuple[FakeLoginCredential, ...] = field(repr=False) prefix: str endpoints: FakeGovBrEndpoints clock: InitVar[Callable[[], datetime]] = field(repr=False) http_application: FakeGovHttpApplication = field(init=False, repr=False) def __post_init__(self, clock: Callable[[], datetime]) -> None: object.__setattr__( self, "http_application", FakeGovHttpApplication(self, clock=clock), )
_DEFAULT_USERS = ( ( FakeUser( sub="11122233344", name="Usuário Fake", email="fake@example.test", email_verified=True, ), SecretStr("senha-ficticia"), ), ( FakeUser( sub="98765432100", name="Bruno Demo", email="bruno@example.test", email_verified=True, ), SecretStr("bruno-demo"), ), )
[docs] def create_fake_gov_simulator( settings: GovBrRuntimeSettings, *, prefix: str, clock: Callable[[], datetime], user_repository: FakeUserRepository | None = None, ) -> FakeGovSimulator: """Compose one fake provider without importing an HTTP framework.""" if settings.provider is not GovBrProvider.FAKE: raise ValueError("fake simulator requires the fake provider") if not _is_canonical_path_prefix(prefix, allow_empty=True): raise ValueError("prefix must be an empty string or a canonical path") settings = GovBrRuntimeSettings.model_validate(settings.model_dump(mode="python")) repository, credentials = _resolve_repository(settings, user_repository) endpoints = _fake_endpoints(settings, prefix=prefix) if settings.oauth is None: raise ValueError("fake runtime requires OAuth settings") oauth = settings.oauth redirect_uri = oauth.redirect_uri provider_settings = FakeGovBrSettings( base_url=endpoints.issuer, issuer=endpoints.issuer, artifact_secret=SecretStr(Fernet.generate_key().decode("ascii")), request_ttl_seconds=settings.fake_request_ttl_seconds, authorization_code_ttl_seconds=settings.fake_authorization_code_ttl_seconds, access_token_ttl_seconds=settings.fake_access_token_ttl_seconds, id_token_ttl_seconds=settings.fake_id_token_ttl_seconds, clients=( FakeClient( client_id=oauth.client_id, client_secret=oauth.client_secret, registered_redirect_uris=(redirect_uri,), ), ), post_logout_redirect_uris=( (oauth.post_logout_redirect_uri,) if oauth.post_logout_redirect_uri is not None else () ), ) provider = FakeGovBrProvider( settings=provider_settings, user_store=repository, replay_store=InMemoryAuthorizationCodeReplayStore(), signing_key=FakeSigningKey.generate(kid="govbr-auth-local-key"), ) return FakeGovSimulator( settings=provider_settings, provider=provider, credential_authenticator=repository, users=repository.list(), credentials=credentials, prefix=prefix, endpoints=endpoints, clock=clock, )
def _resolve_repository( settings: GovBrRuntimeSettings, explicit: FakeUserRepository | None, ) -> tuple[FakeUserRepository, tuple[FakeLoginCredential, ...]]: if explicit is not None: return explicit, () if settings.fake_users_file is not None: return JsonFakeUserRepository.from_file(settings.fake_users_file), () credentials = tuple( FakeLoginCredential( cpf=user.sub, password=password.get_secret_value(), name=user.name, ) for user, password in _DEFAULT_USERS ) return InMemoryFakeUserRepository(_DEFAULT_USERS), credentials def _fake_endpoints( settings: GovBrRuntimeSettings, *, prefix: str, ) -> FakeGovBrEndpoints: base_url = f"{_fake_origin(settings)}{prefix}" issuer = f"{base_url}/" return FakeGovBrEndpoints( authorize=f"{base_url}/authorize", token=f"{base_url}/token", userinfo=f"{base_url}/userinfo", jwks=f"{base_url}/jwk", issuer=issuer, ) def _fake_origin(settings: GovBrRuntimeSettings) -> str: host = settings.fake_host rendered_host = f"[{host}]" if host == "::1" else host return f"http://{rendered_host}:{settings.fake_port}"