From 183d279e41b9ad09de10712a0d81ebbeccc040eb Mon Sep 17 00:00:00 2001 From: Mathieu Suen Date: Mon, 8 May 2023 16:56:30 +0200 Subject: [PATCH] SONAR-19084 Warn when github authentication configuration has missing properties --- .../authentication/ConfigurationForm.tsx | 25 ++++-- .../GithubAuthenticationTab.tsx | 79 +++++++------------ .../hook/useGithubConfiguration.ts | 52 +++++++++++- .../resources/org/sonar/l10n/core.properties | 2 + 4 files changed, 101 insertions(+), 57 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx index 8f6406b8672..e07e859adc6 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/ConfigurationForm.tsx @@ -42,6 +42,7 @@ interface Props { onReload: () => Promise; tab: AuthenticationTabs; excludedField: string[]; + hasLegacyConfiguration?: boolean; } interface ErrorValue { @@ -50,7 +51,16 @@ interface ErrorValue { } export default function ConfigurationForm(props: Props) { - const { create, loading, values, setNewValue, canBeSave, tab, excludedField } = props; + const { + create, + loading, + values, + setNewValue, + canBeSave, + tab, + excludedField, + hasLegacyConfiguration, + } = props; const [errors, setErrors] = React.useState>({}); const headerLabel = translate('settings.authentication.form', create ? 'create' : 'edit', tab); @@ -104,10 +114,13 @@ export default function ConfigurationForm(props: Props) { loading={loading} ariaLabel={translate('settings.authentication.form.loading')} > - + diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx index 88055fb19d1..ca32c00991b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/GithubAuthenticationTab.tsx @@ -17,15 +17,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { isEmpty } from 'lodash'; import React, { useState } from 'react'; import { FormattedMessage } from 'react-intl'; -import { - activateGithubProvisioning, - deactivateGithubProvisioning, - resetSettingValue, - setSettingValue, -} from '../../../../api/settings'; import GitHubSynchronisationWarning from '../../../../app/components/GitHubSynchronisationWarning'; import DocLink from '../../../../components/common/DocLink'; import ConfirmModal from '../../../../components/controls/ConfirmModal'; @@ -42,10 +35,7 @@ import { ExtendedSettingDefinition } from '../../../../types/settings'; import { DOCUMENTATION_LINK_SUFFIXES } from './Authentication'; import AuthenticationFormField from './AuthenticationFormField'; import ConfigurationForm from './ConfigurationForm'; -import useGithubConfiguration, { - GITHUB_ENABLED_FIELD, - GITHUB_JIT_FIELDS, -} from './hook/useGithubConfiguration'; +import useGithubConfiguration, { GITHUB_JIT_FIELDS } from './hook/useGithubConfiguration'; interface GithubAuthenticationProps { definitions: ExtendedSettingDefinition[]; @@ -82,6 +72,10 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps setNewGithubProvisioningStatus, hasGithubProvisioningConfigChange, resetJitSetting, + saveGroup, + changeProvisioning, + toggleEnable, + hasLegacyConfiguration, } = useGithubConfiguration(definitions, props.onReload); const hasDifferentProvider = provider !== undefined && provider !== Provider.Github; @@ -94,40 +88,6 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps setShowEditModal(false); }; - const handleConfirmChangeProvisioning = async () => { - if (newGithubProvisioningStatus && newGithubProvisioningStatus !== githubProvisioningStatus) { - await activateGithubProvisioning(); - await reload(); - } else { - if (newGithubProvisioningStatus !== githubProvisioningStatus) { - await deactivateGithubProvisioning(); - } - await handleSaveGroup(); - } - }; - - const handleSaveGroup = async () => { - await Promise.all( - GITHUB_JIT_FIELDS.map(async (settingKey) => { - const value = values[settingKey]; - if (value.newValue !== undefined) { - if (isEmpty(value.newValue) && typeof value.newValue !== 'boolean') { - await resetSettingValue({ keys: value.definition.key }); - } else { - await setSettingValue(value.definition, value.newValue); - } - } - }) - ); - await reload(); - }; - - const handleToggleEnable = async () => { - const value = values[GITHUB_ENABLED_FIELD]; - await setSettingValue(value.definition, !enabled); - await reload(); - }; - return (
@@ -141,11 +101,29 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps
)}
- {!hasConfiguration ? ( + {!hasConfiguration && !hasLegacyConfiguration && (
{translate('settings.authentication.github.form.not_configured')}
- ) : ( + )} + {!hasConfiguration && hasLegacyConfiguration && ( +
+ + + {translate('documentation')} + + ), + }} + /> + +
+ )} + {hasConfiguration && ( <>
@@ -163,7 +141,7 @@ export default function GithubAuthenticationTab(props: GithubAuthenticationProps

diff --git a/server/sonar-web/src/main/js/apps/settings/components/authentication/hook/useGithubConfiguration.ts b/server/sonar-web/src/main/js/apps/settings/components/authentication/hook/useGithubConfiguration.ts index 168325e60b2..dea619fd54a 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/authentication/hook/useGithubConfiguration.ts +++ b/server/sonar-web/src/main/js/apps/settings/components/authentication/hook/useGithubConfiguration.ts @@ -17,9 +17,15 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { some } from 'lodash'; +import { isEmpty, some } from 'lodash'; import { useCallback, useContext, useEffect, useState } from 'react'; -import { fetchIsGithubProvisioningEnabled } from '../../../../../api/settings'; +import { + activateGithubProvisioning, + deactivateGithubProvisioning, + fetchIsGithubProvisioningEnabled, + resetSettingValue, + setSettingValue, +} from '../../../../../api/settings'; import { AvailableFeaturesContext } from '../../../../../app/components/available-features/AvailableFeaturesContext'; import { Feature } from '../../../../../types/features'; import { ExtendedSettingDefinition } from '../../../../../types/settings'; @@ -28,6 +34,7 @@ import useConfiguration from './useConfiguration'; export const GITHUB_ENABLED_FIELD = 'sonar.auth.github.enabled'; export const GITHUB_APP_ID_FIELD = 'sonar.auth.github.appId'; export const GITHUB_API_URL_FIELD = 'sonar.auth.github.apiUrl'; +export const GITHUB_CLIENT_ID_FIELD = 'sonar.auth.github.clientId.secured'; export const GITHUB_JIT_FIELDS = [ 'sonar.auth.github.organizations', 'sonar.auth.github.allowUsersToSignUp', @@ -76,6 +83,7 @@ export default function useGithubConfiguration( const enabled = values[GITHUB_ENABLED_FIELD]?.value === 'true'; const appId = values[GITHUB_APP_ID_FIELD]?.value as string; const url = values[GITHUB_API_URL_FIELD]?.value; + const clientIdIsNotSet = values[GITHUB_CLIENT_ID_FIELD]?.isNotSet; const reload = useCallback(async () => { await reloadConfig(); @@ -83,6 +91,42 @@ export default function useGithubConfiguration( onReload(); }, [reloadConfig, onReload]); + const changeProvisioning = async () => { + if (newGithubProvisioningStatus && newGithubProvisioningStatus !== githubProvisioningStatus) { + await activateGithubProvisioning(); + await reload(); + } else { + if (newGithubProvisioningStatus !== githubProvisioningStatus) { + await deactivateGithubProvisioning(); + } + await saveGroup(); + } + }; + + const saveGroup = async () => { + await Promise.all( + GITHUB_JIT_FIELDS.map(async (settingKey) => { + const value = values[settingKey]; + if (value.newValue !== undefined) { + if (isEmpty(value.newValue) && typeof value.newValue !== 'boolean') { + await resetSettingValue({ keys: value.definition.key }); + } else { + await setSettingValue(value.definition, value.newValue); + } + } + }) + ); + await reload(); + }; + + const toggleEnable = async () => { + const value = values[GITHUB_ENABLED_FIELD]; + await setSettingValue(value.definition, !enabled); + await reload(); + }; + + const hasLegacyConfiguration = appId === undefined && !clientIdIsNotSet; + return { ...config, reload, @@ -95,6 +139,10 @@ export default function useGithubConfiguration( newGithubProvisioningStatus, setNewGithubProvisioningStatus, hasGithubProvisioningConfigChange, + changeProvisioning, + saveGroup, resetJitSetting, + toggleEnable, + hasLegacyConfiguration, }; } 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 58f7a67c6dc..853047d3aca 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1320,6 +1320,7 @@ settings.authentication.custom_message_information=You can define a custom log-i settings.authentication.custom_message_information.link=General settings.authentication.description=The following settings allow you to delegate authentication via SAML, or any of the following DevOps Platforms: GitHub, GitLab, and Bitbucket. settings.authentication.help=If you need help setting up authentication, read our dedicated {link}. +settings.authentication.legacy_help.github=Your configuration is no longer supported, please checkout the {link} on how to change your configuration. settings.authentication.help.link=documentation settings.authentication.form.create=Create configuration settings.authentication.form.edit=Edit @@ -1343,6 +1344,7 @@ settings.authentication.github.confirm.auto.description=After you switch to auto settings.authentication.github.confirm.jit.description=Switching to Just-in-Time provisioning removes all information provided while automatic provisioning through SCIM was active. These changes cannot be reverted. Are you sure? settings.authentication.github.configuration=GitHub Configuration settings.authentication.github.form.not_configured=GitHub App is not configured +settings.authentication.github.form.legacy_configured=You current configuration is no longer supported. It will continue working but with limitted support.See the {documentation} for more information. settings.authentication.github.enable_first=Enable your GitHub configuration for more provisioning options. settings.authentication.github.form.provisioning_with_github=Automatic user and group provisioning settings.authentication.github.form.provisioning_with_github.description=Users and groups are automatically provisioned from your GitHub organizations. Once activated, managed users and groups can only be modified from your GitHub organizations/teams. Existing local users and groups will be kept. -- 2.39.5