mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: implement user link claims as a typed golang object (#15502)
Move claims from a `debug` column to an actual typed column to be used. This does not functionally change anything, it just adds some Go typing to build on.
This commit is contained in:
@@ -1281,7 +1281,7 @@ func (s *MethodTestSuite) TestUser() {
|
||||
OAuthExpiry: link.OAuthExpiry,
|
||||
UserID: link.UserID,
|
||||
LoginType: link.LoginType,
|
||||
DebugContext: json.RawMessage("{}"),
|
||||
Claims: database.UserLinkClaims{},
|
||||
}).Asserts(rbac.ResourceUserObject(link.UserID), policy.ActionUpdatePersonal).Returns(link)
|
||||
}))
|
||||
s.Run("UpdateUserRoles", s.Subtest(func(db database.Store, check *expects) {
|
||||
|
||||
@@ -726,7 +726,7 @@ func UserLink(t testing.TB, db database.Store, orig database.UserLink) database.
|
||||
OAuthRefreshToken: takeFirst(orig.OAuthRefreshToken, uuid.NewString()),
|
||||
OAuthRefreshTokenKeyID: takeFirst(orig.OAuthRefreshTokenKeyID, sql.NullString{}),
|
||||
OAuthExpiry: takeFirst(orig.OAuthExpiry, dbtime.Now().Add(time.Hour*24)),
|
||||
DebugContext: takeFirstSlice(orig.DebugContext, json.RawMessage("{}")),
|
||||
Claims: orig.Claims,
|
||||
})
|
||||
|
||||
require.NoError(t, err, "insert link")
|
||||
|
||||
@@ -7857,7 +7857,7 @@ func (q *FakeQuerier) InsertUserLink(_ context.Context, args database.InsertUser
|
||||
OAuthRefreshToken: args.OAuthRefreshToken,
|
||||
OAuthRefreshTokenKeyID: args.OAuthRefreshTokenKeyID,
|
||||
OAuthExpiry: args.OAuthExpiry,
|
||||
DebugContext: args.DebugContext,
|
||||
Claims: args.Claims,
|
||||
}
|
||||
|
||||
q.userLinks = append(q.userLinks, link)
|
||||
@@ -9318,7 +9318,7 @@ func (q *FakeQuerier) UpdateUserLink(_ context.Context, params database.UpdateUs
|
||||
link.OAuthRefreshToken = params.OAuthRefreshToken
|
||||
link.OAuthRefreshTokenKeyID = params.OAuthRefreshTokenKeyID
|
||||
link.OAuthExpiry = params.OAuthExpiry
|
||||
link.DebugContext = params.DebugContext
|
||||
link.Claims = params.Claims
|
||||
|
||||
q.userLinks[i] = link
|
||||
return link, nil
|
||||
|
||||
Generated
+2
-2
@@ -1337,14 +1337,14 @@ CREATE TABLE user_links (
|
||||
oauth_expiry timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL,
|
||||
oauth_access_token_key_id text,
|
||||
oauth_refresh_token_key_id text,
|
||||
debug_context jsonb DEFAULT '{}'::jsonb NOT NULL
|
||||
claims jsonb DEFAULT '{}'::jsonb NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN user_links.oauth_access_token_key_id IS 'The ID of the key used to encrypt the OAuth access token. If this is NULL, the access token is not encrypted';
|
||||
|
||||
COMMENT ON COLUMN user_links.oauth_refresh_token_key_id IS 'The ID of the key used to encrypt the OAuth refresh token. If this is NULL, the refresh token is not encrypted';
|
||||
|
||||
COMMENT ON COLUMN user_links.debug_context IS 'Debug information includes information like id_token and userinfo claims.';
|
||||
COMMENT ON COLUMN user_links.claims IS 'Claims from the IDP for the linked user. Includes both id_token and userinfo claims. ';
|
||||
|
||||
CREATE TABLE workspace_agent_log_sources (
|
||||
workspace_agent_id uuid NOT NULL,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE user_links RENAME COLUMN claims TO debug_context;
|
||||
|
||||
COMMENT ON COLUMN user_links.debug_context IS 'Debug information includes information like id_token and userinfo claims.';
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE user_links RENAME COLUMN debug_context TO claims;
|
||||
|
||||
COMMENT ON COLUMN user_links.claims IS 'Claims from the IDP for the linked user. Includes both id_token and userinfo claims. ';
|
||||
@@ -2892,8 +2892,8 @@ type UserLink struct {
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
// The ID of the key used to encrypt the OAuth refresh token. If this is NULL, the refresh token is not encrypted
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
// Debug information includes information like id_token and userinfo claims.
|
||||
DebugContext json.RawMessage `db:"debug_context" json:"debug_context"`
|
||||
// Claims from the IDP for the linked user. Includes both id_token and userinfo claims.
|
||||
Claims UserLinkClaims `db:"claims" json:"claims"`
|
||||
}
|
||||
|
||||
// Visible fields of users are allowed to be joined with other tables for including context of other resources.
|
||||
|
||||
@@ -9689,7 +9689,7 @@ func (q *sqlQuerier) InsertTemplateVersionWorkspaceTag(ctx context.Context, arg
|
||||
|
||||
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.debug_context
|
||||
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
|
||||
FROM
|
||||
user_links
|
||||
INNER JOIN
|
||||
@@ -9712,14 +9712,14 @@ func (q *sqlQuerier) GetUserLinkByLinkedID(ctx context.Context, linkedID string)
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserLinkByUserIDLoginType = `-- name: GetUserLinkByUserIDLoginType :one
|
||||
SELECT
|
||||
user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
FROM
|
||||
user_links
|
||||
WHERE
|
||||
@@ -9743,13 +9743,13 @@ func (q *sqlQuerier) GetUserLinkByUserIDLoginType(ctx context.Context, arg GetUs
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserLinksByUserID = `-- name: GetUserLinksByUserID :many
|
||||
SELECT user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context FROM user_links WHERE user_id = $1
|
||||
SELECT user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims FROM user_links WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetUserLinksByUserID(ctx context.Context, userID uuid.UUID) ([]UserLink, error) {
|
||||
@@ -9770,7 +9770,7 @@ func (q *sqlQuerier) GetUserLinksByUserID(ctx context.Context, userID uuid.UUID)
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -9796,22 +9796,22 @@ INSERT INTO
|
||||
oauth_refresh_token,
|
||||
oauth_refresh_token_key_id,
|
||||
oauth_expiry,
|
||||
debug_context
|
||||
claims
|
||||
)
|
||||
VALUES
|
||||
( $1, $2, $3, $4, $5, $6, $7, $8, $9 ) RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
( $1, $2, $3, $4, $5, $6, $7, $8, $9 ) RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
`
|
||||
|
||||
type InsertUserLinkParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
LinkedID string `db:"linked_id" json:"linked_id"`
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
DebugContext json.RawMessage `db:"debug_context" json:"debug_context"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
LinkedID string `db:"linked_id" json:"linked_id"`
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
Claims UserLinkClaims `db:"claims" json:"claims"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error) {
|
||||
@@ -9824,7 +9824,7 @@ func (q *sqlQuerier) InsertUserLink(ctx context.Context, arg InsertUserLinkParam
|
||||
arg.OAuthRefreshToken,
|
||||
arg.OAuthRefreshTokenKeyID,
|
||||
arg.OAuthExpiry,
|
||||
arg.DebugContext,
|
||||
arg.Claims,
|
||||
)
|
||||
var i UserLink
|
||||
err := row.Scan(
|
||||
@@ -9836,7 +9836,7 @@ func (q *sqlQuerier) InsertUserLink(ctx context.Context, arg InsertUserLinkParam
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -9850,20 +9850,20 @@ SET
|
||||
oauth_refresh_token = $3,
|
||||
oauth_refresh_token_key_id = $4,
|
||||
oauth_expiry = $5,
|
||||
debug_context = $6
|
||||
claims = $6
|
||||
WHERE
|
||||
user_id = $7 AND login_type = $8 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
user_id = $7 AND login_type = $8 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
`
|
||||
|
||||
type UpdateUserLinkParams struct {
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
DebugContext json.RawMessage `db:"debug_context" json:"debug_context"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
Claims UserLinkClaims `db:"claims" json:"claims"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateUserLink(ctx context.Context, arg UpdateUserLinkParams) (UserLink, error) {
|
||||
@@ -9873,7 +9873,7 @@ func (q *sqlQuerier) UpdateUserLink(ctx context.Context, arg UpdateUserLinkParam
|
||||
arg.OAuthRefreshToken,
|
||||
arg.OAuthRefreshTokenKeyID,
|
||||
arg.OAuthExpiry,
|
||||
arg.DebugContext,
|
||||
arg.Claims,
|
||||
arg.UserID,
|
||||
arg.LoginType,
|
||||
)
|
||||
@@ -9887,7 +9887,7 @@ func (q *sqlQuerier) UpdateUserLink(ctx context.Context, arg UpdateUserLinkParam
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -9898,7 +9898,7 @@ UPDATE
|
||||
SET
|
||||
linked_id = $1
|
||||
WHERE
|
||||
user_id = $2 AND login_type = $3 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
user_id = $2 AND login_type = $3 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
`
|
||||
|
||||
type UpdateUserLinkedIDParams struct {
|
||||
@@ -9919,7 +9919,7 @@ func (q *sqlQuerier) UpdateUserLinkedID(ctx context.Context, arg UpdateUserLinke
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ INSERT INTO
|
||||
oauth_refresh_token,
|
||||
oauth_refresh_token_key_id,
|
||||
oauth_expiry,
|
||||
debug_context
|
||||
claims
|
||||
)
|
||||
VALUES
|
||||
( $1, $2, $3, $4, $5, $6, $7, $8, $9 ) RETURNING *;
|
||||
@@ -54,6 +54,6 @@ SET
|
||||
oauth_refresh_token = $3,
|
||||
oauth_refresh_token_key_id = $4,
|
||||
oauth_expiry = $5,
|
||||
debug_context = $6
|
||||
claims = $6
|
||||
WHERE
|
||||
user_id = $7 AND login_type = $8 RETURNING *;
|
||||
|
||||
@@ -79,6 +79,9 @@ sql:
|
||||
- column: "provisioner_job_stats.*_secs"
|
||||
go_type:
|
||||
type: "float64"
|
||||
- column: "user_links.claims"
|
||||
go_type:
|
||||
type: "UserLinkClaims"
|
||||
rename:
|
||||
group_member: GroupMemberTable
|
||||
group_members_expanded: GroupMember
|
||||
|
||||
@@ -207,3 +207,25 @@ func (p *AgentIDNamePair) Scan(src interface{}) error {
|
||||
func (p AgentIDNamePair) Value() (driver.Value, error) {
|
||||
return fmt.Sprintf(`(%s,%s)`, p.ID.String(), p.Name), nil
|
||||
}
|
||||
|
||||
// UserLinkClaims is the returned IDP claims for a given user link.
|
||||
// These claims are fetched at login time. These are the claims that were
|
||||
// used for IDP sync.
|
||||
type UserLinkClaims struct {
|
||||
IDTokenClaims map[string]interface{} `json:"id_token_claims"`
|
||||
UserInfoClaims map[string]interface{} `json:"user_info_claims"`
|
||||
}
|
||||
|
||||
func (a *UserLinkClaims) Scan(src interface{}) error {
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
return json.Unmarshal([]byte(v), &a)
|
||||
case []byte:
|
||||
return json.Unmarshal(v, &a)
|
||||
}
|
||||
return xerrors.Errorf("unexpected type %T", src)
|
||||
}
|
||||
|
||||
func (a UserLinkClaims) Value() (driver.Value, error) {
|
||||
return json.Marshal(a)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user