diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2017-02-01 17:01:57 +0100 |
---|---|---|
committer | Stas Vilchik <stas-vilchik@users.noreply.github.com> | 2017-02-03 11:54:45 +0100 |
commit | 63d06f0b44b99b0ca814d590b1487265db998bc3 (patch) | |
tree | 1c9775e48bc959bd357b58dc7a479ba8217e4273 /server | |
parent | af070afc92b4b36ae75727af3377b4107a0a0203 (diff) | |
download | sonarqube-63d06f0b44b99b0ca814d590b1487265db998bc3.tar.gz sonarqube-63d06f0b44b99b0ca814d590b1487265db998bc3.zip |
SONAR-8729 Create organization's permissions page
Diffstat (limited to 'server')
8 files changed, 114 insertions, 35 deletions
diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js index 9879cec41d5..64d431e88e3 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js @@ -133,11 +133,13 @@ class SettingsNav extends React.Component { </IndexLink> </li> )} - <li> - <IndexLink to="/roles/global" activeClassName="active"> - {translate('global_permissions.page')} - </IndexLink> - </li> + {!this.props.customOrganizations && ( + <li> + <IndexLink to="/roles/global" activeClassName="active"> + {translate('global_permissions.page')} + </IndexLink> + </li> + )} {!this.props.customOrganizations && ( <li> <IndexLink to="/permission_templates" activeClassName="active"> diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js new file mode 100644 index 00000000000..99323ae9858 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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 +import React from 'react'; +import { connect } from 'react-redux'; +import GlobalPermissionsApp from '../../permissions/global/components/App'; +import { getOrganizationByKey } from '../../../store/rootReducer'; +import type { Organization } from '../../../store/organizations/duck'; + +class OrganizationPermissions extends React.Component { + props: { + organization: Organization + }; + + render () { + return ( + <GlobalPermissionsApp organization={this.props.organization}/> + ); + } +} + +const mapStateToProps = (state, ownProps) => ({ + organization: getOrganizationByKey(state, ownProps.params.organizationKey) +}); + +export default connect(mapStateToProps)(OrganizationPermissions); diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js index eff625b4fac..fef65522ef8 100644 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js @@ -26,6 +26,7 @@ const ADMIN_PATHS = [ 'edit', 'groups', 'delete', + 'permissions', 'permission_templates' ]; @@ -58,6 +59,11 @@ export default class OrganizationNavigation extends React.Component { </Link> </li> <li> + <Link to={`/organizations/${organization.key}/permissions`} activeClassName="active"> + {translate('permissions')} + </Link> + </li> + <li> <Link to={`/organizations/${organization.key}/permission_templates`} activeClassName="active"> {translate('permission_templates')} </Link> diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap index 4d4d4d7d237..b61026ce1dd 100644 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap @@ -56,6 +56,15 @@ exports[`test admin 1`] = ` activeClassName="active" onlyActiveOnIndex={false} style={Object {}} + to="/organizations/foo/permissions"> + permissions + </Link> + </li> + <li> + <Link + activeClassName="active" + onlyActiveOnIndex={false} + style={Object {}} to="/organizations/foo/permission_templates"> permission_templates </Link> diff --git a/server/sonar-web/src/main/js/apps/organizations/routes.js b/server/sonar-web/src/main/js/apps/organizations/routes.js index 1f0a8881a21..3885eb9ddf7 100644 --- a/server/sonar-web/src/main/js/apps/organizations/routes.js +++ b/server/sonar-web/src/main/js/apps/organizations/routes.js @@ -25,6 +25,7 @@ import OrganizationFavoriteProjects from './components/OrganizationFavoriteProje import OrganizationAdmin from './components/OrganizationAdmin'; import OrganizationEdit from './components/OrganizationEdit'; import OrganizationGroups from './components/OrganizationGroups'; +import OrganizationPermissions from './components/OrganizationPermissions'; import OrganizationPermissionTemplates from './components/OrganizationPermissionTemplates'; import OrganizationDelete from './components/OrganizationDelete'; @@ -37,6 +38,7 @@ export default ( <Route path="delete" component={OrganizationDelete}/> <Route path="edit" component={OrganizationEdit}/> <Route path="groups" component={OrganizationGroups}/> + <Route path="permissions" component={OrganizationPermissions}/> <Route path="permission_templates" component={OrganizationPermissionTemplates}/> </Route> </Route> diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js index dd781c3cd25..1b1c6c2da78 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js @@ -48,6 +48,12 @@ const PERMISSIONS_ORDER = [ 'provisioning' ]; +const PERMISSIONS_FOR_CUSTOM_ORG = [ + 'admin', + 'scan', + 'provisioning' +]; + class AllHoldersList extends React.Component { componentDidMount () { this.props.loadHolders(); @@ -74,10 +80,16 @@ class AllHoldersList extends React.Component { } render () { - const permissions = PERMISSIONS_ORDER.map(p => ({ + const order = (this.props.organization && !this.props.organization.isDefault) ? + PERMISSIONS_FOR_CUSTOM_ORG : + PERMISSIONS_ORDER; + + const l10nPrefix = this.props.organization ? 'organizations_permissions' : 'global_permissions'; + + const permissions = order.map(p => ({ key: p, - name: translate('global_permissions', p), - description: translate('global_permissions', p, 'desc') + name: translate(l10nPrefix, p), + description: translate(l10nPrefix, p, 'desc') })); return ( @@ -109,19 +121,19 @@ const mapStateToProps = state => ({ selectedPermission: getPermissionsAppSelectedPermission(state) }); -const mapDispatchToProps = dispatch => ({ - loadHolders: () => dispatch(loadHolders()), - onSearch: query => dispatch(updateQuery(query)), - onFilter: filter => dispatch(updateFilter(filter)), - onSelectPermission: permission => dispatch(selectPermission(permission)), +const mapDispatchToProps = (dispatch, ownProps) => ({ + loadHolders: () => dispatch(loadHolders(ownProps.organization)), + onSearch: query => dispatch(updateQuery(query, ownProps.organization)), + onFilter: filter => dispatch(updateFilter(filter, ownProps.organization)), + onSelectPermission: permission => dispatch(selectPermission(permission, ownProps.organization)), grantPermissionToUser: (login, permission) => - dispatch(grantToUser(login, permission)), + dispatch(grantToUser(login, permission, ownProps.organization)), revokePermissionFromUser: (login, permission) => - dispatch(revokeFromUser(login, permission)), + dispatch(revokeFromUser(login, permission, ownProps.organization)), grantPermissionToGroup: (groupName, permission) => - dispatch(grantToGroup(groupName, permission)), + dispatch(grantToGroup(groupName, permission, ownProps.organization)), revokePermissionFromGroup: (groupName, permission) => - dispatch(revokeFromGroup(groupName, permission)) + dispatch(revokeFromGroup(groupName, permission, ownProps.organization)) }); export default connect( diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js index 71ff949fd87..b0cdc95a4ad 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +// @flow import React from 'react'; import PageHeader from './PageHeader'; import AllHoldersList from './AllHoldersList'; @@ -26,12 +27,16 @@ import '../../styles.css'; // TODO helmet export default class App extends React.Component { + props: { + organization?: {} + }; + render () { return ( <div className="page page-limited"> <PageHeader/> <PageError/> - <AllHoldersList/> + <AllHoldersList organization={this.props.organization}/> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js b/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js index eb2021a3b19..2a163720e38 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/store/actions.js @@ -37,7 +37,7 @@ import { getPermissionsAppSelectedPermission } from '../../../../store/rootReducer'; -export const loadHolders = () => (dispatch, getState) => { +export const loadHolders = organization => (dispatch, getState) => { const query = getPermissionsAppQuery(getState()); const filter = getPermissionsAppFilter(getState()); const selectedPermission = getPermissionsAppSelectedPermission(getState()); @@ -47,13 +47,13 @@ export const loadHolders = () => (dispatch, getState) => { const requests = []; if (filter !== 'groups') { - requests.push(api.getGlobalPermissionsUsers(query, selectedPermission)); + requests.push(api.getGlobalPermissionsUsers(query, selectedPermission, organization)); } else { requests.push(Promise.resolve([])); } if (filter !== 'users') { - requests.push(api.getGlobalPermissionsGroups(query, selectedPermission)); + requests.push(api.getGlobalPermissionsGroups(query, selectedPermission, organization)); } else { requests.push(Promise.resolve([])); } @@ -70,46 +70,46 @@ export const loadHolders = () => (dispatch, getState) => { }); }; -export const updateQuery = (query = '') => dispatch => { +export const updateQuery = (query = '', organization) => dispatch => { dispatch({ type: UPDATE_QUERY, query }); if (query.length === 0 || query.length > 2) { - dispatch(loadHolders()); + dispatch(loadHolders(organization)); } }; -export const updateFilter = filter => dispatch => { +export const updateFilter = (filter, organization) => dispatch => { dispatch({ type: UPDATE_FILTER, filter }); - dispatch(loadHolders()); + dispatch(loadHolders(organization)); }; -export const selectPermission = permission => (dispatch, getState) => { +export const selectPermission = (permission, organization) => (dispatch, getState) => { const selectedPermission = getPermissionsAppSelectedPermission(getState()); if (selectedPermission !== permission) { dispatch({ type: SELECT_PERMISSION, permission }); } else { dispatch({ type: SELECT_PERMISSION, permission: null }); } - dispatch(loadHolders()); + dispatch(loadHolders(organization)); }; -export const grantToUser = (login, permission) => dispatch => { - api.grantPermissionToUser(null, login, permission).then(() => { +export const grantToUser = (login, permission, organization) => dispatch => { + api.grantPermissionToUser(null, login, permission, organization).then(() => { dispatch({ type: GRANT_PERMISSION_TO_USER, login, permission }); }).catch(e => { return parseError(e).then(message => dispatch(raiseError(message))); }); }; -export const revokeFromUser = (login, permission) => dispatch => { - api.revokePermissionFromUser(null, login, permission).then(() => { +export const revokeFromUser = (login, permission, organization) => dispatch => { + api.revokePermissionFromUser(null, login, permission, organization).then(() => { dispatch({ type: REVOKE_PERMISSION_TO_USER, login, permission }); }).catch(e => { return parseError(e).then(message => dispatch(raiseError(message))); }); }; -export const grantToGroup = (groupName, permission) => dispatch => { - api.grantPermissionToGroup(null, groupName, permission).then(() => { +export const grantToGroup = (groupName, permission, organization) => dispatch => { + api.grantPermissionToGroup(null, groupName, permission, organization).then(() => { dispatch({ type: GRANT_PERMISSION_TO_GROUP, groupName, @@ -120,8 +120,8 @@ export const grantToGroup = (groupName, permission) => dispatch => { }); }; -export const revokeFromGroup = (groupName, permission) => dispatch => { - api.revokePermissionFromGroup(null, groupName, permission).then(() => { +export const revokeFromGroup = (groupName, permission, organization) => dispatch => { + api.revokePermissionFromGroup(null, groupName, permission, organization).then(() => { dispatch({ type: REVOKE_PERMISSION_FROM_GROUP, groupName, |