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

@@ -413,6 +413,53 @@ class UserService {
throw new Error('Failed to update user groups');
}
}
async findFdiskUserByName(givenName: string, familyName: string): Promise<User | null> {
try {
const result = await pool.query<User>(
`SELECT id, email, authentik_sub, name, preferred_username, given_name,
family_name, profile_picture_url, refresh_token, refresh_token_expires_at,
is_active, last_login_at, created_at, updated_at, preferences,
authentik_groups, sync_source
FROM users
WHERE sync_source = 'fdisk'
AND last_login_at IS NULL
AND LOWER(given_name) = LOWER($1)
AND LOWER(family_name) = LOWER($2)`,
[givenName, familyName]
);
if (result.rows.length === 1) return result.rows[0];
if (result.rows.length > 1) {
logger.warn('Ambiguous FDISK name match on login — skipping merge', { givenName, familyName, count: result.rows.length });
}
return null;
} catch (error) {
logger.error('Error finding FDISK user by name', { error });
return null;
}
}
async claimFdiskUser(userId: string, authentikSub: string, email: string): Promise<User | null> {
try {
const result = await pool.query<User>(
`UPDATE users SET
authentik_sub = $2,
email = $3
WHERE id = $1 AND sync_source = 'fdisk' AND last_login_at IS NULL
RETURNING id, email, authentik_sub, name, preferred_username, given_name,
family_name, profile_picture_url, refresh_token, refresh_token_expires_at,
is_active, last_login_at, created_at, updated_at, preferences,
authentik_groups, sync_source`,
[userId, authentikSub, email]
);
if (result.rows.length === 0) return null;
logger.info('FDISK user claimed by Authentik login', { userId, authentikSub });
return result.rows[0];
} catch (error) {
logger.error('Error claiming FDISK user', { error, userId });
return null;
}
}
}
export default new UserService();