feat: 9.5. Сборка и монтирование
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
Reference in New Issue
Block a user