mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: implement package and cli tool for repairing oidc links (#26418)
This commit is contained in:
Generated
+71
@@ -28866,6 +28866,55 @@ func (q *sqlQuerier) UpsertUserAIProviderKey(ctx context.Context, arg UpsertUser
|
||||
return i, err
|
||||
}
|
||||
|
||||
const countOIDCLinkedIDsByIssuer = `-- name: CountOIDCLinkedIDsByIssuer :many
|
||||
SELECT
|
||||
(CASE
|
||||
WHEN user_links.linked_id = '' THEN ''
|
||||
ELSE split_part(user_links.linked_id, '||', 1)
|
||||
END)::text AS issuer_prefix,
|
||||
COUNT(*)::int AS count
|
||||
FROM
|
||||
user_links
|
||||
INNER JOIN
|
||||
users ON user_links.user_id = users.id
|
||||
WHERE
|
||||
user_links.login_type = 'oidc'
|
||||
AND users.deleted = false
|
||||
GROUP BY issuer_prefix
|
||||
`
|
||||
|
||||
type CountOIDCLinkedIDsByIssuerRow struct {
|
||||
IssuerPrefix string `db:"issuer_prefix" json:"issuer_prefix"`
|
||||
Count int32 `db:"count" json:"count"`
|
||||
}
|
||||
|
||||
// Groups OIDC user links by their issuer prefix (the part before "||" in
|
||||
// linked_id) and returns a count for each. Empty linked_ids are reported
|
||||
// with an empty issuer_prefix. Used for analysis before resetting
|
||||
// mismatched links.
|
||||
func (q *sqlQuerier) CountOIDCLinkedIDsByIssuer(ctx context.Context) ([]CountOIDCLinkedIDsByIssuerRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, countOIDCLinkedIDsByIssuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CountOIDCLinkedIDsByIssuerRow
|
||||
for rows.Next() {
|
||||
var i CountOIDCLinkedIDsByIssuerRow
|
||||
if err := rows.Scan(&i.IssuerPrefix, &i.Count); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getUserLinkByLinkedID = `-- name: GetUserLinkByLinkedID :one
|
||||
SELECT
|
||||
user_links.user_id, user_links.login_type, user_links.linked_id, user_links.oauth_access_token, user_links.oauth_refresh_token, user_links.oauth_expiry, user_links.oauth_access_token_key_id, user_links.oauth_refresh_token_key_id, user_links.claims
|
||||
@@ -29124,6 +29173,28 @@ func (q *sqlQuerier) OIDCClaimFields(ctx context.Context, organizationID uuid.UU
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const unlinkOIDCUsersByIssuerMismatch = `-- name: UnlinkOIDCUsersByIssuerMismatch :execrows
|
||||
UPDATE user_links
|
||||
SET linked_id = ''
|
||||
FROM users
|
||||
WHERE user_links.user_id = users.id
|
||||
AND user_links.login_type = 'oidc'
|
||||
AND user_links.linked_id != ''
|
||||
AND NOT starts_with(user_links.linked_id, $1)
|
||||
AND users.deleted = false
|
||||
`
|
||||
|
||||
// Resets linked_id to ” for OIDC links where the linked_id is non-empty
|
||||
// and does not begin with the expected issuer prefix. This allows users to
|
||||
// re-authenticate under a new OIDC provider.
|
||||
func (q *sqlQuerier) UnlinkOIDCUsersByIssuerMismatch(ctx context.Context, expectedPrefix string) (int64, error) {
|
||||
result, err := q.db.ExecContext(ctx, unlinkOIDCUsersByIssuerMismatch, expectedPrefix)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected()
|
||||
}
|
||||
|
||||
const updateUserLink = `-- name: UpdateUserLink :one
|
||||
UPDATE
|
||||
user_links
|
||||
|
||||
Reference in New Issue
Block a user