diff --git a/packages/core/src/routes/application.test.ts b/packages/core/src/routes/application.test.ts index 1aaf6d2b2..6fc0364ec 100644 --- a/packages/core/src/routes/application.test.ts +++ b/packages/core/src/routes/application.test.ts @@ -169,6 +169,7 @@ describe('application route', () => { 'http://127.0.0.1', 'http://localhost:3002', ], + postLogoutRedirectUris: [], }, }) ).resolves.toHaveProperty('status', 200); @@ -179,6 +180,7 @@ describe('application route', () => { applicationRequest.patch('/applications/foo').send({ oidcClientMetadata: { redirectUris: ['www.example.com', 'com.example://callback'], + postLogoutRedirectUris: [], }, }) ).resolves.toHaveProperty('status', 400); @@ -194,6 +196,7 @@ describe('application route', () => { 'com.example://callback', 'io.logto://Abc123', ], + postLogoutRedirectUris: [], }, }) ).resolves.toHaveProperty('status', 200); @@ -205,6 +208,7 @@ describe('application route', () => { type: ApplicationType.Native, oidcClientMetadata: { redirectUris: ['https://www.example.com', 'com.example/callback'], + postLogoutRedirectUris: [], }, }) ).resolves.toHaveProperty('status', 400); diff --git a/packages/core/src/routes/application.ts b/packages/core/src/routes/application.ts index 403067956..12f5f8ece 100644 --- a/packages/core/src/routes/application.ts +++ b/packages/core/src/routes/application.ts @@ -35,20 +35,25 @@ export default function applicationRoutes( queries.applicationsRoles; const { findRoleByRoleName } = queries.roles; - router.get('/applications', koaPagination(), async (ctx, next) => { - const { limit, offset } = ctx.pagination; + router.get( + '/applications', + koaPagination(), + koaGuard({ response: z.array(Applications.guard), status: 200 }), + async (ctx, next) => { + const { limit, offset } = ctx.pagination; - const [{ count }, applications] = await Promise.all([ - findTotalNumberOfApplications(), - findAllApplications(limit, offset), - ]); + const [{ count }, applications] = await Promise.all([ + findTotalNumberOfApplications(), + findAllApplications(limit, offset), + ]); - // Return totalCount to pagination middleware - ctx.pagination.totalCount = count; - ctx.body = applications; + // Return totalCount to pagination middleware + ctx.pagination.totalCount = count; + ctx.body = applications; - return next(); - }); + return next(); + } + ); router.post( '/applications', @@ -57,6 +62,8 @@ export default function applicationRoutes( .omit({ id: true, createdAt: true }) .partial() .merge(Applications.createGuard.pick({ name: true, type: true })), + response: Applications.guard, + status: [200, 422], }), async (ctx, next) => { const { oidcClientMetadata, ...rest } = ctx.guard.body; @@ -77,6 +84,7 @@ export default function applicationRoutes( koaGuard({ params: object({ id: string().min(1) }), response: Applications.guard.merge(z.object({ isAdmin: z.boolean() })), + status: [200, 404], }), async (ctx, next) => { const { @@ -114,6 +122,8 @@ export default function applicationRoutes( isAdmin: boolean().optional(), }) ), + response: Applications.guard, + status: [200, 404, 500], }), async (ctx, next) => { const { @@ -135,7 +145,11 @@ export default function applicationRoutes( assertThat( internalAdminRole, - new RequestError('entity.not_exists', { name: InternalRole.Admin }) + new RequestError({ + code: 'entity.not_exists', + status: 500, + data: { name: InternalRole.Admin }, + }) ); if (isAdmin && !usedToBeAdmin) { @@ -155,7 +169,11 @@ export default function applicationRoutes( router.delete( '/applications/:id', - koaGuard({ params: object({ id: string().min(1) }) }), + koaGuard({ + params: object({ id: string().min(1) }), + response: z.undefined(), + status: [204, 404], + }), async (ctx, next) => { const { id } = ctx.guard.params; // Note: will need delete cascade when application is joint with other tables diff --git a/packages/integration-tests/src/api/application.ts b/packages/integration-tests/src/api/application.ts index 8778232df..2219a89d7 100644 --- a/packages/integration-tests/src/api/application.ts +++ b/packages/integration-tests/src/api/application.ts @@ -17,6 +17,8 @@ export const createApplication = async (name: string, type: ApplicationType) => }) .json(); +export const getApplications = async () => authedAdminApi.get('applications').json(); + export const getApplication = async (applicationId: string) => authedAdminApi.get(`applications/${applicationId}`).json(); diff --git a/packages/integration-tests/src/tests/api/application.test.ts b/packages/integration-tests/src/tests/api/application.test.ts index 84b0d7e89..84f51eaac 100644 --- a/packages/integration-tests/src/tests/api/application.test.ts +++ b/packages/integration-tests/src/tests/api/application.test.ts @@ -6,13 +6,13 @@ import { getApplication, updateApplication, deleteApplication, + getApplications, } from '#src/api/index.js'; describe('admin console application', () => { it('should create application successfully', async () => { const applicationName = 'test-create-app'; const applicationType = ApplicationType.SPA; - const application = await createApplication(applicationName, applicationType); expect(application.name).toBe(applicationName); @@ -25,7 +25,7 @@ describe('admin console application', () => { }); it('should update application details successfully', async () => { - const application = await createApplication('test-update-app', ApplicationType.SPA); + const application = await createApplication('test-update-app', ApplicationType.Traditional); const newApplicationDescription = `new_${application.description ?? ''}`; @@ -46,8 +46,15 @@ describe('admin console application', () => { expect(updatedApplication.oidcClientMetadata.redirectUris).toEqual(newRedirectUris); }); + it('should fetch all applications created above', async () => { + const applications = await getApplications(); + const applicationNames = applications.map(({ name }) => name); + expect(applicationNames).toContain('test-create-app'); + expect(applicationNames).toContain('test-update-app'); + }); + it('should delete application successfully', async () => { - const application = await createApplication('test-delete-app', ApplicationType.SPA); + const application = await createApplication('test-delete-app', ApplicationType.Native); await deleteApplication(application.id);