diff --git a/internal/userstore/userstore.go b/internal/userstore/userstore.go index 760fc1e..c00937d 100644 --- a/internal/userstore/userstore.go +++ b/internal/userstore/userstore.go @@ -427,7 +427,27 @@ func (s *Store) CleanExpiredTokens() error { // tenantID may be nil for users not associated with a specific tenant. func (s *Store) UpsertLDAPUser(username, email, role string, tenantID *int64) (*User, error) { ctx := context.Background() - _, err := s.pool.Exec(ctx, ` + // First try to update an existing user matched by email (covers the case where + // the stored username differs from the LDAP uid, e.g. "patrick" vs "patrick@domain"). + var u User + err := s.pool.QueryRow(ctx, ` + UPDATE users SET + username = $1, + role = $2, + source = 'ldap', + active = true, + tenant_id = COALESCE($3, tenant_id) + WHERE email = $4 + RETURNING id, username, email, role, source, active, created_at, tenant_id, totp_enabled, totp_reset_at, totp_reset_by + `, username, role, tenantID, email).Scan( + &u.ID, &u.Username, &u.Email, &u.Role, &u.Source, &u.Active, + &u.CreatedAt, &u.TenantID, &u.TOTPEnabled, &u.TOTPResetAt, &u.TOTPResetBy, + ) + if err == nil { + return &u, nil + } + // No existing user with that email — insert fresh. + _, err = s.pool.Exec(ctx, ` INSERT INTO users (username, email, password_hash, role, source, active, created_at, tenant_id) VALUES ($1, $2, '', $3, 'ldap', true, NOW(), $4) ON CONFLICT (username) DO UPDATE SET