0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat(core): list roles filter by userId (#2893)

This commit is contained in:
wangsijie 2023-01-10 17:04:27 +08:00 committed by GitHub
parent 751d6117c1
commit 5d862f617f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 6 deletions

View file

@ -1,7 +1,7 @@
import type { CreateRole, Role } from '@logto/schemas';
import { adminConsoleAdminRoleId, SearchJointMode, Roles } from '@logto/schemas';
import type { OmitAutoSetFields } from '@logto/shared';
import { conditionalSql, convertToIdentifiers } from '@logto/shared';
import { conditionalArraySql, conditionalSql, convertToIdentifiers } from '@logto/shared';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';
@ -28,20 +28,33 @@ const buildRoleConditions = (search: Search) => {
export const defaultUserSearch = { matches: [], isCaseSensitive: false, joint: SearchJointMode.Or };
export const createRolesQueries = (pool: CommonQueryMethods) => {
const countRoles = async (search: Search = defaultUserSearch) =>
const countRoles = async (search: Search = defaultUserSearch, excludeRoleIds: string[] = []) =>
pool.one<{ count: number }>(sql`
select count(*)
from ${table}
where ${fields.id}<>${adminConsoleAdminRoleId}
${conditionalArraySql(
excludeRoleIds,
(value) => sql`and ${fields.id} not in (${sql.join(value, sql`, `)})`
)}
${buildRoleConditions(search)}
`);
const findRoles = async (search: Search, limit?: number, offset?: number) =>
const findRoles = async (
search: Search,
excludeRoleIds: string[] = [],
limit?: number,
offset?: number
) =>
pool.any<Role>(
sql`
select ${sql.join(Object.values(fields), sql`, `)}
from ${table}
where ${fields.id}<>${adminConsoleAdminRoleId}
${conditionalArraySql(
excludeRoleIds,
(value) => sql`and ${fields.id} not in (${sql.join(value, sql`, `)})`
)}
${buildRoleConditions(search)}
${conditionalSql(limit, (value) => sql`limit ${value}`)}
${conditionalSql(offset, (value) => sql`offset ${value}`)}

View file

@ -29,6 +29,7 @@ import {
deleteUsersRolesByUserIdAndRoleId,
findFirstUsersRolesByRoleIdAndUserIds,
findUsersRolesByRoleId,
findUsersRolesByUserId,
insertUsersRoles,
} from '#src/queries/users-roles.js';
import assertThat from '#src/utils/assert-that.js';
@ -46,16 +47,19 @@ export default function roleRoutes<T extends AuthedRouter>(...[router]: RouterIn
return tryThat(
async () => {
const search = parseSearchParamsForSearch(searchParams);
const excludeUserId = searchParams.get('excludeUserId');
const usersRoles = excludeUserId ? await findUsersRolesByUserId(excludeUserId) : [];
const excludeRoleIds = usersRoles.map(({ roleId }) => roleId);
if (disabled) {
ctx.body = await findRoles(search);
ctx.body = await findRoles(search, excludeRoleIds);
return next();
}
const [{ count }, roles] = await Promise.all([
countRoles(search),
findRoles(search, limit, offset),
countRoles(search, excludeRoleIds),
findRoles(search, excludeRoleIds, limit, offset),
]);
const rolesResponse: RoleResponse[] = await Promise.all(

View file

@ -8,6 +8,10 @@ import type { FieldIdentifiers, Table } from './types.js';
export const conditionalSql = <T>(value: T, buildSql: (value: Exclude<T, Falsy>) => SqlSqlToken) =>
notFalsy(value) ? buildSql(value) : sql``;
export const conditionalArraySql = <T>(
value: T[],
buildSql: (value: Exclude<T[], Falsy>) => SqlSqlToken
) => (value.length > 0 ? buildSql(value) : sql``);
export const autoSetFields = Object.freeze(['createdAt', 'updatedAt'] as const);
export type OmitAutoSetFields<T> = Omit<T, typeof autoSetFields[number]>;