From b0c398688bc8bf584d3af8fdbdd338edaaf9b315 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Thu, 28 Sep 2023 12:21:37 +0530 Subject: [PATCH] feat(secret-approval): updated names to secret policy and fixed approval number bug --- backend/src/controllers/v1/index.ts | 4 ++-- ...r.ts => secretApprovalPolicyController.ts} | 24 +++++++++---------- backend/src/index.ts | 4 ++-- ...retApproval.ts => secretApprovalPolicy.ts} | 9 ++++--- backend/src/models/secretApprovalRequest.ts | 7 ++++-- backend/src/routes/v1/index.ts | 4 ++-- ...retApproval.ts => secretApprovalPolicy.ts} | 10 ++++---- backend/src/validation/secretApproval.ts | 4 ++-- .../src/hooks/api/secretApproval/types.ts | 4 ++-- .../SecretApprovalPolicyList.tsx | 9 ++++++- .../components/SecretPolicyForm.tsx | 12 ++++++---- 11 files changed, 54 insertions(+), 37 deletions(-) rename backend/src/controllers/v1/{secretApprovalController.ts => secretApprovalPolicyController.ts} (73%) rename backend/src/models/{secretApproval.ts => secretApprovalPolicy.ts} (74%) rename backend/src/routes/v1/{secretApproval.ts => secretApprovalPolicy.ts} (62%) diff --git a/backend/src/controllers/v1/index.ts b/backend/src/controllers/v1/index.ts index 9dcbb12c2..c2bb1b94d 100644 --- a/backend/src/controllers/v1/index.ts +++ b/backend/src/controllers/v1/index.ts @@ -16,7 +16,7 @@ import * as workspaceController from "./workspaceController"; import * as secretScanningController from "./secretScanningController"; import * as webhookController from "./webhookController"; import * as secretImpsController from "./secretImpsController"; -import * as secretApprovalController from "./secretApprovalController"; +import * as secretApprovalPolicyController from "./secretApprovalPolicyController"; export { authController, @@ -37,5 +37,5 @@ export { secretScanningController, webhookController, secretImpsController, - secretApprovalController + secretApprovalPolicyController }; diff --git a/backend/src/controllers/v1/secretApprovalController.ts b/backend/src/controllers/v1/secretApprovalPolicyController.ts similarity index 73% rename from backend/src/controllers/v1/secretApprovalController.ts rename to backend/src/controllers/v1/secretApprovalPolicyController.ts index 8441a93b0..245932353 100644 --- a/backend/src/controllers/v1/secretApprovalController.ts +++ b/backend/src/controllers/v1/secretApprovalPolicyController.ts @@ -6,13 +6,13 @@ import { getUserProjectPermissions } from "../../ee/services/ProjectRoleService"; import { validateRequest } from "../../helpers/validation"; -import { SecretApproval } from "../../models/secretApproval"; +import { SecretApprovalPolicy } from "../../models/secretApprovalPolicy"; import { BadRequestError } from "../../utils/errors"; import * as reqValidator from "../../validation/secretApproval"; const ERR_SECRET_APPROVAL_NOT_FOUND = BadRequestError({ message: "secret approval not found" }); -export const createSecretApprovalRule = async (req: Request, res: Response) => { +export const createSecretApprovalPolicy = async (req: Request, res: Response) => { const { body: { approvals, secretPath, approvers, environment, workspaceId } } = await validateRequest(reqValidator.CreateSecretApprovalRule, req); @@ -23,7 +23,7 @@ export const createSecretApprovalRule = async (req: Request, res: Response) => { ProjectPermissionSub.SecretApproval ); - const secretApproval = new SecretApproval({ + const secretApproval = new SecretApprovalPolicy({ workspace: workspaceId, secretPath, environment, @@ -37,13 +37,13 @@ export const createSecretApprovalRule = async (req: Request, res: Response) => { }); }; -export const updateSecretApprovalRule = async (req: Request, res: Response) => { +export const updateSecretApprovalPolicy = async (req: Request, res: Response) => { const { body: { approvals, approvers, secretPath }, params: { id } } = await validateRequest(reqValidator.UpdateSecretApprovalRule, req); - const secretApproval = await SecretApproval.findById(id); + const secretApproval = await SecretApprovalPolicy.findById(id); if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND; const { permission } = await getUserProjectPermissions( @@ -55,10 +55,10 @@ export const updateSecretApprovalRule = async (req: Request, res: Response) => { ProjectPermissionSub.SecretApproval ); - const updatedDoc = await SecretApproval.findByIdAndUpdate(id, { + const updatedDoc = await SecretApprovalPolicy.findByIdAndUpdate(id, { approvals, approvers, - $set: secretPath === "-" ? undefined : { secretPath } + ...(secretPath === null ? { $unset: { secretPath: 1 } } : { secretPath }) }); return res.send({ @@ -66,12 +66,12 @@ export const updateSecretApprovalRule = async (req: Request, res: Response) => { }); }; -export const deleteSecretApprovalRule = async (req: Request, res: Response) => { +export const deleteSecretApprovalPolicy = async (req: Request, res: Response) => { const { params: { id } } = await validateRequest(reqValidator.DeleteSecretApprovalRule, req); - const secretApproval = await SecretApproval.findById(id); + const secretApproval = await SecretApprovalPolicy.findById(id); if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND; const { permission } = await getUserProjectPermissions( @@ -83,14 +83,14 @@ export const deleteSecretApprovalRule = async (req: Request, res: Response) => { ProjectPermissionSub.SecretApproval ); - const deletedDoc = await SecretApproval.findByIdAndDelete(id); + const deletedDoc = await SecretApprovalPolicy.findByIdAndDelete(id); return res.send({ approval: deletedDoc }); }; -export const getSecretApprovalRules = async (req: Request, res: Response) => { +export const getSecretApprovalPolicy = async (req: Request, res: Response) => { const { query: { workspaceId } } = await validateRequest(reqValidator.GetSecretApprovalRuleList, req); @@ -101,7 +101,7 @@ export const getSecretApprovalRules = async (req: Request, res: Response) => { ProjectPermissionSub.SecretApproval ); - const doc = await SecretApproval.find({ workspace: workspaceId }); + const doc = await SecretApprovalPolicy.find({ workspace: workspaceId }); return res.send({ approvals: doc diff --git a/backend/src/index.ts b/backend/src/index.ts index c3aed4b7b..2a5159738 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -38,7 +38,7 @@ import { membership as v1MembershipRouter, organization as v1OrganizationRouter, password as v1PasswordRouter, - secretApproval as v1SecretApproval, + secretApprovalPolicy as v1SecretApprovalPolicy, secretImps as v1SecretImpsRouter, secret as v1SecretRouter, secretsFolder as v1SecretsFolder, @@ -177,7 +177,7 @@ const main = async () => { app.use("/api/v1/webhooks", v1WebhooksRouter); app.use("/api/v1/secret-imports", v1SecretImpsRouter); app.use("/api/v1/roles", v1RoleRouter); - app.use("/api/v1/secret-approvals", v1SecretApproval); + app.use("/api/v1/secret-approvals", v1SecretApprovalPolicy); // v2 routes (improvements) app.use("/api/v2/signup", v2SignupRouter); diff --git a/backend/src/models/secretApproval.ts b/backend/src/models/secretApprovalPolicy.ts similarity index 74% rename from backend/src/models/secretApproval.ts rename to backend/src/models/secretApprovalPolicy.ts index f4e2fc92e..9471f82db 100644 --- a/backend/src/models/secretApproval.ts +++ b/backend/src/models/secretApprovalPolicy.ts @@ -1,6 +1,6 @@ import { Schema, Types, model } from "mongoose"; -export interface ISecretApproval { +export interface ISecretApprovalPolicy { _id: Types.ObjectId; workspace: Types.ObjectId; environment: string; @@ -9,7 +9,7 @@ export interface ISecretApproval { approvals: number; } -const secretApprovalSchema = new Schema( +const secretApprovalPolicySchema = new Schema( { workspace: { type: Schema.Types.ObjectId, @@ -41,4 +41,7 @@ const secretApprovalSchema = new Schema( } ); -export const SecretApproval = model("SecretApproval", secretApprovalSchema); +export const SecretApprovalPolicy = model( + "SecretApprovalPolicy", + secretApprovalPolicySchema +); diff --git a/backend/src/models/secretApprovalRequest.ts b/backend/src/models/secretApprovalRequest.ts index 4133f06a7..a145b5773 100644 --- a/backend/src/models/secretApprovalRequest.ts +++ b/backend/src/models/secretApprovalRequest.ts @@ -30,7 +30,7 @@ export interface ISecretApprovalRequest { }[]; } -const secretApprovalSchema = new Schema( +const secretApprovalRequestSchema = new Schema( { approvers: [ { @@ -62,4 +62,7 @@ const secretApprovalSchema = new Schema( } ); -export const SecretApproval = model("SecretApproval", secretApprovalSchema); +export const SecretApprovalRequest = model( + "SecretApprovalRequest", + secretApprovalRequestSchema +); diff --git a/backend/src/routes/v1/index.ts b/backend/src/routes/v1/index.ts index 7c0f94972..cfdccdc92 100644 --- a/backend/src/routes/v1/index.ts +++ b/backend/src/routes/v1/index.ts @@ -17,7 +17,7 @@ import integrationAuth from "./integrationAuth"; import secretsFolder from "./secretsFolder"; import webhooks from "./webhook"; import secretImps from "./secretImps"; -import secretApproval from "./secretApproval"; +import secretApprovalPolicy from "./secretApprovalPolicy"; export { signup, @@ -39,5 +39,5 @@ export { secretsFolder, webhooks, secretImps, - secretApproval + secretApprovalPolicy }; diff --git a/backend/src/routes/v1/secretApproval.ts b/backend/src/routes/v1/secretApprovalPolicy.ts similarity index 62% rename from backend/src/routes/v1/secretApproval.ts rename to backend/src/routes/v1/secretApprovalPolicy.ts index 213bb3cc3..51c2aa3e7 100644 --- a/backend/src/routes/v1/secretApproval.ts +++ b/backend/src/routes/v1/secretApprovalPolicy.ts @@ -1,7 +1,7 @@ import express from "express"; const router = express.Router(); import { requireAuth } from "../../middleware"; -import { secretApprovalController } from "../../controllers/v1"; +import { secretApprovalPolicyController } from "../../controllers/v1"; import { AuthMode } from "../../variables"; router.get( @@ -9,7 +9,7 @@ router.get( requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - secretApprovalController.getSecretApprovalRules + secretApprovalPolicyController.getSecretApprovalPolicy ); router.post( @@ -17,7 +17,7 @@ router.post( requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - secretApprovalController.createSecretApprovalRule + secretApprovalPolicyController.createSecretApprovalPolicy ); router.patch( @@ -25,7 +25,7 @@ router.patch( requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - secretApprovalController.updateSecretApprovalRule + secretApprovalPolicyController.updateSecretApprovalPolicy ); router.delete( @@ -33,7 +33,7 @@ router.delete( requireAuth({ acceptedAuthModes: [AuthMode.JWT] }), - secretApprovalController.deleteSecretApprovalRule + secretApprovalPolicyController.deleteSecretApprovalPolicy ); export default router; diff --git a/backend/src/validation/secretApproval.ts b/backend/src/validation/secretApproval.ts index a25da81b2..9d4b10ce5 100644 --- a/backend/src/validation/secretApproval.ts +++ b/backend/src/validation/secretApproval.ts @@ -10,7 +10,7 @@ export const CreateSecretApprovalRule = z.object({ body: z.object({ workspaceId: z.string(), environment: z.string(), - secretPath: z.string().optional(), + secretPath: z.string().optional().nullable(), approvers: z.string().array().optional(), approvals: z.number().min(1).default(1) }) @@ -23,7 +23,7 @@ export const UpdateSecretApprovalRule = z.object({ body: z.object({ approvers: z.string().array().optional(), approvals: z.number().min(1).optional(), - secretPath: z.string().optional() + secretPath: z.string().optional().nullable() }) }); diff --git a/frontend/src/hooks/api/secretApproval/types.ts b/frontend/src/hooks/api/secretApproval/types.ts index b77fc1a91..8eb486664 100644 --- a/frontend/src/hooks/api/secretApproval/types.ts +++ b/frontend/src/hooks/api/secretApproval/types.ts @@ -10,7 +10,7 @@ export type TSecretApprovalPolicy = { export type TCreateSecretPolicyDTO = { workspaceId: string; environment: string; - secretPath?: string; + secretPath?: string | null; approvers?: string[]; approvals?: number; }; @@ -18,7 +18,7 @@ export type TCreateSecretPolicyDTO = { export type TUpdateSecretPolicyDTO = { id: string; approvers?: string[]; - secretPath?: string; + secretPath?: string | null; approvals?: number; // for invalidating list workspaceId: string; diff --git a/frontend/src/views/SecretApprovalPage/components/SecretApprovalPolicyList/SecretApprovalPolicyList.tsx b/frontend/src/views/SecretApprovalPage/components/SecretApprovalPolicyList/SecretApprovalPolicyList.tsx index dcc27e49f..700b1a785 100644 --- a/frontend/src/views/SecretApprovalPage/components/SecretApprovalPolicyList/SecretApprovalPolicyList.tsx +++ b/frontend/src/views/SecretApprovalPage/components/SecretApprovalPolicyList/SecretApprovalPolicyList.tsx @@ -1,14 +1,16 @@ -import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { faFileShield, faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { Button, DeleteActionModal, + EmptyState, Table, TableContainer, TableSkeleton, TBody, + Td, Th, THead, Tr @@ -96,6 +98,11 @@ export const SecretApprovalPolicyList = ({ workspaceId }: Props) => { {isPoliciesLoading && ( )} + {!isPoliciesLoading && !policies?.length && ( + + + + )} {policies?.map((policy) => ( ( - + )} /> @@ -220,7 +220,11 @@ export const SecretPolicyForm = ({ isError={Boolean(error)} errorText={error?.message} > - + field.onChange(parseInt(el.target.value, 10))} + /> )} />