2022-04-14 14:48:56 +08:00
|
|
|
import { Applications, SnakeCaseOidcConfig } from '@logto/schemas';
|
|
|
|
import camelcaseKeys from 'camelcase-keys';
|
|
|
|
import got from 'got';
|
2021-08-26 22:50:27 +08:00
|
|
|
import { object, string } from 'zod';
|
2021-08-30 11:30:54 +08:00
|
|
|
|
2022-04-14 14:48:56 +08:00
|
|
|
import { port } from '@/env/consts';
|
2021-08-14 21:39:37 +08:00
|
|
|
import koaGuard from '@/middleware/koa-guard';
|
2022-01-11 16:37:09 +08:00
|
|
|
import koaPagination from '@/middleware/koa-pagination';
|
2021-10-11 17:55:17 +08:00
|
|
|
import { buildOidcClientMetadata } from '@/oidc/utils';
|
2021-08-27 00:33:13 +08:00
|
|
|
import {
|
|
|
|
deleteApplicationById,
|
2021-09-01 18:23:53 +08:00
|
|
|
findApplicationById,
|
2021-09-01 20:51:34 +08:00
|
|
|
findAllApplications,
|
2021-08-27 00:33:13 +08:00
|
|
|
insertApplication,
|
|
|
|
updateApplicationById,
|
2022-01-11 16:37:09 +08:00
|
|
|
findTotalNumberOfApplications,
|
2021-08-27 00:33:13 +08:00
|
|
|
} from '@/queries/application';
|
2021-08-18 00:24:00 +08:00
|
|
|
import { buildIdGenerator } from '@/utils/id';
|
|
|
|
|
2021-09-01 17:35:23 +08:00
|
|
|
import { AuthedRouter } from './types';
|
|
|
|
|
2021-08-18 00:24:00 +08:00
|
|
|
const applicationId = buildIdGenerator(21);
|
2021-08-14 21:39:37 +08:00
|
|
|
|
2022-04-14 14:48:56 +08:00
|
|
|
const discoveryUrl = `http://localhost:${port}/oidc/.well-known/openid-configuration`;
|
|
|
|
|
2021-09-01 17:35:23 +08:00
|
|
|
export default function applicationRoutes<T extends AuthedRouter>(router: T) {
|
2022-01-11 16:37:09 +08:00
|
|
|
router.get('/applications', koaPagination(), async (ctx, next) => {
|
|
|
|
const { limit, offset } = ctx.pagination;
|
|
|
|
|
2022-04-14 14:48:56 +08:00
|
|
|
const [{ count }, applications, oidcConfig] = await Promise.all([
|
2022-01-11 16:37:09 +08:00
|
|
|
findTotalNumberOfApplications(),
|
|
|
|
findAllApplications(limit, offset),
|
2022-04-14 14:48:56 +08:00
|
|
|
got(discoveryUrl).json<SnakeCaseOidcConfig>(),
|
2022-01-11 16:37:09 +08:00
|
|
|
]);
|
|
|
|
|
|
|
|
// Return totalCount to pagination middleware
|
|
|
|
ctx.pagination.totalCount = count;
|
2022-04-14 14:48:56 +08:00
|
|
|
ctx.body = applications.map((application) => ({
|
|
|
|
...application,
|
|
|
|
oidcConfig: camelcaseKeys(oidcConfig),
|
|
|
|
}));
|
2022-01-11 16:37:09 +08:00
|
|
|
|
2021-09-01 20:51:34 +08:00
|
|
|
return next();
|
|
|
|
});
|
|
|
|
|
2021-08-14 21:39:37 +08:00
|
|
|
router.post(
|
2021-11-18 11:26:51 +08:00
|
|
|
'/applications',
|
2021-08-14 21:39:37 +08:00
|
|
|
koaGuard({
|
2022-01-18 12:44:08 +08:00
|
|
|
body: Applications.createGuard
|
2021-08-26 22:50:27 +08:00
|
|
|
.omit({ id: true, createdAt: true })
|
|
|
|
.partial()
|
2022-01-18 12:44:08 +08:00
|
|
|
.merge(Applications.createGuard.pick({ name: true, type: true })),
|
2021-08-14 21:39:37 +08:00
|
|
|
}),
|
|
|
|
async (ctx, next) => {
|
2022-04-13 15:23:04 +08:00
|
|
|
const { name, type, oidcClientMetadata, customClientMetadata } = ctx.guard.body;
|
2021-08-14 21:39:37 +08:00
|
|
|
|
2022-04-14 14:48:56 +08:00
|
|
|
const [application, oidcConfig] = await Promise.all([
|
|
|
|
insertApplication({
|
|
|
|
id: applicationId(),
|
|
|
|
type,
|
|
|
|
name,
|
|
|
|
oidcClientMetadata: buildOidcClientMetadata(oidcClientMetadata),
|
|
|
|
customClientMetadata,
|
|
|
|
}),
|
|
|
|
got(discoveryUrl).json<SnakeCaseOidcConfig>(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
ctx.body = {
|
|
|
|
...application,
|
|
|
|
oidcConfig: camelcaseKeys(oidcConfig),
|
|
|
|
};
|
2022-01-27 19:26:34 +08:00
|
|
|
|
2021-08-14 21:39:37 +08:00
|
|
|
return next();
|
|
|
|
}
|
|
|
|
);
|
2021-08-24 00:11:25 +08:00
|
|
|
|
2021-09-01 18:23:53 +08:00
|
|
|
router.get(
|
2021-11-18 11:26:51 +08:00
|
|
|
'/applications/:id',
|
2021-09-01 18:23:53 +08:00
|
|
|
koaGuard({
|
|
|
|
params: object({ id: string().min(1) }),
|
|
|
|
}),
|
|
|
|
async (ctx, next) => {
|
|
|
|
const {
|
|
|
|
params: { id },
|
|
|
|
} = ctx.guard;
|
|
|
|
|
2022-04-14 14:48:56 +08:00
|
|
|
const [application, oidcConfig] = await Promise.all([
|
|
|
|
findApplicationById(id),
|
|
|
|
got(discoveryUrl).json<SnakeCaseOidcConfig>(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
ctx.body = {
|
|
|
|
...application,
|
|
|
|
oidcConfig: camelcaseKeys(oidcConfig),
|
|
|
|
};
|
2022-01-27 19:26:34 +08:00
|
|
|
|
2021-09-01 18:23:53 +08:00
|
|
|
return next();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2021-08-27 00:33:13 +08:00
|
|
|
router.patch(
|
2021-11-18 11:26:51 +08:00
|
|
|
'/applications/:id',
|
2021-08-27 00:33:13 +08:00
|
|
|
koaGuard({
|
|
|
|
params: object({ id: string().min(1) }),
|
2022-01-18 12:44:08 +08:00
|
|
|
body: Applications.createGuard.omit({ id: true, createdAt: true }).partial(),
|
2021-08-27 00:33:13 +08:00
|
|
|
}),
|
|
|
|
async (ctx, next) => {
|
|
|
|
const {
|
|
|
|
params: { id },
|
|
|
|
body,
|
|
|
|
} = ctx.guard;
|
|
|
|
|
2022-04-14 14:48:56 +08:00
|
|
|
const [application, oidcConfig] = await Promise.all([
|
|
|
|
updateApplicationById(id, {
|
|
|
|
...body,
|
|
|
|
}),
|
|
|
|
got(discoveryUrl).json<SnakeCaseOidcConfig>(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
ctx.body = {
|
|
|
|
...application,
|
|
|
|
oidcConfig: camelcaseKeys(oidcConfig),
|
|
|
|
};
|
2022-01-27 19:26:34 +08:00
|
|
|
|
2021-08-27 00:33:13 +08:00
|
|
|
return next();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2021-08-24 00:11:25 +08:00
|
|
|
router.delete(
|
2021-11-18 11:26:51 +08:00
|
|
|
'/applications/:id',
|
2021-08-24 00:11:25 +08:00
|
|
|
koaGuard({ params: object({ id: string().min(1) }) }),
|
|
|
|
async (ctx, next) => {
|
|
|
|
const { id } = ctx.guard.params;
|
|
|
|
// Note: will need delete cascade when application is joint with other tables
|
2022-01-13 16:02:28 +08:00
|
|
|
await findApplicationById(id);
|
2021-08-24 00:11:25 +08:00
|
|
|
await deleteApplicationById(id);
|
|
|
|
ctx.status = 204;
|
2022-01-27 19:26:34 +08:00
|
|
|
|
2021-08-24 00:11:25 +08:00
|
|
|
return next();
|
|
|
|
}
|
|
|
|
);
|
2021-08-14 21:39:37 +08:00
|
|
|
}
|