-
+
Approval Conditions
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicyModal.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicyModal.tsx
index 790ade93f..8ecfad6da 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicyModal.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicyModal.tsx
@@ -15,7 +15,6 @@ import {
import { UsePopUpState } from "@app/hooks/usePopUp";
import { PolicyApprovalSteps } from "./PolicySteps/PolicyApprovalSteps";
-import { PolicyConstraintsStep } from "./PolicySteps/PolicyConstraintsStep";
import { PolicyDetailsStep } from "./PolicySteps/PolicyDetailsStep";
import { PolicyReviewStep } from "./PolicySteps/PolicyReviewStep";
import { PolicyFormSchema, TPolicyForm } from "./PolicySchema";
@@ -26,9 +25,12 @@ type Props = {
};
const FORM_STEPS: { name: string; key: string; fields: (keyof TPolicyForm)[] }[] = [
- { name: "Details", key: "details", fields: ["name", "maxRequestTtl", "constraints"] },
- { name: "Conditions", key: "conditions", fields: ["conditions"] },
- { name: "Approvals", key: "approvals", fields: ["steps"] },
+ {
+ name: "Configuration",
+ key: "configuration",
+ fields: ["name", "constraints", "conditions"]
+ },
+ { name: "Approval Sequence", key: "approvals", fields: ["steps"] },
{ name: "Review", key: "review", fields: [] }
];
@@ -61,8 +63,7 @@ export const PolicyModal = ({ popUp, handlePopUpToggle }: Props) => {
approvers: []
}
]
- },
- mode: "onChange"
+ }
});
const { handleSubmit, trigger, reset } = formMethods;
@@ -184,7 +185,8 @@ export const PolicyModal = ({ popUp, handlePopUpToggle }: Props) => {
return (
handlePopUpToggle("policy", open)}>
@@ -215,9 +217,6 @@ export const PolicyModal = ({ popUp, handlePopUpToggle }: Props) => {
-
-
-
@@ -237,7 +236,8 @@ export const PolicyModal = ({ popUp, handlePopUpToggle }: Props) => {
isLoading={isCreating || isUpdating}
isDisabled={isCreating || isUpdating}
>
- {policyData?.policyId ? "Update" : "Create"} {isFinalStep ? "" : "Next"}
+ {isFinalStep && (policyData?.policyId ? "Update" : "Create")}
+ {!isFinalStep && "Next"}
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySchema.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySchema.tsx
index ff76ddd1b..6115a1a93 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySchema.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySchema.tsx
@@ -28,7 +28,13 @@ export const PolicyFormSchema = z.object({
).nullish(),
conditions: z
.object({
- accountPaths: z.array(z.string().min(1))
+ accountPaths: z
+ .string()
+ .array()
+ .min(1, "Must have at least one account path")
+ .refine((val) => val.every((path) => path.length > 0), {
+ message: "All account paths must be non-empty"
+ })
})
.array()
.min(1, "At least one condition is required"),
@@ -40,7 +46,12 @@ export const PolicyFormSchema = z.object({
}),
steps: z
.object({
- name: z.string().max(128).nullable().optional(),
+ name: z
+ .string()
+ .max(128)
+ .nullable()
+ .optional()
+ .transform((name) => name || null),
requiredApprovals: z.number().min(1).max(100),
notifyApprovers: z.boolean().optional(),
approvers: z
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyApprovalSteps.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyApprovalSteps.tsx
index a1ca976be..1d0fa9993 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyApprovalSteps.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyApprovalSteps.tsx
@@ -78,7 +78,7 @@ export const PolicyApprovalSteps = () => {
{stepFields.map((field, index) => (
-
+
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyConstraintsStep.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyConstraintsStep.tsx
deleted file mode 100644
index 52289ef14..000000000
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyConstraintsStep.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-import { Controller, useFieldArray, useFormContext } from "react-hook-form";
-import { faPlus, faTrash } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-
-import { Button, FormControl, IconButton, Input } from "@app/components/v2";
-
-import { TPolicyForm } from "../PolicySchema";
-
-export const PolicyConstraintsStep = () => {
- const { control } = useFormContext();
-
- const {
- fields: conditionFields,
- append: appendCondition,
- remove: removeCondition
- } = useFieldArray({
- control,
- name: "conditions"
- });
-
- return (
-
-
-
-
- Conditions
-
- Define which resources and account paths this policy applies to
-
-
- }
- onClick={() => appendCondition({ accountPaths: [] })}
- >
- Add Condition
-
-
-
- {conditionFields.map((field, index) => (
-
-
-
-
- Condition {index + 1}
-
- {conditionFields.length > 1 && (
- removeCondition(index)}
- >
-
-
- )}
-
-
- (
-
- {
- const paths = e.target.value
- .split(",")
- .map((path) => path.trim())
- .filter(Boolean);
- pathField.onChange(paths);
- }}
- placeholder="e.g., /admin/**, /users/john, /**"
- />
-
- )}
- />
-
-
- {index < conditionFields.length - 1 && (
-
- )}
-
- ))}
-
-
-
- );
-};
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyDetailsStep.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyDetailsStep.tsx
index ef6800c71..c6f4a3878 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyDetailsStep.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyDetailsStep.tsx
@@ -9,75 +9,61 @@ export const PolicyDetailsStep = () => {
const { control } = useFormContext();
return (
-
- (
-
-
-
- )}
- />
- (
- }
- helperText="Maximum time-to-live for requests. Must be between 1 hour and 30 days. Leave empty for no limit."
- >
-
-
- )}
- />
-
-
-
- PAM Account Access Duration TTL
-
-
- Set minimum and maximum duration (in seconds) for pam account access
-
-
-
- (
- }
- isError={Boolean(error)}
- errorText={error?.message}
- helperText="Must be between 30s and 7 days"
- >
-
-
- )}
- />
- (
- }
- isError={Boolean(error)}
- errorText={error?.message}
- helperText="Must be between 30s and 7 days"
- >
-
-
- )}
- />
-
+
);
};
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyReviewStep.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyReviewStep.tsx
index 7dacb73c9..8caf65eea 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyReviewStep.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/PolicyReviewStep.tsx
@@ -24,7 +24,7 @@ export const PolicyReviewStep = () => {
const { data: members = [] } = useGetWorkspaceUsers(projectId);
const { data: groups = [] } = useListWorkspaceGroups(projectId);
- const { name, maxRequestTtl, conditions, constraints, steps } = watch();
+ const { name, conditions, constraints, steps } = watch();
const getApproverLabel = (approverId: string, approverType: ApproverType) => {
if (approverType === ApproverType.User) {
@@ -45,61 +45,23 @@ export const PolicyReviewStep = () => {
- Policy Details
+ Policy Configuration
-
-
- PAM Account Access Duration TTL
-
-
-
-
-
-
-
-
-
-
-
- Conditions ({conditions.length})
-
-
-
- {conditions.map((condition, index) => (
-
-
- Condition {index + 1}
-
-
-
- Account Paths:
-
- {condition.accountPaths.length > 0
- ? condition.accountPaths.join(", ")
- : "None specified"}
-
-
-
-
- ))}
-
-
-
-
-
-
- Approval Workflow ({steps.length} step{steps.length !== 1 ? "s" : ""})
-
+ Approval Sequence
{steps.map((step, index) => {
@@ -109,7 +71,7 @@ export const PolicyReviewStep = () => {
return (
@@ -187,8 +149,8 @@ export const PolicyReviewStep = () => {
{/* Summary Notice */}
- Please review all the details above. Click "Create" to save this policy or
- "Back" to make changes.
+ Please review all the details above. Submit to save this policy or go back to make
+ changes.
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/index.tsx b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/index.tsx
index 3a59d2b78..6534a1727 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/index.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/PolicyTab/components/PolicySteps/index.tsx
@@ -1,4 +1,3 @@
export { PolicyApprovalSteps } from "./PolicyApprovalSteps";
-export { PolicyConstraintsStep } from "./PolicyConstraintsStep";
export { PolicyDetailsStep } from "./PolicyDetailsStep";
export { PolicyReviewStep } from "./PolicyReviewStep";
diff --git a/frontend/src/pages/pam/ApprovalsPage/components/RequestGrantTab/RequestGrantTab.tsx b/frontend/src/pages/pam/ApprovalsPage/components/RequestGrantTab/RequestGrantTab.tsx
index 9f611aa00..4adbd2ff2 100644
--- a/frontend/src/pages/pam/ApprovalsPage/components/RequestGrantTab/RequestGrantTab.tsx
+++ b/frontend/src/pages/pam/ApprovalsPage/components/RequestGrantTab/RequestGrantTab.tsx
@@ -180,8 +180,11 @@ export const RequestGrantTab = () => {
return (
-
- Access Grants
+
+
+ View and revoke access grants to PAM accounts
@@ -269,7 +272,7 @@ export const RequestGrantTab = () => {
| User |
Account Path |
- Duration |
+ Access Duration |
Status |
Granted |
Expires |
diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountsTable.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountsTable.tsx
index 61a09c1b0..b3bd9676b 100644
--- a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountsTable.tsx
+++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountsTable.tsx
@@ -5,10 +5,10 @@ import {
faArrowDown,
faArrowUp,
faCheckCircle,
+ faClipboardCheck,
faFilter,
faFolderPlus,
faMagnifyingGlass,
- faPen,
faPlus,
faSearch
} from "@fortawesome/free-solid-svg-icons";
@@ -328,11 +328,11 @@ export const PamAccountsTable = ({ projectId }: Props) => {
}
+ leftIcon={}
onClick={() => handlePopUpOpen("requestAccount")}
className="h-10 transition-colors"
>
- Request Account
+ Request Access
{
control={control}
render={({ field, fieldState: { error } }) => (
{
render={({ field, fieldState: { error } }) => (
}
- helperText="Duration of access requested"
errorText={error?.message}
isError={Boolean(error?.message)}
>
@@ -139,7 +139,6 @@ const Content = ({ onOpenChange, account, accountPath }: Props) => {
control={control}
render={({ field, fieldState: { error } }) => (
{
|