-
-
Notifications
You must be signed in to change notification settings - Fork 472
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
143 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
"@logto/core": patch | ||
--- | ||
|
||
fix POST /api/organization-roles API | ||
|
||
When invalid organization scope IDs or resource scope IDs are provided, the API should return a 422 error without creating the organization role. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
/* eslint-disable max-lines */ | ||
// TODO: @darcy reorg to break this file into smaller files | ||
Check warning on line 2 in packages/integration-tests/src/tests/api/organization/organization-role.test.ts GitHub Actions / ESLint Report Analysispackages/integration-tests/src/tests/api/organization/organization-role.test.ts#L2
|
||
import assert from 'node:assert'; | ||
|
||
import { generateStandardId } from '@logto/shared'; | ||
import { isKeyInObject, pick } from '@silverhand/essentials'; | ||
import { HTTPError } from 'ky'; | ||
|
||
import { createResource } from '#src/api/index.js'; | ||
import { createScope } from '#src/api/scope.js'; | ||
import { OrganizationRoleApiTest, OrganizationScopeApiTest } from '#src/helpers/organization.js'; | ||
import { ScopeApiTest } from '#src/helpers/resource.js'; | ||
import { generateScopeName } from '#src/utils.js'; | ||
|
||
const randomId = () => generateStandardId(4); | ||
|
||
|
@@ -179,6 +184,85 @@ describe('organization role APIs', () => { | |
const response = await roleApi.delete('0').catch((error: unknown) => error); | ||
expect(response instanceof HTTPError && response.response.status).toBe(404); | ||
}); | ||
|
||
it('should fail when creating a role with invalid organization scope IDs', async () => { | ||
const invalidScopeId = generateStandardId(); | ||
const response = await roleApi | ||
.create({ | ||
name: 'test' + randomId(), | ||
organizationScopeIds: [invalidScopeId], | ||
}) | ||
.catch((error: unknown) => error); | ||
|
||
assert(response instanceof HTTPError); | ||
const body: unknown = await response.response.json(); | ||
expect(response.response.status).toBe(422); | ||
expect(body).toMatchObject( | ||
expect.objectContaining({ | ||
code: 'organization.roles.invalid_scope_ids', | ||
}) | ||
); | ||
|
||
const roles = await roleApi.getList(); | ||
expect(roles).toHaveLength(0); | ||
}); | ||
|
||
it('should fail when creating a role with invalid resource scope IDs', async () => { | ||
const invalidScopeId = generateStandardId(); | ||
const response = await roleApi | ||
.create({ | ||
name: 'test' + randomId(), | ||
resourceScopeIds: [invalidScopeId], | ||
}) | ||
.catch((error: unknown) => error); | ||
|
||
assert(response instanceof HTTPError); | ||
const body: unknown = await response.response.json(); | ||
expect(response.response.status).toBe(422); | ||
expect(body).toMatchObject( | ||
expect.objectContaining({ | ||
code: 'organization.roles.invalid_resource_scope_ids', | ||
}) | ||
); | ||
|
||
const roles = await roleApi.getList(); | ||
expect(roles).toHaveLength(0); | ||
}); | ||
|
||
it('should successfully create a role with scope IDs are provided', async () => { | ||
const resource = await createResource(); | ||
const scopeName = generateScopeName(); | ||
const createdScope = await createScope(resource.id, scopeName); | ||
|
||
const [scope1, scope2] = await Promise.all([ | ||
scopeApi.create({ name: 'test' + randomId() }), | ||
scopeApi.create({ name: 'test' + randomId() }), | ||
]); | ||
const createdRole = await roleApi.create({ | ||
name: 'test' + randomId(), | ||
organizationScopeIds: [scope1.id, scope2.id], | ||
resourceScopeIds: [createdScope.id], | ||
}); | ||
|
||
expect(createdRole).toHaveProperty('id'); | ||
expect(createdRole).toHaveProperty('name'); | ||
|
||
const scopes = await roleApi.getScopes(createdRole.id); | ||
expect(scopes).toContainEqual( | ||
expect.objectContaining({ | ||
name: scope1.name, | ||
}) | ||
); | ||
expect(scopes).toContainEqual( | ||
expect.objectContaining({ | ||
name: scope2.name, | ||
}) | ||
); | ||
|
||
const { resourceScopes } = await roleApi.get(createdRole.id); | ||
expect(resourceScopes.length).toBe(1); | ||
expect(resourceScopes[0]).toHaveProperty('name', scopeName); | ||
}); | ||
}); | ||
|
||
describe('organization role - scope relations', () => { | ||
|
@@ -397,3 +481,4 @@ describe('organization role APIs', () => { | |
}); | ||
}); | ||
}); | ||
/* eslint-enable max-lines */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
const organizations = { | ||
require_membership: 'The user must be a member of the organization to proceed.', | ||
roles: { | ||
invalid_scope_ids: 'The organization scope IDs are not valid.', | ||
invalid_resource_scope_ids: 'The resource scope IDs are not valid.', | ||
}, | ||
}; | ||
|
||
export default Object.freeze(organizations); |