diff --git a/packages/types/src/api/web/global/scim/index.ts b/packages/types/src/api/web/global/scim/index.ts index e084a0dd1e..167d09b7c7 100644 --- a/packages/types/src/api/web/global/scim/index.ts +++ b/packages/types/src/api/web/global/scim/index.ts @@ -1,2 +1,3 @@ export * from "./users" export * from "./groups" +export * from "./shared" diff --git a/packages/types/src/api/web/global/scim/shared.ts b/packages/types/src/api/web/global/scim/shared.ts index 18b9519850..c01c9c8590 100644 --- a/packages/types/src/api/web/global/scim/shared.ts +++ b/packages/types/src/api/web/global/scim/shared.ts @@ -1,3 +1,5 @@ +import { ScimPatchOperation } from "scim-patch" + export interface ScimListResponse { schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"] totalResults: number @@ -5,3 +7,8 @@ export interface ScimListResponse { startIndex: number itemsPerPage: number } + +export interface ScimUpdateRequest { + schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"] + Operations: ScimPatchOperation[] +} diff --git a/packages/types/src/api/web/global/scim/users.ts b/packages/types/src/api/web/global/scim/users.ts index edc9b8e37e..5dddee1f14 100644 --- a/packages/types/src/api/web/global/scim/users.ts +++ b/packages/types/src/api/web/global/scim/users.ts @@ -52,10 +52,5 @@ export interface ScimCreateUserRequest { roles: [] } -export interface ScimUpdateRequest { - schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"] - Operations: ScimPatchOperation[] -} - export interface ScimUserListResponse extends ScimListResponse {} diff --git a/packages/worker/src/api/routes/global/tests/scim/groups.spec.ts b/packages/worker/src/api/routes/global/tests/scim/groups.spec.ts index 4076ab3477..904c20cf92 100644 --- a/packages/worker/src/api/routes/global/tests/scim/groups.spec.ts +++ b/packages/worker/src/api/routes/global/tests/scim/groups.spec.ts @@ -1,7 +1,11 @@ import tk from "timekeeper" import _ from "lodash" import { mocks, structures } from "@budibase/backend-core/tests" -import { ScimCreateGroupRequest, ScimGroupResponse } from "@budibase/types" +import { + ScimCreateGroupRequest, + ScimGroupResponse, + ScimUpdateRequest, +} from "@budibase/types" import { TestConfiguration } from "../../../../../tests" mocks.licenses.useScimIntegration() @@ -262,4 +266,58 @@ describe("/api/global/scim/v2/groups", () => { await deleteScimGroup(structures.uuid(), { expect: 404 }) }) }) + + describe("PATCH /api/global/scim/v2/groups/:id", () => { + const patchScimGroup = config.api.scimGroupsAPI.patch + + let group: ScimGroupResponse + + beforeEach(async () => { + const body = createScimCreateGroupRequest() + + group = await config.api.scimGroupsAPI.post({ body }) + }) + + it("unauthorised calls are not allowed", async () => { + const response = await patchScimGroup({} as any, { + setHeaders: false, + expect: 403, + }) + + expect(response).toEqual({ message: "Tenant id not set", status: 403 }) + }) + + it("cannot be called when feature is disabled", async () => { + mocks.licenses.useCloudFree() + const response = await patchScimGroup({} as any, { expect: 400 }) + + expect(response).toEqual(featureDisabledResponse) + }) + + it("an existing group can be updated", async () => { + const newDisplayName = structures.generator.word() + + const body: ScimUpdateRequest = { + schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], + Operations: [ + { + op: "Replace", + path: "displayName", + value: newDisplayName, + }, + ], + } + + const response = await patchScimGroup({ id: group.id, body }) + + const expectedScimGroup: ScimGroupResponse = { + ...group, + displayName: newDisplayName, + } + expect(response).toEqual(expectedScimGroup) + + const persistedGroup = await config.api.scimGroupsAPI.find(group.id) + expect(persistedGroup).toEqual(expectedScimGroup) + }) + }) }) diff --git a/packages/worker/src/tests/api/scim/groups.ts b/packages/worker/src/tests/api/scim/groups.ts index 413e85b96a..96ff9aeb67 100644 --- a/packages/worker/src/tests/api/scim/groups.ts +++ b/packages/worker/src/tests/api/scim/groups.ts @@ -2,6 +2,7 @@ import { ScimCreateGroupRequest, ScimGroupListResponse, ScimGroupResponse, + ScimUpdateRequest, } from "@budibase/types" import TestConfiguration from "../../TestConfiguration" import { RequestSettings, ScimTestAPI } from "./shared" @@ -70,4 +71,24 @@ export class ScimGroupsAPI extends ScimTestAPI { ) return res.body as ScimGroupResponse } + + patch = async ( + { + id, + body, + }: { + id: string + body: ScimUpdateRequest + }, + requestSettings?: Partial + ) => { + const res = await this.call( + `/api/global/scim/v2/groups/${id}`, + "patch", + requestSettings, + body + ) + + return res.body as ScimGroupResponse + } }