0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-03 21:48:55 -05:00

refactor(core): throw duplicate error

This commit is contained in:
Gao Sun 2023-10-12 15:12:29 +08:00
parent 996d550382
commit 5fca07ee8d
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
18 changed files with 100 additions and 2 deletions

View file

@ -0,0 +1,23 @@
import { UniqueIntegrityConstraintViolationError } from 'slonik';
import RequestError from '#src/errors/RequestError/index.js';
import { MockTenant } from '#src/test-utils/tenant.js';
import { OrganizationScopeActions } from './organization-scopes.js';
describe('OrganizationScopeActions', () => {
it('should throw RequestError if UniqueIntegrityConstraintViolationError is thrown inside', async () => {
const tenantContext = new MockTenant(undefined, {
organizationScopes: {
insert: async () => {
throw new UniqueIntegrityConstraintViolationError(new Error('test'), 'unique');
},
},
});
const actions = new OrganizationScopeActions(tenantContext.queries.organizationScopes);
await expect(actions.post({ name: 'test' })).rejects.toThrowError(
new RequestError({ code: 'entity.duplicate_value_of_unique_field', field: 'name' })
);
});
});

View file

@ -1,9 +1,36 @@
import { OrganizationScopes } from '@logto/schemas';
import {
type CreateOrganizationScope,
type OrganizationScope,
type OrganizationScopeKeys,
OrganizationScopes,
} from '@logto/schemas';
import { UniqueIntegrityConstraintViolationError } from 'slonik';
import RequestError from '#src/errors/RequestError/index.js';
import SchemaRouter, { SchemaActions } from '#src/utils/SchemaRouter.js';
import { type AuthedRouter, type RouterInitArgs } from './types.js';
export class OrganizationScopeActions extends SchemaActions<
OrganizationScopeKeys,
CreateOrganizationScope,
OrganizationScope
> {
override async post(
data: Omit<CreateOrganizationScope, 'id'>
): Promise<Readonly<OrganizationScope>> {
try {
return await super.post(data);
} catch (error: unknown) {
if (error instanceof UniqueIntegrityConstraintViolationError) {
throw new RequestError({ code: 'entity.duplicate_value_of_unique_field', field: 'name' });
}
throw error;
}
}
}
export default function organizationScopeRoutes<T extends AuthedRouter>(
...[
originalRouter,
@ -12,7 +39,10 @@ export default function organizationScopeRoutes<T extends AuthedRouter>(
},
]: RouterInitArgs<T>
) {
const router = new SchemaRouter(OrganizationScopes, new SchemaActions(organizationScopes));
const router = new SchemaRouter(
OrganizationScopes,
new OrganizationScopeActions(organizationScopes)
);
originalRouter.use(router.routes());
}

View file

@ -1,4 +1,7 @@
import assert from 'node:assert';
import { generateStandardId } from '@logto/shared';
import { isKeyInObject } from '@silverhand/essentials';
import { HTTPError } from 'got';
import {
@ -12,6 +15,19 @@ import {
const randomId = () => generateStandardId(4);
describe('organization scopes', () => {
it('should fail if the name of the new organization scope already exists', async () => {
const name = 'test' + randomId();
await createOrganizationScope(name);
const response = await createOrganizationScope(name).catch((error: unknown) => error);
assert(response instanceof HTTPError);
const { statusCode, body: raw } = response.response;
const body: unknown = JSON.parse(String(raw));
expect(statusCode).toBe(400);
expect(isKeyInObject(body, 'code') && body.code).toBe('entity.duplicate_value_of_unique_field');
});
it('should get organization scopes successfully', async () => {
const [name1, name2] = ['test' + randomId(), 'test' + randomId()];
await createOrganizationScope(name1, 'A test organization scope.');

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} existiert nicht.',
not_exists_with_id: '{{name}} mit ID `{{id}}` existiert nicht.',
not_found: 'Die Ressource wurde nicht gefunden.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,7 @@ const entity = {
not_exists: 'The {{name}} does not exist.',
not_exists_with_id: 'The {{name}} with ID `{{id}}` does not exist.',
not_found: 'The resource does not exist.',
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: 'El {{name}} no existe.',
not_exists_with_id: 'El {{name}} con ID `{{id}}` no existe.',
not_found: 'El recurso no existe.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: "Le {{name}} n'existe pas.",
not_exists_with_id: "Le {{name}} avec l'ID `{{id}}` n'existe pas.",
not_found: "La ressource n'existe pas.",
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} non esiste.',
not_exists_with_id: '{{name}} con ID `{{id}}` non esiste.',
not_found: 'La risorsa non esiste.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}}は存在しません。',
not_exists_with_id: 'IDが`{{id}}`の{{name}}は存在しません。',
not_found: 'リソースが存在しません。',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}}는 존재하지 않아요.',
not_exists_with_id: '{{id}} ID를 가진 {{name}}는 존재하지 않아요.',
not_found: '리소스가 존재하지 않아요.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} nie istnieje.',
not_exists_with_id: '{{name}} o identyfikatorze `{{id}}` nie istnieje.',
not_found: 'Zasób nie istnieje.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: 'O {{name}} não existe.',
not_exists_with_id: 'O {{name}} com ID `{{id}}` não existe.',
not_found: 'O recurso não existe.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} não existe.',
not_exists_with_id: '{{name}} com o ID `{{id}}` não existe.',
not_found: 'O recurso não existe.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} не существует.',
not_exists_with_id: '{{name}} с ID `{{id}}` не существует.',
not_found: 'Ресурс не существует.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} mevcut değil.',
not_exists_with_id: ' `{{id}}` id kimliğine sahip {{name}} mevcut değil.',
not_found: 'Kaynak mevcut değil.',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '该 {{name}} 不存在。',
not_exists_with_id: 'ID 为 `{{id}}` 的 {{name}} 不存在。',
not_found: '该资源不存在。',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '該 {{name}} 不存在。',
not_exists_with_id: 'ID 為 `{{id}}` 的 {{name}} 不存在。',
not_found: '該資源不存在。',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);

View file

@ -5,6 +5,8 @@ const entity = {
not_exists: '{{name}} 不存在。',
not_exists_with_id: 'ID 為 `{{id}}` 的 {{name}} 不存在。',
not_found: '資源不存在。',
/** UNTRANSLATED */
duplicate_value_of_unique_field: 'The value of the unique field `{{field}}` is duplicated.',
};
export default Object.freeze(entity);