- Backup/restore: per-stack tar.gz incl. named-volume snapshots (helper container), upload restore with rename/overwrite/conflict detection. - Notifications: ntfy/Discord/Slack/Gotify/generic webhooks, per-event subscriptions; wired into the update checker and stack lifecycle. - Settings page: update-check interval, webhook CRUD + test, user management (with last-admin safeguards). - Audit log page (searchable, paginated). - Mobile-responsive sidebar/layout. Multi-host agents and remote backup destinations (SFTP/S3) deferred. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
57 lines
1.1 KiB
Python
57 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
|
|
from sqlmodel import Field, SQLModel
|
|
|
|
|
|
def _now() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
class User(SQLModel, table=True):
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
username: str = Field(index=True, unique=True)
|
|
hashed_password: str
|
|
role: str = Field(default="user") # "admin" | "user"
|
|
is_active: bool = Field(default=True)
|
|
created_at: datetime = Field(default_factory=_now)
|
|
|
|
|
|
# --- API schemas ---
|
|
|
|
|
|
class UserRead(SQLModel):
|
|
id: int
|
|
username: str
|
|
role: str
|
|
is_active: bool
|
|
|
|
|
|
class UserCreate(SQLModel):
|
|
username: str
|
|
password: str
|
|
role: str = "admin"
|
|
|
|
|
|
class UserUpdate(SQLModel):
|
|
password: Optional[str] = None
|
|
role: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
|
|
class LoginRequest(SQLModel):
|
|
username: str
|
|
password: str
|
|
|
|
|
|
class TokenPair(SQLModel):
|
|
access_token: str
|
|
refresh_token: str
|
|
token_type: str = "bearer"
|
|
|
|
|
|
class RefreshRequest(SQLModel):
|
|
refresh_token: str
|