Skip to content

Commit c3c23ed

Browse files
authored
chore: add query to fetch top level idp claim fields (#15525)
Adds an api endpoint to grab all available sync field options for IDP sync. This is for autocomplete on idp sync forms. This is required for organization admins to have some insight into the claim fields available when configuring group/role sync.
1 parent 48bb452 commit c3c23ed

File tree

18 files changed

+679
-10
lines changed

18 files changed

+679
-10
lines changed

coderd/apidoc/docs.go

+76
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+68
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbauthz/dbauthz.go

+12
Original file line numberDiff line numberDiff line change
@@ -3283,6 +3283,18 @@ func (q *querier) ListWorkspaceAgentPortShares(ctx context.Context, workspaceID
32833283
return q.db.ListWorkspaceAgentPortShares(ctx, workspaceID)
32843284
}
32853285

3286+
func (q *querier) OIDCClaimFields(ctx context.Context, organizationID uuid.UUID) ([]string, error) {
3287+
resource := rbac.ResourceIdpsyncSettings
3288+
if organizationID != uuid.Nil {
3289+
resource = resource.InOrg(organizationID)
3290+
}
3291+
3292+
if err := q.authorizeContext(ctx, policy.ActionRead, resource); err != nil {
3293+
return nil, err
3294+
}
3295+
return q.db.OIDCClaimFields(ctx, organizationID)
3296+
}
3297+
32863298
func (q *querier) OrganizationMembers(ctx context.Context, arg database.OrganizationMembersParams) ([]database.OrganizationMembersRow, error) {
32873299
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.OrganizationMembers)(ctx, arg)
32883300
}

coderd/database/dbauthz/dbauthz_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,13 @@ func (s *MethodTestSuite) TestLicense() {
626626
}
627627

628628
func (s *MethodTestSuite) TestOrganization() {
629+
s.Run("Deployment/OIDCClaimFields", s.Subtest(func(db database.Store, check *expects) {
630+
check.Args(uuid.Nil).Asserts(rbac.ResourceIdpsyncSettings, policy.ActionRead).Returns([]string{})
631+
}))
632+
s.Run("Organization/OIDCClaimFields", s.Subtest(func(db database.Store, check *expects) {
633+
id := uuid.New()
634+
check.Args(id).Asserts(rbac.ResourceIdpsyncSettings.InOrg(id), policy.ActionRead).Returns([]string{})
635+
}))
629636
s.Run("ByOrganization/GetGroups", s.Subtest(func(db database.Store, check *expects) {
630637
o := dbgen.Organization(s.T(), db, database.Organization{})
631638
a := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID})

coderd/database/dbmem/dbmem.go

+29
Original file line numberDiff line numberDiff line change
@@ -8409,6 +8409,35 @@ func (q *FakeQuerier) ListWorkspaceAgentPortShares(_ context.Context, workspaceI
84098409
return shares, nil
84108410
}
84118411

8412+
func (q *FakeQuerier) OIDCClaimFields(_ context.Context, organizationID uuid.UUID) ([]string, error) {
8413+
orgMembers := q.getOrganizationMemberNoLock(organizationID)
8414+
8415+
var fields []string
8416+
for _, link := range q.userLinks {
8417+
if organizationID != uuid.Nil {
8418+
inOrg := slices.ContainsFunc(orgMembers, func(organizationMember database.OrganizationMember) bool {
8419+
return organizationMember.UserID == link.UserID
8420+
})
8421+
if !inOrg {
8422+
continue
8423+
}
8424+
}
8425+
8426+
if link.LoginType != database.LoginTypeOIDC {
8427+
continue
8428+
}
8429+
8430+
for k := range link.Claims.IDTokenClaims {
8431+
fields = append(fields, k)
8432+
}
8433+
for k := range link.Claims.UserInfoClaims {
8434+
fields = append(fields, k)
8435+
}
8436+
}
8437+
8438+
return slice.Unique(fields), nil
8439+
}
8440+
84128441
func (q *FakeQuerier) OrganizationMembers(_ context.Context, arg database.OrganizationMembersParams) ([]database.OrganizationMembersRow, error) {
84138442
if err := validateDatabaseType(arg); err != nil {
84148443
return []database.OrganizationMembersRow{}, err

coderd/database/dbmetrics/querymetrics.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/modelqueries.go

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package database
33
import (
44
"context"
55
"database/sql"
6+
"encoding/json"
67
"fmt"
78
"strings"
89

@@ -527,3 +528,9 @@ func insertAuthorizedFilter(query string, replaceWith string) (string, error) {
527528
filtered := strings.Replace(query, authorizedQueryPlaceholder, replaceWith, 1)
528529
return filtered, nil
529530
}
531+
532+
// UpdateUserLinkRawJSON is a custom query for unit testing. Do not ever expose this
533+
func (q *sqlQuerier) UpdateUserLinkRawJSON(ctx context.Context, userID uuid.UUID, data json.RawMessage) error {
534+
_, err := q.sdb.ExecContext(ctx, "UPDATE user_links SET claims = $2 WHERE user_id = $1", userID, data)
535+
return err
536+
}

0 commit comments

Comments
 (0)