Files
portfolio-hub/app/schemas/auth.py
T
genichin 3bb3ff547d feat: extend daemon model with daemon status tracking and list support
- Add daemon status tracking with state and metrics (idle, running, error)
- Implement pfhub daemon list CLI command for viewing registered daemons
- Extend auth schema and service for daemon lifecycle management
- Add postgres repository queries for daemon state persistence
- Expand test coverage for daemon registry and status transitions
- Update rel-006 release document with daemon model verification results
- Support daemon graceful shutdown and error recovery patterns
2026-05-14 06:29:52 +00:00

115 lines
3.1 KiB
Python

"""Authentication request and response schemas."""
from __future__ import annotations
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, Field, field_validator
from app.schemas.user import UserResponse
class LoginRequest(BaseModel):
username: str = Field(min_length=1)
password: str = Field(min_length=1)
@field_validator("username")
@classmethod
def normalize_username(cls, value: str) -> str:
normalized = value.strip()
if not normalized:
raise ValueError("username은 비어 있을 수 없습니다")
return normalized
class TokenResponse(BaseModel):
access_token: str
token_type: Literal["bearer"] = "bearer"
expires_at: datetime | None = None
permission: Literal["read", "trade-write", "admin"]
user: UserResponse
class CreateClientTokenRequest(BaseModel):
name: str = Field(min_length=1)
permission: Literal["read", "trade-write", "admin"] | None = None
expires_in_days: int | None = Field(default=None, ge=1, le=3650)
@field_validator("name")
@classmethod
def normalize_name(cls, value: str) -> str:
normalized = value.strip()
if not normalized:
raise ValueError("name은 비어 있을 수 없습니다")
return normalized
class AuthTokenResponse(BaseModel):
id: str
user_id: str
name: str
token_prefix: str
permission: Literal["read", "trade-write", "admin"]
token_type: Literal["session", "client", "service"]
daemon_id: str | None = None
expires_at: datetime | None = None
last_used_at: datetime | None = None
revoked_at: datetime | None = None
created_at: datetime | None = None
class IssuedClientTokenResponse(BaseModel):
token: str
token_type: Literal["bearer"] = "bearer"
auth_token: AuthTokenResponse
class IssuedServiceToken(BaseModel):
token: str
token_type: Literal["bearer"] = "bearer"
auth_token: AuthTokenResponse
class IssueServiceTokenRequest(BaseModel):
name: str = Field(min_length=1)
username: str = Field(min_length=1)
permission: Literal["read", "trade-write", "admin"] = "read"
expires_in_days: int | None = Field(default=None, ge=1, le=3650)
no_expiry: bool = False
daemon_id: str | None = None
class IssueServiceTokenApiResponse(BaseModel):
token: str
token_type: Literal["bearer"] = "bearer"
runtime_id: str | None = None
daemon_id: str | None = None
auth_token: AuthTokenResponse
class ServiceTokenIssueCliResponse(BaseModel):
token_id: str
name: str
expires_at: datetime | None = None
revoked: bool
runtime_id: str | None = None
daemon_id: str | None = None
token: str | None = None
class ServiceTokenRebindCliResponse(BaseModel):
token_id: str
name: str
expires_at: datetime | None = None
revoked: bool
runtime_id: str | None = None
daemon_id: str | None = None
previous_daemon_id: str | None = None
class ServiceTokenRevokeCliResponse(BaseModel):
token_id: str
name: str
revoked: bool
revoked_at: datetime | None = None