feat(sync): sync all FDISK members, auto-creating dashboard accounts for users not yet logged in

This commit is contained in:
Matthias Hochmeister
2026-04-15 14:36:57 +02:00
parent dab4a45b79
commit 719b7bfcdb
12 changed files with 1086 additions and 8 deletions

View File

@@ -98,6 +98,7 @@ export async function syncToDatabase(
let updated = 0;
let unchanged = 0;
let forced = 0;
let created = 0;
let skipped = 0;
for (const member of members) {
@@ -107,8 +108,7 @@ export async function syncToDatabase(
`SELECT mp.user_id
FROM mitglieder_profile mp
JOIN users u ON u.id = mp.user_id
WHERE mp.fdisk_standesbuch_nr = $1
AND u.last_login_at IS NOT NULL`,
WHERE mp.fdisk_standesbuch_nr = $1`,
[member.standesbuchNr]
);
@@ -123,8 +123,7 @@ export async function syncToDatabase(
FROM users u
JOIN mitglieder_profile mp ON mp.user_id = u.id
WHERE LOWER(u.given_name) = LOWER($1)
AND LOWER(u.family_name) = LOWER($2)
AND u.last_login_at IS NOT NULL`,
AND LOWER(u.family_name) = LOWER($2)`,
[member.vorname, member.zuname]
);
@@ -142,8 +141,44 @@ export async function syncToDatabase(
}
if (!userId) {
skipped++;
continue;
// No matching user found — create a new dashboard user pre-seeded from FDISK
const insertResult = await client.query<{ id: string }>(
`INSERT INTO users (authentik_sub, email, name, given_name, family_name, is_active, sync_source)
VALUES ($1, $2, $3, $4, $5, true, 'fdisk')
ON CONFLICT (authentik_sub) DO NOTHING
RETURNING id`,
[
`fdisk:${member.standesbuchNr}`,
`fdisk_sync_${member.standesbuchNr}@intern.noreply`,
`${member.vorname} ${member.zuname}`,
member.vorname,
member.zuname,
]
);
if (insertResult.rows.length > 0) {
userId = insertResult.rows[0].id;
} else {
// ON CONFLICT hit — user already existed (idempotent re-run); fetch it
const existingResult = await client.query<{ id: string }>(
`SELECT id FROM users WHERE authentik_sub = $1`,
[`fdisk:${member.standesbuchNr}`]
);
userId = existingResult.rows[0]?.id ?? null;
}
if (userId) {
await client.query(
`INSERT INTO mitglieder_profile (user_id) VALUES ($1) ON CONFLICT (user_id) DO NOTHING`,
[userId]
);
log(`Created ${member.vorname} ${member.zuname} (${member.standesbuchNr}): new FDISK-only user`);
created++;
} else {
log(`WARN: could not create user for ${member.vorname} ${member.zuname} (${member.standesbuchNr})`);
skipped++;
continue;
}
}
// Fetch current values to detect what actually changed
@@ -222,7 +257,7 @@ export async function syncToDatabase(
}
}
log(`Members: ${updated} changed, ${unchanged} unchanged, ${forced} forced, ${skipped} skipped (no dashboard account)`);
log(`Members: ${updated} changed, ${unchanged} unchanged, ${forced} forced, ${created} created, ${skipped} skipped`);
// Upsert Ausbildungen
let ausbildungNew = 0;