feat(secret-approval): updated names to secret policy and fixed approval number bug

This commit is contained in:
Akhil Mohan
2023-09-28 12:23:01 +05:30
parent c67432a56f
commit b0c398688b
11 changed files with 54 additions and 37 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ import * as workspaceController from "./workspaceController";
import * as secretScanningController from "./secretScanningController"; import * as secretScanningController from "./secretScanningController";
import * as webhookController from "./webhookController"; import * as webhookController from "./webhookController";
import * as secretImpsController from "./secretImpsController"; import * as secretImpsController from "./secretImpsController";
import * as secretApprovalController from "./secretApprovalController"; import * as secretApprovalPolicyController from "./secretApprovalPolicyController";
export { export {
authController, authController,
@@ -37,5 +37,5 @@ export {
secretScanningController, secretScanningController,
webhookController, webhookController,
secretImpsController, secretImpsController,
secretApprovalController secretApprovalPolicyController
}; };
@@ -6,13 +6,13 @@ import {
getUserProjectPermissions getUserProjectPermissions
} from "../../ee/services/ProjectRoleService"; } from "../../ee/services/ProjectRoleService";
import { validateRequest } from "../../helpers/validation"; import { validateRequest } from "../../helpers/validation";
import { SecretApproval } from "../../models/secretApproval"; import { SecretApprovalPolicy } from "../../models/secretApprovalPolicy";
import { BadRequestError } from "../../utils/errors"; import { BadRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/secretApproval"; import * as reqValidator from "../../validation/secretApproval";
const ERR_SECRET_APPROVAL_NOT_FOUND = BadRequestError({ message: "secret approval not found" }); 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 { const {
body: { approvals, secretPath, approvers, environment, workspaceId } body: { approvals, secretPath, approvers, environment, workspaceId }
} = await validateRequest(reqValidator.CreateSecretApprovalRule, req); } = await validateRequest(reqValidator.CreateSecretApprovalRule, req);
@@ -23,7 +23,7 @@ export const createSecretApprovalRule = async (req: Request, res: Response) => {
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
); );
const secretApproval = new SecretApproval({ const secretApproval = new SecretApprovalPolicy({
workspace: workspaceId, workspace: workspaceId,
secretPath, secretPath,
environment, 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 { const {
body: { approvals, approvers, secretPath }, body: { approvals, approvers, secretPath },
params: { id } params: { id }
} = await validateRequest(reqValidator.UpdateSecretApprovalRule, req); } = 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; if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND;
const { permission } = await getUserProjectPermissions( const { permission } = await getUserProjectPermissions(
@@ -55,10 +55,10 @@ export const updateSecretApprovalRule = async (req: Request, res: Response) => {
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
); );
const updatedDoc = await SecretApproval.findByIdAndUpdate(id, { const updatedDoc = await SecretApprovalPolicy.findByIdAndUpdate(id, {
approvals, approvals,
approvers, approvers,
$set: secretPath === "-" ? undefined : { secretPath } ...(secretPath === null ? { $unset: { secretPath: 1 } } : { secretPath })
}); });
return res.send({ 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 { const {
params: { id } params: { id }
} = await validateRequest(reqValidator.DeleteSecretApprovalRule, req); } = 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; if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND;
const { permission } = await getUserProjectPermissions( const { permission } = await getUserProjectPermissions(
@@ -83,14 +83,14 @@ export const deleteSecretApprovalRule = async (req: Request, res: Response) => {
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
); );
const deletedDoc = await SecretApproval.findByIdAndDelete(id); const deletedDoc = await SecretApprovalPolicy.findByIdAndDelete(id);
return res.send({ return res.send({
approval: deletedDoc approval: deletedDoc
}); });
}; };
export const getSecretApprovalRules = async (req: Request, res: Response) => { export const getSecretApprovalPolicy = async (req: Request, res: Response) => {
const { const {
query: { workspaceId } query: { workspaceId }
} = await validateRequest(reqValidator.GetSecretApprovalRuleList, req); } = await validateRequest(reqValidator.GetSecretApprovalRuleList, req);
@@ -101,7 +101,7 @@ export const getSecretApprovalRules = async (req: Request, res: Response) => {
ProjectPermissionSub.SecretApproval ProjectPermissionSub.SecretApproval
); );
const doc = await SecretApproval.find({ workspace: workspaceId }); const doc = await SecretApprovalPolicy.find({ workspace: workspaceId });
return res.send({ return res.send({
approvals: doc approvals: doc
+2 -2
View File
@@ -38,7 +38,7 @@ import {
membership as v1MembershipRouter, membership as v1MembershipRouter,
organization as v1OrganizationRouter, organization as v1OrganizationRouter,
password as v1PasswordRouter, password as v1PasswordRouter,
secretApproval as v1SecretApproval, secretApprovalPolicy as v1SecretApprovalPolicy,
secretImps as v1SecretImpsRouter, secretImps as v1SecretImpsRouter,
secret as v1SecretRouter, secret as v1SecretRouter,
secretsFolder as v1SecretsFolder, secretsFolder as v1SecretsFolder,
@@ -177,7 +177,7 @@ const main = async () => {
app.use("/api/v1/webhooks", v1WebhooksRouter); app.use("/api/v1/webhooks", v1WebhooksRouter);
app.use("/api/v1/secret-imports", v1SecretImpsRouter); app.use("/api/v1/secret-imports", v1SecretImpsRouter);
app.use("/api/v1/roles", v1RoleRouter); app.use("/api/v1/roles", v1RoleRouter);
app.use("/api/v1/secret-approvals", v1SecretApproval); app.use("/api/v1/secret-approvals", v1SecretApprovalPolicy);
// v2 routes (improvements) // v2 routes (improvements)
app.use("/api/v2/signup", v2SignupRouter); app.use("/api/v2/signup", v2SignupRouter);
@@ -1,6 +1,6 @@
import { Schema, Types, model } from "mongoose"; import { Schema, Types, model } from "mongoose";
export interface ISecretApproval { export interface ISecretApprovalPolicy {
_id: Types.ObjectId; _id: Types.ObjectId;
workspace: Types.ObjectId; workspace: Types.ObjectId;
environment: string; environment: string;
@@ -9,7 +9,7 @@ export interface ISecretApproval {
approvals: number; approvals: number;
} }
const secretApprovalSchema = new Schema<ISecretApproval>( const secretApprovalPolicySchema = new Schema<ISecretApprovalPolicy>(
{ {
workspace: { workspace: {
type: Schema.Types.ObjectId, type: Schema.Types.ObjectId,
@@ -41,4 +41,7 @@ const secretApprovalSchema = new Schema<ISecretApproval>(
} }
); );
export const SecretApproval = model<ISecretApproval>("SecretApproval", secretApprovalSchema); export const SecretApprovalPolicy = model<ISecretApprovalPolicy>(
"SecretApprovalPolicy",
secretApprovalPolicySchema
);
+5 -2
View File
@@ -30,7 +30,7 @@ export interface ISecretApprovalRequest {
}[]; }[];
} }
const secretApprovalSchema = new Schema<ISecretApprovalRequest>( const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
{ {
approvers: [ approvers: [
{ {
@@ -62,4 +62,7 @@ const secretApprovalSchema = new Schema<ISecretApprovalRequest>(
} }
); );
export const SecretApproval = model<ISecretApprovalRequest>("SecretApproval", secretApprovalSchema); export const SecretApprovalRequest = model<ISecretApprovalRequest>(
"SecretApprovalRequest",
secretApprovalRequestSchema
);
+2 -2
View File
@@ -17,7 +17,7 @@ import integrationAuth from "./integrationAuth";
import secretsFolder from "./secretsFolder"; import secretsFolder from "./secretsFolder";
import webhooks from "./webhook"; import webhooks from "./webhook";
import secretImps from "./secretImps"; import secretImps from "./secretImps";
import secretApproval from "./secretApproval"; import secretApprovalPolicy from "./secretApprovalPolicy";
export { export {
signup, signup,
@@ -39,5 +39,5 @@ export {
secretsFolder, secretsFolder,
webhooks, webhooks,
secretImps, secretImps,
secretApproval secretApprovalPolicy
}; };
@@ -1,7 +1,7 @@
import express from "express"; import express from "express";
const router = express.Router(); const router = express.Router();
import { requireAuth } from "../../middleware"; import { requireAuth } from "../../middleware";
import { secretApprovalController } from "../../controllers/v1"; import { secretApprovalPolicyController } from "../../controllers/v1";
import { AuthMode } from "../../variables"; import { AuthMode } from "../../variables";
router.get( router.get(
@@ -9,7 +9,7 @@ router.get(
requireAuth({ requireAuth({
acceptedAuthModes: [AuthMode.JWT] acceptedAuthModes: [AuthMode.JWT]
}), }),
secretApprovalController.getSecretApprovalRules secretApprovalPolicyController.getSecretApprovalPolicy
); );
router.post( router.post(
@@ -17,7 +17,7 @@ router.post(
requireAuth({ requireAuth({
acceptedAuthModes: [AuthMode.JWT] acceptedAuthModes: [AuthMode.JWT]
}), }),
secretApprovalController.createSecretApprovalRule secretApprovalPolicyController.createSecretApprovalPolicy
); );
router.patch( router.patch(
@@ -25,7 +25,7 @@ router.patch(
requireAuth({ requireAuth({
acceptedAuthModes: [AuthMode.JWT] acceptedAuthModes: [AuthMode.JWT]
}), }),
secretApprovalController.updateSecretApprovalRule secretApprovalPolicyController.updateSecretApprovalPolicy
); );
router.delete( router.delete(
@@ -33,7 +33,7 @@ router.delete(
requireAuth({ requireAuth({
acceptedAuthModes: [AuthMode.JWT] acceptedAuthModes: [AuthMode.JWT]
}), }),
secretApprovalController.deleteSecretApprovalRule secretApprovalPolicyController.deleteSecretApprovalPolicy
); );
export default router; export default router;
+2 -2
View File
@@ -10,7 +10,7 @@ export const CreateSecretApprovalRule = z.object({
body: z.object({ body: z.object({
workspaceId: z.string(), workspaceId: z.string(),
environment: z.string(), environment: z.string(),
secretPath: z.string().optional(), secretPath: z.string().optional().nullable(),
approvers: z.string().array().optional(), approvers: z.string().array().optional(),
approvals: z.number().min(1).default(1) approvals: z.number().min(1).default(1)
}) })
@@ -23,7 +23,7 @@ export const UpdateSecretApprovalRule = z.object({
body: z.object({ body: z.object({
approvers: z.string().array().optional(), approvers: z.string().array().optional(),
approvals: z.number().min(1).optional(), approvals: z.number().min(1).optional(),
secretPath: z.string().optional() secretPath: z.string().optional().nullable()
}) })
}); });
@@ -10,7 +10,7 @@ export type TSecretApprovalPolicy = {
export type TCreateSecretPolicyDTO = { export type TCreateSecretPolicyDTO = {
workspaceId: string; workspaceId: string;
environment: string; environment: string;
secretPath?: string; secretPath?: string | null;
approvers?: string[]; approvers?: string[];
approvals?: number; approvals?: number;
}; };
@@ -18,7 +18,7 @@ export type TCreateSecretPolicyDTO = {
export type TUpdateSecretPolicyDTO = { export type TUpdateSecretPolicyDTO = {
id: string; id: string;
approvers?: string[]; approvers?: string[];
secretPath?: string; secretPath?: string | null;
approvals?: number; approvals?: number;
// for invalidating list // for invalidating list
workspaceId: string; workspaceId: string;
@@ -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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { import {
Button, Button,
DeleteActionModal, DeleteActionModal,
EmptyState,
Table, Table,
TableContainer, TableContainer,
TableSkeleton, TableSkeleton,
TBody, TBody,
Td,
Th, Th,
THead, THead,
Tr Tr
@@ -96,6 +98,11 @@ export const SecretApprovalPolicyList = ({ workspaceId }: Props) => {
{isPoliciesLoading && ( {isPoliciesLoading && (
<TableSkeleton columns={4} innerKey="secret-policies" className="bg-mineshaft-700" /> <TableSkeleton columns={4} innerKey="secret-policies" className="bg-mineshaft-700" />
)} )}
{!isPoliciesLoading && !policies?.length && (
<Td colSpan={5}>
<EmptyState title="No policies found" icon={faFileShield} />
</Td>
)}
{policies?.map((policy) => ( {policies?.map((policy) => (
<SecretApprovalPolicyRow <SecretApprovalPolicyRow
workspaceId={workspaceId} workspaceId={workspaceId}
@@ -35,7 +35,7 @@ type Props = {
const formSchema = z.object({ const formSchema = z.object({
environment: z.string(), environment: z.string(),
secretPath: z.string().optional(), secretPath: z.string().optional().nullable(),
approvals: z.number().min(1), approvals: z.number().min(1),
approvers: z.string().array().optional() approvers: z.string().array().optional()
}); });
@@ -97,7 +97,7 @@ export const SecretPolicyForm = ({
await updateSecretApprovalPolicy({ await updateSecretApprovalPolicy({
id: editValues?._id, id: editValues?._id,
...data, ...data,
secretPath: data.secretPath ?? "-", secretPath: data.secretPath || null,
workspaceId workspaceId
}); });
createNotification({ createNotification({
@@ -159,7 +159,7 @@ export const SecretPolicyForm = ({
name="secretPath" name="secretPath"
render={({ field, fieldState: { error } }) => ( render={({ field, fieldState: { error } }) => (
<FormControl label="Secret Path" isError={Boolean(error)} errorText={error?.message}> <FormControl label="Secret Path" isError={Boolean(error)} errorText={error?.message}>
<Input {...field} /> <Input {...field} value={field.value || ""} />
</FormControl> </FormControl>
)} )}
/> />
@@ -220,7 +220,11 @@ export const SecretPolicyForm = ({
isError={Boolean(error)} isError={Boolean(error)}
errorText={error?.message} errorText={error?.message}
> >
<Input {...field} type="number" /> <Input
{...field}
type="number"
onChange={(el) => field.onChange(parseInt(el.target.value, 10))}
/>
</FormControl> </FormControl>
)} )}
/> />