94 lines
2.8 KiB
Python
94 lines
2.8 KiB
Python
from typing import Annotated
|
|
|
|
import asyncpg
|
|
from dishka.integrations.fastapi import DishkaRoute, FromDishka
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
from pydantic import BaseModel
|
|
|
|
from utils.policy import repository
|
|
from utils.policy.models import (
|
|
CaptureToggles,
|
|
ChatKind,
|
|
ChatMeta,
|
|
PolicyCreate,
|
|
PolicyRecord,
|
|
)
|
|
from utils.policy.resolver import resolve
|
|
|
|
router = APIRouter(prefix="/api/policy", tags=["policy"], route_class=DishkaRoute)
|
|
|
|
POLICY_CHANGED_CHANNEL = "policy_changed"
|
|
|
|
|
|
class EffectiveQuery(BaseModel):
|
|
account_id: int
|
|
chat_id: int
|
|
kind: ChatKind
|
|
is_bot: bool = False
|
|
is_contact: bool | None = None
|
|
|
|
|
|
@router.get("")
|
|
async def list_policies(
|
|
pool: FromDishka[asyncpg.Pool], account_id: Annotated[int, Query()]
|
|
) -> list[PolicyRecord]:
|
|
return await repository.list_policies(pool, account_id)
|
|
|
|
|
|
@router.get("/effective")
|
|
async def effective_policy(
|
|
pool: FromDishka[asyncpg.Pool], query: Annotated[EffectiveQuery, Query()]
|
|
) -> CaptureToggles:
|
|
folders = await repository.list_folders(pool, query.account_id)
|
|
policies = await repository.load_policy_set(pool, query.account_id)
|
|
chat = ChatMeta(
|
|
chat_id=query.chat_id,
|
|
kind=query.kind,
|
|
is_bot=query.is_bot,
|
|
is_contact=query.is_contact,
|
|
)
|
|
return resolve(chat, folders, policies)
|
|
|
|
|
|
@router.post("", status_code=201)
|
|
async def create_policy(
|
|
pool: FromDishka[asyncpg.Pool], body: PolicyCreate
|
|
) -> PolicyRecord:
|
|
record = await repository.create_policy(
|
|
pool, body.account_id, body.scope_type, body.scope_id, body
|
|
)
|
|
await pool.execute(f"NOTIFY {POLICY_CHANGED_CHANNEL}")
|
|
return record
|
|
|
|
|
|
@router.get("/{policy_id}")
|
|
async def get_policy(pool: FromDishka[asyncpg.Pool], policy_id: int) -> PolicyRecord:
|
|
record = await repository.get_policy(pool, policy_id)
|
|
if record is None:
|
|
raise HTTPException(status_code=404, detail="policy not found")
|
|
return record
|
|
|
|
|
|
@router.put("/{policy_id}")
|
|
async def update_policy(
|
|
pool: FromDishka[asyncpg.Pool],
|
|
policy_id: int,
|
|
body: CaptureToggles,
|
|
account_id: Annotated[int | None, Query()] = None,
|
|
) -> PolicyRecord:
|
|
if account_id is None:
|
|
record = await repository.update_policy(pool, policy_id, body)
|
|
else:
|
|
record = await repository.override_policy(pool, policy_id, account_id, body)
|
|
if record is None:
|
|
raise HTTPException(status_code=404, detail="policy not found")
|
|
await pool.execute(f"NOTIFY {POLICY_CHANGED_CHANNEL}")
|
|
return record
|
|
|
|
|
|
@router.delete("/{policy_id}", status_code=204)
|
|
async def delete_policy(pool: FromDishka[asyncpg.Pool], policy_id: int) -> None:
|
|
if not await repository.delete_policy(pool, policy_id):
|
|
raise HTTPException(status_code=404, detail="policy not found")
|
|
await pool.execute(f"NOTIFY {POLICY_CHANGED_CHANNEL}")
|