feat: auth & admin

This commit is contained in:
2026-06-03 10:40:00 +03:00
parent 4bca90a50e
commit 93199a3095
34 changed files with 1634 additions and 119 deletions
+1
View File
@@ -0,0 +1 @@
"""Pydantic request/response models for the native REST API (``/api/v1``)."""
+20
View File
@@ -0,0 +1,20 @@
"""Auth request/response schemas. Tokens are returned in the body (the client
stores them); refresh is presented back in the body too (offline-first clients
manage their own token store, not cookies)."""
from pydantic import BaseModel, Field
class LoginRequest(BaseModel):
username: str = Field(min_length=1, max_length=64)
password: str = Field(min_length=1)
class RefreshRequest(BaseModel):
refresh_token: str
class TokenResponse(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
+46
View File
@@ -0,0 +1,46 @@
"""User schemas. ``password_hash`` is never exposed — only ``UserResponse``
fields leave the service."""
import datetime as dt
import uuid
from pydantic import BaseModel, ConfigDict, Field
from app.domain.entities import User
class UserResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
username: str
is_superuser: bool
is_active: bool
created_at: dt.datetime
updated_at: dt.datetime
@classmethod
def from_entity(cls, user: User) -> UserResponse:
return cls.model_validate(user)
class CreateUserRequest(BaseModel):
username: str = Field(min_length=1, max_length=64)
password: str = Field(min_length=8)
is_superuser: bool = False
class UpdateUserRequest(BaseModel):
"""Admin patch — every field optional; only provided ones change."""
is_superuser: bool | None = None
is_active: bool | None = None
class ResetPasswordRequest(BaseModel):
new_password: str = Field(min_length=8)
class ChangePasswordRequest(BaseModel):
current_password: str = Field(min_length=1)
new_password: str = Field(min_length=8)