diff options
author | guillaume-peoch-sonarsource <guillaume.peoch@sonarsource.com> | 2023-04-20 12:00:37 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-04-26 20:02:45 +0000 |
commit | 7630fae929b43c1c87e514e1f762db1873c71c5e (patch) | |
tree | fa15d0be82c28004ae22fa2405285397da7b2691 | |
parent | c3f33a9594fa676c90113cd15086acb128e15875 (diff) | |
download | sonarqube-7630fae929b43c1c87e514e1f762db1873c71c5e.tar.gz sonarqube-7630fae929b43c1c87e514e1f762db1873c71c5e.zip |
SONAR-19055 SAML Group config is no longer available for Community and Developer editions
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) { </Button> </div> </div> - {hasScim && ( - <div className="spacer-bottom big-padded bordered display-flex-space-between"> - <form - onSubmit={(e) => { - e.preventDefault(); - if (newScimStatus !== scimStatus) { - setShowConfirmProvisioningModal(true); - } else { - handleSaveGroup(); - } - }} - > - <fieldset className="display-flex-column big-spacer-bottom"> - <label className="h5"> - {translate('settings.authentication.saml.form.provisioning')} - </label> - {samlEnabled ? ( - <div className="display-flex-row spacer-top"> - <RadioCard - label={translate( - 'settings.authentication.saml.form.provisioning_with_scim' - )} - title={translate( - 'settings.authentication.saml.form.provisioning_with_scim' - )} - selected={newScimStatus ?? scimStatus} - onClick={() => setNewScimStatus(true)} - > - <p className="spacer-bottom"> - {translate( - 'settings.authentication.saml.form.provisioning_with_scim.sub' - )} - </p> - <p className="spacer-bottom"> - {translate( - 'settings.authentication.saml.form.provisioning_with_scim.description' - )} - </p> + <div className="spacer-bottom big-padded bordered display-flex-space-between"> + <form + onSubmit={(e) => { + e.preventDefault(); + if (newScimStatus !== scimStatus) { + setShowConfirmProvisioningModal(true); + } else { + handleSaveGroup(); + } + }} + > + <fieldset className="display-flex-column big-spacer-bottom"> + <label className="h5"> + {translate('settings.authentication.saml.form.provisioning')} + </label> + {samlEnabled ? ( + <div className="display-flex-row spacer-top"> + <RadioCard + label={translate('settings.authentication.saml.form.provisioning_with_scim')} + title={translate('settings.authentication.saml.form.provisioning_with_scim')} + selected={newScimStatus ?? scimStatus} + onClick={() => setNewScimStatus(true)} + disabled={!hasScim} + > + {!hasScim ? ( <p> <FormattedMessage - id="settings.authentication.saml.form.provisioning_with_scim.description.doc" + id="settings.authentication.saml.form.provisioning.disabled" defaultMessage={translate( - 'settings.authentication.saml.form.provisioning_with_scim.description.doc' + 'settings.authentication.saml.form.provisioning.disabled' )} values={{ documentation: ( @@ -230,76 +217,104 @@ export default function SamlAuthentication(props: SamlAuthenticationProps) { }} /> </p> - </RadioCard> - <RadioCard - label={translate('settings.authentication.saml.form.provisioning_at_login')} - title={translate('settings.authentication.saml.form.provisioning_at_login')} - selected={!(newScimStatus ?? scimStatus)} - onClick={() => setNewScimStatus(false)} - > - <p> - {translate('settings.authentication.saml.form.provisioning_at_login.sub')} - </p> - {groupValue && ( - <div className="settings-definition"> - <DefinitionDescription definition={groupValue.definition} /> - <div className="settings-definition-right"> - <input - id={groupValue.definition.key} - maxLength={4000} - name={groupValue.definition.key} - onChange={(e) => setNewGroupSetting(e.currentTarget.value)} - type="text" - value={String(groupValue.newValue ?? groupValue.value ?? '')} - aria-label={getPropertyName(groupValue.definition)} - /> - </div> - </div> - )} - </RadioCard> - </div> - ) : ( - <Alert className="big-spacer-top" variant="info"> - {translate('settings.authentication.saml.enable_first')} - </Alert> - )} - </fieldset> - {samlEnabled && ( - <> - <SubmitButton disabled={!hasScimConfigChange}>{translate('save')}</SubmitButton> - <ResetButtonLink - className="spacer-left" - onClick={() => { - setNewScimStatus(undefined); - setNewGroupSetting(); - }} - disabled={!hasScimConfigChange} + ) : ( + <> + <p className="spacer-bottom"> + {translate( + 'settings.authentication.saml.form.provisioning_with_scim.sub' + )} + </p> + <p className="spacer-bottom"> + {translate( + 'settings.authentication.saml.form.provisioning_with_scim.description' + )} + </p> + <p> + <FormattedMessage + id="settings.authentication.saml.form.provisioning_with_scim.description.doc" + defaultMessage={translate( + 'settings.authentication.saml.form.provisioning_with_scim.description.doc' + )} + values={{ + documentation: ( + <DocLink to="/instance-administration/authentication/saml/scim/overview"> + {translate('documentation')} + </DocLink> + ), + }} + /> + </p> + </> + )} + </RadioCard> + <RadioCard + label={translate('settings.authentication.saml.form.provisioning_at_login')} + title={translate('settings.authentication.saml.form.provisioning_at_login')} + selected={!(newScimStatus ?? scimStatus)} + onClick={() => setNewScimStatus(false)} > - {translate('cancel')} - </ResetButtonLink> - </> + <p> + {translate('settings.authentication.saml.form.provisioning_at_login.sub')} + </p> + {groupValue && ( + <div className="settings-definition"> + <DefinitionDescription definition={groupValue.definition} /> + <div className="settings-definition-right"> + <input + id={groupValue.definition.key} + maxLength={4000} + name={groupValue.definition.key} + onChange={(e) => setNewGroupSetting(e.currentTarget.value)} + type="text" + value={String(groupValue.newValue ?? groupValue.value ?? '')} + aria-label={getPropertyName(groupValue.definition)} + /> + </div> + </div> + )} + </RadioCard> + </div> + ) : ( + <Alert className="big-spacer-top" variant="info"> + {translate('settings.authentication.saml.enable_first')} + </Alert> )} - {showConfirmProvisioningModal && ( - <ConfirmModal - onConfirm={() => handleConfirmChangeProvisioning()} - header={translate( - 'settings.authentication.saml.confirm', - newScimStatus ? 'scim' : 'jit' - )} - onClose={() => setShowConfirmProvisioningModal(false)} - isDestructive={!newScimStatus} - confirmButtonText={translate('yes')} + </fieldset> + {samlEnabled && ( + <> + <SubmitButton disabled={!hasScimConfigChange}>{translate('save')}</SubmitButton> + <ResetButtonLink + className="spacer-left" + onClick={() => { + setNewScimStatus(undefined); + setNewGroupSetting(); + }} + disabled={!hasScimConfigChange} > - {translate( - 'settings.authentication.saml.confirm', - newScimStatus ? 'scim' : 'jit', - 'description' - )} - </ConfirmModal> - )} - </form> - </div> - )} + {translate('cancel')} + </ResetButtonLink> + </> + )} + {showConfirmProvisioningModal && ( + <ConfirmModal + onConfirm={() => 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' + )} + </ConfirmModal> + )} + </form> + </div> </> )} {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} > <h2 className="radio-card-header big-spacer-bottom"> <span className="display-flex-center link-radio"> 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. |