Add customizable home dashboard with per-user pinned apps
- Users can pin/unpin any available service on their home page via a Customize mode; preferences persisted via PATCH /api/users/me/preferences - Time-aware greeting renders the user's display name through React JSX (HTML-escaped by design — no dangerouslySetInnerHTML used) - Added dashboard_app_ids JSON column to users table (migration c7e8f9a0b1d2) - /settings now routes to a placeholder page Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -96,3 +96,24 @@ class UserAdminCreate(UserCreate):
|
||||
class Token(BaseModel):
|
||||
access_token: str
|
||||
token_type: str = "bearer"
|
||||
|
||||
|
||||
# ── Dashboard preferences ──────────────────────────────────────────────────────
|
||||
|
||||
class DashboardPrefsOut(BaseModel):
|
||||
app_ids: list[str]
|
||||
|
||||
|
||||
class DashboardPrefsUpdate(BaseModel):
|
||||
app_ids: list[str] = Field(default_factory=list)
|
||||
|
||||
@field_validator("app_ids")
|
||||
@classmethod
|
||||
def validate_app_ids(cls, v: list[str]) -> list[str]:
|
||||
if len(v) > 50:
|
||||
raise ValueError("Cannot pin more than 50 apps")
|
||||
for item in v:
|
||||
# Service IDs are alphanumeric slugs or UUIDs — no HTML/script allowed.
|
||||
if not re.match(r'^[a-zA-Z0-9_\-]{1,64}$', item):
|
||||
raise ValueError(f"Invalid app ID: {item!r}")
|
||||
return v
|
||||
|
||||
Reference in New Issue
Block a user