feat: standardize input styling with tier system, add depth and admin features

- Define 4 input tier CSS classes (input-standard, input-search, input-embedded, input-danger)
  in globals.css, migrating ~50 inputs across ~28 component files to use them
- Add subtle border and inset shadow to solid input tiers for resting-state visibility
- Fix focus ring clipping in settings panel scroll container
- Fix phantom Tailwind tokens (border-border-primary, placeholder-txt-muted)
- Add admin user management panel, storage management, and account deletion utilities
This commit is contained in:
Jannis Braun
2026-03-14 13:49:32 +01:00
parent afbc4b5e31
commit 836f0acef6
45 changed files with 1478 additions and 235 deletions
+4 -20
View File
@@ -1,7 +1,7 @@
import type { FastifyInstance } from 'fastify';
import { eq } from 'drizzle-orm';
import { getDb, schema } from '../db/index.js';
import { authenticate } from '../utils/auth.js';
import { authenticate, requireAdmin } from '../utils/auth.js';
import { config } from '../config.js';
import type { InstanceStreamingLimits, InstanceAdminSettings } from '@backspace/shared';
@@ -33,15 +33,9 @@ export async function settingsRoutes(app: FastifyInstance): Promise<void> {
});
// PATCH /api/settings/streaming — admin only
app.patch<{ Body: Partial<InstanceStreamingLimits> }>('/api/settings/streaming', { preHandler: authenticate }, async (request, reply) => {
app.patch<{ Body: Partial<InstanceStreamingLimits> }>('/api/settings/streaming', { preHandler: [authenticate, requireAdmin] }, async (request, reply) => {
const db = getDb();
// Verify caller is an instance admin
const caller = db.select().from(schema.users).where(eq(schema.users.id, request.userId)).get();
if (!caller || caller.isAdmin !== 1) {
return reply.code(403).send({ error: 'Only instance admins can modify streaming settings', statusCode: 403 });
}
const body = request.body;
const updateData: Record<string, number | string> = { updatedAt: Date.now() };
@@ -129,14 +123,9 @@ export async function settingsRoutes(app: FastifyInstance): Promise<void> {
});
// GET /api/settings/instance — admin only, returns instance admin settings
app.get('/api/settings/instance', { preHandler: authenticate }, async (request, reply) => {
app.get('/api/settings/instance', { preHandler: [authenticate, requireAdmin] }, async (_request, reply) => {
const db = getDb();
const caller = db.select().from(schema.users).where(eq(schema.users.id, request.userId)).get();
if (!caller || caller.isAdmin !== 1) {
return reply.code(403).send({ error: 'Only instance admins can view instance settings', statusCode: 403 });
}
const row = db.select().from(schema.instanceSettings).where(eq(schema.instanceSettings.id, 1)).get();
if (!row) {
return reply.code(500).send({ error: 'Instance settings not initialized', statusCode: 500 });
@@ -152,14 +141,9 @@ export async function settingsRoutes(app: FastifyInstance): Promise<void> {
});
// PATCH /api/settings/instance — admin only, updates instance admin settings
app.patch<{ Body: Partial<InstanceAdminSettings> }>('/api/settings/instance', { preHandler: authenticate }, async (request, reply) => {
app.patch<{ Body: Partial<InstanceAdminSettings> }>('/api/settings/instance', { preHandler: [authenticate, requireAdmin] }, async (request, reply) => {
const db = getDb();
const caller = db.select().from(schema.users).where(eq(schema.users.id, request.userId)).get();
if (!caller || caller.isAdmin !== 1) {
return reply.code(403).send({ error: 'Only instance admins can modify instance settings', statusCode: 403 });
}
const body = request.body;
const updateData: Record<string, number | string> = { updatedAt: Date.now() };