packages/ flattens into: backends/ server protocol adapters (mizan-django, mizan-ts) frontends/ client kernel + framework adapters (mizan-base, mizan-react, mizan-vue, mizan-svelte) workers/ runtime workers (mizan-ssr) cores/ shared language-level primitives (empty for now; mizan-python forthcoming) The frontend kernel (was packages/mizan-runtime, now frontends/mizan-base) is renamed to reflect its role — it's the shared base that frontend adapters depend on directly. Reflects the substrate position that per-framework adapters wrap a single shared kernel; codegen targets the adapter, not the raw kernel. Path updates landed in: Makefile, two Gitea workflows, Dockerfile.test, four example/harness config files, .claude/settings.local.json, four docs (CLAUDE/ISSUES/ROADMAP/AFI_ARCHITECTURE), four codegen templates (stage1 + react/vue/svelte adapters), and three package.jsons (the mizan-base rename plus mizan-vue/svelte peerDeps). Generated files under examples/django-react-site/harness/src/api/ still reference @mizan/runtime — left as-is; they're regenerated artifacts and the harness is non-functional pending the React wrapper-layer codegen. Also folded in a pre-existing fix: the Gitea workflows had working-directory: react / django pointing at a layout that predates packages/, never updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
65 lines
1.8 KiB
Python
65 lines
1.8 KiB
Python
"""
|
|
Django Ninja Security Classes for JWT Authentication
|
|
|
|
Provides authentication classes that can be used with Django Ninja's
|
|
auth parameter to protect API endpoints.
|
|
"""
|
|
|
|
from django.http import HttpRequest
|
|
from ninja.security import HttpBearer
|
|
|
|
from .tokens import decode_token, JWTUser
|
|
|
|
|
|
class JWTAuth(HttpBearer):
|
|
"""
|
|
JWT Bearer token authentication for Django Ninja.
|
|
|
|
Usage:
|
|
from ninja_jwt_session import jwt_auth
|
|
|
|
@api.get("/protected/", auth=jwt_auth)
|
|
def protected_endpoint(request):
|
|
return {"user_id": request.user.id}
|
|
|
|
Or globally:
|
|
api = NinjaExtraAPI(auth=[django_auth, jwt_auth])
|
|
|
|
The token must be passed in the Authorization header:
|
|
Authorization: Bearer <access_token>
|
|
|
|
IMPORTANT: This is stateless - no database query is made.
|
|
request.user is a JWTUser object with id, is_staff, is_superuser.
|
|
If you need the full User object, query it explicitly:
|
|
user = User.objects.get(pk=request.user.id)
|
|
"""
|
|
|
|
def authenticate(self, request: HttpRequest, token: str):
|
|
"""
|
|
Validate the JWT and return a JWTUser if valid.
|
|
|
|
Returns None (authentication failed) if:
|
|
- Token is invalid or expired
|
|
- Token is not an access token
|
|
|
|
Note: No database query is made. The JWTUser is created from
|
|
token claims. This is truly stateless authentication.
|
|
"""
|
|
# Decode and validate the token
|
|
payload = decode_token(token, expected_type="access")
|
|
|
|
if payload is None:
|
|
return None
|
|
|
|
# Create JWTUser from token claims - NO DATABASE QUERY
|
|
jwt_user = JWTUser(payload)
|
|
|
|
# Set request.user for compatibility with code expecting it
|
|
request.user = jwt_user
|
|
|
|
return jwt_user
|
|
|
|
|
|
# Singleton instance for convenience
|
|
jwt_auth = JWTAuth()
|