mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-10 14:24:17 +00:00
🚧 wip: list resource endpoints finished
This commit is contained in:
@@ -131,7 +131,11 @@ export enum ActionsEnum {
|
|||||||
viewLogs = "viewLogs",
|
viewLogs = "viewLogs",
|
||||||
exportLogs = "exportLogs",
|
exportLogs = "exportLogs",
|
||||||
listApprovals = "listApprovals",
|
listApprovals = "listApprovals",
|
||||||
updateApprovals = "updateApprovals"
|
updateApprovals = "updateApprovals",
|
||||||
|
listResourcePolicies = "listResourcePolicies",
|
||||||
|
createResourcePolicies = "createResourcePolicies",
|
||||||
|
updateResourcePolicies = "updateResourcePolicies",
|
||||||
|
deleteResourcePolicies = "deleteResourcePolicies",
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkUserActionPermission(
|
export async function checkUserActionPermission(
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import * as logs from "#private/routers/auditLogs";
|
|||||||
import * as misc from "#private/routers/misc";
|
import * as misc from "#private/routers/misc";
|
||||||
import * as reKey from "#private/routers/re-key";
|
import * as reKey from "#private/routers/re-key";
|
||||||
import * as approval from "#private/routers/approvals";
|
import * as approval from "#private/routers/approvals";
|
||||||
|
import * as resource from "#private/routers/resource";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
@@ -340,6 +341,18 @@ authenticated.get(
|
|||||||
approval.countApprovals
|
approval.countApprovals
|
||||||
);
|
);
|
||||||
|
|
||||||
|
authenticated.get(
|
||||||
|
"/org/:orgId/resource-policies",
|
||||||
|
verifyValidLicense,
|
||||||
|
// verifyValidSubscription(tierMatrix.loginPageDomain), // todo: use the correct subscription ?
|
||||||
|
verifyOrgAccess,
|
||||||
|
verifyLimits,
|
||||||
|
verifyUserHasAction(ActionsEnum.listResourcePolicies),
|
||||||
|
logActionAudit(ActionsEnum.listResourcePolicies),
|
||||||
|
resource.listResourcePolicies
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/org/:orgId/approvals/:approvalId",
|
"/org/:orgId/approvals/:approvalId",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
|
|||||||
@@ -12,3 +12,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from "./getMaintenanceInfo";
|
export * from "./getMaintenanceInfo";
|
||||||
|
export * from "./listResourcePolicies";
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
import response from "@server/lib/response";
|
import response from "@server/lib/response";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
import { sql, eq, or, inArray, and, count } from "drizzle-orm";
|
import { sql, eq, or, inArray, and, count, ilike, asc } from "drizzle-orm";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { fromZodError } from "zod-validation-error";
|
import { fromZodError } from "zod-validation-error";
|
||||||
import { OpenAPITags, registry } from "@server/openApi";
|
import { OpenAPITags, registry } from "@server/openApi";
|
||||||
@@ -97,9 +97,9 @@ function queryResourcePoliciesBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replaced with `PaginatedResponse<T>` when paginated table PR is merged
|
// TODO: replaced with `PaginatedResponse<T>` when paginated table PR is merged
|
||||||
export type ListResourcesResponse = {
|
export type ListResourcePoliciesResponse = {
|
||||||
policies: Awaited<ReturnType<typeof queryResourcePoliciesBase>>;
|
policies: Awaited<ReturnType<typeof queryResourcePoliciesBase>>;
|
||||||
total: number; pageSize: number; page: number;
|
pagination: { total: number; pageSize: number; page: number; };
|
||||||
};
|
};
|
||||||
|
|
||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
@@ -166,6 +166,82 @@ export async function listResourcePolicies(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let accessibleResourcePolicies: Array<{ resourcePolicyId: number; }>;
|
||||||
|
if (req.user) {
|
||||||
|
accessibleResourcePolicies = await db
|
||||||
|
.select({
|
||||||
|
resourcePolicyId: sql<number>`COALESCE(${userResources.resourcePolicyId}, ${roleResources.resourcePolicyId})`
|
||||||
|
})
|
||||||
|
.from(userResources)
|
||||||
|
.fullJoin(
|
||||||
|
roleResources,
|
||||||
|
eq(userResources.resourcePolicyId, roleResources.resourcePolicyId)
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
or(
|
||||||
|
eq(userResources.userId, req.user!.userId),
|
||||||
|
eq(roleResources.roleId, req.userOrgRoleId!)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
accessibleResourcePolicies = await db
|
||||||
|
.select({
|
||||||
|
resourcePolicyId: resourcePolicies.resourcePolicyId
|
||||||
|
})
|
||||||
|
.from(resourcePolicies)
|
||||||
|
.where(eq(resourcePolicies.orgId, orgId));
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessibleResourceIds = accessibleResourcePolicies.map(
|
||||||
|
(resource) => resource.resourcePolicyId
|
||||||
|
);
|
||||||
|
|
||||||
|
const conditions = [
|
||||||
|
and(
|
||||||
|
inArray(resourcePolicies.resourcePolicyId, accessibleResourceIds),
|
||||||
|
eq(resourcePolicies.orgId, orgId)
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
conditions.push(
|
||||||
|
or(
|
||||||
|
ilike(resourcePolicies.name, "%" + query + "%"),
|
||||||
|
ilike(resourcePolicies.niceId, "%" + query + "%"),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseQuery = queryResourcePoliciesBase()
|
||||||
|
.where(and(...conditions));
|
||||||
|
|
||||||
|
// we need to add `as` so that drizzle filters the result as a subquery
|
||||||
|
const countQuery = db.$count(baseQuery.as("filtered_policies"));
|
||||||
|
|
||||||
|
const [rows, totalCount] = await Promise.all([
|
||||||
|
baseQuery
|
||||||
|
.limit(pageSize)
|
||||||
|
.offset(pageSize * (page - 1))
|
||||||
|
.orderBy(asc(resourcePolicies.resourcePolicyId)),
|
||||||
|
countQuery
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response<ListResourcePoliciesResponse>(res, {
|
||||||
|
data: {
|
||||||
|
policies: rows,
|
||||||
|
pagination: {
|
||||||
|
total: totalCount,
|
||||||
|
pageSize,
|
||||||
|
page
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
error: false,
|
||||||
|
message: "Resources retrieved successfully",
|
||||||
|
status: HttpCode.OK
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
return next(
|
return next(
|
||||||
|
|||||||
Reference in New Issue
Block a user