FastAPI and TypeScript improved

This commit is contained in:
2026-06-04 05:14:29 -04:00
parent 67ad91b673
commit 66b2db81fb
28 changed files with 1864 additions and 717 deletions

View File

@@ -0,0 +1,147 @@
"""Unit tests for the adapter-agnostic dispatch core."""
import asyncio
import pytest
from pydantic import BaseModel
from mizan_core.auth import AuthConfig, JWTConfig, INVALID, authenticate, create_access_token
from mizan_core.authguard import enforce_auth
from mizan_core.client.function import client
from mizan_core.dispatch import CacheOrchestrator, DispatchRequest, dispatch_call
from mizan_core.errors import Forbidden, Unauthorized
from mizan_core.invalidation import format_invalidate_header, resolve_invalidation
from mizan_core.registry import clear_registry, register
class Ident:
def __init__(self, authed=True, staff=False, su=False, pk=1):
self.is_authenticated = authed
self.is_staff = staff
self.is_superuser = su
self.pk = pk
# ─── authguard ──────────────────────────────────────────────────────────────
def test_auth_required_anonymous():
with pytest.raises(Unauthorized):
enforce_auth(None, True)
def test_auth_required_authenticated():
enforce_auth(Ident(), True) # no raise
def test_auth_staff_denied_then_allowed():
with pytest.raises(Forbidden):
enforce_auth(Ident(staff=False), "staff")
enforce_auth(Ident(staff=True), "staff")
def test_auth_superuser():
with pytest.raises(Forbidden):
enforce_auth(Ident(su=False), "superuser")
enforce_auth(Ident(su=True), "superuser")
def test_auth_callable_false_and_raise():
with pytest.raises(Forbidden):
enforce_auth(Ident(), lambda r: False)
with pytest.raises(Forbidden, match="custom"):
enforce_auth(Ident(), lambda r: (_ for _ in ()).throw(PermissionError("custom")))
# ─── authenticate / INVALID sentinel ────────────────────────────────────────
def _cfg():
return AuthConfig(jwt=JWTConfig(private_key="k" * 32, public_key="k" * 32))
def test_authenticate_jwt_ok():
cfg = _cfg()
tok = create_access_token("7", "sess", cfg.jwt, is_staff=True)
ident = authenticate({"Authorization": f"Bearer {tok}"}, cfg)
assert ident.pk == 7 and ident.is_staff and ident.is_authenticated
def test_authenticate_bad_token_is_invalid_sentinel():
assert authenticate({"Authorization": "Bearer garbage"}, _cfg()) is INVALID
def test_authenticate_no_token_is_none():
assert authenticate({}, _cfg()) is None
# ─── invalidation + header ──────────────────────────────────────────────────
def test_invalidation_three_tier_and_header():
clear_registry()
UserCtx = "user"
class Out(BaseModel):
ok: bool
@client(context=UserCtx)
def user_profile(request, user_id: int) -> Out:
return Out(ok=True)
@client(affects=UserCtx)
def update_profile(request, user_id: int, name: str) -> Out:
return Out(ok=True)
register(user_profile, "user_profile")
register(update_profile, "update_profile")
# Tier 1: user_id matches context param → scoped
inv = resolve_invalidation(update_profile, {"user_id": 5, "name": "x"})
assert inv == [{"context": "user", "params": {"user_id": 5}}]
assert format_invalidate_header(inv) == "user;user_id=5"
# Tier 3: no matching param → broad
inv2 = resolve_invalidation(update_profile, {"name": "x"})
assert inv2 == ["user"]
clear_registry()
# ─── dispatch_call end to end ───────────────────────────────────────────────
def test_dispatch_call_auth_and_invalidation():
clear_registry()
class Out(BaseModel):
ok: bool
@client(context="user")
def user_profile(request, user_id: int) -> Out:
return Out(ok=True)
@client(affects="user", auth="staff")
def secure_update(request, user_id: int) -> Out:
return Out(ok=True)
register(user_profile, "user_profile")
register(secure_update, "secure_update")
cache = CacheOrchestrator(None, None)
# non-staff rejected
with pytest.raises(Forbidden):
asyncio.run(dispatch_call(
DispatchRequest(identity=Ident(staff=False), args={"user_id": 1}),
"secure_update", cache,
))
# staff passes, invalidation resolved
res = asyncio.run(dispatch_call(
DispatchRequest(identity=Ident(staff=True), args={"user_id": 1}),
"secure_update", cache,
))
assert res.kind == "rpc" and res.data == {"ok": True}
assert res.invalidate == [{"context": "user", "params": {"user_id": 1}}]
assert res.invalidate_header == "user;user_id=1"
clear_registry()