- 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.
97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
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;
|
||
}
|