From 7630fae929b43c1c87e514e1f762db1873c71c5e Mon Sep 17 00:00:00 2001 From: guillaume-peoch-sonarsource Date: Thu, 20 Apr 2023 12:00:37 +0200 Subject: [PATCH] SONAR-19055 SAML Group config is no longer available for Community and Developer editions --- .../authentication/SamlAuthentication.tsx | 233 ++++++++++-------- .../__tests__/Authentication-it.tsx | 13 + .../main/js/components/controls/RadioCard.css | 4 - .../main/js/components/controls/RadioCard.tsx | 3 +- .../resources/org/sonar/l10n/core.properties | 1 + 5 files changed, 140 insertions(+), 114 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/SamlAuthentication.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/SamlAuthentication.tsx index 9492328cbd4..e6e123b5f39 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/authentication/SamlAuthentication.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/SamlAuthentication.tsx @@ -28,9 +28,9 @@ import { } from '../../../../api/settings'; import DocLink from '../../../../components/common/DocLink'; import Link from '../../../../components/common/Link'; -import { Button, ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons'; import ConfirmModal from '../../../../components/controls/ConfirmModal'; import RadioCard from '../../../../components/controls/RadioCard'; +import { Button, ResetButtonLink, SubmitButton } from '../../../../components/controls/buttons'; import CheckIcon from '../../../../components/icons/CheckIcon'; import DeleteIcon from '../../../../components/icons/DeleteIcon'; import EditIcon from '../../../../components/icons/EditIcon'; @@ -40,8 +40,8 @@ import { getBaseUrl } from '../../../../helpers/system'; import { ExtendedSettingDefinition } from '../../../../types/settings'; import { getPropertyName } from '../../utils'; import DefinitionDescription from '../DefinitionDescription'; -import useSamlConfiguration, { SAML_ENABLED_FIELD } from './hook/useLoadSamlSettings'; import SamlConfigurationForm from './SamlConfigurationForm'; +import useSamlConfiguration, { SAML_ENABLED_FIELD } from './hook/useLoadSamlSettings'; interface SamlAuthenticationProps { definitions: ExtendedSettingDefinition[]; @@ -177,49 +177,36 @@ export default function SamlAuthentication(props: SamlAuthenticationProps) { - {hasScim && ( -
-
{ - e.preventDefault(); - if (newScimStatus !== scimStatus) { - setShowConfirmProvisioningModal(true); - } else { - handleSaveGroup(); - } - }} - > -
- - {samlEnabled ? ( -
- setNewScimStatus(true)} - > -

- {translate( - 'settings.authentication.saml.form.provisioning_with_scim.sub' - )} -

-

- {translate( - 'settings.authentication.saml.form.provisioning_with_scim.description' - )} -

+
+ { + e.preventDefault(); + if (newScimStatus !== scimStatus) { + setShowConfirmProvisioningModal(true); + } else { + handleSaveGroup(); + } + }} + > +
+ + {samlEnabled ? ( +
+ setNewScimStatus(true)} + disabled={!hasScim} + > + {!hasScim ? (

-
- setNewScimStatus(false)} - > -

- {translate('settings.authentication.saml.form.provisioning_at_login.sub')} -

- {groupValue && ( -
- -
- setNewGroupSetting(e.currentTarget.value)} - type="text" - value={String(groupValue.newValue ?? groupValue.value ?? '')} - aria-label={getPropertyName(groupValue.definition)} - /> -
-
- )} -
-
- ) : ( - - {translate('settings.authentication.saml.enable_first')} - - )} -
- {samlEnabled && ( - <> - {translate('save')} - { - setNewScimStatus(undefined); - setNewGroupSetting(); - }} - disabled={!hasScimConfigChange} + ) : ( + <> +

+ {translate( + 'settings.authentication.saml.form.provisioning_with_scim.sub' + )} +

+

+ {translate( + 'settings.authentication.saml.form.provisioning_with_scim.description' + )} +

+

+ + {translate('documentation')} + + ), + }} + /> +

+ + )} + + setNewScimStatus(false)} > - {translate('cancel')} -
- +

+ {translate('settings.authentication.saml.form.provisioning_at_login.sub')} +

+ {groupValue && ( +
+ +
+ setNewGroupSetting(e.currentTarget.value)} + type="text" + value={String(groupValue.newValue ?? groupValue.value ?? '')} + aria-label={getPropertyName(groupValue.definition)} + /> +
+
+ )} + +
+ ) : ( + + {translate('settings.authentication.saml.enable_first')} + )} - {showConfirmProvisioningModal && ( - handleConfirmChangeProvisioning()} - header={translate( - 'settings.authentication.saml.confirm', - newScimStatus ? 'scim' : 'jit' - )} - onClose={() => setShowConfirmProvisioningModal(false)} - isDestructive={!newScimStatus} - confirmButtonText={translate('yes')} +
+ {samlEnabled && ( + <> + {translate('save')} + { + setNewScimStatus(undefined); + setNewGroupSetting(); + }} + disabled={!hasScimConfigChange} > - {translate( - 'settings.authentication.saml.confirm', - newScimStatus ? 'scim' : 'jit', - 'description' - )} - - )} - -
- )} + {translate('cancel')} + + + )} + {showConfirmProvisioningModal && ( + handleConfirmChangeProvisioning()} + header={translate( + 'settings.authentication.saml.confirm', + newScimStatus ? 'scim' : 'jit' + )} + onClose={() => setShowConfirmProvisioningModal(false)} + isDestructive={!newScimStatus} + confirmButtonText={translate('yes')} + > + {translate( + 'settings.authentication.saml.confirm', + newScimStatus ? 'scim' : 'jit', + 'description' + )} + + )} + + )} {showEditModal && ( diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-it.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-it.tsx index 0e597dc7bb3..b8136d361e4 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-it.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-it.tsx @@ -189,6 +189,19 @@ describe('SAML tab', () => { expect(await saml.scimProvisioningButton.find()).toBeChecked(); expect(await saml.saveScim.find()).toBeDisabled(); }); + + it('should not allow edtion below Enterprise to select SCIM provisioning', async () => { + const { saml } = ui; + const user = userEvent.setup(); + + renderAuthentication(); + + await saml.createConfiguration(user); + await user.click(await saml.enableConfigButton.find()); + + expect(await saml.jitProvisioningButton.find()).toBeChecked(); + expect(saml.scimProvisioningButton.get()).toHaveAttribute('aria-disabled', 'true'); + }); }); function renderAuthentication(features: Feature[] = []) { diff --git a/server/sonar-web/src/main/js/components/controls/RadioCard.css b/server/sonar-web/src/main/js/components/controls/RadioCard.css index 80bba794114..4f583626f53 100644 --- a/server/sonar-web/src/main/js/components/controls/RadioCard.css +++ b/server/sonar-web/src/main/js/components/controls/RadioCard.css @@ -49,10 +49,6 @@ margin-right: 0; } -.radio-card:focus { - outline: none; -} - .radio-card-vertical { width: 100%; min-height: auto; diff --git a/server/sonar-web/src/main/js/components/controls/RadioCard.tsx b/server/sonar-web/src/main/js/components/controls/RadioCard.tsx index 1e0a7ee30ba..c7241217014 100644 --- a/server/sonar-web/src/main/js/components/controls/RadioCard.tsx +++ b/server/sonar-web/src/main/js/components/controls/RadioCard.tsx @@ -71,7 +71,8 @@ export default function RadioCard(props: Props) { onClick={isActionable && !disabled ? onClick : undefined} role="radio" aria-label={label} - tabIndex={0} + aria-disabled={disabled} + tabIndex={disabled ? -1 : 0} >

diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index aae9c18cab7..87e48c71bf9 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1369,6 +1369,7 @@ settings.authentication.saml.form.provisioning_with_scim=Automatic user and grou settings.authentication.saml.form.provisioning_with_scim.sub=Preferred option when using a supported identity provider. settings.authentication.saml.form.provisioning_with_scim.description=Users and groups are automatically provisioned from your identity provider using the SCIM protocol. Once activated, managed users and groups can only be modified from your identity provider. Existing local users and groups will be kept. settings.authentication.saml.form.provisioning_with_scim.description.doc=For a list of supported providers and more details on automatic provisioning, see {documentation}. +settings.authentication.saml.form.provisioning.disabled=Your current edition does not support provisioning with SCIM. See the {documentation} for more information. settings.authentication.saml.enable_first=Enable your SAML configuration to benefit from automatic user provisioning options. settings.pr_decoration.binding.category=DevOps Platform Integration settings.pr_decoration.binding.no_bindings=A system administrator needs to enable this feature in the global settings. -- 2.39.5