diff --git a/packages/core/src/saml-applications/libraries/saml-applications.ts b/packages/core/src/saml-applications/libraries/saml-applications.ts index 63a685366..8d4257efd 100644 --- a/packages/core/src/saml-applications/libraries/saml-applications.ts +++ b/packages/core/src/saml-applications/libraries/saml-applications.ts @@ -6,6 +6,7 @@ import { import { generateStandardId } from '@logto/shared'; import { removeUndefinedKeys } from '@silverhand/essentials'; +import RequestError from '#src/errors/RequestError/index.js'; import type Queries from '#src/tenants/Queries.js'; import assertThat from '#src/utils/assert-that.js'; @@ -42,7 +43,13 @@ export const createSamlApplicationsLibrary = (queries: Queries) => { const findSamlApplicationById = async (id: string): Promise => { const application = await findApplicationById(id); - assertThat(application.type === ApplicationType.SAML, 'application.saml.saml_application_only'); + assertThat( + application.type === ApplicationType.SAML, + new RequestError({ + code: 'application.saml.saml_application_only', + status: 422, + }) + ); const samlConfig = await findSamlApplicationConfigByApplicationId(application.id); @@ -53,24 +60,20 @@ export const createSamlApplicationsLibrary = (queries: Queries) => { id: string, patchApplicationObject: PatchSamlApplication ): Promise => { - const { name, description, customData, config } = patchApplicationObject; + const { config, ...applicationData } = patchApplicationObject; const originalApplication = await findApplicationById(id); + assertThat( originalApplication.type === ApplicationType.SAML, - 'application.saml.saml_application_only' + new RequestError({ + code: 'application.saml.saml_application_only', + status: 422, + }) ); const [updatedApplication, upToDateSamlConfig] = await Promise.all([ - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - name || description || customData - ? updateApplicationById( - id, - removeUndefinedKeys({ - name, - description, - customData, - }) - ) + Object.keys(applicationData).length > 0 + ? updateApplicationById(id, removeUndefinedKeys(applicationData)) : originalApplication, config ? updateSamlApplicationConfig({ diff --git a/packages/core/src/saml-applications/libraries/utils.ts b/packages/core/src/saml-applications/libraries/utils.ts index 25d4925f7..9a4c52b02 100644 --- a/packages/core/src/saml-applications/libraries/utils.ts +++ b/packages/core/src/saml-applications/libraries/utils.ts @@ -90,8 +90,9 @@ export const ensembleSamlApplication = ({ * Only HTTP-POST binding is supported for receiving SAML assertions at the moment. */ export const validateAcsUrl = (acsUrl: SamlAcsUrl) => { + const { binding } = acsUrl; assertThat( - acsUrl.binding === BindingType.POST, + binding === BindingType.POST, new RequestError({ code: 'application.saml.acs_url_binding_not_supported', status: 422, diff --git a/packages/core/src/saml-applications/routes/index.ts b/packages/core/src/saml-applications/routes/index.ts index c134a6bad..ed3256520 100644 --- a/packages/core/src/saml-applications/routes/index.ts +++ b/packages/core/src/saml-applications/routes/index.ts @@ -8,13 +8,15 @@ import { generateStandardId } from '@logto/shared'; import { removeUndefinedKeys } from '@silverhand/essentials'; import { z } from 'zod'; +import RequestError from '#src/errors/RequestError/index.js'; import koaGuard from '#src/middleware/koa-guard.js'; import { buildOidcClientMetadata } from '#src/oidc/utils.js'; import { generateInternalSecret } from '#src/routes/applications/application-secret.js'; import type { ManagementApiRouter, RouterInitArgs } from '#src/routes/types.js'; -import { ensembleSamlApplication, validateAcsUrl } from '#src/saml-applications/libraries/utils.js'; import assertThat from '#src/utils/assert-that.js'; +import { ensembleSamlApplication, validateAcsUrl } from '../libraries/utils.js'; + export default function samlApplicationRoutes( ...[router, { queries, libraries }]: RouterInitArgs ) { @@ -84,7 +86,7 @@ export default function samlApplicationRoutes( id: z.string(), }), response: samlApplicationResponseGuard, - status: [200, 400, 404], + status: [200, 404, 422], }), async (ctx, next) => { const { id } = ctx.guard.params; @@ -104,7 +106,7 @@ export default function samlApplicationRoutes( params: z.object({ id: z.string() }), body: samlApplicationPatchGuard, response: samlApplicationResponseGuard, - status: [200, 400, 404], + status: [200, 404, 422], }), async (ctx, next) => { const { id } = ctx.guard.params; @@ -122,13 +124,19 @@ export default function samlApplicationRoutes( '/saml-applications/:id', koaGuard({ params: z.object({ id: z.string() }), - status: [204, 400, 404], + status: [204, 422, 404], }), async (ctx, next) => { const { id } = ctx.guard.params; const { type } = await findApplicationById(id); - assertThat(type === ApplicationType.SAML, 'application.saml.saml_application_only'); + assertThat( + type === ApplicationType.SAML, + new RequestError({ + code: 'application.saml.saml_application_only', + status: 422, + }) + ); await deleteApplicationById(id); diff --git a/packages/integration-tests/src/tests/api/application/saml-application.test.ts b/packages/integration-tests/src/tests/api/application/saml-application.test.ts index a41a817cf..08a4eaf95 100644 --- a/packages/integration-tests/src/tests/api/application/saml-application.test.ts +++ b/packages/integration-tests/src/tests/api/application/saml-application.test.ts @@ -91,15 +91,15 @@ describe('SAML application', () => { await expectRejects(deleteSamlApplication(application.id), { code: 'application.saml.saml_application_only', - status: 400, + status: 422, }); await expectRejects(updateSamlApplication(application.id, { name: 'updated' }), { code: 'application.saml.saml_application_only', - status: 400, + status: 422, }); await expectRejects(getSamlApplication(application.id), { code: 'application.saml.saml_application_only', - status: 400, + status: 422, }); await deleteApplication(application.id); }); diff --git a/packages/schemas/src/foundations/jsonb-types/saml-application-configs.ts b/packages/schemas/src/foundations/jsonb-types/saml-application-configs.ts index db985ac0e..7880d8bb5 100644 --- a/packages/schemas/src/foundations/jsonb-types/saml-application-configs.ts +++ b/packages/schemas/src/foundations/jsonb-types/saml-application-configs.ts @@ -19,5 +19,5 @@ export type SamlAcsUrl = { export const samlAcsUrlGuard = z.object({ binding: z.nativeEnum(BindingType), - url: z.string(), + url: z.string().url(), }) satisfies ToZodObject;