feat(mvp): phase 6 - admin panel
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.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type { Actions, PageServerLoad } from './$types.js';
|
||||
import { superValidate, setError } from 'sveltekit-superforms';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { fail } from '@sveltejs/kit';
|
||||
import { requireAdmin } from '$lib/server/middleware/authorize.js';
|
||||
import { prisma } from '$lib/server/prisma.js';
|
||||
import { updateSystemSettingsSchema } from '$lib/utils/validators.js';
|
||||
import { DEFAULTS } from '$lib/utils/constants.js';
|
||||
|
||||
async function getOrCreateSettings() {
|
||||
return prisma.systemSettings.upsert({
|
||||
where: { id: DEFAULTS.SYSTEM_SETTINGS_ID },
|
||||
update: {},
|
||||
create: { id: DEFAULTS.SYSTEM_SETTINGS_ID }
|
||||
});
|
||||
}
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
requireAdmin(event);
|
||||
|
||||
const settings = await getOrCreateSettings();
|
||||
|
||||
const form = await superValidate(
|
||||
{
|
||||
authMode: settings.authMode as 'local' | 'oauth' | 'both',
|
||||
registrationEnabled: settings.registrationEnabled,
|
||||
oauthClientId: settings.oauthClientId,
|
||||
oauthClientSecret: settings.oauthClientSecret,
|
||||
oauthDiscoveryUrl: settings.oauthDiscoveryUrl,
|
||||
defaultTheme: settings.defaultTheme as 'dark' | 'light',
|
||||
defaultPrimaryColor: settings.defaultPrimaryColor,
|
||||
healthcheckDefaults: settings.healthcheckDefaults
|
||||
},
|
||||
zod(updateSystemSettingsSchema)
|
||||
);
|
||||
|
||||
return { settings, form };
|
||||
};
|
||||
|
||||
export const actions: Actions = {
|
||||
update: async (event) => {
|
||||
requireAdmin(event);
|
||||
|
||||
const form = await superValidate(event.request, zod(updateSystemSettingsSchema));
|
||||
|
||||
if (!form.valid) {
|
||||
return fail(400, { form });
|
||||
}
|
||||
|
||||
try {
|
||||
const data: Record<string, unknown> = {};
|
||||
const input = form.data;
|
||||
|
||||
if (input.authMode !== undefined) data.authMode = input.authMode;
|
||||
if (input.registrationEnabled !== undefined) data.registrationEnabled = input.registrationEnabled;
|
||||
if (input.oauthClientId !== undefined) data.oauthClientId = input.oauthClientId;
|
||||
if (input.oauthClientSecret !== undefined) data.oauthClientSecret = input.oauthClientSecret;
|
||||
if (input.oauthDiscoveryUrl !== undefined) data.oauthDiscoveryUrl = input.oauthDiscoveryUrl;
|
||||
if (input.defaultTheme !== undefined) data.defaultTheme = input.defaultTheme;
|
||||
if (input.defaultPrimaryColor !== undefined) data.defaultPrimaryColor = input.defaultPrimaryColor;
|
||||
if (input.healthcheckDefaults !== undefined) data.healthcheckDefaults = input.healthcheckDefaults;
|
||||
|
||||
await prisma.systemSettings.upsert({
|
||||
where: { id: DEFAULTS.SYSTEM_SETTINGS_ID },
|
||||
update: data,
|
||||
create: {
|
||||
id: DEFAULTS.SYSTEM_SETTINGS_ID,
|
||||
...data
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to update settings';
|
||||
return setError(form, '', message);
|
||||
}
|
||||
|
||||
return { form };
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user