# [DEF:backend.src.schemas.profile:Module] # # @TIER: STANDARD # @SEMANTICS: profile, schemas, pydantic, preferences, superset, lookup, security, git, ux # @PURPOSE: Defines API schemas for profile preference persistence, security read-only snapshot, and Superset account lookup. # @LAYER: API # @RELATION: DEPENDS_ON -> pydantic # # @INVARIANT: Schema shapes stay stable for profile UI states and backend preference contracts. # [SECTION: IMPORTS] from datetime import datetime from typing import List, Literal, Optional from pydantic import BaseModel, Field # [/SECTION] # [DEF:ProfilePermissionState:Class] # @TIER: STANDARD # @PURPOSE: Represents one permission badge state for profile read-only security view. class ProfilePermissionState(BaseModel): key: str allowed: bool # [/DEF:ProfilePermissionState:Class] # [DEF:ProfileSecuritySummary:Class] # @TIER: STANDARD # @PURPOSE: Read-only security and access snapshot for current user. class ProfileSecuritySummary(BaseModel): read_only: bool = True auth_source: Optional[str] = None current_role: Optional[str] = None role_source: Optional[str] = None roles: List[str] = Field(default_factory=list) permissions: List[ProfilePermissionState] = Field(default_factory=list) # [/DEF:ProfileSecuritySummary:Class] # [DEF:ProfilePreference:Class] # @TIER: STANDARD # @PURPOSE: Represents persisted profile preference for a single authenticated user. class ProfilePreference(BaseModel): user_id: str superset_username: Optional[str] = None superset_username_normalized: Optional[str] = None show_only_my_dashboards: bool = False git_username: Optional[str] = None git_email: Optional[str] = None has_git_personal_access_token: bool = False git_personal_access_token_masked: Optional[str] = None start_page: Literal["dashboards", "datasets", "reports"] = "dashboards" auto_open_task_drawer: bool = True dashboards_table_density: Literal["compact", "comfortable"] = "comfortable" created_at: datetime updated_at: datetime class Config: from_attributes = True # [/DEF:ProfilePreference:Class] # [DEF:ProfilePreferenceUpdateRequest:Class] # @TIER: STANDARD # @PURPOSE: Request payload for updating current user's profile settings. class ProfilePreferenceUpdateRequest(BaseModel): superset_username: Optional[str] = Field( default=None, description="Apache Superset username bound to current user profile.", ) show_only_my_dashboards: Optional[bool] = Field( default=None, description='When true, "/dashboards" can auto-apply profile filter in main context.', ) git_username: Optional[str] = Field( default=None, description="Git author username used for commit signature.", ) git_email: Optional[str] = Field( default=None, description="Git author email used for commit signature.", ) git_personal_access_token: Optional[str] = Field( default=None, description="Personal Access Token value. Empty string clears existing token.", ) start_page: Optional[ Literal["dashboards", "datasets", "reports", "reports-logs"] ] = Field( default=None, description="Preferred start page after login.", ) auto_open_task_drawer: Optional[bool] = Field( default=None, description="Auto-open task drawer when long-running tasks start.", ) dashboards_table_density: Optional[ Literal["compact", "comfortable", "free"] ] = Field( default=None, description="Preferred table density for dashboard listings.", ) # [/DEF:ProfilePreferenceUpdateRequest:Class] # [DEF:ProfilePreferenceResponse:Class] # @TIER: STANDARD # @PURPOSE: Response envelope for profile preference read/update endpoints. class ProfilePreferenceResponse(BaseModel): status: Literal["success", "error"] = "success" message: Optional[str] = None validation_errors: List[str] = Field(default_factory=list) preference: ProfilePreference security: ProfileSecuritySummary = Field(default_factory=ProfileSecuritySummary) # [/DEF:ProfilePreferenceResponse:Class] # [DEF:SupersetAccountLookupRequest:Class] # @TIER: STANDARD # @PURPOSE: Query contract for Superset account lookup by selected environment. class SupersetAccountLookupRequest(BaseModel): environment_id: str search: Optional[str] = None page_index: int = Field(default=0, ge=0) page_size: int = Field(default=20, ge=1, le=100) sort_column: str = Field(default="username") sort_order: str = Field(default="desc") # [/DEF:SupersetAccountLookupRequest:Class] # [DEF:SupersetAccountCandidate:Class] # @TIER: STANDARD # @PURPOSE: Canonical account candidate projected from Superset users payload. class SupersetAccountCandidate(BaseModel): environment_id: str username: str display_name: Optional[str] = None email: Optional[str] = None is_active: Optional[bool] = None # [/DEF:SupersetAccountCandidate:Class] # [DEF:SupersetAccountLookupResponse:Class] # @TIER: STANDARD # @PURPOSE: Response envelope for Superset account lookup (success or degraded mode). class SupersetAccountLookupResponse(BaseModel): status: Literal["success", "degraded"] environment_id: str page_index: int = Field(ge=0) page_size: int = Field(ge=1, le=100) total: int = Field(ge=0) warning: Optional[str] = None items: List[SupersetAccountCandidate] = Field(default_factory=list) # [/DEF:SupersetAccountLookupResponse:Class] # [/DEF:backend.src.schemas.profile:Module]