diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-05-11 12:24:44 +0200 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2017-05-12 12:37:19 +0200 |
commit | 555c7dd62475cac4e96bfa9ffbed6dd523ea8ad1 (patch) | |
tree | b1b807f9bfb8cdd8e5cd210ccb93e3202a0e3204 | |
parent | 8b20d9b681313b7b6b9bf0071e9169995d434912 (diff) | |
download | sonarqube-555c7dd62475cac4e96bfa9ffbed6dd523ea8ad1.tar.gz sonarqube-555c7dd62475cac4e96bfa9ffbed6dd523ea8ad1.zip |
SONAR-8822 Show the administration menu only to authorized users
6 files changed, 103 insertions, 44 deletions
diff --git a/server/sonar-web/src/main/js/app/components/AdminContainer.js b/server/sonar-web/src/main/js/app/components/AdminContainer.js index da8c9376dbc..86d867a2c5e 100644 --- a/server/sonar-web/src/main/js/app/components/AdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/AdminContainer.js @@ -21,8 +21,7 @@ import React from 'react'; import Helmet from 'react-helmet'; import { connect } from 'react-redux'; import SettingsNav from './nav/settings/SettingsNav'; -import { getCurrentUser, getAppState } from '../../store/rootReducer'; -import { isUserAdmin } from '../../helpers/users'; +import { getAppState } from '../../store/rootReducer'; import { onFail } from '../../store/rootActions'; import { getSettingsNavigation } from '../../api/nav'; import { setAdminPages } from '../../store/appState/duck'; @@ -30,7 +29,7 @@ import { translate } from '../../helpers/l10n'; class AdminContainer extends React.PureComponent { componentDidMount() { - if (!isUserAdmin(this.props.currentUser)) { + if (!this.props.appState.canAdmin) { // workaround cyclic dependencies const handleRequiredAuthorization = require('../utils/handleRequiredAuthorization').default; handleRequiredAuthorization(); @@ -46,14 +45,17 @@ class AdminContainer extends React.PureComponent { } render() { - if (!isUserAdmin(this.props.currentUser) || !this.props.adminPages) { + const { adminPages } = this.props.appState; + + // Check that the adminPages are loaded + if (!adminPages) { return null; } return ( <div> <Helmet title={translate('layout.settings')} /> - <SettingsNav location={this.props.location} extensions={this.props.adminPages} /> + <SettingsNav location={this.props.location} extensions={adminPages} /> {this.props.children} </div> ); @@ -61,8 +63,7 @@ class AdminContainer extends React.PureComponent { } const mapStateToProps = state => ({ - adminPages: getAppState(state).adminPages, - currentUser: getCurrentUser(state) + appState: getAppState(state) }); const mapDispatchToProps = { setAdminPages }; diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js index 1cedcf94211..0a88701f045 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js @@ -20,7 +20,6 @@ import React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../../helpers/l10n'; -import { isUserAdmin } from '../../../../helpers/users'; import { isMySet } from '../../../../apps/issues/utils'; export default class GlobalNavMenu extends React.PureComponent { @@ -106,7 +105,7 @@ export default class GlobalNavMenu extends React.PureComponent { } renderAdministrationLink() { - if (!isUserAdmin(this.props.currentUser)) { + if (!this.props.appState.canAdmin) { return null; } return ( diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js index 99b97c82c4f..33546be3731 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js @@ -27,8 +27,22 @@ it('should work with extensions', () => { qualifiers: ['TRK'] }; const currentUser = { - isLoggedIn: false, - permissions: { global: [] } + isLoggedIn: false + }; + const wrapper = shallow( + <GlobalNavMenu appState={appState} currentUser={currentUser} location={{ pathname: '' }} /> + ); + expect(wrapper).toMatchSnapshot(); +}); + +it('should show administration menu if the user has the rights', () => { + const appState = { + canAdmin: true, + globalPages: [], + qualifiers: ['TRK'] + }; + const currentUser = { + isLoggedIn: false }; const wrapper = shallow( <GlobalNavMenu appState={appState} currentUser={currentUser} location={{ pathname: '' }} /> diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.js.snap b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.js.snap index bc69019f7a0..bb21d44b23e 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.js.snap +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.js.snap @@ -1,5 +1,79 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`should show administration menu if the user has the rights 1`] = ` +<ul + className="nav navbar-nav" +> + <li> + <Link + activeClassName="active" + onlyActiveOnIndex={false} + style={Object {}} + to="/projects" + > + projects.page + </Link> + </li> + <li> + <Link + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/issues", + "query": Object { + "resolved": "false", + }, + } + } + > + issues.page + </Link> + </li> + <li> + <Link + className={null} + onlyActiveOnIndex={false} + style={Object {}} + to="/coding_rules" + > + coding_rules.page + </Link> + </li> + <li> + <Link + activeClassName="active" + onlyActiveOnIndex={false} + style={Object {}} + to="/profiles" + > + quality_profiles.page + </Link> + </li> + <li> + <Link + activeClassName="active" + onlyActiveOnIndex={false} + style={Object {}} + to="/quality_gates" + > + quality_gates.page + </Link> + </li> + <li> + <Link + activeClassName="active" + className="navbar-admin-link" + onlyActiveOnIndex={false} + style={Object {}} + to="/settings" + > + layout.settings + </Link> + </li> +</ul> +`; + exports[`should work with extensions 1`] = ` <ul className="nav navbar-nav" diff --git a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js index 82e5fb84797..1aebb594952 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js @@ -25,16 +25,15 @@ import { Link } from 'react-router'; import OrganizationsList from './OrganizationsList'; import { translate } from '../../../helpers/l10n'; import { fetchIfAnyoneCanCreateOrganizations, fetchMyOrganizations } from './actions'; -import { getMyOrganizations, getSettingValue, getCurrentUser } from '../../../store/rootReducer'; +import { getAppState, getMyOrganizations, getSettingValue } from '../../../store/rootReducer'; import type { Organization } from '../../../store/organizations/duck'; -import { isUserAdmin } from '../../../helpers/users'; class UserOrganizations extends React.PureComponent { mounted: boolean; props: { anyoneCanCreate?: { value: string }, - currentUser: Object, + canAdmin: boolean, children?: React.Element<*>, organizations: Array<Organization>, fetchIfAnyoneCanCreateOrganizations: () => Promise<*>, @@ -65,8 +64,7 @@ class UserOrganizations extends React.PureComponent { const anyoneCanCreate = this.props.anyoneCanCreate != null && this.props.anyoneCanCreate.value === 'true'; - const canCreateOrganizations = - !this.state.loading && (anyoneCanCreate || isUserAdmin(this.props.currentUser)); + const canCreateOrganizations = !this.state.loading && (anyoneCanCreate || this.props.canAdmin); return ( <div className="account-body account-container"> @@ -101,7 +99,7 @@ class UserOrganizations extends React.PureComponent { const mapStateToProps = state => ({ anyoneCanCreate: getSettingValue(state, 'sonar.organizations.anyoneCanCreate'), - currentUser: getCurrentUser(state), + canAdmin: getAppState(state).canAdmin, organizations: getMyOrganizations(state) }); diff --git a/server/sonar-web/src/main/js/helpers/users.js b/server/sonar-web/src/main/js/helpers/users.js deleted file mode 100644 index cebcbf556b4..00000000000 --- a/server/sonar-web/src/main/js/helpers/users.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -// @flow -type User = { - permissions: { - global: Array<string> - } -}; - -export const isUserAdmin = (user: User): boolean => user.permissions.global.includes('admin'); |