Skip to content

Commit 2371153

Browse files
authored
feat: add endpoint for partial updates to org sync mapping (#16316)
1 parent f651ab9 commit 2371153

File tree

17 files changed

+595
-11
lines changed

17 files changed

+595
-11
lines changed

coderd/apidoc/docs.go

Lines changed: 76 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/idpsync/idpsync.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
type IDPSync interface {
2727
OrganizationSyncEntitled() bool
2828
OrganizationSyncSettings(ctx context.Context, db database.Store) (*OrganizationSyncSettings, error)
29-
UpdateOrganizationSettings(ctx context.Context, db database.Store, settings OrganizationSyncSettings) error
29+
UpdateOrganizationSyncSettings(ctx context.Context, db database.Store, settings OrganizationSyncSettings) error
3030
// OrganizationSyncEnabled returns true if all OIDC users are assigned
3131
// to organizations via org sync settings.
3232
// This is used to know when to disable manual org membership assignment.
@@ -70,6 +70,9 @@ type IDPSync interface {
7070
SyncRoles(ctx context.Context, db database.Store, user database.User, params RoleParams) error
7171
}
7272

73+
// AGPLIDPSync implements the IDPSync interface
74+
var _ IDPSync = AGPLIDPSync{}
75+
7376
// AGPLIDPSync is the configuration for syncing user information from an external
7477
// IDP. All related code to syncing user information should be in this package.
7578
type AGPLIDPSync struct {

coderd/idpsync/organization.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (AGPLIDPSync) OrganizationSyncEnabled(_ context.Context, _ database.Store)
3434
return false
3535
}
3636

37-
func (s AGPLIDPSync) UpdateOrganizationSettings(ctx context.Context, db database.Store, settings OrganizationSyncSettings) error {
37+
func (s AGPLIDPSync) UpdateOrganizationSyncSettings(ctx context.Context, db database.Store, settings OrganizationSyncSettings) error {
3838
rlv := s.Manager.Resolver(db)
3939
err := s.SyncSettings.Organization.SetRuntimeValue(ctx, rlv, &settings)
4040
if err != nil {

coderd/runtimeconfig/resolver.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import (
1212
"github.com/coder/coder/v2/coderd/database"
1313
)
1414

15+
// NoopResolver implements the Resolver interface
16+
var _ Resolver = &NoopResolver{}
17+
1518
// NoopResolver is a useful test device.
1619
type NoopResolver struct{}
1720

@@ -31,6 +34,9 @@ func (NoopResolver) DeleteRuntimeConfig(context.Context, string) error {
3134
return ErrEntryNotFound
3235
}
3336

37+
// StoreResolver implements the Resolver interface
38+
var _ Resolver = &StoreResolver{}
39+
3440
// StoreResolver uses the database as the underlying store for runtime settings.
3541
type StoreResolver struct {
3642
db Store

coderd/telemetry/telemetry_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ func TestTelemetry(t *testing.T) {
295295
org, err := db.GetDefaultOrganization(ctx)
296296
require.NoError(t, err)
297297
sync := idpsync.NewAGPLSync(testutil.Logger(t), runtimeconfig.NewManager(), idpsync.DeploymentSyncSettings{})
298-
err = sync.UpdateOrganizationSettings(ctx, db, idpsync.OrganizationSyncSettings{
298+
err = sync.UpdateOrganizationSyncSettings(ctx, db, idpsync.OrganizationSyncSettings{
299299
Field: "organizations",
300300
Mapping: map[string][]uuid.UUID{
301301
"first": {org.ID},

codersdk/idpsync.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ import (
1212
"golang.org/x/xerrors"
1313
)
1414

15+
type IDPSyncMapping[ResourceIdType uuid.UUID | string] struct {
16+
// The IdP claim the user has
17+
Given string
18+
// The ID of the Coder resource the user should be added to
19+
Gets ResourceIdType
20+
}
21+
1522
type GroupSyncSettings struct {
1623
// Field is the name of the claim field that specifies what groups a user
1724
// should be in. If empty, no groups will be synced.
@@ -137,6 +144,26 @@ func (c *Client) PatchOrganizationIDPSyncSettings(ctx context.Context, req Organ
137144
return resp, json.NewDecoder(res.Body).Decode(&resp)
138145
}
139146

147+
// If the same mapping is present in both Add and Remove, Remove will take presidence.
148+
type PatchOrganizationIDPSyncMappingRequest struct {
149+
Add []IDPSyncMapping[uuid.UUID]
150+
Remove []IDPSyncMapping[uuid.UUID]
151+
}
152+
153+
func (c *Client) PatchOrganizationIDPSyncMapping(ctx context.Context, req PatchOrganizationIDPSyncMappingRequest) (OrganizationSyncSettings, error) {
154+
res, err := c.Request(ctx, http.MethodPatch, "/api/v2/settings/idpsync/organization/mapping", req)
155+
if err != nil {
156+
return OrganizationSyncSettings{}, xerrors.Errorf("make request: %w", err)
157+
}
158+
defer res.Body.Close()
159+
160+
if res.StatusCode != http.StatusOK {
161+
return OrganizationSyncSettings{}, ReadBodyAsError(res)
162+
}
163+
var resp OrganizationSyncSettings
164+
return resp, json.NewDecoder(res.Body).Decode(&resp)
165+
}
166+
140167
func (c *Client) GetAvailableIDPSyncFields(ctx context.Context) ([]string, error) {
141168
res, err := c.Request(ctx, http.MethodGet, "/api/v2/settings/idpsync/available-fields", nil)
142169
if err != nil {

docs/reference/api/enterprise.md

Lines changed: 66 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/api/schemas.md

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)