c5166ba3a9
Add admin layout with auth guard, user management (CRUD + group membership), group management, system settings (auth mode, registration, theme, healthcheck), permission editor component, and global search API endpoint.
40 lines
6.3 KiB
Markdown
40 lines
6.3 KiB
Markdown
# Feature Context: Web App Launcher — MVP
|
|
|
|
## Current State
|
|
|
|
Phase 4 (App Registry & Healthcheck) is complete. All app CRUD API routes are implemented at `/api/apps` (GET/POST) and `/api/apps/[id]` (GET/PATCH/DELETE) with Zod validation and auth middleware. Status history is served from `/api/apps/[id]/status`. The healthcheck service performs HTTP HEAD/GET requests with AbortController timeouts, mapping responses to online/offline/degraded/unknown. The scheduler uses node-cron (default: every 60 seconds) with an initial delayed check on startup. Icon resolution supports lucide, simple-icons (CDN), direct URL, and emoji types. The app registry UI at `/apps` renders cards in a responsive grid with category filtering and an inline Superforms create form. Custom icon uploads are handled at `/api/uploads` with type (SVG/PNG/JPG/WebP) and size (<1MB) validation, saving to `static/uploads/`. A Docker healthcheck endpoint at `/api/health` returns 200 with no auth. All Svelte components use runes mode ($state, $derived, $props).
|
|
|
|
Phase 3 (Authentication System) is complete. The full local authentication flow is implemented: login, registration, logout, and JWT token refresh. `hooks.server.ts` validates access tokens on every request, injects `event.locals.user`/`session`, and silently rotates expired tokens via refresh tokens. Protected routes redirect to `/login`; guest-accessible board routes are exempt. Login and registration pages use Superforms + Zod with inline validation errors. Registration respects the `SystemSettings.registrationEnabled` toggle. Reusable middleware helpers (`requireAuth`, `requireAdmin`, `requireRole`) are available for downstream phases. The root layout injects user session into all page data. The root page redirects to the default board or login. `jwt.ts` and `password.ts` are thin re-exports from `authService` (no duplication). Build does not pass yet (Big Bang strategy — expected).
|
|
|
|
Phase 5 (Board, Section & Widget System) is complete. All 20 tasks implemented: 5 API route files for board/section/widget CRUD (`/api/boards`, `/api/boards/[id]`, `/api/boards/[id]/sections`, `/api/boards/[id]/sections/[sid]`, `/api/boards/[id]/sections/[sid]/widgets`), 3 page routes for board list (`/boards`), board view (`/boards/[boardId]`), and board editor (`/boards/[boardId]/edit`), plus 9 Svelte components across board/section/widget directories. Board list API filters by permissions: admins see all, regular users see boards where they have VIEW+ permission via `permissionService.checkPermission()`, guests see only `isGuestAccessible` boards. Board view loads the full hierarchy (board -> sections -> widgets -> app -> latest status) via `boardService.findBoardById`. The board editor uses SvelteKit form actions (updateBoard, addSection/updateSection/deleteSection, addWidget/deleteWidget) with `use:enhance` for progressive enhancement. Section collapse uses Svelte's built-in `slide` transition. Widget grid is responsive CSS grid (2 cols mobile, 3 tablet, 4 desktop). `AppWidget` reuses `AppHealthBadge` for status display.
|
|
|
|
Phase 6 (Admin Panel) is complete. All 18 tasks implemented: admin layout with `requireAdmin` guard in `+layout.server.ts` and nav bar linking Users/Groups/Settings plus Back to Dashboard. User management at `/admin/users` supports full CRUD via Superforms (create with email/displayName/password/role, inline role editing, delete with confirmation) plus group membership management (add/remove users from groups). Group management at `/admin/groups` supports CRUD with inline editing, member count display, and default-group toggle. System settings at `/admin/settings` configures auth mode (local/oauth/both), registration toggle, OAuth fields (stored, non-functional in MVP), default theme (dark/light), default primary color (hex), and healthcheck defaults (JSON). Four admin components created: `UserTable.svelte`, `GroupTable.svelte`, `SettingsForm.svelte`, and `PermissionEditor.svelte` (reusable with `onGrant`/`onRevoke` callback props for entity/target/level selection). Six REST API route files added: `/api/users` (GET/POST), `/api/users/[id]` (GET/PATCH/DELETE), `/api/groups` (GET/POST), `/api/groups/[id]` (GET/PATCH/DELETE), `/api/admin/settings` (GET/PATCH) — all admin-only. Global search endpoint at `/api/search?q=term` searches apps by name/description/category and boards by name/description, filtering results by user permissions via `permissionService.checkPermission`. Self-deletion protection prevents admin from deleting their own account. All forms use Superforms + Zod validation schemas from `$lib/utils/validators.ts`.
|
|
|
|
## Temporary Workarounds
|
|
|
|
- Permission model uses polymorphic pattern (entityType/targetType strings) without FK relations to avoid SQLite dual-FK constraint issues. Queries are done manually in `permissionService.ts`.
|
|
- JSON fields (backgroundConfig, config, healthcheckDefaults) are stored as String in SQLite and parsed at the application layer.
|
|
- `package.json` `prisma.seed` config triggers a deprecation warning — migrate to `prisma.config.ts` when upgrading to Prisma 7.
|
|
|
|
## Cross-Phase Dependencies
|
|
|
|
- Phase 2 depends on Phase 1 (project scaffolding, Prisma setup)
|
|
- Phase 3 depends on Phase 2 (user/group models, auth service) ✅
|
|
- Phase 4 depends on Phase 2 (app model, services layer)
|
|
- Phase 5 depends on Phase 2 (board/section/widget models) and Phase 4 (app widget references apps)
|
|
- Phase 6 depends on Phases 3-5 (admin needs auth, app, board entities)
|
|
- Phase 7 depends on Phase 1 (Tailwind, shadcn-svelte) and Phase 5 (board layout to polish)
|
|
- Phase 8 depends on all prior phases
|
|
|
|
## Implementation Notes
|
|
|
|
- Big Bang strategy: intermediate phases may not build/pass tests. Only Phase 8 must result in a fully working build.
|
|
- SQLite with Prisma — single file DB at `data/launcher.db`
|
|
- All env config via environment variables; `.env.example` provided as template
|
|
- Svelte 5 runes mode: use `$state`, `$derived`, `$effect` — NOT legacy stores for component state
|
|
- shadcn-svelte uses Bits UI primitives — each component is a local file, not a library import
|
|
- `App.Locals` uses `email` + `displayName` fields (aligned with User model, updated in Phase 2)
|
|
- Prisma client singleton at `src/lib/server/prisma.ts` — use this for all DB access
|
|
- Services export pure async functions (not classes), use immutable patterns
|
|
- `tsx` devDependency added for running the seed script
|