Enhance Prisma schema and documentation for dashboard features

- Added new models for DashboardAccessRule and DashboardAuditLog to the Prisma schema, improving access control and logging capabilities.
- Updated GuildSettings model to include timezone support.
- Revised PHASE-TRACKING.md to reflect the completion of Phase 5 and outline upcoming Phase 6 features, including dashboard layout and settings framework.
- Exported new phase 6 features in shared index for better modularity.
This commit is contained in:
smueller
2026-07-22 13:50:14 +02:00
parent 6f3da6bb15
commit 7bc1684566
22 changed files with 645 additions and 15 deletions

View File

@@ -0,0 +1,149 @@
import { z } from 'zod';
const LocaleSchema = z.enum(['de', 'en']);
export const DashboardModuleIdSchema = z.enum([
'moderation',
'automod',
'logging',
'welcome',
'verification',
'leveling',
'economy',
'fun',
'giveaways',
'tickets',
'selfroles',
'tags',
'starboard',
'suggestions',
'birthdays',
'tempvoice',
'stats',
'feeds',
'scheduler',
'guildbackup'
]);
export type DashboardModuleId = z.infer<typeof DashboardModuleIdSchema>;
export const DashboardModuleGroupSchema = z.enum([
'moderation',
'engagement',
'utility',
'community',
'integrations'
]);
export type DashboardModuleGroup = z.infer<typeof DashboardModuleGroupSchema>;
export const DASHBOARD_MODULES = [
{ id: 'moderation', group: 'moderation', href: 'moderation' },
{ id: 'automod', group: 'moderation', href: 'automod' },
{ id: 'logging', group: 'moderation', href: 'logging' },
{ id: 'welcome', group: 'engagement', href: 'welcome' },
{ id: 'verification', group: 'engagement', href: 'verification' },
{ id: 'leveling', group: 'engagement', href: 'leveling' },
{ id: 'economy', group: 'engagement', href: 'economy' },
{ id: 'fun', group: 'engagement', href: 'fun' },
{ id: 'giveaways', group: 'community', href: 'giveaways' },
{ id: 'tickets', group: 'community', href: 'tickets' },
{ id: 'selfroles', group: 'community', href: 'selfroles' },
{ id: 'tags', group: 'utility', href: 'tags' },
{ id: 'starboard', group: 'community', href: 'starboard' },
{ id: 'suggestions', group: 'community', href: 'suggestions' },
{ id: 'birthdays', group: 'community', href: 'birthdays' },
{ id: 'tempvoice', group: 'utility', href: 'tempvoice' },
{ id: 'stats', group: 'integrations', href: 'stats' },
{ id: 'feeds', group: 'integrations', href: 'feeds' },
{ id: 'scheduler', group: 'integrations', href: 'scheduler' },
{ id: 'guildbackup', group: 'integrations', href: 'backup' }
] as const satisfies ReadonlyArray<{
id: DashboardModuleId;
group: DashboardModuleGroup;
href: string;
}>;
export const SessionUserSchema = z.object({
id: z.string().min(1),
username: z.string().min(1),
globalName: z.string().nullable(),
avatar: z.string().nullable(),
locale: LocaleSchema.optional()
});
export type SessionUser = z.infer<typeof SessionUserSchema>;
export const DashboardGuildSchema = z.object({
id: z.string().min(1),
name: z.string().min(1),
icon: z.string().nullable(),
botPresent: z.boolean(),
permissions: z.string()
});
export type DashboardGuild = z.infer<typeof DashboardGuildSchema>;
export const GuildGeneralSettingsSchema = z.object({
locale: LocaleSchema,
timezone: z.string().min(1).max(64),
moderationEnabled: z.boolean()
});
export type GuildGeneralSettings = z.infer<typeof GuildGeneralSettingsSchema>;
export const GuildGeneralSettingsPatchSchema = GuildGeneralSettingsSchema.partial().refine(
(value) => Object.keys(value).length > 0,
{ message: 'At least one field is required' }
);
export type GuildGeneralSettingsPatch = z.infer<typeof GuildGeneralSettingsPatchSchema>;
export const ModuleStatusSchema = z.object({
id: DashboardModuleIdSchema,
enabled: z.boolean(),
group: DashboardModuleGroupSchema,
href: z.string()
});
export type ModuleStatus = z.infer<typeof ModuleStatusSchema>;
export const ModulesUpdateSchema = z.object({
modules: z.record(DashboardModuleIdSchema, z.boolean()).refine((value) => Object.keys(value).length > 0, {
message: 'At least one module toggle is required'
})
});
export type ModulesUpdate = z.infer<typeof ModulesUpdateSchema>;
export const DashboardAccessRuleSchema = z.object({
id: z.string().optional(),
roleId: z.string().regex(/^\d{17,20}$/),
modules: z.union([z.literal('all'), z.array(DashboardModuleIdSchema).min(1)])
});
export type DashboardAccessRule = z.infer<typeof DashboardAccessRuleSchema>;
export const DashboardAccessRulesUpdateSchema = z.object({
rules: z.array(DashboardAccessRuleSchema)
});
export type DashboardAccessRulesUpdate = z.infer<typeof DashboardAccessRulesUpdateSchema>;
export const DashboardAuditEntrySchema = z.object({
id: z.string(),
guildId: z.string().nullable(),
actorUserId: z.string(),
action: z.string(),
path: z.string().nullable(),
createdAt: z.string()
});
export type DashboardAuditEntry = z.infer<typeof DashboardAuditEntrySchema>;
export const DISCORD_PERMISSION_MANAGE_GUILD = 1n << 5n;
export function hasManageGuildPermission(permissions: string | bigint): boolean {
const value = typeof permissions === 'bigint' ? permissions : BigInt(permissions);
return (value & DISCORD_PERMISSION_MANAGE_GUILD) === DISCORD_PERMISSION_MANAGE_GUILD;
}