mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
feat(core): add pagination and search to role users (#2927)
This commit is contained in:
parent
6d874d5250
commit
900b87b9a5
3 changed files with 52 additions and 10 deletions
|
@ -105,7 +105,7 @@ export const createUserQueries = (pool: CommonQueryMethods) => {
|
|||
`
|
||||
);
|
||||
|
||||
const buildUserConditions = (search: Search, excludeUserIds: string[]) => {
|
||||
const buildUserConditions = (search: Search, excludeUserIds: string[], userIds?: string[]) => {
|
||||
const hasSearch = search.matches.length > 0;
|
||||
const searchFields = [
|
||||
Users.fields.id,
|
||||
|
@ -127,6 +127,16 @@ export const createUserQueries = (pool: CommonQueryMethods) => {
|
|||
`;
|
||||
}
|
||||
|
||||
if (userIds) {
|
||||
return sql`
|
||||
where ${fields.id} in (${userIds.length > 0 ? sql.join(userIds, sql`, `) : sql`null`})
|
||||
${conditionalSql(
|
||||
hasSearch,
|
||||
() => sql`and (${buildConditionsFromSearch(search, searchFields)})`
|
||||
)}
|
||||
`;
|
||||
}
|
||||
|
||||
return conditionalSql(
|
||||
hasSearch,
|
||||
() => sql`where ${buildConditionsFromSearch(search, searchFields)}`
|
||||
|
@ -135,18 +145,23 @@ export const createUserQueries = (pool: CommonQueryMethods) => {
|
|||
|
||||
const defaultUserSearch = { matches: [], isCaseSensitive: false, joint: SearchJointMode.Or };
|
||||
|
||||
const countUsers = async (search: Search = defaultUserSearch, excludeUserIds: string[] = []) =>
|
||||
const countUsers = async (
|
||||
search: Search = defaultUserSearch,
|
||||
excludeUserIds: string[] = [],
|
||||
userIds?: string[]
|
||||
) =>
|
||||
pool.one<{ count: number }>(sql`
|
||||
select count(*)
|
||||
from ${table}
|
||||
${buildUserConditions(search, excludeUserIds)}
|
||||
${buildUserConditions(search, excludeUserIds, userIds)}
|
||||
`);
|
||||
|
||||
const findUsers = async (
|
||||
limit: number,
|
||||
offset: number,
|
||||
search: Search,
|
||||
excludeUserIds: string[] = []
|
||||
excludeUserIds: string[] = [],
|
||||
userIds?: string[]
|
||||
) =>
|
||||
pool.any<User>(
|
||||
sql`
|
||||
|
@ -155,7 +170,7 @@ export const createUserQueries = (pool: CommonQueryMethods) => {
|
|||
sql`,`
|
||||
)}
|
||||
from ${table}
|
||||
${buildUserConditions(search, excludeUserIds)}
|
||||
${buildUserConditions(search, excludeUserIds, userIds)}
|
||||
limit ${limit}
|
||||
offset ${offset}
|
||||
`
|
||||
|
|
|
@ -44,6 +44,8 @@ const { insertRolesScopes } = rolesScopes;
|
|||
const users = {
|
||||
findUsersByIds: jest.fn(),
|
||||
findUserById: jest.fn(),
|
||||
countUsers: jest.fn(async () => ({ count: 1 })),
|
||||
findUsers: jest.fn(async () => [mockUser]),
|
||||
};
|
||||
const { findUsersByIds } = users;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ export default function roleRoutes<T extends AuthedRouter>(
|
|||
updateRoleById,
|
||||
},
|
||||
scopes: { findScopeById },
|
||||
users: { findUserById, findUsersByIds },
|
||||
users: { findUserById, findUsersByIds, countUsers, findUsers },
|
||||
usersRoles: {
|
||||
countUsersRolesByRoleId,
|
||||
deleteUsersRolesByUserIdAndRoleId,
|
||||
|
@ -190,6 +190,7 @@ export default function roleRoutes<T extends AuthedRouter>(
|
|||
|
||||
router.get(
|
||||
'/roles/:id/users',
|
||||
koaPagination(),
|
||||
koaGuard({
|
||||
params: object({ id: string().min(1) }),
|
||||
}),
|
||||
|
@ -197,13 +198,37 @@ export default function roleRoutes<T extends AuthedRouter>(
|
|||
const {
|
||||
params: { id },
|
||||
} = ctx.guard;
|
||||
const { limit, offset } = ctx.pagination;
|
||||
const { searchParams } = ctx.request.URL;
|
||||
|
||||
await findRoleById(id);
|
||||
const usersRoles = await findUsersRolesByRoleId(id);
|
||||
const users = await findUsersByIds(usersRoles.map(({ userId }) => userId));
|
||||
ctx.body = users.map((user) => pick(user, ...userInfoSelectFields));
|
||||
|
||||
return next();
|
||||
return tryThat(
|
||||
async () => {
|
||||
const search = parseSearchParamsForSearch(searchParams);
|
||||
const usersRoles = await findUsersRolesByRoleId(id);
|
||||
const userIds = usersRoles.map(({ userId }) => userId);
|
||||
|
||||
const [{ count }, users] = await Promise.all([
|
||||
countUsers(search, undefined, userIds),
|
||||
findUsers(limit, offset, search, undefined, userIds),
|
||||
]);
|
||||
|
||||
ctx.pagination.totalCount = count;
|
||||
ctx.body = users.map((user) => pick(user, ...userInfoSelectFields));
|
||||
|
||||
return next();
|
||||
},
|
||||
(error) => {
|
||||
if (error instanceof TypeError) {
|
||||
throw new RequestError(
|
||||
{ code: 'request.invalid_input', details: error.message },
|
||||
error
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue