Update LDAP permissioning, styling of org auth section

This commit is contained in:
Tuan Dang
2024-02-27 11:36:35 -08:00
parent a04a9a1bd3
commit 3641875b24
8 changed files with 59 additions and 70 deletions

View File

@ -61,7 +61,7 @@ export const ldapConfigServiceFactory = ({
caCert
}: TCreateLdapCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Ldap);
const plan = await licenseService.getPlan(orgId);
if (!plan.ldap)
@ -154,7 +154,7 @@ export const ldapConfigServiceFactory = ({
caCert
}: TUpdateLdapCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Ldap);
const plan = await licenseService.getPlan(orgId);
if (!plan.ldap)
@ -274,7 +274,7 @@ export const ldapConfigServiceFactory = ({
const getLdapCfgWithPermissionCheck = async ({ actor, actorId, orgId, actorOrgId }: TOrgPermission) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Ldap);
return getLdapCfg({
orgId
});

View File

@ -17,6 +17,7 @@ export enum OrgPermissionSubjects {
IncidentAccount = "incident-contact",
Sso = "sso",
Scim = "scim",
Ldap = "ldap",
Billing = "billing",
SecretScanning = "secret-scanning",
Identity = "identity"
@ -31,6 +32,7 @@ export type OrgPermissionSet =
| [OrgPermissionActions, OrgPermissionSubjects.IncidentAccount]
| [OrgPermissionActions, OrgPermissionSubjects.Sso]
| [OrgPermissionActions, OrgPermissionSubjects.Scim]
| [OrgPermissionActions, OrgPermissionSubjects.Ldap]
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
| [OrgPermissionActions, OrgPermissionSubjects.Billing]
| [OrgPermissionActions, OrgPermissionSubjects.Identity];
@ -76,6 +78,11 @@ const buildAdminPermission = () => {
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Scim);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Scim);
can(OrgPermissionActions.Read, OrgPermissionSubjects.Ldap);
can(OrgPermissionActions.Create, OrgPermissionSubjects.Ldap);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Ldap);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Ldap);
can(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
can(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);

View File

@ -15,6 +15,7 @@ export enum OrgPermissionSubjects {
IncidentAccount = "incident-contact",
Scim = "scim",
Sso = "sso",
Ldap = "ldap",
Billing = "billing",
SecretScanning = "secret-scanning",
Identity = "identity"
@ -29,6 +30,7 @@ export type OrgPermissionSet =
| [OrgPermissionActions, OrgPermissionSubjects.IncidentAccount]
| [OrgPermissionActions, OrgPermissionSubjects.Scim]
| [OrgPermissionActions, OrgPermissionSubjects.Sso]
| [OrgPermissionActions, OrgPermissionSubjects.Ldap]
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
| [OrgPermissionActions, OrgPermissionSubjects.Billing]
| [OrgPermissionActions, OrgPermissionSubjects.Identity];

View File

@ -82,6 +82,12 @@ const SIMPLE_PERMISSION_OPTIONS = [
icon: faSignIn,
formName: "sso"
},
{
title: "LDAP",
subtitle: "Define organization level LDAP requirements",
icon: faSignIn,
formName: "ldap"
},
{
title: "SCIM",
subtitle: "Define organization level SCIM requirements",

View File

@ -35,6 +35,7 @@ export const formSchema = z.object({
"secret-scanning": generalPermissionSchema,
sso: generalPermissionSchema,
scim: generalPermissionSchema,
ldap: generalPermissionSchema,
billing: generalPermissionSchema,
identity: generalPermissionSchema
})

View File

@ -3,11 +3,16 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { OrgPermissionCan } from "@app/components/permissions";
import { Button, Switch } from "@app/components/v2";
import {
Button,
Switch,
UpgradePlanModal
} from "@app/components/v2";
import {
OrgPermissionActions,
OrgPermissionSubjects,
useOrganization,
useSubscription
} from "@app/context";
import {
useCreateLDAPConfig,
@ -20,18 +25,24 @@ import { LDAPModal } from "./LDAPModal";
export const OrgLDAPSection = (): JSX.Element => {
const { currentOrg } = useOrganization();
const { subscription } = useSubscription();
const { createNotification } = useNotificationContext();
const { data, isLoading } = useGetLDAPConfig(currentOrg?.id ?? "");
const { mutateAsync } = useUpdateLDAPConfig();
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
"addLDAP"
"addLDAP",
"upgradePlan"
] as const);
const { mutateAsync: createMutateAsync } = useCreateLDAPConfig();
const handleSamlSSOToggle = async (value: boolean) => { // TODO: rename to LDAP toggle
const handleLDAPToggle = async (value: boolean) => {
try {
if (!currentOrg?.id) return;
if (!subscription?.ldap) {
handlePopUpOpen("upgradePlan");
return;
}
await mutateAsync({
organizationId: currentOrg?.id,
@ -53,7 +64,7 @@ export const OrgLDAPSection = (): JSX.Element => {
const addLDAPBtnClick = async () => {
try {
if (currentOrg) {
if (subscription?.ldap && currentOrg) {
if (!data) {
// case: LDAP is not configured
// -> initialize empty LDAP configuration
@ -68,6 +79,8 @@ export const OrgLDAPSection = (): JSX.Element => {
}
handlePopUpOpen("addLDAP");
} else {
handlePopUpOpen("upgradePlan");
}
} catch (err) {
console.error(err);
@ -77,9 +90,9 @@ export const OrgLDAPSection = (): JSX.Element => {
return (
<div className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600">
<div className="flex items-center mb-8">
<h2 className="text-xl font-semibold flex-1 text-white">LDAP Configuration</h2>
<h2 className="text-xl font-semibold flex-1 text-white">LDAP</h2>
{!isLoading && (
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Sso}>
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Ldap}>
{(isAllowed) => (
<Button
onClick={addLDAPBtnClick}
@ -87,7 +100,7 @@ export const OrgLDAPSection = (): JSX.Element => {
isDisabled={!isAllowed}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
>
{data ? "Update LDAP" : "Set up LDAP"}
Configure
</Button>
)}
</OrgPermissionCan>
@ -95,43 +108,30 @@ export const OrgLDAPSection = (): JSX.Element => {
</div>
{data && (
<div className="mb-4">
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Ldap}>
{(isAllowed) => (
<Switch
id="enable-saml-sso"
onCheckedChange={(value) => handleSamlSSOToggle(value)}
onCheckedChange={(value) => handleLDAPToggle(value)}
isChecked={data ? data.isActive : false}
isDisabled={!isAllowed}
>
Enable LDAP
Enable
</Switch>
)}
</OrgPermissionCan>
</div>
)}
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">URL</h3>
<p className="text-gray-400 text-md">{data && data.url !== "" ? data.url : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Bind DN</h3>
<p className="text-gray-400 text-md">{data && data.bindDN !== "" ? data.bindDN : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Bind Pass</h3>
<p className="text-gray-400 text-md">
{data && data.bindPass !== "" ? "*".repeat(data.bindPass.length) : "-"}
</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Search Base / User DN</h3>
<p className="text-gray-400 text-md">{data && data.searchBase !== "" ? data.searchBase : "-"}</p>
</div>
<LDAPModal
popUp={popUp}
handlePopUpClose={handlePopUpClose}
handlePopUpToggle={handlePopUpToggle}
/>
<UpgradePlanModal
isOpen={popUp.upgradePlan.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
text="You can use LDAP authentication if you switch to Infisical's Enterprise plan."
/>
</div>
);
};

View File

@ -66,7 +66,7 @@ export const OrgScimSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-8 flex items-center">
<h2 className="flex-1 text-xl font-semibold text-white">SCIM Configuration</h2>
<h2 className="flex-1 text-xl font-semibold text-white">SCIM</h2>
<OrgPermissionCan I={OrgPermissionActions.Read} a={OrgPermissionSubjects.Scim}>
{(isAllowed) => (
<Button
@ -75,7 +75,7 @@ export const OrgScimSection = () => {
isDisabled={!isAllowed}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
>
Manage SCIM Tokens
Configure
</Button>
)}
</OrgPermissionCan>
@ -94,7 +94,7 @@ export const OrgScimSection = () => {
isChecked={currentOrg?.scimEnabled ?? false}
isDisabled={!isAllowed}
>
Enable SCIM Provisioning
Enable
</Switch>
)}
</OrgPermissionCan>

View File

@ -1,6 +1,5 @@
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from "date-fns";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { OrgPermissionCan } from "@app/components/permissions";
@ -16,12 +15,6 @@ import { usePopUp } from "@app/hooks/usePopUp";
import { SSOModal } from "./SSOModal";
const ssoAuthProviderMap: { [key: string]: string } = {
"okta-saml": "Okta SAML",
"azure-saml": "Azure SAML",
"jumpcloud-saml": "JumpCloud SAML"
};
export const OrgSSOSection = (): JSX.Element => {
const { currentOrg } = useOrganization();
const { subscription } = useSubscription();
@ -38,6 +31,11 @@ export const OrgSSOSection = (): JSX.Element => {
const handleSamlSSOToggle = async (value: boolean) => {
try {
if (!currentOrg?.id) return;
if (!subscription?.samlSSO) {
handlePopUpOpen("upgradePlan");
return;
}
await mutateAsync({
organizationId: currentOrg?.id,
@ -85,7 +83,7 @@ export const OrgSSOSection = (): JSX.Element => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-8 flex items-center">
<h2 className="flex-1 text-xl font-semibold text-white">SAML SSO Configuration</h2>
<h2 className="flex-1 text-xl font-semibold text-white">SAML</h2>
{!isLoading && (
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Sso}>
{(isAllowed) => (
@ -95,13 +93,13 @@ export const OrgSSOSection = (): JSX.Element => {
isDisabled={!isAllowed}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
>
{data ? "Update SAML SSO" : "Set up SAML SSO"}
Configure
</Button>
)}
</OrgPermissionCan>
)}
</div>
{data && (
{/* {data && ( */}
<div className="mb-4">
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
{(isAllowed) => (
@ -111,36 +109,11 @@ export const OrgSSOSection = (): JSX.Element => {
isChecked={data ? data.isActive : false}
isDisabled={!isAllowed}
>
Enable SAML SSO
Enable
</Switch>
)}
</OrgPermissionCan>
</div>
)}
<div className="mb-4">
<h3 className="text-sm text-mineshaft-400">SSO identifier</h3>
<p className="text-md text-gray-400">{data && data.id !== "" ? data.id : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-sm text-mineshaft-400">Type</h3>
<p className="text-md text-gray-400">
{data && data.authProvider !== "" ? ssoAuthProviderMap[data.authProvider] : "-"}
</p>
</div>
<div className="mb-4">
<h3 className="text-sm text-mineshaft-400">Entrypoint</h3>
<p className="text-md text-gray-400">
{data && data.entryPoint !== "" ? data.entryPoint : "-"}
</p>
</div>
<div className="mb-4">
<h3 className="text-sm text-mineshaft-400">Issuer</h3>
<p className="text-md text-gray-400">{data && data.issuer !== "" ? data.issuer : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-sm text-mineshaft-400">Last Logged In</h3>
<p className="text-md text-gray-400">{data?.lastUsed ? format(new Date(data?.lastUsed), "yyyy-MM-dd HH:mm:ss") : "-"}</p>
</div>
<SSOModal
popUp={popUp}
handlePopUpClose={handlePopUpClose}