feat: create message capture policies
This commit is contained in:
@@ -5,6 +5,7 @@ import asyncpg
|
||||
from dishka.integrations.fastapi import FromDishka, inject, setup_dishka
|
||||
from fastapi import FastAPI
|
||||
|
||||
from api.routers import folders, policy
|
||||
from dependencies.container import container
|
||||
|
||||
|
||||
@@ -27,4 +28,7 @@ async def health(pool: FromDishka[asyncpg.Pool]) -> dict[str, bool]:
|
||||
return {"db": db_ok, "timescaledb": bool(timescale_ok)}
|
||||
|
||||
|
||||
app.include_router(policy.router)
|
||||
app.include_router(folders.router)
|
||||
|
||||
setup_dishka(container, app)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
from typing import Annotated
|
||||
|
||||
import asyncpg
|
||||
from dishka.integrations.fastapi import FromDishka, inject
|
||||
from fastapi import APIRouter, Query
|
||||
|
||||
from utils.policy import repository
|
||||
from utils.policy.models import FolderSpec
|
||||
|
||||
router = APIRouter(prefix="/api/folders", tags=["folders"])
|
||||
|
||||
|
||||
def _serialize(spec: FolderSpec) -> dict:
|
||||
return {
|
||||
"folder_id": spec.folder_id,
|
||||
"order_index": spec.order_index,
|
||||
"title": spec.title,
|
||||
"include_ids": sorted(spec.include_ids),
|
||||
"exclude_ids": sorted(spec.exclude_ids),
|
||||
"pinned_ids": sorted(spec.pinned_ids),
|
||||
"contacts": spec.contacts,
|
||||
"non_contacts": spec.non_contacts,
|
||||
"groups": spec.groups,
|
||||
"broadcasts": spec.broadcasts,
|
||||
"bots": spec.bots,
|
||||
"is_chatlist": spec.is_chatlist,
|
||||
}
|
||||
|
||||
|
||||
@router.get("")
|
||||
@inject
|
||||
async def list_folders(
|
||||
pool: FromDishka[asyncpg.Pool], account_id: Annotated[int, Query()]
|
||||
) -> list[dict]:
|
||||
folders = await repository.list_folders(pool, account_id)
|
||||
return [_serialize(spec) for spec in folders]
|
||||
@@ -0,0 +1,87 @@
|
||||
from typing import Annotated
|
||||
|
||||
import asyncpg
|
||||
from dishka.integrations.fastapi import FromDishka, inject
|
||||
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"])
|
||||
|
||||
|
||||
class EffectiveQuery(BaseModel):
|
||||
account_id: int
|
||||
chat_id: int
|
||||
kind: ChatKind
|
||||
is_bot: bool = False
|
||||
is_contact: bool | None = None
|
||||
|
||||
|
||||
@router.get("")
|
||||
@inject
|
||||
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")
|
||||
@inject
|
||||
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)
|
||||
@inject
|
||||
async def create_policy(
|
||||
pool: FromDishka[asyncpg.Pool], body: PolicyCreate
|
||||
) -> PolicyRecord:
|
||||
return await repository.create_policy(
|
||||
pool, body.account_id, body.scope_type, body.scope_id, body
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{policy_id}")
|
||||
@inject
|
||||
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}")
|
||||
@inject
|
||||
async def update_policy(
|
||||
pool: FromDishka[asyncpg.Pool], policy_id: int, body: CaptureToggles
|
||||
) -> PolicyRecord:
|
||||
record = await repository.update_policy(pool, policy_id, body)
|
||||
if record is None:
|
||||
raise HTTPException(status_code=404, detail="policy not found")
|
||||
return record
|
||||
|
||||
|
||||
@router.delete("/{policy_id}", status_code=204)
|
||||
@inject
|
||||
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")
|
||||
Reference in New Issue
Block a user