Implement premium features and GDPR compliance in bot and WebUI

- Added new models for premium tier configurations and assignments, enabling feature limits for free and premium users.
- Introduced GDPR deletion logging and commands for user data management.
- Enhanced logging configuration with retention days for audit logs.
- Updated bot commands and job processing to include new premium and GDPR functionalities.
- Improved localization with new keys for premium features and GDPR commands in both English and German.
- Added UI components for managing premium settings and logging retention in the WebUI.
This commit is contained in:
smueller
2026-07-22 16:59:23 +02:00
parent 4852f16f79
commit 08af99ed52
42 changed files with 1546 additions and 30 deletions

View File

@@ -36,6 +36,8 @@ import {
presenceQueue,
presenceQueueName,
reminderQueueName,
retentionQueue,
retentionQueueName,
scheduleQueueName,
suggestionsQueueName,
ticketQueue,
@@ -321,6 +323,20 @@ export function startWorkers(context: BotContext): Worker[] {
logger.error({ jobId: job?.id, error }, 'Presence refresh job failed');
});
const retentionWorker = new Worker(
retentionQueueName,
async (job) => {
if (job.name !== 'purgeExpiredLogs') {
return;
}
await runLogRetentionJob(context);
},
{ connection: redis }
);
retentionWorker.on('failed', (job, error) => {
logger.error({ jobId: job?.id, error }, 'Log retention job failed');
});
return [
moderationWorker,
backupWorker,
@@ -335,7 +351,8 @@ export function startWorkers(context: BotContext): Worker[] {
scheduleWorker,
guildBackupWorker,
suggestionsWorker,
presenceWorker
presenceWorker,
retentionWorker
];
}
@@ -403,6 +420,41 @@ export async function ensureRecurringJobs(): Promise<void> {
removeOnFail: 5
}
);
await retentionQueue.add(
'purgeExpiredLogs',
{},
{
repeat: { pattern: '15 4 * * *' },
removeOnComplete: 20,
removeOnFail: 20
}
);
}
async function runLogRetentionJob(context: BotContext): Promise<void> {
const configs = await context.prisma.loggingConfig.findMany({
where: { retentionDays: { gt: 0 } },
select: { guildId: true, retentionDays: true }
});
for (const config of configs) {
const cutoff = new Date(Date.now() - config.retentionDays * 24 * 60 * 60 * 1000);
const [cases, audits] = await Promise.all([
context.prisma.case.deleteMany({
where: { guildId: config.guildId, createdAt: { lt: cutoff } }
}),
context.prisma.dashboardAuditLog.deleteMany({
where: { guildId: config.guildId, createdAt: { lt: cutoff } }
})
]);
if (cases.count > 0 || audits.count > 0) {
logger.info(
{ guildId: config.guildId, cases: cases.count, audits: audits.count, retentionDays: config.retentionDays },
'Log retention purge completed'
);
}
}
}
async function runPgDumpBackup(): Promise<void> {