From a852b15a1e9e67cee00670dede4f67a925d3d6f0 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Thu, 28 Nov 2024 15:32:31 -0800 Subject: [PATCH 1/7] improvement: move environment filters beneath static filters --- .../SecretOverviewPage/SecretOverviewPage.tsx | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx index cb49f8509..56059e5bf 100644 --- a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx +++ b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx @@ -722,26 +722,6 @@ export const SecretOverviewPage = () => { - Choose visible environments - {userAvailableEnvs.map((availableEnv) => { - const { id: envId, name } = availableEnv; - - const isEnvSelected = visibleEnvs.map((env) => env.id).includes(envId); - return ( - { - e.preventDefault(); - handleEnvSelect(envId); - }} - key={envId} - disabled={visibleEnvs?.length === 1} - icon={isEnvSelected && } - iconPos="right" - > -
{name}
-
- ); - })} {/* )} diff --git a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx index e96cd3e2d..2f386f53b 100644 --- a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx +++ b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx @@ -1,18 +1,12 @@ -import { useEffect } from "react"; +import { useEffect, useMemo } from "react"; import { Controller, useForm } from "react-hook-form"; -import { faCheckCircle } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; import { Button, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuTrigger, + FilterableSelect, FormControl, Input, Modal, @@ -46,21 +40,34 @@ type Props = { const formSchema = z .object({ - environment: z.string(), + environment: z.object({ slug: z.string(), name: z.string() }), name: z.string().optional(), secretPath: z.string().optional(), approvals: z.number().min(1), - approvers: z - .object({ type: z.nativeEnum(ApproverType), id: z.string() }) + userApprovers: z + .object({ type: z.literal(ApproverType.User), id: z.string() }) + .array() + .default([]), + groupApprovers: z + .object({ type: z.literal(ApproverType.Group), id: z.string() }) .array() - .min(1) .default([]), policyType: z.nativeEnum(PolicyType), enforcementLevel: z.nativeEnum(EnforcementLevel) }) - .refine((data) => data.approvers, { - path: ["approvers"], - message: "At least one approver should be provided." + .superRefine((data, ctx) => { + if (!(data.groupApprovers.length || data.userApprovers.length)) { + ctx.addIssue({ + path: ["userApprovers"], + code: z.ZodIssueCode.custom, + message: "At least one approver should be provided" + }); + ctx.addIssue({ + path: ["groupApprovers"], + code: z.ZodIssueCode.custom, + message: "At least one approver should be provided" + }); + } }); type TFormSchema = z.infer; @@ -84,8 +91,15 @@ export const AccessPolicyForm = ({ values: editValues ? { ...editValues, - environment: editValues.environment.slug, - approvers: editValues?.approvers || [], + environment: editValues.environment, + userApprovers: + editValues?.approvers + ?.filter((approver) => approver.type === ApproverType.User) + .map(({ id, type }) => ({ id, type: type as ApproverType.User })) || [], + groupApprovers: + editValues?.approvers + ?.filter((approver) => approver.type === ApproverType.Group) + .map(({ id, type }) => ({ id, type: type as ApproverType.Group })) || [], approvals: editValues?.approvals } : undefined @@ -110,18 +124,27 @@ export const AccessPolicyForm = ({ const approversRequired = watch("approvals") || 1; - const handleCreatePolicy = async (data: TFormSchema) => { + const handleCreatePolicy = async ({ + environment, + groupApprovers, + userApprovers, + ...data + }: TFormSchema) => { if (!projectId) return; try { if (data.policyType === PolicyType.ChangePolicy) { await createSecretApprovalPolicy({ ...data, + approvers: [...userApprovers, ...groupApprovers], + environment: environment.slug, workspaceId: currentWorkspace?.id || "" }); } else { await createAccessApprovalPolicy({ ...data, + approvers: [...userApprovers, ...groupApprovers], + environment: environment.slug, projectSlug }); } @@ -139,7 +162,12 @@ export const AccessPolicyForm = ({ } }; - const handleUpdatePolicy = async (data: TFormSchema) => { + const handleUpdatePolicy = async ({ + environment, + userApprovers, + groupApprovers, + ...data + }: TFormSchema) => { if (!projectId || !projectSlug) return; if (!editValues?.id) return; @@ -148,12 +176,15 @@ export const AccessPolicyForm = ({ await updateSecretApprovalPolicy({ id: editValues?.id, ...data, + approvers: [...userApprovers, ...groupApprovers], workspaceId: currentWorkspace?.id || "" }); } else { await updateAccessApprovalPolicy({ id: editValues?.id, ...data, + approvers: [...userApprovers, ...groupApprovers], + environment: environment.slug, projectSlug }); } @@ -179,9 +210,35 @@ export const AccessPolicyForm = ({ } }; + const memberOptions = useMemo( + () => + members.map(({ inviteEmail, user: { firstName, lastName, id: userId, username } }) => ({ + id: userId, + type: ApproverType.User, + label: + firstName || lastName + ? `${firstName ?? ""} ${lastName ?? ""}`.trim() + : username || inviteEmail + })), + [members] + ); + + const groupOptions = useMemo( + () => + groups?.map(({ group }) => ({ + id: group.id, + type: ApproverType.Group, + label: group.name + })), + [groups] + ); + return ( - +
( - + onChange={onChange} + placeholder="Select environment..." + options={environments} + getOptionValue={(option) => option.slug} + getOptionLabel={(option) => option.name} + /> )} /> @@ -331,127 +381,60 @@ export const AccessPolicyForm = ({
( - - - e.type === ApproverType.User).length - ? `${value.filter((e) => e.type === ApproverType.User).length} selected` - : "None" - } - className="text-left" - /> - - - - Select members that are allowed to approve requests - - {members.map(({ user }) => { - const { id: userId } = user; - const isChecked = - value?.filter( - (el: { id: string; type: ApproverType }) => - el.id === userId && el.type === ApproverType.User - ).length > 0; - return ( - { - evt.preventDefault(); - onChange( - isChecked - ? value?.filter( - (el: { id: string; type: ApproverType }) => - el.id !== userId && el.type !== ApproverType.User - ) - : [...(value || []), { id: userId, type: ApproverType.User }] - ); - }} - key={`create-policy-members-${userId}`} - iconPos="right" - icon={isChecked && } - > - {user.username} - - ); - })} - - + option.id} + getOptionLabel={(option) => { + const member = members?.find((m) => m.user.id === option.id); + + if (!member) return option.id; + + const { + inviteEmail, + user: { firstName, lastName, username, email } + } = member; + + return firstName || lastName + ? `${firstName ?? ""} ${lastName ?? ""}`.trim() + : username || email || inviteEmail; + }} + value={value} + onChange={onChange} + /> )} /> ( - - - e.type === ApproverType.Group).length - ? `${ - value?.filter((e) => e.type === ApproverType.Group).length - } selected` - : "None" - } - className="text-left" - /> - - - - Select groups that are allowed to approve requests - - {groups && - groups.map(({ group }) => { - const { id } = group; - const isChecked = - value?.filter( - (el: { id: string; type: ApproverType }) => - el.id === id && el.type === ApproverType.Group - ).length > 0; - - return ( - { - evt.preventDefault(); - onChange( - isChecked - ? value?.filter( - (el: { id: string; type: ApproverType }) => - el.id !== id && el.type !== ApproverType.Group - ) - : [...(value || []), { id, type: ApproverType.Group }] - ); - }} - key={`create-policy-members-${id}`} - iconPos="right" - icon={isChecked && } - > - {group.name} - - ); - })} - - + option.id} + getOptionLabel={(option) => + groups?.find(({ group }) => group.id === option.id)?.group.name ?? option.id + } + value={value} + onChange={onChange} + /> )} /> From bb094f60c1c1d0437392741d65e2214939eae78f Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 29 Nov 2024 10:44:05 -0800 Subject: [PATCH 3/7] improvement: update secret approval policy form to use filterable selects w/ UI revisions --- .../v2/FilterableSelect/FilterableSelect.tsx | 17 +- frontend/src/helpers/members.ts | 12 + .../ApprovalPolicyList/ApprovalPolicyList.tsx | 8 +- .../components/AccessPolicyModal.tsx | 284 +++++++++--------- .../components/ApprovalPolicyRow.tsx | 236 ++++----------- 5 files changed, 238 insertions(+), 319 deletions(-) create mode 100644 frontend/src/helpers/members.ts diff --git a/frontend/src/components/v2/FilterableSelect/FilterableSelect.tsx b/frontend/src/components/v2/FilterableSelect/FilterableSelect.tsx index bca2bf516..f17083248 100644 --- a/frontend/src/components/v2/FilterableSelect/FilterableSelect.tsx +++ b/frontend/src/components/v2/FilterableSelect/FilterableSelect.tsx @@ -34,17 +34,22 @@ export const FilterableSelect = ({ tabSelectsValue={tabSelectsValue} components={{ DropdownIndicator, ClearIndicator, MultiValueRemove, Option }} classNames={{ - container: () => "w-full text-sm font-inter", - control: ({ isFocused }) => + container: ({ isDisabled }) => + twMerge("w-full text-sm font-inter", isDisabled && "!pointer-events-auto opacity-50"), + control: ({ isFocused, isDisabled }) => twMerge( - isFocused ? "border-primary-400/50" : "border-mineshaft-600 hover:border-gray-400", - "border w-full p-0.5 rounded-md text-mineshaft-200 font-inter bg-mineshaft-900 hover:cursor-pointer" + isFocused ? "border-primary-400/50" : "border-mineshaft-600 ", + `border w-full p-0.5 rounded-md text-mineshaft-200 font-inter bg-mineshaft-900 ${ + isDisabled ? "!cursor-not-allowed" : "hover:border-gray-400 hover:cursor-pointer" + } ` ), placeholder: () => `${isMulti ? "py-[0.22rem]" : "leading-7"} text-mineshaft-400 text-sm pl-1`, - input: () => "pl-1 py-0.5", + input: () => "pl-1", valueContainer: () => - `p-1 max-h-[14rem] ${isMulti ? "!overflow-y-auto thin-scrollbar" : ""} gap-1`, + `px-1 max-h-[8.2rem] ${ + isMulti ? "!overflow-y-auto thin-scrollbar py-1" : "py-[0.1rem]" + } gap-1`, singleValue: () => "leading-7 ml-1", multiValue: () => "bg-mineshaft-600 text-sm rounded items-center py-0.5 px-2 gap-1.5", multiValueLabel: () => "leading-6 text-sm", diff --git a/frontend/src/helpers/members.ts b/frontend/src/helpers/members.ts new file mode 100644 index 000000000..871ef3ec6 --- /dev/null +++ b/frontend/src/helpers/members.ts @@ -0,0 +1,12 @@ +import { TWorkspaceUser } from "@app/hooks/api/users/types"; + +export const getMemberLabel = (member: TWorkspaceUser) => { + const { + inviteEmail, + user: { firstName, lastName, username, email } + } = member; + + return firstName || lastName + ? `${firstName ?? ""} ${lastName ?? ""}`.trim() + : username || email || inviteEmail; +}; diff --git a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx index a3e06459e..de8daec9e 100644 --- a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx +++ b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx @@ -188,8 +188,8 @@ export const ApprovalPolicyList = ({ workspaceId }: IProps) => { Name Environment Secret Path - Eligible Approvers - Eligible Group Approvers + Eligible Approvers + Eligible Group Approvers Approval Required @@ -256,9 +256,9 @@ export const ApprovalPolicyList = ({ workspaceId }: IProps) => { {!!currentWorkspace && filteredPolicies?.map((policy) => (
- ( - - - - )} - /> - ( - - - - )} - /> - ( - - option.slug} - getOptionLabel={(option) => option.name} - /> - - )} - /> - ( - - - - )} - /> - ( - - field.onChange(parseInt(el.target.value, 10))} - /> - - )} - /> - ( - - {field.value === EnforcementLevel.Hard - ? `Hard enforcement requires at least ${approversRequired} approver(s) to approve the request.` - : `At least ${approversRequired} approver(s) must approve the request; however, the requester can bypass approval requirements in emergencies.`} -
- } - > - onChange(val as PolicyType)} + className="w-full border border-mineshaft-500" + > + {Object.values(PolicyType).map((policyType) => { + return ( + + {policyDetails[policyType].name} + + ); + })} + + + )} + /> + ( + - {Object.values(EnforcementLevel).map((level) => { - return ( - - {level} - - ); - })} - - - )} - /> + field.onChange(parseInt(el.target.value, 10))} + /> + + )} + /> + ( + + + + )} + /> + ( + +

+ Determines the level of enforcement for required approvers of a request: +

+

+ Hard enforcement requires at least{" "} + {approversRequired} approver(s) to + approve the request.` +

+

+ Soft enforcement At least{" "} + {approversRequired} approver(s) must + approve the request; however, the requester can bypass approval + requirements in emergencies. +

+ + } + > + +
+ )} + /> + + ( + + option.slug} + getOptionLabel={(option) => option.name} + /> + + )} + /> + ( + + + + )} + /> +

Approvers

@@ -399,14 +414,7 @@ export const AccessPolicyForm = ({ if (!member) return option.id; - const { - inviteEmail, - user: { firstName, lastName, username, email } - } = member; - - return firstName || lastName - ? `${firstName ?? ""} ${lastName ?? ""}`.trim() - : username || email || inviteEmail; + return getMemberLabel(member); }} value={value} onChange={onChange} diff --git a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx index 4b13029df..5b9a882cd 100644 --- a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx +++ b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx @@ -1,5 +1,5 @@ -import { useState } from "react"; -import { faCheckCircle, faEllipsis } from "@fortawesome/free-solid-svg-icons"; +import { useMemo } from "react"; +import { faEllipsis } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { twMerge } from "tailwind-merge"; @@ -8,19 +8,19 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, - DropdownMenuLabel, DropdownMenuTrigger, - Input, Td, + Tooltip, Tr } from "@app/components/v2"; import { Badge } from "@app/components/v2/Badge"; -import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission } from "@app/context"; +import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; +import { getMemberLabel } from "@app/helpers/members"; import { policyDetails } from "@app/helpers/policies"; -import { useUpdateAccessApprovalPolicy, useUpdateSecretApprovalPolicy } from "@app/hooks/api"; -import { Approver, ApproverType } from "@app/hooks/api/accessApproval/types"; +import { Approver } from "@app/hooks/api/accessApproval/types"; import { TGroupMembership } from "@app/hooks/api/groups/types"; import { EnforcementLevel, PolicyType } from "@app/hooks/api/policies/enums"; +import { ApproverType } from "@app/hooks/api/secretApproval/types"; import { WorkspaceEnv } from "@app/hooks/api/types"; import { TWorkspaceUser } from "@app/hooks/api/users/types"; @@ -35,14 +35,14 @@ interface IPolicy { updatedAt: Date; policyType: PolicyType; enforcementLevel: EnforcementLevel; -}; +} type Props = { policy: IPolicy; members?: TWorkspaceUser[]; groups?: TGroupMembership[]; - projectSlug: string; - workspaceId: string; + // projectSlug: string; + // workspaceId: string; onEdit: () => void; onDelete: () => void; }; @@ -51,175 +51,69 @@ export const ApprovalPolicyRow = ({ policy, members = [], groups = [], - projectSlug, - workspaceId, + // projectSlug, + // workspaceId, onEdit, onDelete }: Props) => { - const [selectedApprovers, setSelectedApprovers] = useState(policy.approvers?.filter((approver) => approver.type === ApproverType.User) || []); - const [selectedGroupApprovers, setSelectedGroupApprovers] = useState(policy.approvers?.filter((approver) => approver.type === ApproverType.Group) || []); - const { mutate: updateAccessApprovalPolicy, isLoading: isAccessApprovalPolicyLoading } = useUpdateAccessApprovalPolicy(); - const { mutate: updateSecretApprovalPolicy, isLoading: isSecretApprovalPolicyLoading } = useUpdateSecretApprovalPolicy(); - const isLoading = isAccessApprovalPolicyLoading || isSecretApprovalPolicyLoading; + // TODO(scott): add back to enable editing from modal? edit modal for policy is fine for now + // const [selectedApprovers, setSelectedApprovers] = useState( + // policy.approvers?.filter((approver) => approver.type === ApproverType.User) || [] + // ); + // const [selectedGroupApprovers, setSelectedGroupApprovers] = useState( + // policy.approvers?.filter((approver) => approver.type === ApproverType.Group) || [] + // ); + // const { mutate: updateAccessApprovalPolicy, isLoading: isAccessApprovalPolicyLoading } = + // useUpdateAccessApprovalPolicy(); + // const { mutate: updateSecretApprovalPolicy, isLoading: isSecretApprovalPolicyLoading } = + // useUpdateSecretApprovalPolicy(); + // const isLoading = isAccessApprovalPolicyLoading || isSecretApprovalPolicyLoading; + // + // const { permission } = useProjectPermission(); - const { permission } = useProjectPermission(); + const labels = useMemo(() => { + const usersInPolicy = policy.approvers + ?.filter((approver) => approver.type === ApproverType.User) + .map((approver) => approver.id); + + const groupsInPolicy = policy.approvers + ?.filter((approver) => approver.type === ApproverType.Group) + .map((approver) => approver.id); + + const memberLabels = usersInPolicy?.length + ? members + .filter((member) => usersInPolicy?.includes(member.user.id)) + .map((member) => getMemberLabel(member)) + .join(", ") + : null; + + const groupLabels = groupsInPolicy?.length + ? groups + .filter(({ group }) => groupsInPolicy?.includes(group.id)) + .map(({ group }) => group.name) + .join(", ") + : null; + + return { + members: memberLabels, + groups: groupLabels + }; + }, [policy, members, groups]); return ( {policy.name} {policy.environment.slug} {policy.secretPath || "*"} - - { - if (!isOpen) { - if (policy.policyType === PolicyType.AccessPolicy) { - updateAccessApprovalPolicy( - { - projectSlug, - id: policy.id, - approvers: selectedApprovers.concat(selectedGroupApprovers), - }, - { - onError: () => { - setSelectedApprovers(policy?.approvers?.filter((approver) => approver.type === ApproverType.User) || []); - } - } - ); - } else { - updateSecretApprovalPolicy( - { - workspaceId, - id: policy.id, - approvers: selectedApprovers.concat(selectedGroupApprovers), - }, - { - onError: () => { - setSelectedApprovers(policy?.approvers?.filter((approver) => approver.type === ApproverType.User) || []); - } - } - ); - } - } else { - setSelectedApprovers(policy?.approvers?.filter((approver) => approver.type === ApproverType.User) || []); - } - }} - > - - - - - - Select members that are allowed to approve changes - - {members?.map(({ user }) => { - const userId = user.id; - const isChecked = selectedApprovers?.filter((el: { id: string, type: ApproverType }) => el.id === userId && el.type === ApproverType.User).length > 0; - return ( - { - evt.preventDefault(); - setSelectedApprovers((state) => - isChecked ? state.filter((el) => el.id !== userId || el.type !== ApproverType.User) : [...state, { id: userId, type: ApproverType.User }] - ); - }} - key={`create-policy-members-${userId}`} - iconPos="right" - icon={isChecked && } - > - {user.username} - - ); - })} - - + + +

{labels.members ?? "-"}

+ - - { - if (!isOpen) { - if (policy.policyType === PolicyType.AccessPolicy) { - updateAccessApprovalPolicy( - { - projectSlug, - id: policy.id, - approvers: selectedApprovers.concat(selectedGroupApprovers), - }, - { - onError: () => { - setSelectedGroupApprovers(policy?.approvers?.filter((approver) => approver.type === ApproverType.Group) || []); - } - }, - ); - } else { - updateSecretApprovalPolicy( - { - workspaceId, - id: policy.id, - approvers: selectedApprovers.concat(selectedGroupApprovers), - }, - { - onError: () => { - setSelectedGroupApprovers(policy?.approvers?.filter((approver) => approver.type === ApproverType.Group) || []); - } - } - ); - } - } else { - setSelectedGroupApprovers(policy?.approvers?.filter((approver) => approver.type === ApproverType.Group) || []); - } - }} - > - - - - - - Select groups that are allowed to approve requests - - {groups && groups.map(({ group }) => { - const { id } = group; - const isChecked = selectedGroupApprovers?.filter((el: { id: string, type: ApproverType }) => el.id === id && el.type === ApproverType.Group).length > 0; - return ( - { - evt.preventDefault(); - setSelectedGroupApprovers( - isChecked - ? selectedGroupApprovers?.filter((el) => el.id !== id || el.type !== ApproverType.Group) - : [...(selectedGroupApprovers || []), { id, type: ApproverType.Group }] - ); - }} - key={`create-policy-groups-${id}`} - iconPos="right" - icon={isChecked && } - > - {group.name} - - ); - })} - - + + +

{labels.groups ?? "-"}

+
{policy.approvals} @@ -229,12 +123,12 @@ export const ApprovalPolicyRow = ({ - -
+ +
- + Date: Fri, 29 Nov 2024 10:44:26 -0800 Subject: [PATCH 4/7] chore: revert license --- backend/src/ee/services/license/license-fns.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index ad49c4119..70c299564 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -37,7 +37,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ status: null, trial_end: null, has_used_trial: true, - secretApproval: true, + secretApproval: false, secretRotation: true, caCrl: false, instanceUserManagement: false, From 62910e93ca18e3facaccbb0859abcfaf73423683 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 29 Nov 2024 10:52:49 -0800 Subject: [PATCH 5/7] fix: remove labels for options(outdated) --- backend/src/ee/services/license/license-fns.ts | 2 +- .../components/AccessPolicyModal.tsx | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index 70c299564..ad49c4119 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -37,7 +37,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ status: null, trial_end: null, has_used_trial: true, - secretApproval: false, + secretApproval: true, secretRotation: true, caCrl: false, instanceUserManagement: false, diff --git a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx index a00790a89..9f5aeec5a 100644 --- a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx +++ b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/components/AccessPolicyModal.tsx @@ -213,13 +213,9 @@ export const AccessPolicyForm = ({ const memberOptions = useMemo( () => - members.map(({ inviteEmail, user: { firstName, lastName, id: userId, username } }) => ({ - id: userId, - type: ApproverType.User, - label: - firstName || lastName - ? `${firstName ?? ""} ${lastName ?? ""}`.trim() - : username || inviteEmail + members.map((member) => ({ + id: member.user.id, + type: ApproverType.User })), [members] ); @@ -228,8 +224,7 @@ export const AccessPolicyForm = ({ () => groups?.map(({ group }) => ({ id: group.id, - type: ApproverType.Group, - label: group.name + type: ApproverType.Group })), [groups] ); From ae51fbb8f279596cea05f13cea3f2ff41333d9bc Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Fri, 29 Nov 2024 10:53:22 -0800 Subject: [PATCH 6/7] chore: revert license --- backend/src/ee/services/license/license-fns.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index ad49c4119..70c299564 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -37,7 +37,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ status: null, trial_end: null, has_used_trial: true, - secretApproval: true, + secretApproval: false, secretRotation: true, caCrl: false, instanceUserManagement: false, From afa2f383c529edb8d053ec20f0128732d1b538d2 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Mon, 2 Dec 2024 09:35:03 -0800 Subject: [PATCH 7/7] improvement: address feedback --- .../ApprovalPolicyList/ApprovalPolicyList.tsx | 2 -- .../components/ApprovalPolicyRow.tsx | 29 +++++-------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx index de8daec9e..d2a4e3788 100644 --- a/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx +++ b/frontend/src/views/SecretApprovalPage/components/ApprovalPolicyList/ApprovalPolicyList.tsx @@ -256,9 +256,7 @@ export const ApprovalPolicyList = ({ workspaceId }: IProps) => { {!!currentWorkspace && filteredPolicies?.map((policy) => ( void; onDelete: () => void; }; @@ -51,26 +49,9 @@ export const ApprovalPolicyRow = ({ policy, members = [], groups = [], - // projectSlug, - // workspaceId, onEdit, onDelete }: Props) => { - // TODO(scott): add back to enable editing from modal? edit modal for policy is fine for now - // const [selectedApprovers, setSelectedApprovers] = useState( - // policy.approvers?.filter((approver) => approver.type === ApproverType.User) || [] - // ); - // const [selectedGroupApprovers, setSelectedGroupApprovers] = useState( - // policy.approvers?.filter((approver) => approver.type === ApproverType.Group) || [] - // ); - // const { mutate: updateAccessApprovalPolicy, isLoading: isAccessApprovalPolicyLoading } = - // useUpdateAccessApprovalPolicy(); - // const { mutate: updateSecretApprovalPolicy, isLoading: isSecretApprovalPolicyLoading } = - // useUpdateSecretApprovalPolicy(); - // const isLoading = isAccessApprovalPolicyLoading || isSecretApprovalPolicyLoading; - // - // const { permission } = useProjectPermission(); - const labels = useMemo(() => { const usersInPolicy = policy.approvers ?.filter((approver) => approver.type === ApproverType.User) @@ -106,12 +87,18 @@ export const ApprovalPolicyRow = ({ {policy.environment.slug} {policy.secretPath || "*"} - +

{labels.members ?? "-"}

- +

{labels.groups ?? "-"}