feat(dashboard,admin): widget group customization and FDISK data purge
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
-- Migration: 083_allow_null_profile_status
|
||||
-- Allow mitglieder_profile.status to be NULL (for FDISK data purge).
|
||||
-- Rollback:
|
||||
-- ALTER TABLE mitglieder_profile DROP CONSTRAINT IF EXISTS mitglieder_profile_status_check;
|
||||
-- ALTER TABLE mitglieder_profile ALTER COLUMN status SET NOT NULL;
|
||||
-- ALTER TABLE mitglieder_profile ALTER COLUMN status SET DEFAULT 'aktiv';
|
||||
-- ALTER TABLE mitglieder_profile ADD CONSTRAINT mitglieder_profile_status_check
|
||||
-- CHECK (status IN ('aktiv','passiv','ehrenmitglied','jugendfeuerwehr','anwärter','ausgetreten'));
|
||||
|
||||
-- 1. Drop existing CHECK constraint
|
||||
ALTER TABLE mitglieder_profile DROP CONSTRAINT IF EXISTS mitglieder_profile_status_check;
|
||||
|
||||
-- 2. Allow NULLs
|
||||
ALTER TABLE mitglieder_profile ALTER COLUMN status DROP NOT NULL;
|
||||
|
||||
-- 3. Remove default
|
||||
ALTER TABLE mitglieder_profile ALTER COLUMN status DROP DEFAULT;
|
||||
|
||||
-- 4. Re-add CHECK allowing NULL
|
||||
ALTER TABLE mitglieder_profile ADD CONSTRAINT mitglieder_profile_status_check
|
||||
CHECK (status IS NULL OR status IN (
|
||||
'aktiv',
|
||||
'passiv',
|
||||
'ehrenmitglied',
|
||||
'jugendfeuerwehr',
|
||||
'anwärter',
|
||||
'ausgetreten'
|
||||
));
|
||||
@@ -368,31 +368,74 @@ router.delete(
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DELETE /api/admin/debug/user/:userId/profile — delete mitglieder_profile row
|
||||
// DELETE /api/admin/users/:userId/fdisk-data — purge FDISK-synced data
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
router.delete(
|
||||
'/debug/user/:userId/profile',
|
||||
'/users/:userId/fdisk-data',
|
||||
authenticate,
|
||||
requirePermission('admin:write'),
|
||||
async (req: Request, res: Response): Promise<void> => {
|
||||
const targetUserId = req.params.userId;
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
const userId = req.params.userId;
|
||||
const result = await pool.query(
|
||||
'DELETE FROM mitglieder_profile WHERE user_id = $1',
|
||||
[userId]
|
||||
await client.query('BEGIN');
|
||||
|
||||
// Null out FDISK-synced profile fields
|
||||
const profileResult = await client.query(
|
||||
`UPDATE mitglieder_profile
|
||||
SET status = NULL,
|
||||
eintrittsdatum = NULL,
|
||||
austrittsdatum = NULL,
|
||||
geburtsdatum = NULL,
|
||||
geburtsort = NULL,
|
||||
geschlecht = NULL,
|
||||
beruf = NULL,
|
||||
wohnort = NULL,
|
||||
plz = NULL,
|
||||
dienstgrad = NULL,
|
||||
updated_at = NOW()
|
||||
WHERE user_id = $1`,
|
||||
[targetUserId]
|
||||
);
|
||||
|
||||
if ((result.rowCount ?? 0) === 0) {
|
||||
res.status(404).json({ success: false, message: 'Kein Profil fuer diesen Benutzer gefunden' });
|
||||
return;
|
||||
}
|
||||
const ausbildungen = await client.query(
|
||||
'DELETE FROM ausbildungen WHERE user_id = $1',
|
||||
[targetUserId]
|
||||
);
|
||||
const befoerderungen = await client.query(
|
||||
'DELETE FROM befoerderungen WHERE user_id = $1',
|
||||
[targetUserId]
|
||||
);
|
||||
const untersuchungen = await client.query(
|
||||
'DELETE FROM untersuchungen WHERE user_id = $1',
|
||||
[targetUserId]
|
||||
);
|
||||
const fahrgenehmigungen = await client.query(
|
||||
'DELETE FROM fahrgenehmigungen WHERE user_id = $1',
|
||||
[targetUserId]
|
||||
);
|
||||
|
||||
logger.info('Admin deleted user profile data', { userId, admin: req.user?.id });
|
||||
res.json({ success: true, message: 'Profildaten geloescht' });
|
||||
await client.query('COMMIT');
|
||||
|
||||
logger.info('Admin purged FDISK data', { targetUserId, adminId: req.user?.id });
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
profileFieldsCleared: profileResult.rowCount ?? 0,
|
||||
ausbildungen: ausbildungen.rowCount ?? 0,
|
||||
befoerderungen: befoerderungen.rowCount ?? 0,
|
||||
untersuchungen: untersuchungen.rowCount ?? 0,
|
||||
fahrgenehmigungen: fahrgenehmigungen.rowCount ?? 0,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Failed to delete user profile', { error, userId: req.params.userId });
|
||||
res.status(500).json({ success: false, message: 'Fehler beim Loeschen der Profildaten' });
|
||||
await client.query('ROLLBACK');
|
||||
logger.error('Failed to purge FDISK data', { error, targetUserId });
|
||||
res.status(500).json({ success: false, message: 'Fehler beim Löschen der FDISK-Daten' });
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user