From e842dc0642adf2a7cfb87b33b24caec1c3de0392 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 29 Jan 2025 23:37:15 +0000 Subject: [PATCH 1/4] add route for updating the non-mapping fields --- codersdk/idpsync.go | 19 ++++++++++ enterprise/coderd/coderd.go | 1 + enterprise/coderd/idpsync.go | 70 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/codersdk/idpsync.go b/codersdk/idpsync.go index 2cc1f51ee3011..2513209d30b2a 100644 --- a/codersdk/idpsync.go +++ b/codersdk/idpsync.go @@ -137,6 +137,25 @@ func (c *Client) PatchOrganizationIDPSyncSettings(ctx context.Context, req Organ return resp, json.NewDecoder(res.Body).Decode(&resp) } +type OrganizationSyncConfig struct { + Field string `json:"field"` + AssignDefault bool `json:"assign_default"` +} + +func (c *Client) PatchOrganizationIDPSyncConfig(ctx context.Context, req OrganizationSyncConfig) (OrganizationSyncSettings, error) { + res, err := c.Request(ctx, http.MethodPatch, "/api/v2/settings/idpsync/organization/config", req) + if err != nil { + return OrganizationSyncSettings{}, xerrors.Errorf("make request: %w", err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + return OrganizationSyncSettings{}, ReadBodyAsError(res) + } + var resp OrganizationSyncSettings + return resp, json.NewDecoder(res.Body).Decode(&resp) +} + func (c *Client) GetAvailableIDPSyncFields(ctx context.Context) ([]string, error) { res, err := c.Request(ctx, http.MethodGet, "/api/v2/settings/idpsync/available-fields", nil) if err != nil { diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index b32f763720b9d..16fdee321dfa4 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -295,6 +295,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { r.Route("/organization", func(r chi.Router) { r.Get("/", api.organizationIDPSyncSettings) r.Patch("/", api.patchOrganizationIDPSyncSettings) + r.Patch("/config", api.patchOrganizationIDPSyncConfig) }) r.Get("/available-fields", api.deploymentIDPSyncClaimFields) r.Get("/field-values", api.deploymentIDPSyncClaimFieldValues) diff --git a/enterprise/coderd/idpsync.go b/enterprise/coderd/idpsync.go index 192d61ea996c6..d40cba669ab84 100644 --- a/enterprise/coderd/idpsync.go +++ b/enterprise/coderd/idpsync.go @@ -317,6 +317,76 @@ func (api *API) patchOrganizationIDPSyncSettings(rw http.ResponseWriter, r *http }) } +// @Summary Update organization IdP Sync basic configuration +// @ID update-organization-idp-sync-config +// @Security CoderSessionToken +// @Produce json +// @Accept json +// @Tags Enterprise +// @Success 200 {object} codersdk.OrganizationSyncSettings +// @Param request body codersdk.OrganizationSyncSettings true "New settings" +// @Router /settings/idpsync/organization [patch] +func (api *API) patchOrganizationIDPSyncConfig(rw http.ResponseWriter, r *http.Request) { + ctx := r.Context() + auditor := *api.AGPL.Auditor.Load() + aReq, commitAudit := audit.InitRequest[idpsync.OrganizationSyncSettings](rw, &audit.RequestParams{ + Audit: auditor, + Log: api.Logger, + Request: r, + Action: database.AuditActionWrite, + }) + defer commitAudit() + + if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceIdpsyncSettings) { + httpapi.Forbidden(rw) + return + } + + var req codersdk.OrganizationSyncConfig + if !httpapi.Read(ctx, rw, r, &req) { + return + } + + var settings *idpsync.OrganizationSyncSettings + //nolint:gocritic // Requires system context to update runtime config + sysCtx := dbauthz.AsSystemRestricted(ctx) + err := database.ReadModifyUpdate(api.Database, func(tx database.Store) error { + existing, err := api.IDPSync.OrganizationSyncSettings(sysCtx, tx) + if err != nil { + return err + } + aReq.Old = *existing + + err = api.IDPSync.UpdateOrganizationSettings(sysCtx, tx, idpsync.OrganizationSyncSettings{ + Field: req.Field, + AssignDefault: req.AssignDefault, + Mapping: existing.Mapping, + }) + if err != nil { + return err + } + + settings, err = api.IDPSync.OrganizationSyncSettings(sysCtx, tx) + if err != nil { + httpapi.InternalServerError(rw, err) + return err + } + + return nil + }) + if err != nil { + httpapi.InternalServerError(rw, err) + return + } + + aReq.New = *settings + httpapi.Write(ctx, rw, http.StatusOK, codersdk.OrganizationSyncSettings{ + Field: settings.Field, + Mapping: settings.Mapping, + AssignDefault: settings.AssignDefault, + }) +} + // @Summary Get the available organization idp sync claim fields // @ID get-the-available-organization-idp-sync-claim-fields // @Security CoderSessionToken From 8ab2c01b554304d7f1cba9ad25e4e32682041361 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 30 Jan 2025 18:20:10 +0000 Subject: [PATCH 2/4] tests uwu --- codersdk/idpsync.go | 4 +- enterprise/coderd/idpsync.go | 2 +- enterprise/coderd/idpsync_test.go | 79 +++++++++++++++++++++++++++++-- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/codersdk/idpsync.go b/codersdk/idpsync.go index 72a126d2c01ca..df49f496af4e1 100644 --- a/codersdk/idpsync.go +++ b/codersdk/idpsync.go @@ -144,12 +144,12 @@ func (c *Client) PatchOrganizationIDPSyncSettings(ctx context.Context, req Organ return resp, json.NewDecoder(res.Body).Decode(&resp) } -type OrganizationSyncConfig struct { +type PatchOrganizationIDPSyncConfigRequest struct { Field string `json:"field"` AssignDefault bool `json:"assign_default"` } -func (c *Client) PatchOrganizationIDPSyncConfig(ctx context.Context, req OrganizationSyncConfig) (OrganizationSyncSettings, error) { +func (c *Client) PatchOrganizationIDPSyncConfig(ctx context.Context, req PatchOrganizationIDPSyncConfigRequest) (OrganizationSyncSettings, error) { res, err := c.Request(ctx, http.MethodPatch, "/api/v2/settings/idpsync/organization/config", req) if err != nil { return OrganizationSyncSettings{}, xerrors.Errorf("make request: %w", err) diff --git a/enterprise/coderd/idpsync.go b/enterprise/coderd/idpsync.go index 5ff4d489a88ce..46e2fe7fd1679 100644 --- a/enterprise/coderd/idpsync.go +++ b/enterprise/coderd/idpsync.go @@ -344,7 +344,7 @@ func (api *API) patchOrganizationIDPSyncConfig(rw http.ResponseWriter, r *http.R return } - var req codersdk.OrganizationSyncConfig + var req codersdk.PatchOrganizationIDPSyncConfigRequest if !httpapi.Read(ctx, rw, r, &req) { return } diff --git a/enterprise/coderd/idpsync_test.go b/enterprise/coderd/idpsync_test.go index fb9ece7e45285..3b8401079d089 100644 --- a/enterprise/coderd/idpsync_test.go +++ b/enterprise/coderd/idpsync_test.go @@ -20,7 +20,7 @@ import ( "github.com/coder/serpent" ) -func TestGetGroupSyncConfig(t *testing.T) { +func TestGetGroupSyncSettings(t *testing.T) { t.Parallel() t.Run("OK", func(t *testing.T) { @@ -83,7 +83,7 @@ func TestGetGroupSyncConfig(t *testing.T) { }) } -func TestPatchGroupSyncConfig(t *testing.T) { +func TestPatchGroupSyncSettings(t *testing.T) { t.Parallel() t.Run("OK", func(t *testing.T) { @@ -141,7 +141,7 @@ func TestPatchGroupSyncConfig(t *testing.T) { }) } -func TestGetRoleSyncConfig(t *testing.T) { +func TestGetRoleSyncSettings(t *testing.T) { t.Parallel() t.Run("OK", func(t *testing.T) { @@ -175,7 +175,7 @@ func TestGetRoleSyncConfig(t *testing.T) { }) } -func TestPatchRoleSyncConfig(t *testing.T) { +func TestPatchRoleSyncSettings(t *testing.T) { t.Parallel() t.Run("OK", func(t *testing.T) { @@ -322,6 +322,77 @@ func TestPatchOrganizationSyncSettings(t *testing.T) { require.Equal(t, http.StatusForbidden, apiError.StatusCode()) }) } +func TestPatchOrganizationSyncConfig(t *testing.T) { + t.Parallel() + + t.Run("OK", func(t *testing.T) { + t.Parallel() + + owner, user := coderdenttest.New(t, &coderdenttest.Options{ + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureCustomRoles: 1, + codersdk.FeatureMultipleOrganizations: 1, + }, + }, + }) + + mapping := map[string][]uuid.UUID{"wibble": {user.OrganizationID}} + + ctx := testutil.Context(t, testutil.WaitShort) + //nolint:gocritic // Only owners can change Organization IdP sync settings + _, err := owner.PatchOrganizationIDPSyncSettings(ctx, codersdk.OrganizationSyncSettings{ + Field: "wibble", + AssignDefault: true, + Mapping: mapping, + }) + + require.NoError(t, err) + + fetchedSettings, err := owner.OrganizationIDPSyncSettings(ctx) + require.NoError(t, err) + require.Equal(t, "wibble", fetchedSettings.Field) + require.Equal(t, true, fetchedSettings.AssignDefault) + require.Equal(t, mapping, fetchedSettings.Mapping) + + ctx = testutil.Context(t, testutil.WaitShort) + settings, err := owner.PatchOrganizationIDPSyncConfig(ctx, codersdk.PatchOrganizationIDPSyncConfigRequest{ + Field: "wobble", + }) + + require.NoError(t, err) + require.Equal(t, "wobble", settings.Field) + require.Equal(t, false, settings.AssignDefault) + require.Equal(t, mapping, settings.Mapping) + + fetchedSettings, err = owner.OrganizationIDPSyncSettings(ctx) + require.NoError(t, err) + require.Equal(t, "wobble", fetchedSettings.Field) + require.Equal(t, false, fetchedSettings.AssignDefault) + require.Equal(t, mapping, fetchedSettings.Mapping) + }) + + t.Run("NotAuthorized", func(t *testing.T) { + t.Parallel() + + owner, user := coderdenttest.New(t, &coderdenttest.Options{ + LicenseOptions: &coderdenttest.LicenseOptions{ + Features: license.Features{ + codersdk.FeatureCustomRoles: 1, + codersdk.FeatureMultipleOrganizations: 1, + }, + }, + }) + + member, _ := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID) + + ctx := testutil.Context(t, testutil.WaitShort) + _, err := member.PatchOrganizationIDPSyncConfig(ctx, codersdk.PatchOrganizationIDPSyncConfigRequest{}) + var apiError *codersdk.Error + require.ErrorAs(t, err, &apiError) + require.Equal(t, http.StatusForbidden, apiError.StatusCode()) + }) +} func TestPatchOrganizationSyncMapping(t *testing.T) { t.Parallel() From 0f4350e74ed99b508fe17164f91c3d011fe13d0f Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 30 Jan 2025 18:40:18 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=8F=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coderd/apidoc/docs.go | 50 +++++++++++++++++++++++++++ coderd/apidoc/swagger.json | 44 ++++++++++++++++++++++++ docs/reference/api/enterprise.md | 56 +++++++++++++++++++++++++++++++ docs/reference/api/schemas.md | 16 +++++++++ enterprise/coderd/idpsync.go | 4 +-- enterprise/coderd/idpsync_test.go | 1 + site/src/api/typesGenerated.ts | 6 ++++ 7 files changed, 175 insertions(+), 2 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 8c86456da1619..c7852a2d6f560 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -4248,6 +4248,45 @@ const docTemplate = `{ } } }, + "/settings/idpsync/organization/config": { + "patch": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Enterprise" + ], + "summary": "Update organization IdP Sync basic configuration", + "operationId": "update-organization-idp-sync-config", + "parameters": [ + { + "description": "New config values", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.PatchOrganizationIDPSyncConfigRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.OrganizationSyncSettings" + } + } + } + } + }, "/settings/idpsync/organization/mapping": { "patch": { "security": [ @@ -12459,6 +12498,17 @@ const docTemplate = `{ } } }, + "codersdk.PatchOrganizationIDPSyncConfigRequest": { + "type": "object", + "properties": { + "assign_default": { + "type": "boolean" + }, + "field": { + "type": "string" + } + } + }, "codersdk.PatchOrganizationIDPSyncMappingRequest": { "type": "object", "properties": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index d65a421382fda..c336fa0b5427e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -3744,6 +3744,39 @@ } } }, + "/settings/idpsync/organization/config": { + "patch": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["Enterprise"], + "summary": "Update organization IdP Sync basic configuration", + "operationId": "update-organization-idp-sync-config", + "parameters": [ + { + "description": "New config values", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.PatchOrganizationIDPSyncConfigRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.OrganizationSyncSettings" + } + } + } + } + }, "/settings/idpsync/organization/mapping": { "patch": { "security": [ @@ -11234,6 +11267,17 @@ } } }, + "codersdk.PatchOrganizationIDPSyncConfigRequest": { + "type": "object", + "properties": { + "assign_default": { + "type": "boolean" + }, + "field": { + "type": "string" + } + } + }, "codersdk.PatchOrganizationIDPSyncMappingRequest": { "type": "object", "properties": { diff --git a/docs/reference/api/enterprise.md b/docs/reference/api/enterprise.md index 96a89c1486d8a..ad332b31ee810 100644 --- a/docs/reference/api/enterprise.md +++ b/docs/reference/api/enterprise.md @@ -2677,6 +2677,62 @@ curl -X PATCH http://coder-server:8080/api/v2/settings/idpsync/organization \ To perform this operation, you must be authenticated. [Learn more](authentication.md). +## Update organization IdP Sync basic configuration + +### Code samples + +```shell +# Example request using curl +curl -X PATCH http://coder-server:8080/api/v2/settings/idpsync/organization/config \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PATCH /settings/idpsync/organization/config` + +> Body parameter + +```json +{ + "assign_default": true, + "field": "string" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +|--------|------|------------------------------------------------------------------------------------------------------------|----------|-------------------| +| `body` | body | [codersdk.PatchOrganizationIDPSyncConfigRequest](schemas.md#codersdkpatchorganizationidpsyncconfigrequest) | true | New config values | + +### Example responses + +> 200 Response + +```json +{ + "field": "string", + "mapping": { + "property1": [ + "string" + ], + "property2": [ + "string" + ] + }, + "organization_assign_default": true +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------| +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.OrganizationSyncSettings](schemas.md#codersdkorganizationsyncsettings) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + ## Update organization IdP Sync mapping ### Code samples diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 85193978930f0..61160c03d3cd3 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -4180,6 +4180,22 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith | `quota_allowance` | integer | false | | | | `remove_users` | array of string | false | | | +## codersdk.PatchOrganizationIDPSyncConfigRequest + +```json +{ + "assign_default": true, + "field": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|------------------|---------|----------|--------------|-------------| +| `assign_default` | boolean | false | | | +| `field` | string | false | | | + ## codersdk.PatchOrganizationIDPSyncMappingRequest ```json diff --git a/enterprise/coderd/idpsync.go b/enterprise/coderd/idpsync.go index 46e2fe7fd1679..5f9c72111421e 100644 --- a/enterprise/coderd/idpsync.go +++ b/enterprise/coderd/idpsync.go @@ -326,8 +326,8 @@ func (api *API) patchOrganizationIDPSyncSettings(rw http.ResponseWriter, r *http // @Accept json // @Tags Enterprise // @Success 200 {object} codersdk.OrganizationSyncSettings -// @Param request body codersdk.OrganizationSyncSettings true "New settings" -// @Router /settings/idpsync/organization [patch] +// @Param request body codersdk.PatchOrganizationIDPSyncConfigRequest true "New config values" +// @Router /settings/idpsync/organization/config [patch] func (api *API) patchOrganizationIDPSyncConfig(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() auditor := *api.AGPL.Auditor.Load() diff --git a/enterprise/coderd/idpsync_test.go b/enterprise/coderd/idpsync_test.go index 3b8401079d089..6c9a83895322c 100644 --- a/enterprise/coderd/idpsync_test.go +++ b/enterprise/coderd/idpsync_test.go @@ -322,6 +322,7 @@ func TestPatchOrganizationSyncSettings(t *testing.T) { require.Equal(t, http.StatusForbidden, apiError.StatusCode()) }) } + func TestPatchOrganizationSyncConfig(t *testing.T) { t.Parallel() diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 0de33cca7b66e..3f9cf15a3cd1d 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1465,6 +1465,12 @@ export interface PatchGroupRequest { readonly quota_allowance: number | null; } +// From codersdk/idpsync.go +export interface PatchOrganizationIDPSyncConfigRequest { + readonly field: string; + readonly assign_default: boolean; +} + // From codersdk/idpsync.go export interface PatchOrganizationIDPSyncMappingRequest { readonly Add: readonly IDPSyncMapping[]; From 49add10063371c83bc1817301e7c2acc1bb48ad2 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 30 Jan 2025 18:48:31 +0000 Subject: [PATCH 4/4] jerk --- coderd/apidoc/docs.go | 2 +- coderd/apidoc/swagger.json | 2 +- docs/reference/api/enterprise.md | 2 +- enterprise/coderd/idpsync.go | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index c7852a2d6f560..028cd23a76557 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -4264,7 +4264,7 @@ const docTemplate = `{ "tags": [ "Enterprise" ], - "summary": "Update organization IdP Sync basic configuration", + "summary": "Update organization IdP Sync config", "operationId": "update-organization-idp-sync-config", "parameters": [ { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index c336fa0b5427e..1a45371c380d6 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -3754,7 +3754,7 @@ "consumes": ["application/json"], "produces": ["application/json"], "tags": ["Enterprise"], - "summary": "Update organization IdP Sync basic configuration", + "summary": "Update organization IdP Sync config", "operationId": "update-organization-idp-sync-config", "parameters": [ { diff --git a/docs/reference/api/enterprise.md b/docs/reference/api/enterprise.md index ad332b31ee810..8145331d878d3 100644 --- a/docs/reference/api/enterprise.md +++ b/docs/reference/api/enterprise.md @@ -2677,7 +2677,7 @@ curl -X PATCH http://coder-server:8080/api/v2/settings/idpsync/organization \ To perform this operation, you must be authenticated. [Learn more](authentication.md). -## Update organization IdP Sync basic configuration +## Update organization IdP Sync config ### Code samples diff --git a/enterprise/coderd/idpsync.go b/enterprise/coderd/idpsync.go index 5f9c72111421e..bda63cf2a7976 100644 --- a/enterprise/coderd/idpsync.go +++ b/enterprise/coderd/idpsync.go @@ -319,7 +319,7 @@ func (api *API) patchOrganizationIDPSyncSettings(rw http.ResponseWriter, r *http }) } -// @Summary Update organization IdP Sync basic configuration +// @Summary Update organization IdP Sync config // @ID update-organization-idp-sync-config // @Security CoderSessionToken // @Produce json @@ -370,7 +370,6 @@ func (api *API) patchOrganizationIDPSyncConfig(rw http.ResponseWriter, r *http.R settings, err = api.IDPSync.OrganizationSyncSettings(sysCtx, tx) if err != nil { - httpapi.InternalServerError(rw, err) return err } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy