mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 12:04:03 +00:00
feat(rbac): implemented granular blocking of actions based on permissions on org level ui
This commit is contained in:
@@ -3,7 +3,8 @@ import { useTranslation } from "react-i18next";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { OrgGeneralPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||
import { withPermission } from "@app/hoc";
|
||||
import { useGetRoles } from "@app/hooks/api";
|
||||
|
||||
import { OrgMembersTable } from "./components/OrgMembersTable";
|
||||
@@ -14,45 +15,48 @@ enum TabSections {
|
||||
Roles = "roles"
|
||||
}
|
||||
|
||||
export const MembersPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { currentOrg } = useOrganization();
|
||||
export const MembersPage = withPermission(
|
||||
() => {
|
||||
const { t } = useTranslation();
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
const orgId = currentOrg?._id || "";
|
||||
const orgId = currentOrg?._id || "";
|
||||
|
||||
const { data: roles } = useGetRoles({
|
||||
orgId
|
||||
});
|
||||
const { data: roles } = useGetRoles({
|
||||
orgId
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||
<div className="mb-6 w-full py-6 px-6 max-w-7xl mx-auto">
|
||||
<p className="mr-4 mb-4 text-3xl font-semibold text-white">
|
||||
{t("section.members.org-members")}
|
||||
</p>
|
||||
<Tabs defaultValue={TabSections.Member}>
|
||||
<TabList>
|
||||
<Tab value={TabSections.Member}>Members</Tab>
|
||||
{process.env.NEXT_PUBLIC_NEW_PERMISSION_FLAG === "true" && (
|
||||
<Tab value={TabSections.Roles}>Roles</Tab>
|
||||
)}
|
||||
</TabList>
|
||||
<TabPanel value={TabSections.Member}>
|
||||
<motion.div
|
||||
key="panel-1"
|
||||
transition={{ duration: 0.15 }}
|
||||
initial={{ opacity: 0, translateX: 30 }}
|
||||
animate={{ opacity: 1, translateX: 0 }}
|
||||
exit={{ opacity: 0, translateX: 30 }}
|
||||
>
|
||||
<OrgMembersTable roles={roles} />
|
||||
</motion.div>
|
||||
</TabPanel>
|
||||
<TabPanel value={TabSections.Roles}>
|
||||
<OrgRoleTabSection roles={roles} />
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
return (
|
||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||
<div className="mb-6 w-full py-6 px-6 max-w-7xl mx-auto">
|
||||
<p className="mr-4 mb-4 text-3xl font-semibold text-white">
|
||||
{t("section.members.org-members")}
|
||||
</p>
|
||||
<Tabs defaultValue={TabSections.Member}>
|
||||
<TabList>
|
||||
<Tab value={TabSections.Member}>Members</Tab>
|
||||
{process.env.NEXT_PUBLIC_NEW_PERMISSION_FLAG === "true" && (
|
||||
<Tab value={TabSections.Roles}>Roles</Tab>
|
||||
)}
|
||||
</TabList>
|
||||
<TabPanel value={TabSections.Member}>
|
||||
<motion.div
|
||||
key="panel-1"
|
||||
transition={{ duration: 0.15 }}
|
||||
initial={{ opacity: 0, translateX: 30 }}
|
||||
animate={{ opacity: 1, translateX: 0 }}
|
||||
exit={{ opacity: 0, translateX: 30 }}
|
||||
>
|
||||
<OrgMembersTable roles={roles} />
|
||||
</motion.div>
|
||||
</TabPanel>
|
||||
<TabPanel value={TabSections.Roles}>
|
||||
<OrgRoleTabSection roles={roles} />
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
},
|
||||
{ action: OrgGeneralPermissionActions.Read, subject: OrgPermissionSubjects.Member }
|
||||
);
|
||||
|
||||
+101
-70
@@ -14,6 +14,7 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
decryptAssymmetric,
|
||||
encryptAssymmetric
|
||||
@@ -41,7 +42,14 @@ import {
|
||||
Tr,
|
||||
UpgradePlanModal
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization, useSubscription, useUser, useWorkspace } from "@app/context";
|
||||
import {
|
||||
OrgGeneralPermissionActions,
|
||||
OrgPermissionSubjects,
|
||||
useOrganization,
|
||||
useSubscription,
|
||||
useUser,
|
||||
useWorkspace
|
||||
} from "@app/context";
|
||||
import { usePopUp, useToggle } from "@app/hooks";
|
||||
import {
|
||||
useAddUserToOrg,
|
||||
@@ -297,27 +305,32 @@ export const OrgMembersTable = ({ roles = [] }: Props) => {
|
||||
placeholder="Search members..."
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (!isLoadingSSOConfig && ssoConfig && ssoConfig.isActive) {
|
||||
createNotification({
|
||||
text: "You cannot invite users when SAML SSO is configured for your organization",
|
||||
type: "error"
|
||||
});
|
||||
<OrgPermissionCan I={OrgGeneralPermissionActions.Create} a={OrgPermissionSubjects.Member}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isDisabled={!isAllowed}
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (!isLoadingSSOConfig && ssoConfig && ssoConfig.isActive) {
|
||||
createNotification({
|
||||
text: "You cannot invite users when SAML SSO is configured for your organization",
|
||||
type: "error"
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMoreUsersNotAllowed) {
|
||||
handlePopUpOpen("upgradePlan");
|
||||
} else {
|
||||
handlePopUpOpen("addMember");
|
||||
}
|
||||
}}
|
||||
>
|
||||
Add Member
|
||||
</Button>
|
||||
if (isMoreUsersNotAllowed) {
|
||||
handlePopUpOpen("upgradePlan");
|
||||
} else {
|
||||
handlePopUpOpen("addMember");
|
||||
}
|
||||
}}
|
||||
>
|
||||
Add Member
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
<div>
|
||||
<TableContainer>
|
||||
@@ -345,48 +358,59 @@ export const OrgMembersTable = ({ roles = [] }: Props) => {
|
||||
<Td>{name}</Td>
|
||||
<Td>{email}</Td>
|
||||
<Td>
|
||||
{status === "accepted" && (
|
||||
<Select
|
||||
defaultValue={
|
||||
role === "custom" ? findRoleFromId(customRole)?.slug : role
|
||||
}
|
||||
isDisabled={userId === u?._id}
|
||||
className="w-40 bg-mineshaft-600"
|
||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
||||
onValueChange={(selectedRole) =>
|
||||
onRoleChange(orgMembershipId, selectedRole)
|
||||
}
|
||||
>
|
||||
{roles
|
||||
.filter(({ slug }) =>
|
||||
slug === "owner" ? isIamOwner || role === "owner" : true
|
||||
)
|
||||
.map(({ slug, name: roleName }) => (
|
||||
<SelectItem value={slug} key={`owner-option-${slug}`}>
|
||||
{roleName}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
{(status === "invited" || status === "verified") &&
|
||||
serverDetails?.emailConfigured && (
|
||||
<Button
|
||||
className="w-40"
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
onClick={() => onAddUserToOrg(email)}
|
||||
>
|
||||
Resend Invite
|
||||
</Button>
|
||||
<OrgPermissionCan
|
||||
I={OrgGeneralPermissionActions.Edit}
|
||||
a={OrgPermissionSubjects.Member}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<>
|
||||
{status === "accepted" && (
|
||||
<Select
|
||||
defaultValue={
|
||||
role === "custom" ? findRoleFromId(customRole)?.slug : role
|
||||
}
|
||||
isDisabled={userId === u?._id || !isAllowed}
|
||||
className="w-40 bg-mineshaft-600"
|
||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
||||
onValueChange={(selectedRole) =>
|
||||
onRoleChange(orgMembershipId, selectedRole)
|
||||
}
|
||||
>
|
||||
{roles
|
||||
.filter(({ slug }) =>
|
||||
slug === "owner" ? isIamOwner || role === "owner" : true
|
||||
)
|
||||
.map(({ slug, name: roleName }) => (
|
||||
<SelectItem value={slug} key={`owner-option-${slug}`}>
|
||||
{roleName}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
{(status === "invited" || status === "verified") &&
|
||||
serverDetails?.emailConfigured && (
|
||||
<Button
|
||||
isDisabled={!isAllowed}
|
||||
className="w-40"
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
onClick={() => onAddUserToOrg(email)}
|
||||
>
|
||||
Resend Invite
|
||||
</Button>
|
||||
)}
|
||||
{status === "completed" && (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
isDisabled={!isAllowed}
|
||||
onClick={() => onGrantAccess(u?._id, u?.publicKey)}
|
||||
>
|
||||
Grant Access
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{status === "completed" && (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
onClick={() => onGrantAccess(u?._id, u?.publicKey)}
|
||||
>
|
||||
Grant Access
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</Td>
|
||||
<Td>
|
||||
{userWs ? (
|
||||
@@ -428,16 +452,23 @@ export const OrgMembersTable = ({ roles = [] }: Props) => {
|
||||
</Td>
|
||||
<Td>
|
||||
{userId !== u?._id && (
|
||||
<IconButton
|
||||
ariaLabel="delete"
|
||||
colorSchema="danger"
|
||||
isDisabled={userId === u?._id}
|
||||
onClick={() =>
|
||||
handlePopUpOpen("removeMember", { id: orgMembershipId })
|
||||
}
|
||||
<OrgPermissionCan
|
||||
I={OrgGeneralPermissionActions.Delete}
|
||||
a={OrgPermissionSubjects.Member}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrash} />
|
||||
</IconButton>
|
||||
{(isAllowed) => (
|
||||
<IconButton
|
||||
ariaLabel="delete"
|
||||
colorSchema="danger"
|
||||
isDisabled={userId === u?._id || !isAllowed}
|
||||
onClick={() =>
|
||||
handlePopUpOpen("removeMember", { id: orgMembershipId })
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrash} />
|
||||
</IconButton>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
|
||||
+6
-4
@@ -38,10 +38,9 @@ export const BillingPermission = ({ isNonEditable, setValue, control }: Props) =
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += rule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
@@ -52,11 +51,14 @@ export const BillingPermission = ({ isNonEditable, setValue, control }: Props) =
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
val === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setValue(
|
||||
|
||||
+6
-8
@@ -38,10 +38,9 @@ export const IncidentContactPermission = ({ isNonEditable, setValue, control }:
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += rule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
@@ -52,14 +51,16 @@ export const IncidentContactPermission = ({ isNonEditable, setValue, control }:
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
val === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.incident-contact",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
@@ -67,7 +68,6 @@ export const IncidentContactPermission = ({ isNonEditable, setValue, control }:
|
||||
);
|
||||
break;
|
||||
case Permission.FullAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.incident-contact",
|
||||
{ read: true, edit: true, create: true, delete: true },
|
||||
@@ -75,7 +75,6 @@ export const IncidentContactPermission = ({ isNonEditable, setValue, control }:
|
||||
);
|
||||
break;
|
||||
case Permission.ReadOnly:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.incident-contact",
|
||||
{ read: true, edit: false, create: false, delete: false },
|
||||
@@ -83,7 +82,6 @@ export const IncidentContactPermission = ({ isNonEditable, setValue, control }:
|
||||
);
|
||||
break;
|
||||
default:
|
||||
setIsCustom.on();
|
||||
setValue(
|
||||
"permissions.incident-contact",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
|
||||
+10
-7
@@ -31,31 +31,34 @@ const PERMISSIONS = [
|
||||
] as const;
|
||||
|
||||
export const MemberPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
const memberRule = useWatch({
|
||||
const rule = useWatch({
|
||||
control,
|
||||
name: "permissions.member"
|
||||
});
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(memberRule || {}) as Array<keyof typeof memberRule>;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += memberRule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
if (score === totalActions) return Permission.FullAccess;
|
||||
if (score === 1 && memberRule.read) return Permission.ReadOnly;
|
||||
if (score === 1 && rule.read) return Permission.ReadOnly;
|
||||
|
||||
return Permission.Custom;
|
||||
}, [memberRule, isCustom]);
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setValue(
|
||||
|
||||
+10
-11
@@ -31,34 +31,36 @@ const PERMISSIONS = [
|
||||
] as const;
|
||||
|
||||
export const RolePermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
const roleRule = useWatch({
|
||||
const rule = useWatch({
|
||||
control,
|
||||
name: "permissions.role"
|
||||
});
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(roleRule || {}) as Array<keyof typeof roleRule>;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += roleRule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
if (score === totalActions) return Permission.FullAccess;
|
||||
if (score === 1 && roleRule.read) return Permission.ReadOnly;
|
||||
if (score === 1 && rule.read) return Permission.ReadOnly;
|
||||
|
||||
return Permission.Custom;
|
||||
}, [roleRule, isCustom]);
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.role",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
@@ -66,7 +68,6 @@ export const RolePermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
);
|
||||
break;
|
||||
case Permission.FullAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.role",
|
||||
{ read: true, edit: true, create: true, delete: true },
|
||||
@@ -74,7 +75,6 @@ export const RolePermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
);
|
||||
break;
|
||||
case Permission.ReadOnly:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.role",
|
||||
{ read: true, edit: false, create: false, delete: false },
|
||||
@@ -82,7 +82,6 @@ export const RolePermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
);
|
||||
break;
|
||||
default:
|
||||
setIsCustom.on();
|
||||
setValue(
|
||||
"permissions.role",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
|
||||
+6
-7
@@ -38,10 +38,9 @@ export const SecretScannigPermission = ({ isNonEditable, setValue, control }: Pr
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += rule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
@@ -52,13 +51,16 @@ export const SecretScannigPermission = ({ isNonEditable, setValue, control }: Pr
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.secret-scanning",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
@@ -66,7 +68,6 @@ export const SecretScannigPermission = ({ isNonEditable, setValue, control }: Pr
|
||||
);
|
||||
break;
|
||||
case Permission.FullAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.secret-scanning",
|
||||
{ read: true, edit: true, create: true, delete: true },
|
||||
@@ -74,7 +75,6 @@ export const SecretScannigPermission = ({ isNonEditable, setValue, control }: Pr
|
||||
);
|
||||
break;
|
||||
case Permission.ReadOnly:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.secret-scanning",
|
||||
{ read: true, edit: false, create: false, delete: false },
|
||||
@@ -82,7 +82,6 @@ export const SecretScannigPermission = ({ isNonEditable, setValue, control }: Pr
|
||||
);
|
||||
break;
|
||||
default:
|
||||
setIsCustom.on();
|
||||
setValue(
|
||||
"permissions.secret-scanning",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
|
||||
+6
-7
@@ -38,10 +38,9 @@ export const SettingsPermission = ({ isNonEditable, setValue, control }: Props)
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += rule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
@@ -52,13 +51,16 @@ export const SettingsPermission = ({ isNonEditable, setValue, control }: Props)
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.settings",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
@@ -66,7 +68,6 @@ export const SettingsPermission = ({ isNonEditable, setValue, control }: Props)
|
||||
);
|
||||
break;
|
||||
case Permission.FullAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.settings",
|
||||
{ read: true, edit: true, create: true, delete: true },
|
||||
@@ -74,7 +75,6 @@ export const SettingsPermission = ({ isNonEditable, setValue, control }: Props)
|
||||
);
|
||||
break;
|
||||
case Permission.ReadOnly:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.settings",
|
||||
{ read: true, edit: false, create: false, delete: false },
|
||||
@@ -82,7 +82,6 @@ export const SettingsPermission = ({ isNonEditable, setValue, control }: Props)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
setIsCustom.on();
|
||||
setValue(
|
||||
"permissions.settings",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
|
||||
+6
-7
@@ -38,10 +38,9 @@ export const SsoPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += rule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
@@ -52,13 +51,16 @@ export const SsoPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.sso",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
@@ -66,7 +68,6 @@ export const SsoPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
);
|
||||
break;
|
||||
case Permission.FullAccess:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.sso",
|
||||
{ read: true, edit: true, create: true, delete: true },
|
||||
@@ -74,7 +75,6 @@ export const SsoPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
);
|
||||
break;
|
||||
case Permission.ReadOnly:
|
||||
setIsCustom.off();
|
||||
setValue(
|
||||
"permissions.sso",
|
||||
{ read: true, edit: false, create: false, delete: false },
|
||||
@@ -82,7 +82,6 @@ export const SsoPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
);
|
||||
break;
|
||||
default:
|
||||
setIsCustom.on();
|
||||
setValue(
|
||||
"permissions.sso",
|
||||
{ read: false, edit: false, create: false, delete: false },
|
||||
|
||||
+6
-4
@@ -36,10 +36,9 @@ export const WorkspacePermission = ({ isNonEditable, setValue, control }: Props)
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
let score = 0;
|
||||
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||
const totalActions = PERMISSIONS.length;
|
||||
actions.forEach((key) => (score += rule[key] ? 1 : 0));
|
||||
const score = actions.map((key) => (rule[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||
|
||||
if (isCustom) return Permission.Custom;
|
||||
if (score === 0) return Permission.NoAccess;
|
||||
@@ -50,11 +49,14 @@ export const WorkspacePermission = ({ isNonEditable, setValue, control }: Props)
|
||||
}, [rule, isCustom]);
|
||||
|
||||
useEffect(() => {
|
||||
selectedPermissionCategory === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
}, [selectedPermissionCategory]);
|
||||
|
||||
const handlePermissionChange = (val: Permission) => {
|
||||
val === Permission.Custom ? setIsCustom.on() : setIsCustom.off();
|
||||
if (val === Permission.Custom) setIsCustom.on();
|
||||
else setIsCustom.off();
|
||||
|
||||
switch (val) {
|
||||
case Permission.NoAccess:
|
||||
setValue("permissions.workspace", { read: false, create: false }, { shouldDirty: true });
|
||||
|
||||
Reference in New Issue
Block a user