2022-01-28 00:33:57 -05:00
|
|
|
import { userInfoSelectFields } from '@logto/schemas';
|
|
|
|
import pick from 'lodash.pick';
|
|
|
|
import { InvalidInputError } from 'slonik';
|
|
|
|
import { object, string } from 'zod';
|
|
|
|
|
|
|
|
import koaGuard from '@/middleware/koa-guard';
|
2022-02-16 02:55:08 -05:00
|
|
|
import koaPagination from '@/middleware/koa-pagination';
|
2022-01-28 00:33:57 -05:00
|
|
|
import { findRolesByRoleNames } from '@/queries/roles';
|
2022-02-16 02:55:08 -05:00
|
|
|
import { findAllUsers, findTotalNumberOfUsers, findUserById, updateUserById } from '@/queries/user';
|
2022-01-28 00:33:57 -05:00
|
|
|
|
|
|
|
import { AuthedRouter } from './types';
|
|
|
|
|
|
|
|
export default function adminUserRoutes<T extends AuthedRouter>(router: T) {
|
2022-02-16 02:55:08 -05:00
|
|
|
router.get('/users', koaPagination(), async (ctx, next) => {
|
|
|
|
const { limit, offset } = ctx.pagination;
|
|
|
|
|
|
|
|
const [{ count }, users] = await Promise.all([
|
|
|
|
findTotalNumberOfUsers(),
|
|
|
|
findAllUsers(limit, offset),
|
|
|
|
]);
|
|
|
|
|
|
|
|
ctx.pagination.totalCount = count;
|
2022-01-28 00:33:57 -05:00
|
|
|
ctx.body = users.map((user) => pick(user, ...userInfoSelectFields));
|
|
|
|
|
|
|
|
return next();
|
|
|
|
});
|
|
|
|
|
|
|
|
router.patch(
|
|
|
|
'/users/:userId/roleNames',
|
|
|
|
koaGuard({
|
|
|
|
params: object({ userId: string().min(1) }),
|
|
|
|
body: object({ roleNames: string().array() }),
|
|
|
|
}),
|
|
|
|
async (ctx, next) => {
|
|
|
|
const {
|
|
|
|
params: { userId },
|
|
|
|
body: { roleNames },
|
|
|
|
} = ctx.guard;
|
|
|
|
|
|
|
|
await findUserById(userId);
|
|
|
|
|
|
|
|
// Temp solution to validate the existence of input roleNames
|
|
|
|
if (roleNames.length > 0) {
|
|
|
|
const roles = await findRolesByRoleNames(roleNames);
|
|
|
|
|
|
|
|
if (roles.length !== roleNames.length) {
|
|
|
|
const resourcesNotFound = roleNames.filter(
|
|
|
|
(roleName) => !roles.some(({ name }) => roleName === name)
|
|
|
|
);
|
|
|
|
// TODO: Should be cached by the error handler and return request error
|
|
|
|
throw new InvalidInputError(`role names (${resourcesNotFound.join(',')}) are not valid`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const user = await updateUserById(userId, { roleNames });
|
|
|
|
ctx.body = pick(user, ...userInfoSelectFields);
|
|
|
|
|
|
|
|
return next();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|