mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
list policies endpoint
This commit is contained in:
@@ -58,6 +58,33 @@ export const registerApprovalPolicyEndpoints = <P extends TApprovalPolicy>({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "List approval policies",
|
||||||
|
querystring: z.object({
|
||||||
|
projectId: z.string().uuid()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
policies: z.array(policyResponseSchema)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { policies } = await server.services.approvalPolicy.list(policyType, req.query.projectId, req.permission);
|
||||||
|
|
||||||
|
// TODO: Audit log
|
||||||
|
|
||||||
|
return { policies };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "/:policyId",
|
url: "/:policyId",
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import { TableName } from "@app/db/schemas";
|
|||||||
import { DatabaseError } from "@app/lib/errors";
|
import { DatabaseError } from "@app/lib/errors";
|
||||||
import { ormify } from "@app/lib/knex";
|
import { ormify } from "@app/lib/knex";
|
||||||
|
|
||||||
import { ApproverType } from "./approval-policy-enums";
|
import { ApprovalPolicyType, ApproverType } from "./approval-policy-enums";
|
||||||
|
import { ApprovalPolicyStep } from "./approval-policy-types";
|
||||||
|
|
||||||
// Approval Policy
|
// Approval Policy
|
||||||
export type TApprovalPolicyDALFactory = ReturnType<typeof approvalPolicyDALFactory>;
|
export type TApprovalPolicyDALFactory = ReturnType<typeof approvalPolicyDALFactory>;
|
||||||
@@ -25,25 +26,23 @@ export const approvalPolicyDALFactory = (db: TDbClient) => {
|
|||||||
.whereIn("policyStepId", stepIds)
|
.whereIn("policyStepId", stepIds)
|
||||||
.select("policyStepId", "userId", "groupId");
|
.select("policyStepId", "userId", "groupId");
|
||||||
|
|
||||||
const approversByStepId = approvers.reduce<Record<string, { type: string; id: string }[]>>((acc, approver) => {
|
const approversByStepId = approvers.reduce<Record<string, { type: ApproverType; id: string }[]>>(
|
||||||
const stepApprovers = acc[approver.policyStepId] || [];
|
(acc, approver) => {
|
||||||
stepApprovers.push({
|
const stepApprovers = acc[approver.policyStepId] || [];
|
||||||
type: approver.userId ? ApproverType.User : ApproverType.Group,
|
stepApprovers.push({
|
||||||
id: (approver.userId || approver.groupId) as string
|
type: approver.userId ? ApproverType.User : ApproverType.Group,
|
||||||
});
|
id: (approver.userId || approver.groupId) as string
|
||||||
acc[approver.policyStepId] = stepApprovers;
|
});
|
||||||
return acc;
|
acc[approver.policyStepId] = stepApprovers;
|
||||||
}, {});
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
return steps.map((step) => {
|
return steps.map((step) => {
|
||||||
const stepApprovers = approversByStepId[step.id] || [];
|
const stepApprovers = approversByStepId[step.id] || [];
|
||||||
|
|
||||||
const formattedStep: {
|
const formattedStep: ApprovalPolicyStep = {
|
||||||
name?: string;
|
|
||||||
requiredApprovals: number;
|
|
||||||
notifyApprovers?: boolean;
|
|
||||||
approvers: { type: string; id: string }[];
|
|
||||||
} = {
|
|
||||||
requiredApprovals: step.requiredApprovals,
|
requiredApprovals: step.requiredApprovals,
|
||||||
approvers: stepApprovers
|
approvers: stepApprovers
|
||||||
};
|
};
|
||||||
@@ -62,9 +61,77 @@ export const approvalPolicyDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findByProjectId = async (policyType: ApprovalPolicyType, projectId: string) => {
|
||||||
|
try {
|
||||||
|
const dbInstance = db.replicaNode();
|
||||||
|
const policies = await dbInstance(TableName.ApprovalPolicies).where({ type: policyType, projectId });
|
||||||
|
|
||||||
|
if (!policies.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const policyIds = policies.map((p) => p.id);
|
||||||
|
|
||||||
|
const steps = await dbInstance(TableName.ApprovalPolicySteps)
|
||||||
|
.whereIn("policyId", policyIds)
|
||||||
|
.orderBy("stepNumber", "asc");
|
||||||
|
|
||||||
|
const stepsByPolicyId: Record<string, ApprovalPolicyStep[]> = {};
|
||||||
|
|
||||||
|
if (steps.length) {
|
||||||
|
const stepIds = steps.map((step) => step.id);
|
||||||
|
|
||||||
|
const approvers = await dbInstance(TableName.ApprovalPolicyStepApprovers)
|
||||||
|
.whereIn("policyStepId", stepIds)
|
||||||
|
.select("policyStepId", "userId", "groupId");
|
||||||
|
|
||||||
|
const approversByStepId = approvers.reduce<Record<string, { type: ApproverType; id: string }[]>>(
|
||||||
|
(acc, approver) => {
|
||||||
|
const stepApprovers = acc[approver.policyStepId] || [];
|
||||||
|
stepApprovers.push({
|
||||||
|
type: approver.userId ? ApproverType.User : ApproverType.Group,
|
||||||
|
id: (approver.userId || approver.groupId) as string
|
||||||
|
});
|
||||||
|
acc[approver.policyStepId] = stepApprovers;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
steps.forEach((step) => {
|
||||||
|
const stepApprovers = approversByStepId[step.id] || [];
|
||||||
|
const formattedStep: ApprovalPolicyStep = {
|
||||||
|
requiredApprovals: step.requiredApprovals,
|
||||||
|
approvers: stepApprovers
|
||||||
|
};
|
||||||
|
|
||||||
|
if (step.name) {
|
||||||
|
formattedStep.name = step.name;
|
||||||
|
}
|
||||||
|
if (typeof step.notifyApprovers === "boolean") {
|
||||||
|
formattedStep.notifyApprovers = step.notifyApprovers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stepsByPolicyId[step.policyId]) {
|
||||||
|
stepsByPolicyId[step.policyId] = [];
|
||||||
|
}
|
||||||
|
stepsByPolicyId[step.policyId].push(formattedStep);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return policies.map((policy) => ({
|
||||||
|
...policy,
|
||||||
|
steps: stepsByPolicyId[policy.id] || []
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "Find approval policies by project id" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...orm,
|
...orm,
|
||||||
findStepsByPolicyId
|
findStepsByPolicyId,
|
||||||
|
findByProjectId
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,25 @@ export const approvalPolicyServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const list = async (policyType: ApprovalPolicyType, projectId: string, actor: OrgServiceActor) => {
|
||||||
|
const { hasRole } = await permissionService.getProjectPermission({
|
||||||
|
actor: actor.type,
|
||||||
|
actorAuthMethod: actor.authMethod,
|
||||||
|
actorId: actor.id,
|
||||||
|
actorOrgId: actor.orgId,
|
||||||
|
projectId,
|
||||||
|
actionProjectType: ActionProjectType.Any
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasRole(ProjectMembershipRole.Admin)) {
|
||||||
|
throw new ForbiddenRequestError({ message: "User has insufficient privileges" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const policies = await approvalPolicyDAL.findByProjectId(policyType, projectId);
|
||||||
|
|
||||||
|
return { policies };
|
||||||
|
};
|
||||||
|
|
||||||
const getById = async (policyId: string, actor: OrgServiceActor) => {
|
const getById = async (policyId: string, actor: OrgServiceActor) => {
|
||||||
const policy = await approvalPolicyDAL.findById(policyId);
|
const policy = await approvalPolicyDAL.findById(policyId);
|
||||||
if (!policy) {
|
if (!policy) {
|
||||||
@@ -270,6 +289,7 @@ export const approvalPolicyServiceFactory = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
create,
|
create,
|
||||||
|
list,
|
||||||
getById,
|
getById,
|
||||||
updateById,
|
updateById,
|
||||||
deleteById
|
deleteById
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { TApprovalPolicyDALFactory, TApprovalRequestGrantsDALFactory } from "./approval-policy-dal";
|
import {
|
||||||
|
TApprovalPolicyDALFactory,
|
||||||
|
TApprovalRequestGrantsDALFactory
|
||||||
|
} from "@app/services/approval-policy/approval-policy-dal";
|
||||||
|
|
||||||
import { ApprovalPolicyType, ApproverType } from "./approval-policy-enums";
|
import { ApprovalPolicyType, ApproverType } from "./approval-policy-enums";
|
||||||
import {
|
import {
|
||||||
TPamAccessPolicy,
|
TPamAccessPolicy,
|
||||||
@@ -12,6 +16,16 @@ export type TApprovalPolicyInputs = TPamAccessPolicyInputs;
|
|||||||
export type TApprovalPolicyConditions = TPamAccessPolicyConditions;
|
export type TApprovalPolicyConditions = TPamAccessPolicyConditions;
|
||||||
export type TApprovalPolicyConstraints = TPamAccessPolicyConstraints;
|
export type TApprovalPolicyConstraints = TPamAccessPolicyConstraints;
|
||||||
|
|
||||||
|
export interface ApprovalPolicyStep {
|
||||||
|
name?: string | null;
|
||||||
|
requiredApprovals: number;
|
||||||
|
notifyApprovers?: boolean;
|
||||||
|
approvers: {
|
||||||
|
type: ApproverType;
|
||||||
|
id: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
// DTOs
|
// DTOs
|
||||||
export interface TCreatePolicyDTO {
|
export interface TCreatePolicyDTO {
|
||||||
projectId: TApprovalPolicy["projectId"];
|
projectId: TApprovalPolicy["projectId"];
|
||||||
@@ -19,15 +33,7 @@ export interface TCreatePolicyDTO {
|
|||||||
maxRequestTtlSeconds?: TApprovalPolicy["maxRequestTtlSeconds"];
|
maxRequestTtlSeconds?: TApprovalPolicy["maxRequestTtlSeconds"];
|
||||||
conditions: TApprovalPolicy["conditions"]["conditions"];
|
conditions: TApprovalPolicy["conditions"]["conditions"];
|
||||||
constraints: TApprovalPolicy["constraints"]["constraints"];
|
constraints: TApprovalPolicy["constraints"]["constraints"];
|
||||||
steps: {
|
steps: ApprovalPolicyStep[];
|
||||||
name?: string | null;
|
|
||||||
requiredApprovals: number;
|
|
||||||
notifyApprovers?: boolean;
|
|
||||||
approvers: {
|
|
||||||
type: ApproverType.User | ApproverType.Group;
|
|
||||||
id: string;
|
|
||||||
}[];
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TUpdatePolicyDTO {
|
export interface TUpdatePolicyDTO {
|
||||||
@@ -35,15 +41,7 @@ export interface TUpdatePolicyDTO {
|
|||||||
maxRequestTtlSeconds?: TApprovalPolicy["maxRequestTtlSeconds"];
|
maxRequestTtlSeconds?: TApprovalPolicy["maxRequestTtlSeconds"];
|
||||||
conditions?: TApprovalPolicy["conditions"]["conditions"];
|
conditions?: TApprovalPolicy["conditions"]["conditions"];
|
||||||
constraints?: TApprovalPolicy["constraints"]["constraints"];
|
constraints?: TApprovalPolicy["constraints"]["constraints"];
|
||||||
steps?: {
|
steps?: ApprovalPolicyStep[];
|
||||||
name?: string | null;
|
|
||||||
requiredApprovals: number;
|
|
||||||
notifyApprovers?: boolean;
|
|
||||||
approvers: {
|
|
||||||
type: ApproverType.User | ApproverType.Group;
|
|
||||||
id: string;
|
|
||||||
}[];
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Factory
|
// Factory
|
||||||
|
|||||||
Reference in New Issue
Block a user