feat: 9.5. Сборка и монтирование

This commit is contained in:
2026-10-12 17:12:27 +03:00
parent 707ba4aaff
commit 9d9e190328
3 changed files with 57 additions and 1 deletions
+11 -1
View File
@@ -1,7 +1,8 @@
import json
from typing import Any
from uuid import uuid4
from ariadne import MutationType, QueryType, convert_kwargs_to_snake_case
from ariadne import MutationType, ObjectType, QueryType, convert_kwargs_to_snake_case
from graphql import GraphQLError
from sqlalchemy import select
@@ -19,6 +20,8 @@ from app.models import AuditEvent, OAuthClient, User
query = QueryType()
mutation = MutationType()
audit_event = ObjectType("AuditEvent")
# me – возвращает `info.context["user"]`;
@query.field("me")
@@ -128,3 +131,10 @@ def resolve_disable_user(_, info: Any, user_id: int) -> User:
actor = info.context.get("user")
write_event(db, "user.disabled", actor_id=actor.id if actor else None)
return user
@audit_event.field("metadata")
def resolve_metadata(obj: AuditEvent, info: Any) -> str | None:
if obj.metadata_json is None:
return None
return json.dumps(obj.metadata_json, ensure_ascii=False)
+44
View File
@@ -0,0 +1,44 @@
from datetime import datetime
from pathlib import Path
from typing import Any
from ariadne import ScalarType, load_schema_from_path, make_executable_schema
from ariadne import snake_case_fallback_resolvers
from ariadne.asgi import GraphQL
from app.graphql.context import get_context_value
from app.graphql.directives import IsAdminDirective, IsAuthenticatedDirective
from app.graphql.resolvers import audit_event, mutation, query
datetime_scalar = ScalarType("DateTime")
@datetime_scalar.serializer
def _serialize_datetime(value: Any) -> str:
if isinstance(value, datetime):
return value.isoformat()
return str(value)
# Загрузить SDL-схему из файла (в Ariadne есть функция load_schema_from_path)
type_defs = load_schema_from_path(str(Path(__file__).parent / "schema.graphql"))
# Собрать исполняемую схему через `make_executable_schema`, передав:
schema = make_executable_schema(
# типы;
type_defs,
# объекты `query` и `mutation` из `resolvers.py`;
query,
mutation,
audit_event,
datetime_scalar,
snake_case_fallback_resolvers,
# словарь директив `{"isAuthenticated": ..., "isAdmin": ...}`.
directives={
"isAuthenticated": IsAuthenticatedDirective,
"isAdmin": IsAdminDirective,
},
)
# Обернуть схему в ASGI-приложение `GraphQL(schema, context_value=..., debug=True)`.
graphql_app = GraphQL(schema, context_value=get_context_value, debug=True)
+2
View File
@@ -2,7 +2,9 @@ from fastapi import FastAPI
from app.auth.router import router as auth_router
from app.config import settings
from app.graphql.schema import graphql_app
app = FastAPI(title=settings.app_name)
app.include_router(auth_router)
app.mount("/graphql", graphql_app)