Add editable site name and finish service image upload

User asked to remove the hardcoded "TeaBoy" branding and let admins
change the system name. Also completes the in-progress service image
upload work via App Storage.

Changes:
- New app_settings table (single row id=1) with siteNameAr/siteNameEn
- New /settings endpoints: GET (public) + PATCH (admin)
- Atomic ensureSettingsRow via INSERT ... ON CONFLICT DO NOTHING
  to avoid race conditions
- New SiteSettingsPanel tab in admin page (Arabic + English inputs)
- New useAppName hook reads settings, updates document.title, falls
  back to defaults while loading
- Login + register pages now display the dynamic site name
- Service image upload (App Storage) wired via useUpload + presigned
  GCS URL flow; admin component ServiceImageUploader
- Storage routes: /storage/uploads/request-url and /storage/objects/*
  now require auth (closes previously-open endpoints flagged by review)
- Added AppSettings/UpdateAppSettingsBody + storage schemas to
  openapi.yaml; regenerated client and zod
- Exposed UploadResponse from @workspace/object-storage-web; added
  composite:true so it can be referenced by teaboy-os tsconfig

Validation: typechecks pass for api-server and teaboy-os; settings GET
returns row; upload URL endpoint returns 401 without auth.
This commit is contained in:
riyadhafraa
2026-04-20 11:06:15 +00:00
parent 8df5e76d29
commit 397a384785
19 changed files with 446 additions and 29 deletions
+61
View File
@@ -236,6 +236,43 @@ paths:
"204":
description: Deleted
# Settings
/settings:
get:
operationId: getAppSettings
tags: [settings]
summary: Get application settings (public)
responses:
"200":
description: Current settings
content:
application/json:
schema:
$ref: "#/components/schemas/AppSettings"
patch:
operationId: updateAppSettings
tags: [settings]
summary: Update application settings (admin)
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateAppSettingsBody"
responses:
"200":
description: Updated settings
content:
application/json:
schema:
$ref: "#/components/schemas/AppSettings"
"400":
description: Invalid input
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
# Storage
/storage/uploads/request-url:
post:
@@ -1140,6 +1177,30 @@ components:
- isRead
- createdAt
AppSettings:
type: object
required: [siteNameAr, siteNameEn]
properties:
siteNameAr:
type: string
siteNameEn:
type: string
updatedAt:
type: string
format: date-time
UpdateAppSettingsBody:
type: object
properties:
siteNameAr:
type: string
minLength: 1
maxLength: 200
siteNameEn:
type: string
minLength: 1
maxLength: 200
RequestUploadUrlBody:
type: object
required: [name, size, contentType]