feat: allow secret approvals with user groups

This commit is contained in:
Meet
2024-09-20 08:51:48 +05:30
parent 009be0ded8
commit 081502848d
16 changed files with 248 additions and 21 deletions
+5
View File
@@ -806,5 +806,10 @@ declare module "knex/types/tables" {
TAccessApprovalPoliciesGroupApproversInsert, TAccessApprovalPoliciesGroupApproversInsert,
TAccessApprovalPoliciesGroupApproversInsert TAccessApprovalPoliciesGroupApproversInsert
>; >;
[TableName.SecretApprovalPolicyGroupApprover]: KnexOriginal.CompositeTableType<
TSecretApprovalPoliciesGroupApprovers,
TSecretApprovalPoliciesGroupApproversInsert,
TSecretApprovalPoliciesGroupApproversInsert
>;
} }
} }
@@ -0,0 +1,22 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
import { createOnUpdateTrigger } from "../utils";
export async function up(knex: Knex): Promise<void> {
if (!(await knex.schema.hasTable(TableName.SecretApprovalPolicyGroupApprover))) {
await knex.schema.createTable(TableName.SecretApprovalPolicyGroupApprover, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.uuid("approverGroupId").notNullable();
t.foreign("approverGroupId").references("id").inTable(TableName.Groups).onDelete("CASCADE");
t.uuid("policyId").notNullable();
t.foreign("policyId").references("id").inTable(TableName.SecretApprovalPolicy).onDelete("CASCADE");
t.timestamps(true, true, true);
});
await createOnUpdateTrigger(knex, TableName.SecretApprovalPolicyGroupApprover);
}
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists(TableName.SecretApprovalPolicyGroupApprover);
}
+1
View File
@@ -72,6 +72,7 @@ export * from "./saml-configs";
export * from "./scim-tokens"; export * from "./scim-tokens";
export * from "./secret-approval-policies"; export * from "./secret-approval-policies";
export * from "./secret-approval-policies-approvers"; export * from "./secret-approval-policies-approvers";
export * from "./secret-approval-policies-group-approvers";
export * from "./secret-approval-request-secret-tags"; export * from "./secret-approval-request-secret-tags";
export * from "./secret-approval-request-secret-tags-v2"; export * from "./secret-approval-request-secret-tags-v2";
export * from "./secret-approval-requests"; export * from "./secret-approval-requests";
+1
View File
@@ -78,6 +78,7 @@ export enum TableName {
AccessApprovalRequestReviewer = "access_approval_requests_reviewers", AccessApprovalRequestReviewer = "access_approval_requests_reviewers",
SecretApprovalPolicy = "secret_approval_policies", SecretApprovalPolicy = "secret_approval_policies",
SecretApprovalPolicyApprover = "secret_approval_policies_approvers", SecretApprovalPolicyApprover = "secret_approval_policies_approvers",
SecretApprovalPolicyGroupApprover = "secret_approval_policies_group_approvers",
SecretApprovalRequest = "secret_approval_requests", SecretApprovalRequest = "secret_approval_requests",
SecretApprovalRequestReviewer = "secret_approval_requests_reviewers", SecretApprovalRequestReviewer = "secret_approval_requests_reviewers",
SecretApprovalRequestSecret = "secret_approval_requests_secrets", SecretApprovalRequestSecret = "secret_approval_requests_secrets",
@@ -0,0 +1,25 @@
// Code generated by automation script, DO NOT EDIT.
// Automated by pulling database and generating zod schema
// To update. Just run npm run generate:schema
// Written by akhilmhdh.
import { z } from "zod";
import { TImmutableDBKeys } from "./models";
export const SecretApprovalPoliciesGroupApproversSchema = z.object({
id: z.string().uuid(),
approverGroupId: z.string().uuid(),
policyId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date()
});
export type TSecretApprovalPoliciesGroupApprovers = z.infer<typeof SecretApprovalPoliciesGroupApproversSchema>;
export type TSecretApprovalPoliciesGroupApproversInsert = Omit<
z.input<typeof SecretApprovalPoliciesGroupApproversSchema>,
TImmutableDBKeys
>;
export type TSecretApprovalPoliciesGroupApproversUpdate = Partial<
Omit<z.input<typeof SecretApprovalPoliciesGroupApproversSchema>, TImmutableDBKeys>
>;
@@ -27,13 +27,14 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
.nullable() .nullable()
.default("/") .default("/")
.transform((val) => (val ? removeTrailingSlash(val) : val)), .transform((val) => (val ? removeTrailingSlash(val) : val)),
approvers: z.string().array().min(1), approvers: z.string().array().optional().default([]),
groupApprovers: z.string().array().optional().default([]),
approvals: z.number().min(1).default(1), approvals: z.number().min(1).default(1),
enforcementLevel: z.nativeEnum(EnforcementLevel).default(EnforcementLevel.Hard) enforcementLevel: z.nativeEnum(EnforcementLevel).default(EnforcementLevel.Hard)
}) })
.refine((data) => data.approvals <= data.approvers.length, { .refine((data) => data.approvers || data.groupApprovers, {
path: ["approvals"], path: ["approvers", "groupApprovers"],
message: "The number of approvals should be lower than the number of approvers." message: "At least one approver should be provided."
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -70,8 +71,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
body: z body: z
.object({ .object({
name: z.string().optional(), name: z.string().optional(),
approvers: z.string().array().min(1), approvers: z.string().array().optional().default([]),
approvals: z.number().min(1).default(1), approvals: z.number().min(1).default(1),
groupApprovers: z.string().array().optional().default([]),
secretPath: z secretPath: z
.string() .string()
.optional() .optional()
@@ -80,9 +82,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
.transform((val) => (val === "" ? "/" : val)), .transform((val) => (val === "" ? "/" : val)),
enforcementLevel: z.nativeEnum(EnforcementLevel).optional() enforcementLevel: z.nativeEnum(EnforcementLevel).optional()
}) })
.refine((data) => data.approvals <= data.approvers.length, { .refine((data) => data.approvers.length > 0 || data.groupApprovers.length > 0, {
path: ["approvals"], path: ["approvers", "groupApprovers"],
message: "The number of approvals should be lower than the number of approvers." message: "At least one approver should be provided."
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -151,6 +153,11 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
.object({ .object({
userId: z.string() userId: z.string()
}) })
.array(),
groupApprovers: z
.object({
groupId: z.string()
})
.array() .array()
}) })
.array() .array()
@@ -46,7 +46,11 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
id: z.string(), id: z.string(),
name: z.string(), name: z.string(),
approvals: z.number(), approvals: z.number(),
approvers: z.string().array(), approvers: z
.object({
userId: z.string()
})
.array(),
secretPath: z.string().optional().nullable(), secretPath: z.string().optional().nullable(),
enforcementLevel: z.string() enforcementLevel: z.string()
}), }),
@@ -54,7 +58,11 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
commits: z.object({ op: z.string(), secretId: z.string().nullable().optional() }).array(), commits: z.object({ op: z.string(), secretId: z.string().nullable().optional() }).array(),
environment: z.string(), environment: z.string(),
reviewers: z.object({ userId: z.string(), status: z.string() }).array(), reviewers: z.object({ userId: z.string(), status: z.string() }).array(),
approvers: z.string().array() approvers: z
.object({
userId: z.string()
})
.array()
}).array() }).array()
}) })
} }
@@ -22,13 +22,29 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
) )
.leftJoin(TableName.Users, `${TableName.SecretApprovalPolicyApprover}.approverUserId`, `${TableName.Users}.id`) .leftJoin(TableName.Users, `${TableName.SecretApprovalPolicyApprover}.approverUserId`, `${TableName.Users}.id`)
.leftJoin(
TableName.SecretApprovalPolicyGroupApprover,
`${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyGroupApprover}.policyId`
)
.leftJoin(
TableName.UserGroupMembership,
`${TableName.SecretApprovalPolicyGroupApprover}.approverGroupId`,
`${TableName.UserGroupMembership}.userId`
)
.select( .select(
tx.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover), tx.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover),
tx.ref("email").withSchema(TableName.Users).as("approverEmail"), tx.ref("email").withSchema(TableName.Users).as("approverEmail"),
tx.ref("firstName").withSchema(TableName.Users).as("approverFirstName"), tx.ref("firstName").withSchema(TableName.Users).as("approverFirstName"),
tx.ref("lastName").withSchema(TableName.Users).as("approverLastName") tx.ref("lastName").withSchema(TableName.Users).as("approverLastName")
) )
.select(
tx.ref("approverGroupId").withSchema(TableName.SecretApprovalPolicyGroupApprover),
tx.ref("userId").withSchema(TableName.UserGroupMembership).as("approverGroupUserId"),
tx.ref("email").withSchema(TableName.Users).as("approverGroupEmail"),
tx.ref("firstName").withSchema(TableName.Users).as("approverGroupFirstName"),
tx.ref("lastName").withSchema(TableName.Users).as("approverGroupLastName")
)
.select( .select(
tx.ref("name").withSchema(TableName.Environment).as("envName"), tx.ref("name").withSchema(TableName.Environment).as("envName"),
tx.ref("slug").withSchema(TableName.Environment).as("envSlug"), tx.ref("slug").withSchema(TableName.Environment).as("envSlug"),
@@ -61,6 +77,16 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
firstName: approverFirstName, firstName: approverFirstName,
lastName: approverLastName lastName: approverLastName
}) })
},
{
key: "approverGroupUserId",
label: "userApprovers" as const,
mapper: ({ approverGroupUserId, approverGroupEmail, approverGroupFirstName, approverGroupLastName }) => ({
userId: approverGroupUserId,
email: approverGroupEmail,
firstName: approverGroupFirstName,
lastName: approverGroupLastName
})
} }
] ]
}); });
@@ -89,6 +115,13 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
mapper: ({ approverUserId }) => ({ mapper: ({ approverUserId }) => ({
userId: approverUserId userId: approverUserId
}) })
},
{
key: "approverGroupId",
label: "groupApprovers" as const,
mapper: ({ approverGroupId }) => ({
groupId: approverGroupId
})
} }
] ]
}); });
@@ -0,0 +1,12 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TSecretApprovalPolicyGroupApproverDALFactory = ReturnType<
typeof secretApprovalPolicyGroupApproverDALFactory
>;
export const secretApprovalPolicyGroupApproverDALFactory = (db: TDbClient) => {
const sapGroupApproverOrm = ormify(db, TableName.SecretApprovalPolicyGroupApprover);
return sapGroupApproverOrm;
};
@@ -11,6 +11,7 @@ import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal
import { TLicenseServiceFactory } from "../license/license-service"; import { TLicenseServiceFactory } from "../license/license-service";
import { TSecretApprovalPolicyApproverDALFactory } from "./secret-approval-policy-approver-dal"; import { TSecretApprovalPolicyApproverDALFactory } from "./secret-approval-policy-approver-dal";
import { TSecretApprovalPolicyDALFactory } from "./secret-approval-policy-dal"; import { TSecretApprovalPolicyDALFactory } from "./secret-approval-policy-dal";
import { TSecretApprovalPolicyGroupApproverDALFactory } from "./secret-approval-policy-group-approver-dal";
import { import {
TCreateSapDTO, TCreateSapDTO,
TDeleteSapDTO, TDeleteSapDTO,
@@ -29,6 +30,7 @@ type TSecretApprovalPolicyServiceFactoryDep = {
secretApprovalPolicyDAL: TSecretApprovalPolicyDALFactory; secretApprovalPolicyDAL: TSecretApprovalPolicyDALFactory;
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">; projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">;
secretApprovalPolicyApproverDAL: TSecretApprovalPolicyApproverDALFactory; secretApprovalPolicyApproverDAL: TSecretApprovalPolicyApproverDALFactory;
secretApprovalPolicyGroupApproverDAL: TSecretApprovalPolicyGroupApproverDALFactory;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan">;
}; };
@@ -38,6 +40,7 @@ export const secretApprovalPolicyServiceFactory = ({
secretApprovalPolicyDAL, secretApprovalPolicyDAL,
permissionService, permissionService,
secretApprovalPolicyApproverDAL, secretApprovalPolicyApproverDAL,
secretApprovalPolicyGroupApproverDAL,
projectEnvDAL, projectEnvDAL,
licenseService licenseService
}: TSecretApprovalPolicyServiceFactoryDep) => { }: TSecretApprovalPolicyServiceFactoryDep) => {
@@ -49,12 +52,16 @@ export const secretApprovalPolicyServiceFactory = ({
actorAuthMethod, actorAuthMethod,
approvals, approvals,
approvers, approvers,
groupApprovers,
projectId, projectId,
secretPath, secretPath,
environment, environment,
enforcementLevel enforcementLevel
}: TCreateSapDTO) => { }: TCreateSapDTO) => {
if (approvals > approvers.length) if (!groupApprovers && !approvers)
throw new BadRequestError({ message: "Either of approvers or group approvers must be provided" });
if (!groupApprovers && approvals > approvers.length)
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" }); throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getProjectPermission(
@@ -91,6 +98,7 @@ export const secretApprovalPolicyServiceFactory = ({
}, },
tx tx
); );
await secretApprovalPolicyApproverDAL.insertMany( await secretApprovalPolicyApproverDAL.insertMany(
approvers.map((approverUserId) => ({ approvers.map((approverUserId) => ({
approverUserId, approverUserId,
@@ -98,6 +106,14 @@ export const secretApprovalPolicyServiceFactory = ({
})), })),
tx tx
); );
await secretApprovalPolicyGroupApproverDAL.insertMany(
groupApprovers.map((approverGroupId) => ({
approverGroupId,
policyId: doc.id
})),
tx
);
return doc; return doc;
}); });
return { ...secretApproval, environment: env, projectId }; return { ...secretApproval, environment: env, projectId };
@@ -105,6 +121,7 @@ export const secretApprovalPolicyServiceFactory = ({
const updateSecretApprovalPolicy = async ({ const updateSecretApprovalPolicy = async ({
approvers, approvers,
groupApprovers,
secretPath, secretPath,
name, name,
actorId, actorId,
@@ -156,6 +173,16 @@ export const secretApprovalPolicyServiceFactory = ({
tx tx
); );
} }
if (groupApprovers) {
await secretApprovalPolicyGroupApproverDAL.delete({ policyId: doc.id }, tx);
await secretApprovalPolicyGroupApproverDAL.insertMany(
groupApprovers.map((approverGroupId) => ({
approverGroupId,
policyId: doc.id
})),
tx
);
}
return doc; return doc;
}); });
return { return {
@@ -5,6 +5,7 @@ export type TCreateSapDTO = {
secretPath?: string | null; secretPath?: string | null;
environment: string; environment: string;
approvers: string[]; approvers: string[];
groupApprovers: string[];
projectId: string; projectId: string;
name: string; name: string;
enforcementLevel: EnforcementLevel; enforcementLevel: EnforcementLevel;
@@ -14,7 +15,8 @@ export type TUpdateSapDTO = {
secretPolicyId: string; secretPolicyId: string;
approvals?: number; approvals?: number;
secretPath?: string | null; secretPath?: string | null;
approvers: string[]; approvers?: string[];
groupApprovers?: string[];
name?: string; name?: string;
enforcementLevel?: EnforcementLevel; enforcementLevel?: EnforcementLevel;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
@@ -48,16 +48,31 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalRequest}.committerUserId`, `${TableName.SecretApprovalRequest}.committerUserId`,
`committerUser.id` `committerUser.id`
) )
.join( .leftJoin(
TableName.SecretApprovalPolicyApprover, TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalPolicy}.id`, `${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyApprover}.policyId` `${TableName.SecretApprovalPolicyApprover}.policyId`
) )
.join<TUsers>( .leftJoin<TUsers>(
db(TableName.Users).as("secretApprovalPolicyApproverUser"), db(TableName.Users).as("secretApprovalPolicyApproverUser"),
`${TableName.SecretApprovalPolicyApprover}.approverUserId`, `${TableName.SecretApprovalPolicyApprover}.approverUserId`,
"secretApprovalPolicyApproverUser.id" "secretApprovalPolicyApproverUser.id"
) )
.leftJoin(
TableName.SecretApprovalPolicyGroupApprover,
`${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyGroupApprover}.policyId`
)
.leftJoin(
TableName.UserGroupMembership,
`${TableName.SecretApprovalPolicyGroupApprover}.approverGroupId`,
`${TableName.UserGroupMembership}.groupId`
)
.leftJoin<TUsers>(
db(TableName.Users).as("secretApprovalPolicyGroupApproverUser"),
`${TableName.UserGroupMembership}.userId`,
`secretApprovalPolicyGroupApproverUser.id`
)
.leftJoin( .leftJoin(
TableName.SecretApprovalRequestReviewer, TableName.SecretApprovalRequestReviewer,
`${TableName.SecretApprovalRequest}.id`, `${TableName.SecretApprovalRequest}.id`,
@@ -71,10 +86,15 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
.select(selectAllTableCols(TableName.SecretApprovalRequest)) .select(selectAllTableCols(TableName.SecretApprovalRequest))
.select( .select(
tx.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover), tx.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover),
tx.ref("userId").withSchema(TableName.UserGroupMembership).as("approverGroupUserId"),
tx.ref("email").withSchema("secretApprovalPolicyApproverUser").as("approverEmail"), tx.ref("email").withSchema("secretApprovalPolicyApproverUser").as("approverEmail"),
tx.ref("email").withSchema("secretApprovalPolicyGroupApproverUser").as("approverGroupEmail"),
tx.ref("username").withSchema("secretApprovalPolicyApproverUser").as("approverUsername"), tx.ref("username").withSchema("secretApprovalPolicyApproverUser").as("approverUsername"),
tx.ref("username").withSchema("secretApprovalPolicyGroupApproverUser").as("approverGroupUsername"),
tx.ref("firstName").withSchema("secretApprovalPolicyApproverUser").as("approverFirstName"), tx.ref("firstName").withSchema("secretApprovalPolicyApproverUser").as("approverFirstName"),
tx.ref("firstName").withSchema("secretApprovalPolicyGroupApproverUser").as("approverGroupFirstName"),
tx.ref("lastName").withSchema("secretApprovalPolicyApproverUser").as("approverLastName"), tx.ref("lastName").withSchema("secretApprovalPolicyApproverUser").as("approverLastName"),
tx.ref("lastName").withSchema("secretApprovalPolicyGroupApproverUser").as("approverGroupLastName"),
tx.ref("email").withSchema("statusChangedByUser").as("statusChangedByUserEmail"), tx.ref("email").withSchema("statusChangedByUser").as("statusChangedByUserEmail"),
tx.ref("username").withSchema("statusChangedByUser").as("statusChangedByUserUsername"), tx.ref("username").withSchema("statusChangedByUser").as("statusChangedByUserUsername"),
tx.ref("firstName").withSchema("statusChangedByUser").as("statusChangedByUserFirstName"), tx.ref("firstName").withSchema("statusChangedByUser").as("statusChangedByUserFirstName"),
@@ -164,6 +184,23 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
lastName, lastName,
username username
}) })
},
{
key: "approverGroupUserId",
label: "approvers" as const,
mapper: ({
approverGroupUserId,
approverGroupEmail: email,
approverGroupUsername: username,
approverGroupLastName: lastName,
approverGroupFirstName: firstName
}) => ({
userId: approverGroupUserId,
email,
firstName,
lastName,
username
})
} }
] ]
}); });
@@ -236,11 +273,21 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalRequest}.policyId`, `${TableName.SecretApprovalRequest}.policyId`,
`${TableName.SecretApprovalPolicy}.id` `${TableName.SecretApprovalPolicy}.id`
) )
.join( .leftJoin(
TableName.SecretApprovalPolicyApprover, TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalPolicy}.id`, `${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyApprover}.policyId` `${TableName.SecretApprovalPolicyApprover}.policyId`
) )
.leftJoin(
TableName.SecretApprovalPolicyGroupApprover,
`${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyGroupApprover}.policyId`
)
.leftJoin(
TableName.UserGroupMembership,
`${TableName.SecretApprovalPolicyGroupApprover}.approverGroupId`,
`${TableName.UserGroupMembership}.groupId`
)
.join<TUsers>( .join<TUsers>(
db(TableName.Users).as("committerUser"), db(TableName.Users).as("committerUser"),
`${TableName.SecretApprovalRequest}.committerUserId`, `${TableName.SecretApprovalRequest}.committerUserId`,
@@ -269,6 +316,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
void bd void bd
.where(`${TableName.SecretApprovalPolicyApprover}.approverUserId`, userId) .where(`${TableName.SecretApprovalPolicyApprover}.approverUserId`, userId)
.orWhere(`${TableName.SecretApprovalRequest}.committerUserId`, userId) .orWhere(`${TableName.SecretApprovalRequest}.committerUserId`, userId)
.orWhere(`${TableName.UserGroupMembership}.userId`, userId)
) )
.select(selectAllTableCols(TableName.SecretApprovalRequest)) .select(selectAllTableCols(TableName.SecretApprovalRequest))
.select( .select(
@@ -289,6 +337,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
db.ref("enforcementLevel").withSchema(TableName.SecretApprovalPolicy).as("policyEnforcementLevel"), db.ref("enforcementLevel").withSchema(TableName.SecretApprovalPolicy).as("policyEnforcementLevel"),
db.ref("approvals").withSchema(TableName.SecretApprovalPolicy).as("policyApprovals"), db.ref("approvals").withSchema(TableName.SecretApprovalPolicy).as("policyApprovals"),
db.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover), db.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover),
db.ref("userId").withSchema(TableName.UserGroupMembership).as("approverGroupUserId"),
db.ref("email").withSchema("committerUser").as("committerUserEmail"), db.ref("email").withSchema("committerUser").as("committerUserEmail"),
db.ref("username").withSchema("committerUser").as("committerUserUsername"), db.ref("username").withSchema("committerUser").as("committerUserUsername"),
db.ref("firstName").withSchema("committerUser").as("committerUserFirstName"), db.ref("firstName").withSchema("committerUser").as("committerUserFirstName"),
@@ -334,7 +383,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
{ {
key: "approverUserId", key: "approverUserId",
label: "approvers" as const, label: "approvers" as const,
mapper: ({ approverUserId }) => approverUserId mapper: ({ approverUserI: userId }) => ({ userId })
}, },
{ {
key: "commitId", key: "commitId",
@@ -344,6 +393,11 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
id, id,
secretId secretId
}) })
},
{
key: "approverGroupUserId",
label: "approvers" as const,
mapper: ({ approverGroupUserId: userId }) => ({ userId })
} }
] ]
}); });
@@ -371,11 +425,21 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalRequest}.policyId`, `${TableName.SecretApprovalRequest}.policyId`,
`${TableName.SecretApprovalPolicy}.id` `${TableName.SecretApprovalPolicy}.id`
) )
.join( .leftJoin(
TableName.SecretApprovalPolicyApprover, TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalPolicy}.id`, `${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyApprover}.policyId` `${TableName.SecretApprovalPolicyApprover}.policyId`
) )
.leftJoin(
TableName.SecretApprovalPolicyGroupApprover,
`${TableName.SecretApprovalPolicy}.id`,
`${TableName.SecretApprovalPolicyGroupApprover}.policyId`
)
.leftJoin(
TableName.UserGroupMembership,
`${TableName.SecretApprovalPolicyGroupApprover}.approverGroupId`,
`${TableName.UserGroupMembership}.groupId`
)
.join<TUsers>( .join<TUsers>(
db(TableName.Users).as("committerUser"), db(TableName.Users).as("committerUser"),
`${TableName.SecretApprovalRequest}.committerUserId`, `${TableName.SecretApprovalRequest}.committerUserId`,
@@ -404,6 +468,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
void bd void bd
.where(`${TableName.SecretApprovalPolicyApprover}.approverUserId`, userId) .where(`${TableName.SecretApprovalPolicyApprover}.approverUserId`, userId)
.orWhere(`${TableName.SecretApprovalRequest}.committerUserId`, userId) .orWhere(`${TableName.SecretApprovalRequest}.committerUserId`, userId)
.orWhere(`${TableName.UserGroupMembership}.userId`, userId)
) )
.select(selectAllTableCols(TableName.SecretApprovalRequest)) .select(selectAllTableCols(TableName.SecretApprovalRequest))
.select( .select(
@@ -424,6 +489,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
db.ref("approvals").withSchema(TableName.SecretApprovalPolicy).as("policyApprovals"), db.ref("approvals").withSchema(TableName.SecretApprovalPolicy).as("policyApprovals"),
db.ref("enforcementLevel").withSchema(TableName.SecretApprovalPolicy).as("policyEnforcementLevel"), db.ref("enforcementLevel").withSchema(TableName.SecretApprovalPolicy).as("policyEnforcementLevel"),
db.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover), db.ref("approverUserId").withSchema(TableName.SecretApprovalPolicyApprover),
db.ref("userId").withSchema(TableName.UserGroupMembership).as("approverGroupUserId"),
db.ref("email").withSchema("committerUser").as("committerUserEmail"), db.ref("email").withSchema("committerUser").as("committerUserEmail"),
db.ref("username").withSchema("committerUser").as("committerUserUsername"), db.ref("username").withSchema("committerUser").as("committerUserUsername"),
db.ref("firstName").withSchema("committerUser").as("committerUserFirstName"), db.ref("firstName").withSchema("committerUser").as("committerUserFirstName"),
@@ -469,7 +535,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
{ {
key: "approverUserId", key: "approverUserId",
label: "approvers" as const, label: "approvers" as const,
mapper: ({ approverUserId }) => approverUserId mapper: ({ approverUserId: userId }) => ({ userId })
}, },
{ {
key: "commitId", key: "commitId",
@@ -479,6 +545,13 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
id, id,
secretId secretId
}) })
},
{
key: "approverGroupUserId",
label: "approvers" as const,
mapper: ({ approverGroupUserId: userId }) => ({
userId
})
} }
] ]
}); });
+3
View File
@@ -52,6 +52,7 @@ import { scimDALFactory } from "@app/ee/services/scim/scim-dal";
import { scimServiceFactory } from "@app/ee/services/scim/scim-service"; import { scimServiceFactory } from "@app/ee/services/scim/scim-service";
import { secretApprovalPolicyApproverDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-approver-dal"; import { secretApprovalPolicyApproverDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-approver-dal";
import { secretApprovalPolicyDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-dal"; import { secretApprovalPolicyDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-dal";
import { secretApprovalPolicyGroupApproverDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-group-approver-dal";
import { secretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service"; import { secretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
import { secretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal"; import { secretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal";
import { secretApprovalRequestReviewerDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-reviewer-dal"; import { secretApprovalRequestReviewerDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-reviewer-dal";
@@ -300,6 +301,7 @@ export const registerRoutes = async (
const accessApprovalRequestReviewerDAL = accessApprovalRequestReviewerDALFactory(db); const accessApprovalRequestReviewerDAL = accessApprovalRequestReviewerDALFactory(db);
const sapApproverDAL = secretApprovalPolicyApproverDALFactory(db); const sapApproverDAL = secretApprovalPolicyApproverDALFactory(db);
const sapGroupApproverDAL = secretApprovalPolicyGroupApproverDALFactory(db);
const secretApprovalPolicyDAL = secretApprovalPolicyDALFactory(db); const secretApprovalPolicyDAL = secretApprovalPolicyDALFactory(db);
const secretApprovalRequestDAL = secretApprovalRequestDALFactory(db); const secretApprovalRequestDAL = secretApprovalRequestDALFactory(db);
const secretApprovalRequestReviewerDAL = secretApprovalRequestReviewerDALFactory(db); const secretApprovalRequestReviewerDAL = secretApprovalRequestReviewerDALFactory(db);
@@ -379,6 +381,7 @@ export const registerRoutes = async (
const secretApprovalPolicyService = secretApprovalPolicyServiceFactory({ const secretApprovalPolicyService = secretApprovalPolicyServiceFactory({
projectEnvDAL, projectEnvDAL,
secretApprovalPolicyApproverDAL: sapApproverDAL, secretApprovalPolicyApproverDAL: sapApproverDAL,
secretApprovalPolicyGroupApproverDAL: sapGroupApproverDAL,
permissionService, permissionService,
secretApprovalPolicyDAL, secretApprovalPolicyDAL,
licenseService licenseService
@@ -14,6 +14,7 @@ export const useCreateSecretApprovalPolicy = () => {
workspaceId, workspaceId,
approvals, approvals,
approvers, approvers,
groupApprovers,
secretPath, secretPath,
name, name,
enforcementLevel enforcementLevel
@@ -23,6 +24,7 @@ export const useCreateSecretApprovalPolicy = () => {
workspaceId, workspaceId,
approvals, approvals,
approvers, approvers,
groupApprovers,
secretPath, secretPath,
name, name,
enforcementLevel enforcementLevel
@@ -39,10 +41,11 @@ export const useUpdateSecretApprovalPolicy = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation<{}, {}, TUpdateSecretPolicyDTO>({ return useMutation<{}, {}, TUpdateSecretPolicyDTO>({
mutationFn: async ({ id, approvers, approvals, secretPath, name, enforcementLevel }) => { mutationFn: async ({ id, approvers, groupApprovers, approvals, secretPath, name, enforcementLevel }) => {
const { data } = await apiRequest.patch(`/api/v1/secret-approvals/${id}`, { const { data } = await apiRequest.patch(`/api/v1/secret-approvals/${id}`, {
approvals, approvals,
approvers, approvers,
groupApprovers,
secretPath, secretPath,
name, name,
enforcementLevel enforcementLevel
@@ -10,6 +10,7 @@ export type TSecretApprovalPolicy = {
secretPath?: string; secretPath?: string;
approvals: number; approvals: number;
userApprovers: { userId: string }[]; userApprovers: { userId: string }[];
groupApprovers: { groupId: string }[];
updatedAt: Date; updatedAt: Date;
enforcementLevel: EnforcementLevel; enforcementLevel: EnforcementLevel;
}; };
@@ -30,6 +31,7 @@ export type TCreateSecretPolicyDTO = {
environment: string; environment: string;
secretPath?: string | null; secretPath?: string | null;
approvers?: string[]; approvers?: string[];
groupApprovers?: string[];
approvals?: number; approvals?: number;
enforcementLevel: EnforcementLevel; enforcementLevel: EnforcementLevel;
}; };
@@ -38,6 +40,7 @@ export type TUpdateSecretPolicyDTO = {
id: string; id: string;
name?: string; name?: string;
approvers?: string[]; approvers?: string[];
groupApprovers?: string[];
secretPath?: string | null; secretPath?: string | null;
approvals?: number; approvals?: number;
enforcementLevel?: EnforcementLevel; enforcementLevel?: EnforcementLevel;
@@ -89,7 +89,8 @@ export const ApprovalPolicyRow = ({
{ {
workspaceId, workspaceId,
id: policy.id, id: policy.id,
approvers: selectedApprovers approvers: selectedApprovers,
groupApprovers: selectedGroupApprovers
}, },
{ onSettled: () => { } } { onSettled: () => { } }
); );
@@ -164,6 +165,7 @@ export const ApprovalPolicyRow = ({
workspaceId, workspaceId,
id: policy.id, id: policy.id,
approvers: selectedApprovers, approvers: selectedApprovers,
groupApprovers: selectedGroupApprovers
}, },
{ onSettled: () => { } } { onSettled: () => { } }
); );