Проект разделен на два репозитория
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import Annotated, Literal
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, StringConstraints, model_validator
|
||||
|
||||
Checksum = Annotated[str, StringConstraints(pattern=r"^sha256:[0-9a-f]{64}$")]
|
||||
|
||||
|
||||
class StrictModel(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid", strict=True)
|
||||
|
||||
|
||||
class Attachment(StrictModel):
|
||||
attachment_id: UUID
|
||||
quarantine_object_key: Annotated[str, StringConstraints(min_length=1, max_length=1024)]
|
||||
quarantine_version_id: Annotated[str, StringConstraints(min_length=1, max_length=512)]
|
||||
quarantine_etag: Annotated[str, StringConstraints(min_length=1, max_length=512)]
|
||||
mime_type: Annotated[str, StringConstraints(min_length=1, max_length=127)]
|
||||
size_bytes: int = Field(ge=1, le=5_242_880)
|
||||
checksum: Checksum
|
||||
|
||||
@model_validator(mode="after")
|
||||
def canonical_key(self) -> Attachment:
|
||||
uuid = r"[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"
|
||||
pattern = rf"^quarantine/users/{uuid}/dialogs/{uuid}/{uuid}$"
|
||||
if not self.quarantine_object_key.isascii() or not re.fullmatch(
|
||||
pattern, self.quarantine_object_key
|
||||
):
|
||||
raise ValueError("quarantine_object_key is not canonical")
|
||||
return self
|
||||
|
||||
|
||||
class TextCheck(StrictModel):
|
||||
message_id: UUID
|
||||
content_kind: Literal["text"]
|
||||
text: Annotated[str, StringConstraints(min_length=1, max_length=10_000)]
|
||||
attachment: None = None
|
||||
|
||||
|
||||
class FileCheck(StrictModel):
|
||||
message_id: UUID
|
||||
content_kind: Literal["file"]
|
||||
text: Literal[""]
|
||||
attachment: Attachment
|
||||
|
||||
|
||||
CheckRequest = Annotated[TextCheck | FileCheck, Field(discriminator="content_kind")]
|
||||
|
||||
|
||||
class Verdict(StrictModel):
|
||||
verdict: Literal["allow", "deny"]
|
||||
processing_mode: Literal["standard", "mock"]
|
||||
config_version: int
|
||||
rule_id: str
|
||||
rules_version: str
|
||||
reason_code: Literal["message_blocked"] | None = None
|
||||
|
||||
|
||||
class Pending(StrictModel):
|
||||
verdict: Literal["pending"] = "pending"
|
||||
processing_mode: Literal["standard"] = "standard"
|
||||
config_version: int
|
||||
task_id: UUID
|
||||
poll_after_ms: int = 2000
|
||||
expires_at: datetime
|
||||
rules_version: str
|
||||
|
||||
|
||||
class ErrorBody(StrictModel):
|
||||
code: str
|
||||
message: str
|
||||
request_id: str
|
||||
details: dict[str, object] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class ErrorEnvelope(StrictModel):
|
||||
error: ErrorBody
|
||||
Reference in New Issue
Block a user