Files
NexaPantry/backend/app/schemas/common.py
nessi 5ed613d441
Some checks failed
CI / backend (push) Failing after 17s
CI / frontend (push) Successful in 31s
CI / docker (push) Has been skipped
fix: improve SMTP configuration and error handling
- Change default use_tls from True to False to match typical STARTTLS setup
- Add MailDeliveryError exception for mail delivery failures
- Wrap send_mail calls in try-catch blocks to handle errors gracefully
- Return 502 status code with error details when mail delivery fails
- Add SMTP security mode selector in frontend (STARTTLS/TLS/None)
- Add test mail form to admin panel
- Handle empty SMTP credentials properly in update_mail_settings
- Catch
2026-06-04 11:00:11 +02:00

162 lines
4.2 KiB
Python

from datetime import date, datetime
from pydantic import BaseModel, EmailStr, Field
class Message(BaseModel):
message: str
class SetupStatus(BaseModel):
needs_setup: bool
instance: dict | None = None
class SetupCreate(BaseModel):
name: str = Field(min_length=1, max_length=160)
email: EmailStr
password: str = Field(min_length=12, max_length=256)
language: str
theme: str
public_url: str = Field(min_length=1, max_length=500)
instance_name: str = Field(min_length=1, max_length=160)
timezone: str = Field(min_length=1, max_length=80)
class LoginRequest(BaseModel):
email: EmailStr
password: str = Field(min_length=1, max_length=256)
class UserOut(BaseModel):
id: str
email: EmailStr
name: str
instance_role: str
language: str
theme: str
timezone: str
is_active: bool
onboarding_completed: bool
model_config = {"from_attributes": True}
class UserCreate(BaseModel):
email: EmailStr
name: str = Field(min_length=1, max_length=160)
role: str = "user"
send_invite: bool = True
class UserUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=160)
language: str | None = None
theme: str | None = None
timezone: str | None = None
instance_role: str | None = None
is_active: bool | None = None
onboarding_completed: bool | None = None
class InviteAccept(BaseModel):
token: str
name: str = Field(min_length=1, max_length=160)
password: str = Field(min_length=12, max_length=256)
language: str
theme: str
home_name: str | None = Field(default=None, max_length=160)
join_code: str | None = Field(default=None, max_length=40)
class HomeOut(BaseModel):
id: str
name: str
expiry_warning_days: int
daily_summary_enabled: bool
daily_summary_time: str
role: str | None = None
model_config = {"from_attributes": True}
class HomeCreate(BaseModel):
name: str = Field(min_length=1, max_length=160)
class HomeSettingsUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=160)
expiry_warning_days: int | None = Field(default=None, ge=0, le=60)
daily_summary_enabled: bool | None = None
daily_summary_time: str | None = Field(default=None, pattern=r"^\d{2}:\d{2}$")
class JoinCodeOut(BaseModel):
join_code: str
expires_at: datetime
class ProductIn(BaseModel):
name: str = Field(min_length=1, max_length=220)
barcode: str | None = Field(default=None, max_length=80)
brand: str | None = Field(default=None, max_length=160)
category: str = Field(default="Other", max_length=120)
location: str = Field(default="Pantry", max_length=120)
quantity: float = Field(default=1, ge=0)
unit: str = Field(default="pcs", max_length=32)
expires_at: date | None = None
min_quantity: float = Field(default=0, ge=0)
notes: str | None = Field(default=None, max_length=5000)
image_url: str | None = Field(default=None, max_length=1000)
class ProductOut(ProductIn):
id: str
home_id: str
status: str
model_config = {"from_attributes": True}
class ShoppingItemIn(BaseModel):
name: str = Field(min_length=1, max_length=220)
category: str = Field(default="Other", max_length=120)
quantity: float = Field(default=1, ge=0)
unit: str = Field(default="pcs", max_length=32)
product_id: str | None = None
class ShoppingItemOut(ShoppingItemIn):
id: str
home_id: str
checked: bool
model_config = {"from_attributes": True}
class MailSettingsIn(BaseModel):
smtp_host: str | None = Field(default=None, max_length=220)
smtp_port: int = Field(default=587, ge=1, le=65535)
smtp_user: str | None = Field(default=None, max_length=220)
smtp_password: str | None = Field(default=None, max_length=1000)
use_tls: bool = False
use_starttls: bool = True
sender_address: EmailStr | None = None
sender_name: str = Field(default="NexaPantry", max_length=160)
class MailSettingsOut(BaseModel):
smtp_host: str | None
smtp_port: int
smtp_user: str | None
has_password: bool
use_tls: bool
use_starttls: bool
sender_address: EmailStr | None
sender_name: str
class TestMailIn(BaseModel):
to: EmailStr