roles table

This commit is contained in:
Fred KISSIE
2026-03-23 21:34:44 +01:00
parent 062bec23b6
commit 294532ecbb
6 changed files with 187 additions and 152 deletions

View File

@@ -3,34 +3,68 @@ import response from "@server/lib/response";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import HttpCode from "@server/types/HttpCode";
import { and, eq, inArray, sql } from "drizzle-orm";
import { and, asc, desc, eq, inArray, like, sql } from "drizzle-orm";
import { ActionsEnum } from "@server/auth/actions";
import { NextFunction, Request, Response } from "express";
import createHttpError from "http-errors";
import { object, z } from "zod";
import { fromError } from "zod-validation-error";
import type { PaginatedResponse } from "@server/types/Pagination";
const listRolesParamsSchema = z.strictObject({
orgId: z.string()
});
const listRolesSchema = z.object({
limit: z
.string()
pageSize: z.coerce
.number<string>() // for prettier formatting
.int()
.positive()
.optional()
.default("1000")
.transform(Number)
.pipe(z.int().nonnegative()),
offset: z
.string()
.catch(20)
.default(20)
.openapi({
type: "integer",
default: 20,
description: "Number of items per page"
}),
page: z.coerce
.number<string>() // for prettier formatting
.int()
.min(0)
.optional()
.default("0")
.transform(Number)
.pipe(z.int().nonnegative())
.catch(1)
.default(1)
.openapi({
type: "integer",
default: 1,
description: "Page number to retrieve"
}),
query: z.string().optional(),
sort_by: z
.enum(["name"])
.optional()
.catch(undefined)
.openapi({
type: "string",
enum: ["name"],
description: "Field to sort by"
}),
order: z
.enum(["asc", "desc"])
.optional()
.default("asc")
.catch("asc")
.openapi({
type: "string",
enum: ["asc", "desc"],
default: "asc",
description: "Sort order"
})
});
async function queryRoles(orgId: string, limit: number, offset: number) {
return await db
function queryRolesBase() {
return db
.select({
roleId: roles.roleId,
orgId: roles.orgId,
@@ -45,20 +79,15 @@ async function queryRoles(orgId: string, limit: number, offset: number) {
sshUnixGroups: roles.sshUnixGroups
})
.from(roles)
.leftJoin(orgs, eq(roles.orgId, orgs.orgId))
.where(eq(roles.orgId, orgId))
.limit(limit)
.offset(offset);
.leftJoin(orgs, eq(roles.orgId, orgs.orgId));
// .where(eq(roles.orgId, orgId))
// .limit(limit)
// .offset(offset);
}
export type ListRolesResponse = {
roles: NonNullable<Awaited<ReturnType<typeof queryRoles>>>;
pagination: {
total: number;
limit: number;
offset: number;
};
};
export type ListRolesResponse = PaginatedResponse<{
roles: NonNullable<Awaited<ReturnType<typeof queryRolesBase>>>;
}>;
registry.registerPath({
method: "get",
@@ -88,7 +117,7 @@ export async function listRoles(
);
}
const { limit, offset } = parsedQuery.data;
const { page, pageSize, query, sort_by, order } = parsedQuery.data;
const parsedParams = listRolesParamsSchema.safeParse(req.params);
if (!parsedParams.success) {
@@ -102,14 +131,36 @@ export async function listRoles(
const { orgId } = parsedParams.data;
const countQuery: any = db
.select({ count: sql<number>`cast(count(*) as integer)` })
.from(roles)
.where(eq(roles.orgId, orgId));
const conditions = [and(eq(roles.orgId, orgId))];
const rolesList = await queryRoles(orgId, limit, offset);
const totalCountResult = await countQuery;
const totalCount = totalCountResult[0].count;
if (query) {
conditions.push(
like(sql`LOWER(${roles.name})`, "%" + query.toLowerCase() + "%")
);
}
const countQuery = db.$count(
queryRolesBase()
.where(and(...conditions))
.as("filtered_roles")
);
const rolesListQuery = queryRolesBase()
.where(and(...conditions))
.limit(pageSize)
.offset(pageSize * (page - 1))
.orderBy(
sort_by
? order === "asc"
? asc(roles[sort_by])
: desc(roles[sort_by])
: asc(roles.name)
);
const [totalCount, rolesList] = await Promise.all([
countQuery,
rolesListQuery
]);
let rolesWithAllowSsh = rolesList;
if (rolesList.length > 0) {
@@ -135,8 +186,8 @@ export async function listRoles(
roles: rolesWithAllowSsh,
pagination: {
total: totalCount,
limit,
offset
page,
pageSize
}
},
success: true,