You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
403 lines
9.8 KiB
Python
403 lines
9.8 KiB
Python
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
from admin_app.core import AdminCredentialStrategy
|
|
from shared.contracts import AdminPermission, ServiceName, StaffRole, ToolLifecycleStatus, ToolParameterType
|
|
|
|
|
|
class AdminRootResponse(BaseModel):
|
|
service: str
|
|
status: str
|
|
message: str
|
|
environment: str
|
|
|
|
|
|
class AdminHealthResponse(BaseModel):
|
|
service: str
|
|
status: str
|
|
version: str
|
|
|
|
|
|
class AdminSystemInfoResponse(BaseModel):
|
|
service: str
|
|
app_name: str
|
|
environment: str
|
|
version: str
|
|
api_prefix: str
|
|
debug: bool
|
|
|
|
|
|
class AdminAuthenticatedStaffResponse(BaseModel):
|
|
id: int
|
|
email: str
|
|
display_name: str
|
|
role: StaffRole
|
|
is_active: bool
|
|
|
|
|
|
class AdminCurrentAccessResponse(BaseModel):
|
|
service: str
|
|
staff_account: AdminAuthenticatedStaffResponse
|
|
permissions: list[str]
|
|
|
|
|
|
class AdminCapabilityResponse(BaseModel):
|
|
service: str
|
|
action: str
|
|
allowed: bool
|
|
role: StaffRole
|
|
|
|
|
|
class AdminAuditEntryResponse(BaseModel):
|
|
id: int
|
|
actor_staff_account_id: int | None
|
|
event_type: str
|
|
resource_type: str
|
|
resource_id: str | None
|
|
outcome: str
|
|
message: str | None
|
|
payload_json: dict | None
|
|
ip_address: str | None
|
|
user_agent: str | None
|
|
created_at: datetime
|
|
|
|
|
|
class AdminAuditListResponse(BaseModel):
|
|
service: str
|
|
events: list[AdminAuditEntryResponse]
|
|
|
|
|
|
class AdminRuntimeApplicationConfigurationResponse(BaseModel):
|
|
app_name: str
|
|
environment: str
|
|
version: str
|
|
api_prefix: str
|
|
debug: bool
|
|
|
|
|
|
class AdminRuntimeDatabaseConfigurationResponse(BaseModel):
|
|
host: str
|
|
port: int
|
|
name: str
|
|
cloud_sql_configured: bool
|
|
|
|
|
|
class AdminPanelSessionConfigurationResponse(BaseModel):
|
|
access_cookie_name: str
|
|
refresh_cookie_name: str
|
|
cookie_path: str
|
|
same_site: str
|
|
secure_cookies: bool
|
|
|
|
|
|
class AdminSystemRuntimeConfigurationPayload(BaseModel):
|
|
application: AdminRuntimeApplicationConfigurationResponse
|
|
database: AdminRuntimeDatabaseConfigurationResponse
|
|
panel_session: AdminPanelSessionConfigurationResponse
|
|
|
|
|
|
class AdminConfigurationSourceResponse(BaseModel):
|
|
key: str
|
|
source: str
|
|
mutable: bool
|
|
description: str
|
|
|
|
|
|
class AdminSystemRuntimeConfigurationResponse(BaseModel):
|
|
service: str
|
|
runtime: AdminSystemRuntimeConfigurationPayload
|
|
|
|
|
|
class AdminSystemSecurityConfigurationResponse(BaseModel):
|
|
service: str
|
|
security: AdminCredentialStrategy
|
|
|
|
|
|
class AdminSystemConfigurationResponse(BaseModel):
|
|
service: str
|
|
runtime: AdminSystemRuntimeConfigurationPayload
|
|
security: AdminCredentialStrategy
|
|
sources: list[AdminConfigurationSourceResponse]
|
|
|
|
|
|
class AdminLoginRequest(BaseModel):
|
|
email: str
|
|
password: str = Field(min_length=1)
|
|
|
|
@field_validator("email")
|
|
@classmethod
|
|
def validate_email(cls, value: str) -> str:
|
|
normalized = value.strip().lower()
|
|
if "@" not in normalized or normalized.startswith("@") or normalized.endswith("@"):
|
|
raise ValueError("email must be a valid administrative login")
|
|
return normalized
|
|
|
|
|
|
class AdminRefreshTokenRequest(BaseModel):
|
|
refresh_token: str = Field(min_length=1)
|
|
|
|
|
|
class AdminSessionResponse(BaseModel):
|
|
session_id: int
|
|
access_token: str
|
|
refresh_token: str
|
|
token_type: str
|
|
expires_in_seconds: int
|
|
staff_account: AdminAuthenticatedStaffResponse
|
|
|
|
|
|
class AdminLogoutResponse(BaseModel):
|
|
service: str
|
|
status: str
|
|
message: str
|
|
session_id: int
|
|
|
|
|
|
class AdminPanelWebSessionResponse(BaseModel):
|
|
service: str
|
|
status: str
|
|
message: str
|
|
session_id: int
|
|
expires_in_seconds: int
|
|
staff_account: AdminAuthenticatedStaffResponse
|
|
redirect_to: str | None = None
|
|
|
|
|
|
class AdminPanelLogoutResponse(BaseModel):
|
|
service: str
|
|
status: str
|
|
message: str
|
|
session_id: int | None
|
|
redirect_to: str
|
|
|
|
|
|
class AdminToolManagementMetricResponse(BaseModel):
|
|
key: str
|
|
label: str
|
|
value: str
|
|
description: str
|
|
|
|
|
|
class AdminToolLifecycleStageResponse(BaseModel):
|
|
code: ToolLifecycleStatus
|
|
label: str
|
|
description: str
|
|
|
|
|
|
class AdminToolParameterTypeResponse(BaseModel):
|
|
code: ToolParameterType
|
|
label: str
|
|
description: str
|
|
|
|
|
|
class AdminToolManagementActionResponse(BaseModel):
|
|
key: str
|
|
label: str
|
|
href: str
|
|
required_permission: AdminPermission
|
|
description: str
|
|
|
|
|
|
class AdminToolOverviewResponse(BaseModel):
|
|
service: str
|
|
mode: str
|
|
metrics: list[AdminToolManagementMetricResponse]
|
|
workflow: list[AdminToolLifecycleStageResponse]
|
|
actions: list[AdminToolManagementActionResponse]
|
|
next_steps: list[str]
|
|
|
|
|
|
class AdminToolContractsResponse(BaseModel):
|
|
service: str
|
|
publication_source_service: ServiceName
|
|
publication_target_service: ServiceName
|
|
lifecycle_statuses: list[AdminToolLifecycleStageResponse]
|
|
parameter_types: list[AdminToolParameterTypeResponse]
|
|
publication_fields: list[str]
|
|
published_tool_fields: list[str]
|
|
|
|
|
|
class AdminToolDraftSummaryResponse(BaseModel):
|
|
draft_id: str
|
|
tool_name: str
|
|
display_name: str
|
|
status: ToolLifecycleStatus
|
|
summary: str
|
|
owner_name: str | None = None
|
|
updated_at: datetime | None = None
|
|
|
|
|
|
class AdminToolDraftListResponse(BaseModel):
|
|
service: str
|
|
storage_status: str
|
|
message: str
|
|
drafts: list[AdminToolDraftSummaryResponse]
|
|
supported_statuses: list[ToolLifecycleStatus]
|
|
|
|
|
|
class AdminToolReviewQueueEntryResponse(BaseModel):
|
|
entry_id: str
|
|
tool_name: str
|
|
display_name: str
|
|
status: ToolLifecycleStatus
|
|
gate: str
|
|
summary: str
|
|
owner_name: str | None = None
|
|
queued_at: datetime | None = None
|
|
|
|
|
|
class AdminToolReviewQueueResponse(BaseModel):
|
|
service: str
|
|
queue_mode: str
|
|
message: str
|
|
items: list[AdminToolReviewQueueEntryResponse]
|
|
supported_statuses: list[ToolLifecycleStatus]
|
|
|
|
|
|
class AdminToolPublicationSummaryResponse(BaseModel):
|
|
publication_id: str
|
|
tool_name: str
|
|
display_name: str
|
|
description: str
|
|
domain: str
|
|
version: int
|
|
status: ToolLifecycleStatus
|
|
parameter_count: int
|
|
implementation_module: str
|
|
implementation_callable: str
|
|
published_by: str | None = None
|
|
published_at: datetime | None = None
|
|
|
|
|
|
class AdminToolPublicationListResponse(BaseModel):
|
|
service: str
|
|
source: str
|
|
target_service: ServiceName
|
|
publications: list[AdminToolPublicationSummaryResponse]
|
|
|
|
class AdminToolDraftIntakeParameterRequest(BaseModel):
|
|
name: str = Field(min_length=1, max_length=64)
|
|
parameter_type: ToolParameterType
|
|
description: str = Field(min_length=1, max_length=180)
|
|
required: bool = True
|
|
|
|
@field_validator("name")
|
|
@classmethod
|
|
def normalize_name(cls, value: str) -> str:
|
|
return value.strip().lower()
|
|
|
|
@field_validator("description")
|
|
@classmethod
|
|
def normalize_description(cls, value: str) -> str:
|
|
return value.strip()
|
|
|
|
|
|
class AdminToolDraftIntakeRequest(BaseModel):
|
|
tool_name: str = Field(min_length=3, max_length=64)
|
|
display_name: str = Field(min_length=4, max_length=120)
|
|
domain: str = Field(min_length=3, max_length=40)
|
|
description: str = Field(min_length=16, max_length=280)
|
|
business_goal: str = Field(min_length=12, max_length=280)
|
|
parameters: list[AdminToolDraftIntakeParameterRequest] = Field(default_factory=list, max_length=10)
|
|
|
|
@field_validator("tool_name")
|
|
@classmethod
|
|
def normalize_tool_name(cls, value: str) -> str:
|
|
return value.strip().lower()
|
|
|
|
@field_validator("display_name", "description", "business_goal")
|
|
@classmethod
|
|
def strip_text_fields(cls, value: str) -> str:
|
|
return value.strip()
|
|
|
|
@field_validator("domain")
|
|
@classmethod
|
|
def normalize_domain(cls, value: str) -> str:
|
|
return value.strip().lower()
|
|
|
|
|
|
class AdminToolDraftIntakePreviewParameterResponse(BaseModel):
|
|
name: str
|
|
parameter_type: ToolParameterType
|
|
description: str
|
|
required: bool
|
|
|
|
|
|
class AdminToolDraftIntakePreviewResponse(BaseModel):
|
|
draft_id: str
|
|
tool_name: str
|
|
display_name: str
|
|
domain: str
|
|
status: ToolLifecycleStatus
|
|
summary: str
|
|
business_goal: str
|
|
parameter_count: int
|
|
required_parameter_count: int
|
|
requires_director_approval: bool
|
|
owner_name: str | None = None
|
|
parameters: list[AdminToolDraftIntakePreviewParameterResponse]
|
|
|
|
|
|
class AdminToolDraftIntakeResponse(BaseModel):
|
|
service: str
|
|
storage_status: str
|
|
message: str
|
|
draft_preview: AdminToolDraftIntakePreviewResponse
|
|
warnings: list[str]
|
|
next_steps: list[str]
|
|
|
|
class AdminCollaboratorSummaryResponse(BaseModel):
|
|
id: int
|
|
email: str
|
|
display_name: str
|
|
role: StaffRole
|
|
is_active: bool
|
|
last_login_at: datetime | None = None
|
|
created_at: datetime | None = None
|
|
updated_at: datetime | None = None
|
|
|
|
|
|
class AdminCollaboratorListResponse(BaseModel):
|
|
service: str
|
|
total: int
|
|
active_count: int
|
|
inactive_count: int
|
|
collaborators: list[AdminCollaboratorSummaryResponse]
|
|
|
|
|
|
class AdminCollaboratorCreateRequest(BaseModel):
|
|
email: str
|
|
display_name: str = Field(min_length=3, max_length=150)
|
|
password: str = Field(min_length=1)
|
|
is_active: bool = True
|
|
|
|
@field_validator("email")
|
|
@classmethod
|
|
def normalize_email(cls, value: str) -> str:
|
|
normalized = value.strip().lower()
|
|
if "@" not in normalized or normalized.startswith("@") or normalized.endswith("@"):
|
|
raise ValueError("email must be a valid administrative login")
|
|
return normalized
|
|
|
|
@field_validator("display_name")
|
|
@classmethod
|
|
def normalize_display_name(cls, value: str) -> str:
|
|
return value.strip()
|
|
|
|
|
|
class AdminCollaboratorCreateResponse(BaseModel):
|
|
service: str
|
|
message: str
|
|
collaborator: AdminCollaboratorSummaryResponse
|
|
|
|
|
|
class AdminCollaboratorStatusUpdateRequest(BaseModel):
|
|
is_active: bool
|
|
|
|
|
|
class AdminCollaboratorStatusUpdateResponse(BaseModel):
|
|
service: str
|
|
message: str
|
|
collaborator: AdminCollaboratorSummaryResponse
|