feat(postbox): enforce unified inbox separation
This commit is contained in:
@@ -5,6 +5,7 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
|
||||
from govoplan_postbox.backend.grouping_policies import PostboxGroupingPolicyMode
|
||||
from govoplan_postbox.backend.protection_profiles import (
|
||||
POSTBOX_MANAGED_ENVELOPE_PROFILE,
|
||||
POSTBOX_PLAINTEXT_PROFILE,
|
||||
@@ -58,6 +59,7 @@ class PostboxDirectoryItem(BaseModel):
|
||||
key_epoch: int = Field(default=1, ge=1)
|
||||
encryption_vault_id: str | None = None
|
||||
protection_policy: dict[str, Any] = Field(default_factory=dict)
|
||||
grouping_policy: dict[str, Any] = Field(default_factory=dict)
|
||||
access: PostboxAccessDecisionResponse | None = None
|
||||
resource_revision: int = Field(default=1, ge=1)
|
||||
etag: str | None = None
|
||||
@@ -465,6 +467,16 @@ class PostboxProtectionPolicyPayload(BaseModel):
|
||||
return self
|
||||
|
||||
|
||||
class PostboxGroupingPolicyPayload(BaseModel):
|
||||
mode: PostboxGroupingPolicyMode = "allow"
|
||||
reason: str | None = Field(default=None, max_length=1000)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def normalize_reason(self) -> "PostboxGroupingPolicyPayload":
|
||||
self.reason = self.reason.strip() if self.reason else None
|
||||
return self
|
||||
|
||||
|
||||
class PostboxExactCreateRequest(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=500)
|
||||
description: str | None = None
|
||||
@@ -478,6 +490,9 @@ class PostboxExactCreateRequest(BaseModel):
|
||||
protection_policy: PostboxProtectionPolicyPayload = Field(
|
||||
default_factory=PostboxProtectionPolicyPayload
|
||||
)
|
||||
grouping_policy: PostboxGroupingPolicyPayload = Field(
|
||||
default_factory=PostboxGroupingPolicyPayload
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_encryption(self) -> "PostboxExactCreateRequest":
|
||||
@@ -498,6 +513,11 @@ class PostboxProtectionPolicyUpdateRequest(BaseModel):
|
||||
protection_policy: PostboxProtectionPolicyPayload
|
||||
|
||||
|
||||
class PostboxGroupingPolicyUpdateRequest(BaseModel):
|
||||
base_revision: int = Field(ge=1)
|
||||
grouping_policy: PostboxGroupingPolicyPayload
|
||||
|
||||
|
||||
class PostboxTemplateRevisionPayload(BaseModel):
|
||||
function_type_id: str | None = Field(default=None, max_length=36)
|
||||
scope_kind: Literal["tenant", "unit", "subtree", "unit_type"] = "tenant"
|
||||
@@ -522,6 +542,9 @@ class PostboxTemplateRevisionPayload(BaseModel):
|
||||
protection_policy: PostboxProtectionPolicyPayload = Field(
|
||||
default_factory=PostboxProtectionPolicyPayload
|
||||
)
|
||||
grouping_policy: PostboxGroupingPolicyPayload = Field(
|
||||
default_factory=PostboxGroupingPolicyPayload
|
||||
)
|
||||
routing_policy: PostboxRoutingPolicyPayload = Field(
|
||||
default_factory=PostboxRoutingPolicyPayload
|
||||
)
|
||||
@@ -861,10 +884,22 @@ class PostboxGroupingUpdateRequest(PostboxGroupingPayload):
|
||||
base_revision: int = Field(ge=1)
|
||||
|
||||
|
||||
class PostboxGroupingConstraintItem(BaseModel):
|
||||
code: Literal[
|
||||
"source_requires_separation",
|
||||
"classification_separation_required",
|
||||
]
|
||||
mode: PostboxGroupingPolicyMode
|
||||
postbox_id: str
|
||||
reason: str | None = None
|
||||
enforced_by: Literal["postbox_configuration"] = "postbox_configuration"
|
||||
|
||||
|
||||
class PostboxGroupingItem(PostboxGroupingPayload):
|
||||
id: str
|
||||
total_count: int = Field(default=0, ge=0)
|
||||
unread_count: int = Field(default=0, ge=0)
|
||||
constraints: list[PostboxGroupingConstraintItem] = Field(default_factory=list)
|
||||
resource_revision: int = Field(ge=1)
|
||||
etag: str
|
||||
created_at: datetime
|
||||
|
||||
Reference in New Issue
Block a user