0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

chore(core,test): add status code guard for SIE, custom phrase and config APIs (#3813)

This commit is contained in:
Darcy Ye 2023-05-08 10:43:57 +08:00 committed by GitHub
parent 4d475bfa3b
commit 520e0c3df3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 11 deletions

View file

@ -140,7 +140,7 @@ describe('customPhraseRoutes', () => {
const response = await customPhraseRequest const response = await customPhraseRequest
.put(`/custom-phrases/${mockLanguageTag}`) .put(`/custom-phrases/${mockLanguageTag}`)
.send(translation); .send(translation);
expect(response.status).toEqual(400); expect(response.status).toEqual(422);
}); });
it('should call upsertCustomPhrase with specified language tag', async () => { it('should call upsertCustomPhrase with specified language tag', async () => {
@ -183,9 +183,9 @@ describe('customPhraseRoutes', () => {
expect(response.status).toEqual(404); expect(response.status).toEqual(404);
}); });
it('should return 400 status code when specified custom phrase is used as fallback language in sign-in experience', async () => { it('should return 409 status code when specified custom phrase is used as fallback language in sign-in experience', async () => {
const response = await customPhraseRequest.delete(`/custom-phrases/${mockFallbackLanguage}`); const response = await customPhraseRequest.delete(`/custom-phrases/${mockFallbackLanguage}`);
expect(response.status).toEqual(400); expect(response.status).toEqual(409);
}); });
it('should return 400 status code when the language tag is invalid', async () => { it('should return 400 status code when the language tag is invalid', async () => {

View file

@ -48,7 +48,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
koaGuard({ koaGuard({
params: object({ languageTag: languageTagGuard }), params: object({ languageTag: languageTagGuard }),
response: CustomPhrases.guard, response: CustomPhrases.guard,
status: [200], status: [200, 404],
}), }),
async (ctx, next) => { async (ctx, next) => {
const { const {
@ -67,7 +67,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
params: object({ languageTag: languageTagGuard }), params: object({ languageTag: languageTagGuard }),
body: translationGuard, body: translationGuard,
response: CustomPhrases.guard, response: CustomPhrases.guard,
status: [200], status: [200, 422],
}), }),
async (ctx, next) => { async (ctx, next) => {
const { const {
@ -79,7 +79,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
assertThat( assertThat(
isStrictlyPartial(resource.en.translation, translation), isStrictlyPartial(resource.en.translation, translation),
new RequestError('localization.invalid_translation_structure') new RequestError({ code: 'localization.invalid_translation_structure', status: 422 })
); );
ctx.body = await upsertCustomPhrase(languageTag, translation); ctx.body = await upsertCustomPhrase(languageTag, translation);
@ -92,7 +92,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
'/custom-phrases/:languageTag', '/custom-phrases/:languageTag',
koaGuard({ koaGuard({
params: object({ languageTag: languageTagGuard }), params: object({ languageTag: languageTagGuard }),
status: [204], status: [204, 404, 409],
}), }),
async (ctx, next) => { async (ctx, next) => {
const { const {
@ -106,6 +106,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
if (fallbackLanguage === languageTag) { if (fallbackLanguage === languageTag) {
throw new RequestError({ throw new RequestError({
code: 'localization.cannot_delete_default_language', code: 'localization.cannot_delete_default_language',
status: 409,
languageTag, languageTag,
}); });
} }

View file

@ -11,7 +11,7 @@ export default function logtoConfigRoutes<T extends AuthedRouter>(
router.get( router.get(
'/configs/admin-console', '/configs/admin-console',
koaGuard({ response: adminConsoleDataGuard, status: 200 }), koaGuard({ response: adminConsoleDataGuard, status: [200, 404] }),
async (ctx, next) => { async (ctx, next) => {
const { value } = await getAdminConsoleConfig(); const { value } = await getAdminConsoleConfig();
ctx.body = value; ctx.body = value;
@ -25,7 +25,7 @@ export default function logtoConfigRoutes<T extends AuthedRouter>(
koaGuard({ koaGuard({
body: adminConsoleDataGuard.partial(), body: adminConsoleDataGuard.partial(),
response: adminConsoleDataGuard, response: adminConsoleDataGuard,
status: 200, status: [200, 404],
}), }),
async (ctx, next) => { async (ctx, next) => {
const { value } = await updateAdminConsoleConfig(ctx.guard.body); const { value } = await updateAdminConsoleConfig(ctx.guard.body);

View file

@ -25,7 +25,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
'/sign-in-exp', '/sign-in-exp',
koaGuard({ koaGuard({
response: SignInExperiences.guard, response: SignInExperiences.guard,
status: [200], status: [200, 404],
}), }),
async (ctx, next) => { async (ctx, next) => {
ctx.body = await findDefaultSignInExperience(); ctx.body = await findDefaultSignInExperience();
@ -48,7 +48,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
) )
.partial(), .partial(),
response: SignInExperiences.guard, response: SignInExperiences.guard,
status: [200], status: [200, 400, 404, 422],
}), }),
async (ctx, next) => { async (ctx, next) => {
const { const {

View file

@ -60,6 +60,12 @@ describe('custom-phrase flow', () => {
expect(zhTranslationNew).toEqual(mockZhTranslationUpdated); expect(zhTranslationNew).toEqual(mockZhTranslationUpdated);
}); });
it('fail to update an existing custom phrase with invalid translation keys', async () => {
await expect(
createOrUpdateCustomPhrase('zh', { ...mockZhTranslationUpdated, invalidKey: 'invalid value' })
).rejects.toThrow(HTTPError);
});
it('failed to get a custom phrase with invalid language tag (zh-ZH)', async () => { it('failed to get a custom phrase with invalid language tag (zh-ZH)', async () => {
await expect(getCustomPhrase('zh-ZH')).rejects.toThrow(HTTPError); await expect(getCustomPhrase('zh-ZH')).rejects.toThrow(HTTPError);
}); });
@ -86,6 +92,10 @@ describe('custom-phrase flow', () => {
await expect(deleteCustomPhrase('zh-TW')).rejects.toThrow(HTTPError); await expect(deleteCustomPhrase('zh-TW')).rejects.toThrow(HTTPError);
}); });
it('fail to delete a custom phrase which has been set as fallback language', async () => {
await expect(deleteCustomPhrase('en')).rejects.toThrow(HTTPError);
});
it('delete all custom phrases', async () => { it('delete all custom phrases', async () => {
await deleteCustomPhrase('zh'); await deleteCustomPhrase('zh');
await deleteCustomPhrase('en-US'); await deleteCustomPhrase('en-US');

View file

@ -1,4 +1,7 @@
import { SignInIdentifier } from '@logto/schemas';
import { getSignInExperience, updateSignInExperience } from '#src/api/index.js'; import { getSignInExperience, updateSignInExperience } from '#src/api/index.js';
import { createResponseWithCode } from '#src/helpers/admin-tenant.js';
describe('admin console sign-in experience', () => { describe('admin console sign-in experience', () => {
it('should get sign-in experience successfully', async () => { it('should get sign-in experience successfully', async () => {
@ -25,4 +28,18 @@ describe('admin console sign-in experience', () => {
const updatedSignInExperience = await updateSignInExperience(newSignInExperience); const updatedSignInExperience = await updateSignInExperience(newSignInExperience);
expect(updatedSignInExperience).toMatchObject(newSignInExperience); expect(updatedSignInExperience).toMatchObject(newSignInExperience);
}); });
it('throw 400 when fail to validate SIE', async () => {
const newSignInExperience = {
signUp: {
identifiers: [SignInIdentifier.Username],
password: false,
verify: false,
},
};
await expect(updateSignInExperience(newSignInExperience)).rejects.toMatchObject(
createResponseWithCode(400)
);
});
}); });