Files

135 lines
3.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from datetime import datetime
from pydantic import BaseModel, EmailStr, field_validator
import re
from .models import UserRole, UserStatus
# ── Auth ─────────────────────────────────────────────────────────────────────
class UserRegister(BaseModel):
username: str
email: EmailStr
password: str
role: UserRole = UserRole.student
@field_validator("username")
@classmethod
def username_valid(cls, v: str) -> str:
v = v.strip()
if not re.match(r"^[A-Za-z0-9_]{3,64}$", v):
raise ValueError(
"Username must be 364 characters, letters/numbers/underscore only."
)
return v
@field_validator("password")
@classmethod
def password_strength(cls, v: str) -> str:
if len(v) < 8:
raise ValueError("Password must be at least 8 characters.")
return v
class UserLogin(BaseModel):
username: str
password: str
class UserOut(BaseModel):
id: int
username: str
email: str
role: UserRole
status: UserStatus
created_at: datetime
model_config = {"from_attributes": True}
class UserApprove(BaseModel):
status: UserStatus
class UserRoleUpdate(BaseModel):
role: UserRole
class ChangePassword(BaseModel):
current_password: str
new_password: str
@field_validator("new_password")
@classmethod
def password_strength(cls, v: str) -> str:
if len(v) < 8:
raise ValueError("Password must be at least 8 characters.")
return v
class TokenPayload(BaseModel):
sub: int # user id
exp: int
# ── PDFs ──────────────────────────────────────────────────────────────────────
class PDFOut(BaseModel):
id: int
user_id: int
owner_username: str
title: str
total_pages: int | None
created_at: datetime
model_config = {"from_attributes": True}
class PDFUploadResult(BaseModel):
filename: str
success: bool
pdf: PDFOut | None = None
error: str | None = None
# ── Annotations ───────────────────────────────────────────────────────────────
class AnnotationIn(BaseModel):
canvas_data: dict
# ── Audio ─────────────────────────────────────────────────────────────────────
class AudioOut(BaseModel):
id: int
pdf_id: int
track_name: str
page_number: int | None
sort_order: int
created_at: datetime
model_config = {"from_attributes": True}
class AudioPatch(BaseModel):
track_name: str | None = None
page_number: int | None = None
sort_order: int | None = None
class AudioUploadResult(BaseModel):
filename: str
success: bool
audio: AudioOut | None = None
error: str | None = None
class AnnotationOut(BaseModel):
id: int
pdf_id: int
page_number: int
canvas_data: dict
updated_at: datetime
model_config = {"from_attributes": True}