From a6d7d32156faa3f63bc1a85d994392793a2d58b5 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 12 Mar 2024 09:37:28 -0700 Subject: [PATCH 1/2] Draft revamp org auth tab --- .../services/license/__mocks__/licence-fns.ts | 6 +- .../src/ee/services/license/licence-fns.ts | 6 +- .../src/ee/services/license/license-types.ts | 6 +- .../OrgSettingsPage/OrgSettingsPage.tsx | 2 +- .../components/OrgAuthTab/OrgAuthTab.tsx | 2 +- .../OrgAuthTab/OrgGeneralAuthSection.tsx | 49 +++++++--- .../components/OrgAuthTab/OrgLDAPSection.tsx | 76 +++++++-------- .../components/OrgAuthTab/OrgSCIMSection.tsx | 60 ++++++------ .../components/OrgAuthTab/OrgSSOSection.tsx | 95 ++++++++++--------- .../components/OrgTabGroup/OrgTabGroup.tsx | 2 +- 10 files changed, 165 insertions(+), 139 deletions(-) diff --git a/backend/src/ee/services/license/__mocks__/licence-fns.ts b/backend/src/ee/services/license/__mocks__/licence-fns.ts index 8f52939c5..0a466c57c 100644 --- a/backend/src/ee/services/license/__mocks__/licence-fns.ts +++ b/backend/src/ee/services/license/__mocks__/licence-fns.ts @@ -17,9 +17,9 @@ export const getDefaultOnPremFeatures = () => { customAlerts: false, auditLogs: false, auditLogsRetentionDays: 0, - samlSSO: false, - scim: false, - ldap: false, + samlSSO: true, + scim: true, + ldap: true, status: null, trial_end: null, has_used_trial: true, diff --git a/backend/src/ee/services/license/licence-fns.ts b/backend/src/ee/services/license/licence-fns.ts index 8dca96737..98f8c5f24 100644 --- a/backend/src/ee/services/license/licence-fns.ts +++ b/backend/src/ee/services/license/licence-fns.ts @@ -23,9 +23,9 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ customAlerts: false, auditLogs: false, auditLogsRetentionDays: 0, - samlSSO: false, - scim: false, - ldap: false, + samlSSO: true, + scim: true, + ldap: true, status: null, trial_end: null, has_used_trial: true, diff --git a/backend/src/ee/services/license/license-types.ts b/backend/src/ee/services/license/license-types.ts index 80f422380..830cacf99 100644 --- a/backend/src/ee/services/license/license-types.ts +++ b/backend/src/ee/services/license/license-types.ts @@ -24,9 +24,9 @@ export type TFeatureSet = { customAlerts: false; auditLogs: false; auditLogsRetentionDays: 0; - samlSSO: false; - scim: false; - ldap: false; + samlSSO: true; + scim: true; + ldap: true; status: null; trial_end: null; has_used_trial: true; diff --git a/frontend/src/views/Settings/OrgSettingsPage/OrgSettingsPage.tsx b/frontend/src/views/Settings/OrgSettingsPage/OrgSettingsPage.tsx index 29e4eaff5..8c9a64222 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/OrgSettingsPage.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/OrgSettingsPage.tsx @@ -7,7 +7,7 @@ export const OrgSettingsPage = () => { return (
-
+

{t("settings.org.title")}

diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx index c4b03bae6..322798d16 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx @@ -9,7 +9,7 @@ import { OrgSSOSection } from "./OrgSSOSection"; export const OrgAuthTab = withPermission( () => { return ( -
+
diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx index ef81a6cab..57de34052 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgGeneralAuthSection.tsx @@ -59,25 +59,44 @@ export const OrgGeneralAuthSection = () => { } return ( -
-

Settings

- - {(isAllowed) => ( - handleEnforceOrgAuthToggle(value)} - isChecked={currentOrg?.authEnforced ?? false} - isDisabled={!isAllowed} - > - Enforce SAML SSO - - )} - + <> +
+
+

Allow users to send invites

+ + {(isAllowed) => ( + handleEnforceOrgAuthToggle(value)} + isChecked={currentOrg?.authEnforced ?? false} + isDisabled={!isAllowed} + /> + )} + +
+

Allow members to invite new users to this organization

+
+
+
+

Enforce SAML SSO

+ + {(isAllowed) => ( + handleEnforceOrgAuthToggle(value)} + isChecked={currentOrg?.authEnforced ?? false} + isDisabled={!isAllowed} + /> + )} + +
+

Enforce members to authenticate via SAML to access this organization

+
handlePopUpToggle("upgradePlan", isOpen)} text="You can enforce SAML SSO if you switch to Infisical's Pro plan." /> -
+ ); } \ No newline at end of file diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx index c1ac93db8..b7f957698 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx @@ -1,6 +1,3 @@ -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { OrgPermissionCan } from "@app/components/permissions"; import { @@ -27,7 +24,7 @@ export const OrgLDAPSection = (): JSX.Element => { const { currentOrg } = useOrganization(); const { subscription } = useSubscription(); const { createNotification } = useNotificationContext(); - const { data, isLoading } = useGetLDAPConfig(currentOrg?.id ?? ""); + const { data } = useGetLDAPConfig(currentOrg?.id ?? ""); const { mutateAsync } = useUpdateLDAPConfig(); const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ "addLDAP", @@ -88,50 +85,53 @@ export const OrgLDAPSection = (): JSX.Element => { }; return ( -
-
-

LDAP

- {!isLoading && ( + <> +
+
+
+

LDAP

{(isAllowed) => ( )} - )} -
- {data && ( -
- - {(isAllowed) => ( - handleLDAPToggle(value)} - isChecked={data ? data.isActive : false} - isDisabled={!isAllowed} - > - Enable - - )} -
- )} - - handlePopUpToggle("upgradePlan", isOpen)} - text="You can use LDAP authentication if you switch to Infisical's Enterprise plan." - /> -
+

Manage LDAP authentication configuration

+
+
+
+

Enable LDAP

+ + {(isAllowed) => ( + handleLDAPToggle(value)} + isChecked={data ? data.isActive : false} + isDisabled={!isAllowed} + > + Enable + + )} + +
+

Allow members to authenticate into Infisical with LDAP

+
+ + handlePopUpToggle("upgradePlan", isOpen)} + text="You can use LDAP authentication if you switch to Infisical's Enterprise plan." + /> + ); }; \ No newline at end of file diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx index bb1f4ff94..f599bc07a 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSCIMSection.tsx @@ -1,6 +1,3 @@ -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { OrgPermissionCan } from "@app/components/permissions"; import { @@ -64,40 +61,47 @@ export const OrgScimSection = () => { } return ( -
-
-

SCIM

- + <> +
+
+
+

SCIM

+ {(isAllowed) => ( )} +
+

Manage SCIM configuration

+
+
+
+

Enable SCIM

+ + {(isAllowed) => ( + { + if (subscription?.scim) { + handleEnableSCIMToggle(value) + } else { + handlePopUpOpen("upgradePlan"); + } + }} + isChecked={currentOrg?.scimEnabled ?? false} + isDisabled={!isAllowed} + /> + )} + +
+

Allow member provisioning/deprovisioning with SCIM

- - {(isAllowed) => ( - { - if (subscription?.scim) { - handleEnableSCIMToggle(value) - } else { - handlePopUpOpen("upgradePlan"); - } - }} - isChecked={currentOrg?.scimEnabled ?? false} - isDisabled={!isAllowed} - > - Enable - - )} - { onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)} text="You can use SCIM Provisioning if you switch to Infisical's Enterprise plan." /> -
+ ); } \ No newline at end of file diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx index 9f03bdc7f..240a1db2e 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx @@ -1,6 +1,3 @@ -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { OrgPermissionCan } from "@app/components/permissions"; import { Button, Switch, UpgradePlanModal } from "@app/components/v2"; @@ -81,49 +78,55 @@ export const OrgSSOSection = (): JSX.Element => { }; return ( -
-
-

SAML

- {!isLoading && ( - - {(isAllowed) => ( - - )} - - )} -
- {/* {data && ( */} -
- - {(isAllowed) => ( - handleSamlSSOToggle(value)} - isChecked={data ? data.isActive : false} - isDisabled={!isAllowed} - > - Enable - - )} - + <> +
+
+
+

SAML

+ {!isLoading && ( + + {(isAllowed) => ( + + )} + + )}
- - handlePopUpToggle("upgradePlan", isOpen)} - text="You can use SAML SSO if you switch to Infisical's Pro plan." - /> -
+

Manage SAML authentication configuration

+
+
+
+

Enable SAML

+ {!isLoading && ( + + {(isAllowed) => ( + handleSamlSSOToggle(value)} + isChecked={data ? data.isActive : false} + isDisabled={!isAllowed} + /> + )} + + )} +
+

Allow members to authenticate into Infisical with SAML

+
+ + handlePopUpToggle("upgradePlan", isOpen)} + text="You can use SAML SSO if you switch to Infisical's Pro plan." + /> + ); }; diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgTabGroup/OrgTabGroup.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgTabGroup/OrgTabGroup.tsx index cacbf1b59..d4c01d0ef 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgTabGroup/OrgTabGroup.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgTabGroup/OrgTabGroup.tsx @@ -6,7 +6,7 @@ import { OrgGeneralTab } from "../OrgGeneralTab"; const tabs = [ { name: "General", key: "tab-org-general" }, - { name: "Authentication", key: "tab-org-auth" } + { name: "Security", key: "tab-org-security" } ]; export const OrgTabGroup = () => { return ( From 2ca03abec27226d2f51969ad63d631652b444766 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 12 Mar 2024 16:18:17 -0700 Subject: [PATCH 2/2] Update org settings > general tab ui --- backend/src/ee/routes/v1/ldap-router.ts | 20 +++-- .../ldap-config/ldap-config-service.ts | 6 +- .../services/license/__mocks__/licence-fns.ts | 6 +- .../src/ee/services/license/licence-fns.ts | 6 +- .../src/ee/services/license/license-types.ts | 6 +- .../saml-config/saml-config-service.ts | 7 +- docs/mint.json | 8 -- .../components/OrgAuthTab/LDAPModal.tsx | 10 +-- .../OrgAuthTab/OrgGeneralAuthSection.tsx | 4 +- .../components/OrgAuthTab/OrgLDAPSection.tsx | 36 ++++---- .../components/OrgAuthTab/SSOModal.tsx | 20 ++--- .../OrgDeleteSection/OrgDeleteSection.tsx | 29 +++--- .../OrgGeneralTab/OrgGeneralTab.tsx | 5 +- .../OrgIncidentContactsSection.tsx | 21 +++-- .../OrgNameChangeSection.tsx | 52 +++++++---- .../OrgSlugChangeSection.tsx | 88 ------------------- .../components/OrgSlugChangeSection/index.tsx | 1 - 17 files changed, 129 insertions(+), 196 deletions(-) delete mode 100644 frontend/src/views/Settings/OrgSettingsPage/components/OrgSlugChangeSection/OrgSlugChangeSection.tsx delete mode 100644 frontend/src/views/Settings/OrgSettingsPage/components/OrgSlugChangeSection/index.tsx diff --git a/backend/src/ee/routes/v1/ldap-router.ts b/backend/src/ee/routes/v1/ldap-router.ts index 97527e783..de472ff29 100644 --- a/backend/src/ee/routes/v1/ldap-router.ts +++ b/backend/src/ee/routes/v1/ldap-router.ts @@ -164,15 +164,17 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => { method: "PATCH", onRequest: verifyAuth([AuthMode.JWT]), schema: { - body: z.object({ - organizationId: z.string().trim(), - isActive: z.boolean().optional(), - url: z.string().trim().optional(), - bindDN: z.string().trim().optional(), - bindPass: z.string().trim().optional(), - searchBase: z.string().trim().optional(), - caCert: z.string().trim().optional() - }), + body: z + .object({ + isActive: z.boolean(), + url: z.string().trim(), + bindDN: z.string().trim(), + bindPass: z.string().trim(), + searchBase: z.string().trim(), + caCert: z.string().trim() + }) + .partial() + .merge(z.object({ organizationId: z.string() })), response: { 200: LdapConfigsSchema } diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts index 37e1fb6f8..e9ae0264a 100644 --- a/backend/src/ee/services/ldap-config/ldap-config-service.ts +++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts @@ -180,21 +180,21 @@ export const ldapConfigServiceFactory = ({ keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding }); - if (bindDN) { + if (bindDN !== undefined) { const { ciphertext: encryptedBindDN, iv: bindDNIV, tag: bindDNTag } = encryptSymmetric(bindDN, key); updateQuery.encryptedBindDN = encryptedBindDN; updateQuery.bindDNIV = bindDNIV; updateQuery.bindDNTag = bindDNTag; } - if (bindPass) { + if (bindPass !== undefined) { const { ciphertext: encryptedBindPass, iv: bindPassIV, tag: bindPassTag } = encryptSymmetric(bindPass, key); updateQuery.encryptedBindPass = encryptedBindPass; updateQuery.bindPassIV = bindPassIV; updateQuery.bindPassTag = bindPassTag; } - if (caCert) { + if (caCert !== undefined) { const { ciphertext: encryptedCACert, iv: caCertIV, tag: caCertTag } = encryptSymmetric(caCert, key); updateQuery.encryptedCACert = encryptedCACert; updateQuery.caCertIV = caCertIV; diff --git a/backend/src/ee/services/license/__mocks__/licence-fns.ts b/backend/src/ee/services/license/__mocks__/licence-fns.ts index 0a466c57c..8f52939c5 100644 --- a/backend/src/ee/services/license/__mocks__/licence-fns.ts +++ b/backend/src/ee/services/license/__mocks__/licence-fns.ts @@ -17,9 +17,9 @@ export const getDefaultOnPremFeatures = () => { customAlerts: false, auditLogs: false, auditLogsRetentionDays: 0, - samlSSO: true, - scim: true, - ldap: true, + samlSSO: false, + scim: false, + ldap: false, status: null, trial_end: null, has_used_trial: true, diff --git a/backend/src/ee/services/license/licence-fns.ts b/backend/src/ee/services/license/licence-fns.ts index 98f8c5f24..8dca96737 100644 --- a/backend/src/ee/services/license/licence-fns.ts +++ b/backend/src/ee/services/license/licence-fns.ts @@ -23,9 +23,9 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ customAlerts: false, auditLogs: false, auditLogsRetentionDays: 0, - samlSSO: true, - scim: true, - ldap: true, + samlSSO: false, + scim: false, + ldap: false, status: null, trial_end: null, has_used_trial: true, diff --git a/backend/src/ee/services/license/license-types.ts b/backend/src/ee/services/license/license-types.ts index 830cacf99..80f422380 100644 --- a/backend/src/ee/services/license/license-types.ts +++ b/backend/src/ee/services/license/license-types.ts @@ -24,9 +24,9 @@ export type TFeatureSet = { customAlerts: false; auditLogs: false; auditLogsRetentionDays: 0; - samlSSO: true; - scim: true; - ldap: true; + samlSSO: false; + scim: false; + ldap: false; status: null; trial_end: null; has_used_trial: true; diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts index d944803f8..e9249d4aa 100644 --- a/backend/src/ee/services/saml-config/saml-config-service.ts +++ b/backend/src/ee/services/saml-config/saml-config-service.ts @@ -172,7 +172,7 @@ export const samlConfigServiceFactory = ({ keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding }); - if (entryPoint) { + if (entryPoint !== undefined) { const { ciphertext: encryptedEntryPoint, iv: entryPointIV, @@ -182,18 +182,19 @@ export const samlConfigServiceFactory = ({ updateQuery.entryPointIV = entryPointIV; updateQuery.entryPointTag = entryPointTag; } - if (issuer) { + if (issuer !== undefined) { const { ciphertext: encryptedIssuer, iv: issuerIV, tag: issuerTag } = encryptSymmetric(issuer, key); updateQuery.encryptedIssuer = encryptedIssuer; updateQuery.issuerIV = issuerIV; updateQuery.issuerTag = issuerTag; } - if (cert) { + if (cert !== undefined) { const { ciphertext: encryptedCert, iv: certIV, tag: certTag } = encryptSymmetric(cert, key); updateQuery.encryptedCert = encryptedCert; updateQuery.certIV = certIV; updateQuery.certTag = certTag; } + const [ssoConfig] = await samlConfigDAL.update({ orgId }, updateQuery); await orgDAL.updateById(orgId, { authEnforced: false, scimEnabled: false }); diff --git a/docs/mint.json b/docs/mint.json index 5da117548..cb6ce08ac 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -158,14 +158,6 @@ "documentation/platform/ldap/general" ] }, - { - "group": "LDAP", - "pages": [ - "documentation/platform/ldap/overview", - "documentation/platform/ldap/jumpcloud", - "documentation/platform/ldap/general" - ] - }, { "group": "SCIM", "pages": [ diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/LDAPModal.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/LDAPModal.tsx index 37bc87e2c..c0e7cf772 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/LDAPModal.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/LDAPModal.tsx @@ -21,10 +21,10 @@ import { import { UsePopUpState } from "@app/hooks/usePopUp"; const LDAPFormSchema = z.object({ - url: z.string().min(1, "URL is requiredx"), - bindDN: z.string().min(1, "Bind DN is requiredx"), - bindPass: z.string().min(1, "Bind Pass is required"), - searchBase: z.string().min(1, "Search Base is required"), + url: z.string().default(""), + bindDN: z.string().default(""), + bindPass: z.string().default(""), + searchBase: z.string().default(""), caCert: z.string().optional() }); @@ -122,7 +122,7 @@ export const LDAPModal = ({ reset(); }} > - +
{ return ( <> -
+ {/*

Allow users to send invites

@@ -75,7 +75,7 @@ export const OrgGeneralAuthSection = () => {

Allow members to invite new users to this organization

-
+
*/}

Enforce SAML SSO

diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx index b7f957698..48dfcd271 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgLDAPSection.tsx @@ -104,24 +104,26 @@ export const OrgLDAPSection = (): JSX.Element => {

Manage LDAP authentication configuration

-
-
-

Enable LDAP

- - {(isAllowed) => ( - handleLDAPToggle(value)} - isChecked={data ? data.isActive : false} - isDisabled={!isAllowed} - > - Enable - - )} - + {data && ( +
+
+

Enable LDAP

+ + {(isAllowed) => ( + handleLDAPToggle(value)} + isChecked={data ? data.isActive : false} + isDisabled={!isAllowed} + > + Enable + + )} + +
+

Allow members to authenticate into Infisical with LDAP

-

Allow members to authenticate into Infisical with LDAP

-
+ )} ; +export type AddSSOFormData = z.infer; type Props = { popUp: UsePopUpState<["addSSO"]>; @@ -60,7 +60,7 @@ export const SSOModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) defaultValues: { authProvider: AuthProvider.OKTA_SAML }, - resolver: yupResolver(schema) + resolver: zodResolver(schema) }); useEffect(() => { @@ -173,7 +173,7 @@ export const SSOModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) reset(); }} > - + { }; return ( -
-

Danger Zone

- + <> +
+
+

Danger Zone

+ +
{ deleteKey="confirm" onDeleteApproved={handleDeleteOrgSubmit} /> -
+ ); }; diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx index 69f1547b7..e51272ebf 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgGeneralTab/OrgGeneralTab.tsx @@ -3,15 +3,12 @@ import { useOrgPermission } from "@app/context"; import { OrgDeleteSection } from "../OrgDeleteSection"; import { OrgIncidentContactsSection } from "../OrgIncidentContactsSection"; import { OrgNameChangeSection } from "../OrgNameChangeSection"; -import { OrgSlugChangeSection } from "../OrgSlugChangeSection"; export const OrgGeneralTab = () => { const { membership } = useOrgPermission(); - return ( -
+
- {membership && membership.role === "admin" && }
diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx index fbb4987a7..61639f524 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsSection.tsx @@ -18,9 +18,10 @@ export const OrgIncidentContactsSection = () => { const { permission } = useOrgPermission(); return ( -
-
-

{t("section.incident.incident-contacts")}

+ <> +
+
+

{t("section.incident.incident-contacts")}

{(isAllowed) => (
- {permission.can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount) ? ( - - ) : ( - - )} +
+ {permission.can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount) ? ( + + ) : ( + + )} +
-
+ ); }; diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx index 66b45e116..e009ff9b8 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx @@ -10,7 +10,12 @@ import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@a import { useUpdateOrg } from "@app/hooks/api"; const formSchema = yup.object({ - name: yup.string().required().label("Project Name") + name: yup.string().required().label("Organization Name"), + slug: yup + .string() + .matches(/^[a-zA-Z0-9-]+$/, "Name must only contain alphanumeric characters or hyphens") + .required() + .label("Organization Slug") }); type FormData = yup.InferType; @@ -25,40 +30,44 @@ export const OrgNameChangeSection = (): JSX.Element => { useEffect(() => { if (currentOrg) { - reset({ name: currentOrg.name }); + reset({ + name: currentOrg.name, + slug: currentOrg.slug + }); } }, [currentOrg]); - const onFormSubmit = async ({ name }: FormData) => { + const onFormSubmit = async ({ name, slug }: FormData) => { try { if (!currentOrg?.id) return; - if (name === "") return; - await mutateAsync({ orgId: currentOrg?.id, name }); + await mutateAsync({ + orgId: currentOrg?.id, + name, + slug + }); + createNotification({ - text: "Successfully renamed organization", + text: "Successfully updated organization details", type: "success" }); } catch (error) { console.error(error); createNotification({ - text: "Failed to rename organization", + text: "Failed to update organization details", type: "error" }); } }; return ( - -

Organization Name

-
+ +
+

Organization Name

( - + )} @@ -66,6 +75,19 @@ export const OrgNameChangeSection = (): JSX.Element => { name="name" />
+
+

Organization Slug

+ ( + + + + )} + control={control} + name="slug" + /> +
{(isAllowed) => ( - )} - - - ); -} \ No newline at end of file diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgSlugChangeSection/index.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgSlugChangeSection/index.tsx deleted file mode 100644 index a4218cbd3..000000000 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgSlugChangeSection/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { OrgSlugChangeSection } from "./OrgSlugChangeSection"; \ No newline at end of file