diff --git a/README.md b/README.md index 871cafb38..cdb8cebde 100644 --- a/README.md +++ b/README.md @@ -1945,13 +1945,29 @@ searchRes.data.keys.forEach((key) => { }); // Update an existing management key. -// IMPORTANT: All parameters will override whatever values are currently set in the existing key. +// IMPORTANT: All parameters will override whatever values are currently set in the existing key, +// except reBac: when it is omitted, the key keeps its current roles. await descopeClient.management.managementKey.update( 'key-id', 'updated-key-name', 'Updated description', - ['1.2.3.4'], // updated permitted IPs 'active', // status: 'active' or 'inactive' + ['1.2.3.4'], // updated permitted IPs +); + +// Update the roles of an existing management key. +// When reBac is provided it replaces the key's current roles. The key secret is not rotated. +await descopeClient.management.managementKey.update( + 'key-id', + 'updated-key-name', + 'Updated description', + 'active', + ['1.2.3.4'], + { + companyRoles: ['Admin'], + projectRoles: [{ projectIds: ['project-id'], roles: ['Project Admin'] }], + tagRoles: [{ tags: ['production'], roles: ['Read Only'] }], + }, ); // Delete management keys by IDs. diff --git a/lib/management/managementKey.test.ts b/lib/management/managementKey.test.ts index 36e0a8872..1c4237613 100644 --- a/lib/management/managementKey.test.ts +++ b/lib/management/managementKey.test.ts @@ -89,6 +89,43 @@ describe('Management Management Keys', () => { permittedIps: ['1.1.1.1'], status: 'inactive', }); + expect(mockHttpClient.patch.mock.calls[0][1]).not.toHaveProperty('reBac'); + expect(resp.data).toEqual(mockMgmtKey); + }); + + it('should send reBac when provided', async () => { + const httpResponse = { + ok: true, + json: () => ({ key: mockMgmtKey }), + clone: () => ({ + json: () => Promise.resolve({ key: mockMgmtKey }), + }), + status: 200, + }; + mockHttpClient.patch.mockResolvedValue(httpResponse); + + const reBac = { + companyRoles: ['role1'], + projectRoles: [{ projectIds: ['p1'], roles: ['role2'] }], + tagRoles: [{ tags: ['t1'], roles: ['role3'] }], + }; + const resp = await management.managementKey.update( + 'mk1', + 'updated-key', + 'updated-desc', + 'active', + ['1.1.1.1'], + reBac, + ); + + expect(mockHttpClient.patch).toHaveBeenCalledWith(apiPaths.managementKey.update, { + id: 'mk1', + name: 'updated-key', + description: 'updated-desc', + permittedIps: ['1.1.1.1'], + status: 'active', + reBac, + }); expect(resp.data).toEqual(mockMgmtKey); }); }); diff --git a/lib/management/managementKey.ts b/lib/management/managementKey.ts index 63e25e7ed..76e8adadc 100644 --- a/lib/management/managementKey.ts +++ b/lib/management/managementKey.ts @@ -26,6 +26,7 @@ const withManagementKey = (httpClient: HttpClient) => ({ description: string, status: MgmtKeyStatus, permittedIps?: string[], + reBac?: MgmtKeyReBac, ): Promise> => transformResponse( httpClient.patch(apiPaths.managementKey.update, { @@ -34,6 +35,8 @@ const withManagementKey = (httpClient: HttpClient) => ({ description, permittedIps, status, + // reBac is sent only when provided, so omitting it keeps the key's current roles + ...(reBac !== undefined ? { reBac } : {}), }), (data) => data.key, ),