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

@@ -0,0 +1,96 @@
import type { PrismaClient } from '@prisma/client';
export type GdprDeletionSummary = {
warnings: number;
modNotes: number;
memberLevels: number;
memberEconomies: number;
inventoryItems: number;
birthdays: number;
afkStatuses: number;
reminders: number;
inviteStats: number;
casesAnonymized: number;
userPremium: number;
userRecord: number;
};
/**
* Deletes or anonymizes personal data for a Discord user across guilds.
* Moderation case history is anonymized (targetUserId cleared to a placeholder)
* so server audit integrity is preserved.
*/
export async function deleteUserPersonalData(
prisma: PrismaClient,
userId: string,
guildId: string | null
): Promise<GdprDeletionSummary> {
const scope = guildId ? { guildId, userId } : { userId };
const caseScope = guildId
? { guildId, targetUserId: userId }
: { targetUserId: userId };
const [
warnings,
modNotes,
memberLevels,
memberEconomies,
inventoryItems,
birthdays,
afkStatuses,
reminders,
inviteStats,
inviteJoins,
casesAnonymized,
userPremium
] = await prisma.$transaction([
prisma.warning.deleteMany({ where: scope }),
prisma.modNote.deleteMany({ where: scope }),
prisma.memberLevel.deleteMany({ where: scope }),
prisma.memberEconomy.deleteMany({ where: scope }),
prisma.inventoryItem.deleteMany({ where: scope }),
prisma.birthday.deleteMany({ where: scope }),
prisma.afkStatus.deleteMany({ where: scope }),
prisma.reminder.deleteMany({ where: { userId, ...(guildId ? { guildId } : {}) } }),
prisma.inviteStat.deleteMany({
where: guildId ? { guildId, inviterId: userId } : { inviterId: userId }
}),
prisma.inviteJoin.deleteMany({ where: scope }),
prisma.case.updateMany({
where: caseScope,
data: { targetUserId: '0', reason: '[redacted GDPR deletion]' }
}),
prisma.userPremiumAssignment.deleteMany({ where: { userId } })
]);
let userRecord = 0;
if (!guildId) {
const deleted = await prisma.user.deleteMany({ where: { id: userId } });
userRecord = deleted.count;
}
const summary: GdprDeletionSummary = {
warnings: warnings.count,
modNotes: modNotes.count,
memberLevels: memberLevels.count,
memberEconomies: memberEconomies.count,
inventoryItems: inventoryItems.count,
birthdays: birthdays.count,
afkStatuses: afkStatuses.count,
reminders: reminders.count,
inviteStats: inviteStats.count + inviteJoins.count,
casesAnonymized: casesAnonymized.count,
userPremium: userPremium.count,
userRecord
};
await prisma.gdprDeletionLog.create({
data: {
userId,
guildId,
summary
}
});
return summary;
}