diff options
author | guillaume-peoch-sonarsource <guillaume.peoch@sonarsource.com> | 2024-02-02 12:32:07 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-02-05 10:09:38 +0000 |
commit | f87b5668f3639a6fd9a2b26b1369989a55c2a810 (patch) | |
tree | d9d8f20d930882b44d17a32b21c754fedb9e7043 /server | |
parent | 95f9d0ec9698724e9785b871ac6dd5df0af1f800 (diff) | |
download | sonarqube-f87b5668f3639a6fd9a2b26b1369989a55c2a810.tar.gz sonarqube-f87b5668f3639a6fd9a2b26b1369989a55c2a810.zip |
SONAR-21508 SONAR-21483 Fix SSF-530 and Fix SSF-548
Diffstat (limited to 'server')
3 files changed, 149 insertions, 17 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/AuthenticationServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/AuthenticationServiceMock.ts index 45f584f34ec..7b5837dad9b 100644 --- a/server/sonar-web/src/main/js/api/mocks/AuthenticationServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/AuthenticationServiceMock.ts @@ -31,6 +31,11 @@ export default class AuthenticationServiceMock { mockSettingValue({ key: 'sonar.auth.saml.certificate.secured' }), mockSettingValue({ key: 'sonar.auth.saml.enabled', value: 'false' }), mockSettingValue({ key: 'sonar.auth.github.enabled', value: 'true' }), + mockSettingValue({ key: 'sonar.auth.github.allowUsersToSignUp', value: 'true' }), + mockSettingValue({ key: 'sonar.auth.gitlab.enabled', value: 'true' }), + mockSettingValue({ key: 'sonar.auth.gitlab.allowUsersToSignUp', value: 'true' }), + mockSettingValue({ key: 'sonar.auth.bitbucket.enabled', value: 'true' }), + mockSettingValue({ key: 'sonar.auth.bitbucket.allowUsersToSignUp', value: 'true' }), ]; constructor() { diff --git a/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.tsx b/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.tsx index 23c644f6265..974cb95f07b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.tsx @@ -42,12 +42,12 @@ interface Props { interface State { settings: SettingDefinitionAndValue[]; - displayGithubOrganizationWarning: boolean; + displaySecurityWarning: boolean; } export default class CategoryDefinitionsList extends React.PureComponent<Props, State> { mounted = false; - state: State = { settings: [], displayGithubOrganizationWarning: false }; + state: State = { settings: [], displaySecurityWarning: false }; componentDidMount() { this.mounted = true; @@ -65,17 +65,37 @@ export default class CategoryDefinitionsList extends React.PureComponent<Props, this.mounted = false; } - shouldDisplayGithubWarning = (settings: SettingDefinitionAndValue[]) => { + shouldDisplaySecurityWarning = (settings: SettingDefinitionAndValue[]) => { const { category, subCategory } = this.props; - if (category !== 'authentication' || subCategory !== 'github') { + if (category !== 'authentication' || subCategory === 'saml') { return false; } - const isGithubEnabled = settings.find((s) => s.definition.key === 'sonar.auth.github.enabled'); - const organizationsSetting = settings.find( - (s) => s.definition.key === 'sonar.auth.github.organizations' + const isEnabled = settings.find( + (s) => s.definition.key === `sonar.auth.${subCategory}.enabled` ); + const isAllowUsersToSignUpEnabled = settings.find( + (s) => s.definition.key === `sonar.auth.${subCategory}.allowUsersToSignUp` + ); + let organizationsSetting; + if (subCategory === 'github') { + organizationsSetting = settings.find( + (s) => s.definition.key === `sonar.auth.${subCategory}.organizations` + ); + } + if (subCategory === 'bitbucket') { + organizationsSetting = settings.find( + (s) => s.definition.key === `sonar.auth.${subCategory}.workspaces` + ); + } + if (subCategory === 'gitlab') { + organizationsSetting = settings.find( + (s) => s.definition.key === `sonar.auth.${subCategory}.allowedGroups` + ); + } + if ( - isGithubEnabled?.settingValue?.value === 'true' && + isEnabled?.settingValue?.value === 'true' && + isAllowUsersToSignUpEnabled?.settingValue?.value === 'true' && organizationsSetting?.settingValue === undefined ) { return true; @@ -106,26 +126,32 @@ export default class CategoryDefinitionsList extends React.PureComponent<Props, }; }); - const displayGithubOrganizationWarning = this.shouldDisplayGithubWarning(settings); + const displaySecurityWarning = this.shouldDisplaySecurityWarning(settings); - this.setState({ settings, displayGithubOrganizationWarning }); + this.setState({ settings, displaySecurityWarning }); }; render() { const { category, component, subCategory, displaySubCategoryTitle } = this.props; - const { settings, displayGithubOrganizationWarning } = this.state; + const { settings, displaySecurityWarning } = this.state; return ( <> - {displayGithubOrganizationWarning && ( + {displaySecurityWarning && ( <Alert variant="error"> <FormattedMessage - id="settings.authentication.github.organization.warning" - defaultMessage={translate('settings.authentication.github.organization.warning')} + id={`settings.authentication.${subCategory}.organization.warning`} + defaultMessage={translate( + `settings.authentication.${subCategory}.organization.warning` + )} values={{ learn_more: ( - <DocLink to="/instance-administration/authentication/github/#setting-your-authentication-settings-in-sonarqube"> - {translate('settings.authentication.github.organization.warning.learn_more')} + <DocLink + to={`/instance-administration/authentication/${ + subCategory === 'bitbucket' ? 'bitbucket-cloud' : subCategory + }/#setting-your-authentication-settings-in-sonarqube`} + > + {translate('learn_more')} </DocLink> ), }} 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 1678dc3a726..fbe92039271 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 @@ -80,7 +80,11 @@ const ui = { textbox1: byRole('textbox', { name: 'test1' }), textbox2: byRole('textbox', { name: 'test2' }), githubTab: byRole('tab', { name: 'github GitHub' }), + gitlabTab: byRole('tab', { name: 'gitlab GitLab' }), + bitbucketTab: byRole('tab', { name: 'bitbucket Bitbucket' }), githubOrganizationWarning: byText('settings.authentication.github.organization.warning'), + gitlabOrganizationWarning: byText('settings.authentication.gitlab.organization.warning'), + bitbucketOrganizationWarning: byText('settings.authentication.bitbucket.organization.warning'), }; it('should render tabs and allow navigation', async () => { @@ -220,12 +224,21 @@ describe('GitHub tab', () => { key: 'sonar.auth.github.enabled', category: 'authentication', subCategory: 'github', - name: '"Enabled"', + name: 'Enabled', description: 'Enable GitHub users to login. Value is ignored if client ID and secret are not defined.', type: SettingType.BOOLEAN, }), mockDefinition({ + key: 'sonar.auth.github.allowUsersToSignUp', + category: 'authentication', + subCategory: 'github', + name: 'Allow users to sign-up', + description: + 'Allow new users to authenticate. When set to false, only existing users will be able to authenticate to the server.', + type: SettingType.BOOLEAN, + }), + mockDefinition({ key: 'sonar.auth.github.organizations', category: 'authentication', subCategory: 'github', @@ -246,6 +259,94 @@ describe('GitHub tab', () => { }); }); +describe('GitLab tab', () => { + it('should display a warning if gitlab authentication is enabled but no organizations are whitelisted', async () => { + const user = userEvent.setup(); + + const definitions = [ + mockDefinition({ + key: 'sonar.auth.gitlab.enabled', + category: 'authentication', + subCategory: 'gitlab', + name: '"Enabled"', + description: + 'Enable gitlab users to login. Value is ignored if client ID and secret are not defined.', + type: SettingType.BOOLEAN, + }), + mockDefinition({ + key: 'sonar.auth.gitlab.allowUsersToSignUp', + category: 'authentication', + subCategory: 'gitlab', + name: 'Allow users to sign-up', + description: + 'Allow new users to authenticate. When set to false, only existing users will be able to authenticate to the server.', + type: SettingType.BOOLEAN, + }), + mockDefinition({ + key: 'sonar.auth.gitlab.allowedGroups', + category: 'authentication', + subCategory: 'gitlab', + name: 'Allowed Groups', + description: + 'Only members of these groups will be able to authenticate to the server. If a user is a member of any of the group listed they will be authenticated.', + type: SettingType.BOOLEAN, + fields: [], + multiValues: true, + options: [], + }), + ]; + + renderAuthentication(definitions); + + await user.click(await ui.gitlabTab.find()); + expect(ui.gitlabOrganizationWarning.get()).toBeInTheDocument(); + }); +}); + +describe('bitbucket tab', () => { + it('should display a warning if bitbucket authentication is enabled but no organizations are whitelisted', async () => { + const user = userEvent.setup(); + + const definitions = [ + mockDefinition({ + key: 'sonar.auth.bitbucket.enabled', + category: 'authentication', + subCategory: 'bitbucket', + name: '"Enabled"', + description: + 'Enable bitbucket users to login. Value is ignored if client ID and secret are not defined.', + type: SettingType.BOOLEAN, + }), + mockDefinition({ + key: 'sonar.auth.bitbucket.allowUsersToSignUp', + category: 'authentication', + subCategory: 'bitbucket', + name: 'Allow users to sign-up', + description: + 'Allow new users to authenticate. When set to false, only existing users will be able to authenticate to the server.', + type: SettingType.BOOLEAN, + }), + mockDefinition({ + key: 'sonar.auth.bitbucket.organizations', + category: 'authentication', + subCategory: 'bitbucket', + name: 'Organizations', + description: + 'Only members of these organizations will be able to authenticate to the server. If a user is a member of any of the organizations listed they will be authenticated.', + type: SettingType.BOOLEAN, + fields: [], + multiValues: true, + options: [], + }), + ]; + + renderAuthentication(definitions); + + await user.click(await ui.bitbucketTab.find()); + expect(ui.bitbucketOrganizationWarning.get()).toBeInTheDocument(); + }); +}); + function renderAuthentication(definitions: ExtendedSettingDefinition[], features: Feature[] = []) { renderComponent( <AvailableFeaturesContext.Provider value={features}> |