mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-18 02:56:57 +00:00
Allow multiple environments on secret and access policies
This commit is contained in:
@@ -26,6 +26,7 @@ export interface TAccessApprovalPolicyDALFactory
|
||||
>,
|
||||
customFilter?: {
|
||||
policyId?: string;
|
||||
envId?: string;
|
||||
},
|
||||
tx?: Knex
|
||||
) => Promise<
|
||||
@@ -55,11 +56,6 @@ export interface TAccessApprovalPolicyDALFactory
|
||||
allowedSelfApprovals: boolean;
|
||||
secretPath: string;
|
||||
deletedAt?: Date | null | undefined;
|
||||
environment: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
projectId: string;
|
||||
bypassers: (
|
||||
| {
|
||||
@@ -72,6 +68,11 @@ export interface TAccessApprovalPolicyDALFactory
|
||||
type: BypasserType.Group;
|
||||
}
|
||||
)[];
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}[];
|
||||
}[]
|
||||
>;
|
||||
findById: (
|
||||
@@ -95,11 +96,11 @@ export interface TAccessApprovalPolicyDALFactory
|
||||
allowedSelfApprovals: boolean;
|
||||
secretPath: string;
|
||||
deletedAt?: Date | null | undefined;
|
||||
environment: {
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
}[];
|
||||
projectId: string;
|
||||
}
|
||||
| undefined
|
||||
@@ -143,6 +144,26 @@ export interface TAccessApprovalPolicyDALFactory
|
||||
}
|
||||
| undefined
|
||||
>;
|
||||
findPoliciesByEnvIdAndSecretPath: (
|
||||
{ envIds, secretPath }: { envIds: string[]; secretPath: string },
|
||||
tx?: Knex
|
||||
) => Promise<{
|
||||
name: string;
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
approvals: number;
|
||||
enforcementLevel: string;
|
||||
allowedSelfApprovals: boolean;
|
||||
secretPath: string;
|
||||
deletedAt?: Date | null | undefined;
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}[];
|
||||
projectId: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface TAccessApprovalPolicyServiceFactory {
|
||||
@@ -367,6 +388,7 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
filter: TFindFilter<TAccessApprovalPolicies & { projectId: string }>,
|
||||
customFilter?: {
|
||||
policyId?: string;
|
||||
envId?: string;
|
||||
}
|
||||
) => {
|
||||
const result = await tx(TableName.AccessApprovalPolicy)
|
||||
@@ -377,7 +399,17 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
void qb.where(`${TableName.AccessApprovalPolicy}.id`, "=", customFilter.policyId);
|
||||
}
|
||||
})
|
||||
.join(TableName.Environment, `${TableName.AccessApprovalPolicy}.envId`, `${TableName.Environment}.id`)
|
||||
.where((qb) => {
|
||||
if (customFilter?.envId) {
|
||||
void qb.where(`${TableName.AccessApprovalPolicyEnvironment}.envId`, "=", customFilter.envId);
|
||||
}
|
||||
})
|
||||
.join(
|
||||
TableName.AccessApprovalPolicyEnvironment,
|
||||
`${TableName.AccessApprovalPolicy}.id`,
|
||||
`${TableName.AccessApprovalPolicyEnvironment}.policyId`
|
||||
)
|
||||
.join(TableName.Environment, `${TableName.AccessApprovalPolicyEnvironment}.envId`, `${TableName.Environment}.id`)
|
||||
.leftJoin(
|
||||
TableName.AccessApprovalPolicyApprover,
|
||||
`${TableName.AccessApprovalPolicy}.id`,
|
||||
@@ -404,7 +436,7 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
.select(tx.ref("bypasserGroupId").withSchema(TableName.AccessApprovalPolicyBypasser))
|
||||
.select(tx.ref("name").withSchema(TableName.Environment).as("envName"))
|
||||
.select(tx.ref("slug").withSchema(TableName.Environment).as("envSlug"))
|
||||
.select(tx.ref("id").withSchema(TableName.Environment).as("envId"))
|
||||
.select(tx.ref("id").withSchema(TableName.Environment).as("environmentId"))
|
||||
.select(tx.ref("projectId").withSchema(TableName.Environment))
|
||||
.select(selectAllTableCols(TableName.AccessApprovalPolicy));
|
||||
|
||||
@@ -448,6 +480,15 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
sequence: approverSequence,
|
||||
approvalsRequired
|
||||
})
|
||||
},
|
||||
{
|
||||
key: "environmentId",
|
||||
label: "environments" as const,
|
||||
mapper: ({ environmentId: id, envName, envSlug }) => ({
|
||||
id,
|
||||
name: envName,
|
||||
slug: envSlug
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -470,11 +511,6 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
data: docs,
|
||||
key: "id",
|
||||
parentMapper: (data) => ({
|
||||
environment: {
|
||||
id: data.envId,
|
||||
name: data.envName,
|
||||
slug: data.envSlug
|
||||
},
|
||||
projectId: data.projectId,
|
||||
...AccessApprovalPoliciesSchema.parse(data)
|
||||
// secretPath: data.secretPath || undefined,
|
||||
@@ -517,6 +553,15 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
id,
|
||||
type: BypasserType.Group as const
|
||||
})
|
||||
},
|
||||
{
|
||||
key: "environmentId",
|
||||
label: "environments" as const,
|
||||
mapper: ({ environmentId: id, envName, envSlug }) => ({
|
||||
id,
|
||||
name: envName,
|
||||
slug: envSlug
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -545,14 +590,20 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
buildFindFilter(
|
||||
{
|
||||
envId,
|
||||
secretPath
|
||||
},
|
||||
TableName.AccessApprovalPolicy
|
||||
)
|
||||
)
|
||||
.join(
|
||||
TableName.AccessApprovalPolicyEnvironment,
|
||||
`${TableName.AccessApprovalPolicyEnvironment}.policyId`,
|
||||
`${TableName.AccessApprovalPolicy}.id`
|
||||
)
|
||||
.where(`${TableName.AccessApprovalPolicyEnvironment}.envId`, "=", envId)
|
||||
.orderBy("deletedAt", "desc")
|
||||
.orderByRaw(`"deletedAt" IS NULL`)
|
||||
.select(selectAllTableCols(TableName.AccessApprovalPolicy))
|
||||
.first();
|
||||
|
||||
return result;
|
||||
@@ -561,5 +612,81 @@ export const accessApprovalPolicyDALFactory = (db: TDbClient): TAccessApprovalPo
|
||||
}
|
||||
};
|
||||
|
||||
return { ...accessApprovalPolicyOrm, find, findById, softDeleteById, findLastValidPolicy };
|
||||
const findPoliciesByEnvIdAndSecretPath: TAccessApprovalPolicyDALFactory["findPoliciesByEnvIdAndSecretPath"] = async (
|
||||
{ envIds, secretPath },
|
||||
tx
|
||||
) => {
|
||||
try {
|
||||
const docs = await (tx || db.replicaNode())(TableName.AccessApprovalPolicy)
|
||||
.join(
|
||||
TableName.AccessApprovalPolicyEnvironment,
|
||||
`${TableName.AccessApprovalPolicyEnvironment}.policyId`,
|
||||
`${TableName.AccessApprovalPolicy}.id`
|
||||
)
|
||||
.join(
|
||||
TableName.Environment,
|
||||
`${TableName.AccessApprovalPolicyEnvironment}.envId`,
|
||||
`${TableName.Environment}.id`
|
||||
)
|
||||
.where(
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
buildFindFilter(
|
||||
{
|
||||
$in: {
|
||||
envId: envIds
|
||||
}
|
||||
},
|
||||
TableName.AccessApprovalPolicyEnvironment
|
||||
)
|
||||
)
|
||||
.where(
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
buildFindFilter(
|
||||
{
|
||||
secretPath
|
||||
},
|
||||
TableName.AccessApprovalPolicy
|
||||
)
|
||||
)
|
||||
.whereNull(`${TableName.AccessApprovalPolicy}.deletedAt`)
|
||||
.orderBy("deletedAt", "desc")
|
||||
.orderByRaw(`"deletedAt" IS NULL`)
|
||||
.select(selectAllTableCols(TableName.AccessApprovalPolicy))
|
||||
.select(db.ref("name").withSchema(TableName.Environment).as("envName"))
|
||||
.select(db.ref("slug").withSchema(TableName.Environment).as("envSlug"))
|
||||
.select(db.ref("id").withSchema(TableName.Environment).as("environmentId"))
|
||||
.select(db.ref("projectId").withSchema(TableName.Environment));
|
||||
const formattedDocs = sqlNestRelationships({
|
||||
data: docs,
|
||||
key: "id",
|
||||
parentMapper: (data) => ({
|
||||
projectId: data.projectId,
|
||||
...AccessApprovalPoliciesSchema.parse(data)
|
||||
}),
|
||||
childrenMapper: [
|
||||
{
|
||||
key: "environmentId",
|
||||
label: "environments" as const,
|
||||
mapper: ({ environmentId: id, envName, envSlug }) => ({
|
||||
id,
|
||||
name: envName,
|
||||
slug: envSlug
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
return formattedDocs?.[0];
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "FindPoliciesByEnvIdAndSecretPath" });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
...accessApprovalPolicyOrm,
|
||||
find,
|
||||
findById,
|
||||
softDeleteById,
|
||||
findLastValidPolicy,
|
||||
findPoliciesByEnvIdAndSecretPath
|
||||
};
|
||||
};
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||
|
||||
export type TAccessApprovalPolicyEnvironmentDALFactory = ReturnType<typeof accessApprovalPolicyEnvironmentDALFactory>;
|
||||
|
||||
export const accessApprovalPolicyEnvironmentDALFactory = (db: TDbClient) => {
|
||||
const accessApprovalPolicyEnvironmentOrm = ormify(db, TableName.AccessApprovalPolicyEnvironment);
|
||||
|
||||
const findAvailablePoliciesIds = async (envId: string, tx?: Knex) => {
|
||||
try {
|
||||
const docs = await (tx || db.replicaNode())(TableName.AccessApprovalPolicyEnvironment)
|
||||
.join(
|
||||
TableName.AccessApprovalPolicy,
|
||||
`${TableName.AccessApprovalPolicyEnvironment}.policyId`,
|
||||
`${TableName.AccessApprovalPolicy}.id`
|
||||
)
|
||||
.where({ [`${TableName.AccessApprovalPolicyEnvironment}.envId` as "envId"]: envId })
|
||||
.whereNull(`${TableName.AccessApprovalPolicy}.deletedAt`)
|
||||
.select(selectAllTableCols(TableName.AccessApprovalPolicyEnvironment));
|
||||
return docs;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "findAvailablePoliciesIds" });
|
||||
}
|
||||
};
|
||||
|
||||
return { ...accessApprovalPolicyEnvironmentOrm, findAvailablePoliciesIds };
|
||||
};
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
TAccessApprovalPolicyBypasserDALFactory
|
||||
} from "./access-approval-policy-approver-dal";
|
||||
import { TAccessApprovalPolicyDALFactory } from "./access-approval-policy-dal";
|
||||
import { TAccessApprovalPolicyEnvironmentDALFactory } from "./access-approval-policy-environment-dal";
|
||||
import {
|
||||
ApproverType,
|
||||
BypasserType,
|
||||
@@ -44,12 +45,14 @@ type TAccessApprovalPolicyServiceFactoryDep = {
|
||||
additionalPrivilegeDAL: Pick<TProjectUserAdditionalPrivilegeDALFactory, "delete">;
|
||||
accessApprovalRequestReviewerDAL: Pick<TAccessApprovalRequestReviewerDALFactory, "update" | "delete">;
|
||||
orgMembershipDAL: Pick<TOrgMembershipDALFactory, "find">;
|
||||
accessApprovalPolicyEnvironmentDAL: TAccessApprovalPolicyEnvironmentDALFactory;
|
||||
};
|
||||
|
||||
export const accessApprovalPolicyServiceFactory = ({
|
||||
accessApprovalPolicyDAL,
|
||||
accessApprovalPolicyApproverDAL,
|
||||
accessApprovalPolicyBypasserDAL,
|
||||
accessApprovalPolicyEnvironmentDAL,
|
||||
groupDAL,
|
||||
permissionService,
|
||||
projectEnvDAL,
|
||||
@@ -62,21 +65,22 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
}: TAccessApprovalPolicyServiceFactoryDep): TAccessApprovalPolicyServiceFactory => {
|
||||
const $policyExists = async ({
|
||||
envId,
|
||||
envIds,
|
||||
secretPath,
|
||||
policyId
|
||||
}: {
|
||||
envId: string;
|
||||
envId?: string;
|
||||
envIds?: string[];
|
||||
secretPath: string;
|
||||
policyId?: string;
|
||||
}) => {
|
||||
const policy = await accessApprovalPolicyDAL
|
||||
.findOne({
|
||||
envId,
|
||||
secretPath,
|
||||
deletedAt: null
|
||||
})
|
||||
.catch(() => null);
|
||||
|
||||
if (!envId && !envIds) {
|
||||
throw new BadRequestError({ message: "Must provide either envId or envIds" });
|
||||
}
|
||||
const policy = await accessApprovalPolicyDAL.findPoliciesByEnvIdAndSecretPath({
|
||||
secretPath,
|
||||
envIds: envId ? [envId] : envIds || []
|
||||
});
|
||||
return policyId ? policy && policy.id !== policyId : Boolean(policy);
|
||||
};
|
||||
|
||||
@@ -92,6 +96,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
bypassers,
|
||||
projectSlug,
|
||||
environment,
|
||||
environments,
|
||||
enforcementLevel,
|
||||
allowedSelfApprovals,
|
||||
approvalsRequired
|
||||
@@ -123,13 +128,23 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
ProjectPermissionActions.Create,
|
||||
ProjectPermissionSub.SecretApproval
|
||||
);
|
||||
const env = await projectEnvDAL.findOne({ slug: environment, projectId: project.id });
|
||||
if (!env) throw new NotFoundError({ message: `Environment with slug '${environment}' not found` });
|
||||
const mergedEnvs = (environment ? [environment] : environments) || [];
|
||||
if (mergedEnvs.length === 0) {
|
||||
throw new BadRequestError({ message: "Must provide either environment or environments" });
|
||||
}
|
||||
const envs = await projectEnvDAL.find({ $in: { slug: mergedEnvs }, projectId: project.id });
|
||||
if (!envs.length || envs.length !== mergedEnvs.length) {
|
||||
const notFoundEnvs = mergedEnvs.filter((env) => !envs.find((el) => el.slug === env));
|
||||
throw new NotFoundError({ message: `One or more environments not found: ${notFoundEnvs.join(", ")}` });
|
||||
}
|
||||
|
||||
if (await $policyExists({ envId: env.id, secretPath })) {
|
||||
throw new BadRequestError({
|
||||
message: `A policy for secret path '${secretPath}' already exists in environment '${environment}'`
|
||||
});
|
||||
for (const env of envs) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
if (await $policyExists({ envId: env.id, secretPath })) {
|
||||
throw new BadRequestError({
|
||||
message: `A policy for secret path '${secretPath}' already exists in environment '${env.slug}'`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let approverUserIds = userApprovers;
|
||||
@@ -197,7 +212,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
const accessApproval = await accessApprovalPolicyDAL.transaction(async (tx) => {
|
||||
const doc = await accessApprovalPolicyDAL.create(
|
||||
{
|
||||
envId: env.id,
|
||||
envId: envs[0].id,
|
||||
approvals,
|
||||
secretPath,
|
||||
name,
|
||||
@@ -206,6 +221,10 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await accessApprovalPolicyEnvironmentDAL.insertMany(
|
||||
envs.map((el) => ({ policyId: doc.id, envId: el.id })),
|
||||
tx
|
||||
);
|
||||
|
||||
if (approverUserIds.length) {
|
||||
await accessApprovalPolicyApproverDAL.insertMany(
|
||||
@@ -258,7 +277,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
return doc;
|
||||
});
|
||||
|
||||
return { ...accessApproval, environment: env, projectId: project.id };
|
||||
return { ...accessApproval, environments: envs, projectId: project.id, environment: envs[0] };
|
||||
};
|
||||
|
||||
const getAccessApprovalPolicyByProjectSlug: TAccessApprovalPolicyServiceFactory["getAccessApprovalPolicyByProjectSlug"] =
|
||||
@@ -276,7 +295,10 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
});
|
||||
|
||||
const accessApprovalPolicies = await accessApprovalPolicyDAL.find({ projectId: project.id, deletedAt: null });
|
||||
return accessApprovalPolicies;
|
||||
return accessApprovalPolicies.map((policy) => ({
|
||||
...policy,
|
||||
environment: policy.environments[0]
|
||||
}));
|
||||
};
|
||||
|
||||
const updateAccessApprovalPolicy: TAccessApprovalPolicyServiceFactory["updateAccessApprovalPolicy"] = async ({
|
||||
@@ -292,7 +314,8 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
approvals,
|
||||
enforcementLevel,
|
||||
allowedSelfApprovals,
|
||||
approvalsRequired
|
||||
approvalsRequired,
|
||||
environments
|
||||
}: TUpdateAccessApprovalPolicy) => {
|
||||
const groupApprovers = approvers.filter((approver) => approver.type === ApproverType.Group);
|
||||
|
||||
@@ -320,15 +343,23 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
|
||||
}
|
||||
|
||||
let envs = accessApprovalPolicy.environments;
|
||||
if (
|
||||
environments &&
|
||||
(environments.length !== envs.length || environments.some((env) => !envs.find((el) => el.slug === env)))
|
||||
) {
|
||||
envs = await projectEnvDAL.find({ $in: { slug: environments }, projectId: accessApprovalPolicy.projectId });
|
||||
}
|
||||
|
||||
if (
|
||||
await $policyExists({
|
||||
envId: accessApprovalPolicy.envId,
|
||||
envIds: envs.map((env) => env.id),
|
||||
secretPath: secretPath || accessApprovalPolicy.secretPath,
|
||||
policyId: accessApprovalPolicy.id
|
||||
})
|
||||
) {
|
||||
throw new BadRequestError({
|
||||
message: `A policy for secret path '${secretPath}' already exists in environment '${accessApprovalPolicy.environment.slug}'`
|
||||
message: `A policy for secret path '${secretPath}' already exists`
|
||||
});
|
||||
}
|
||||
|
||||
@@ -484,6 +515,14 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (environments) {
|
||||
await accessApprovalPolicyEnvironmentDAL.delete({ policyId: doc.id }, tx);
|
||||
await accessApprovalPolicyEnvironmentDAL.insertMany(
|
||||
envs.map((env) => ({ policyId: doc.id, envId: env.id })),
|
||||
tx
|
||||
);
|
||||
}
|
||||
|
||||
await accessApprovalPolicyBypasserDAL.delete({ policyId: doc.id }, tx);
|
||||
|
||||
if (bypasserUserIds.length) {
|
||||
@@ -513,7 +552,8 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
|
||||
return {
|
||||
...updatedPolicy,
|
||||
environment: accessApprovalPolicy.environment,
|
||||
environments: accessApprovalPolicy.environments,
|
||||
environment: accessApprovalPolicy.environments[0],
|
||||
projectId: accessApprovalPolicy.projectId
|
||||
};
|
||||
};
|
||||
@@ -563,7 +603,10 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
}
|
||||
});
|
||||
|
||||
return policy;
|
||||
return {
|
||||
...policy,
|
||||
environment: policy.environments[0]
|
||||
};
|
||||
};
|
||||
|
||||
const getAccessPolicyCountByEnvSlug: TAccessApprovalPolicyServiceFactory["getAccessPolicyCountByEnvSlug"] = async ({
|
||||
@@ -592,11 +635,13 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug });
|
||||
if (!environment) throw new NotFoundError({ message: `Environment with slug '${envSlug}' not found` });
|
||||
|
||||
const policies = await accessApprovalPolicyDAL.find({
|
||||
envId: environment.id,
|
||||
projectId: project.id,
|
||||
deletedAt: null
|
||||
});
|
||||
const policies = await accessApprovalPolicyDAL.find(
|
||||
{
|
||||
projectId: project.id,
|
||||
deletedAt: null
|
||||
},
|
||||
{ envId: environment.id }
|
||||
);
|
||||
if (!policies) throw new NotFoundError({ message: `No policies found in environment with slug '${envSlug}'` });
|
||||
|
||||
return { count: policies.length };
|
||||
@@ -627,7 +672,10 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
||||
|
||||
return policy;
|
||||
return {
|
||||
...policy,
|
||||
environment: policy.environments[0]
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -26,7 +26,8 @@ export enum BypasserType {
|
||||
export type TCreateAccessApprovalPolicy = {
|
||||
approvals: number;
|
||||
secretPath: string;
|
||||
environment: string;
|
||||
environment?: string;
|
||||
environments?: string[];
|
||||
approvers: (
|
||||
| { type: ApproverType.Group; id: string; sequence?: number }
|
||||
| { type: ApproverType.User; id?: string; username?: string; sequence?: number }
|
||||
@@ -58,6 +59,7 @@ export type TUpdateAccessApprovalPolicy = {
|
||||
enforcementLevel?: EnforcementLevel;
|
||||
allowedSelfApprovals: boolean;
|
||||
approvalsRequired?: { numberOfApprovals: number; stepNumber: number }[];
|
||||
environments?: string[];
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDeleteAccessApprovalPolicy = {
|
||||
@@ -113,6 +115,15 @@ export interface TAccessApprovalPolicyServiceFactory {
|
||||
slug: string;
|
||||
position: number;
|
||||
};
|
||||
environments: {
|
||||
name: string;
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
projectId: string;
|
||||
slug: string;
|
||||
position: number;
|
||||
}[];
|
||||
projectId: string;
|
||||
name: string;
|
||||
id: string;
|
||||
@@ -153,6 +164,11 @@ export interface TAccessApprovalPolicyServiceFactory {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}[];
|
||||
projectId: string;
|
||||
}>;
|
||||
updateAccessApprovalPolicy: ({
|
||||
@@ -168,13 +184,19 @@ export interface TAccessApprovalPolicyServiceFactory {
|
||||
approvals,
|
||||
enforcementLevel,
|
||||
allowedSelfApprovals,
|
||||
approvalsRequired
|
||||
approvalsRequired,
|
||||
environments
|
||||
}: TUpdateAccessApprovalPolicy) => Promise<{
|
||||
environment: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}[];
|
||||
projectId: string;
|
||||
name: string;
|
||||
id: string;
|
||||
@@ -225,6 +247,11 @@ export interface TAccessApprovalPolicyServiceFactory {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}[];
|
||||
projectId: string;
|
||||
bypassers: (
|
||||
| {
|
||||
@@ -276,6 +303,11 @@ export interface TAccessApprovalPolicyServiceFactory {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
environments: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
}[];
|
||||
projectId: string;
|
||||
bypassers: (
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user