Browse Source

SONAR-8729 Create organization's permissions page

tags/6.3-RC1
Stas Vilchik 7 years ago
parent
commit
63d06f0b44

+ 7
- 5
server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js View File

@@ -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">

+ 43
- 0
server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js View File

@@ -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);

+ 6
- 0
server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js View File

@@ -26,6 +26,7 @@ const ADMIN_PATHS = [
'edit',
'groups',
'delete',
'permissions',
'permission_templates'
];

@@ -57,6 +58,11 @@ export default class OrganizationNavigation extends React.Component {
{translate('user_groups.page')}
</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')}

+ 9
- 0
server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap View File

@@ -51,6 +51,15 @@ exports[`test admin 1`] = `
user_groups.page
</Link>
</li>
<li>
<Link
activeClassName="active"
onlyActiveOnIndex={false}
style={Object {}}
to="/organizations/foo/permissions">
permissions
</Link>
</li>
<li>
<Link
activeClassName="active"

+ 2
- 0
server/sonar-web/src/main/js/apps/organizations/routes.js View File

@@ -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>

+ 24
- 12
server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js View File

@@ -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(

+ 6
- 1
server/sonar-web/src/main/js/apps/permissions/global/components/App.js View File

@@ -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>
);
}

+ 17
- 17
server/sonar-web/src/main/js/apps/permissions/global/store/actions.js View File

@@ -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,

+ 21
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -2315,6 +2315,27 @@ global_permissions.scan.desc=Ability to get all settings required to perform an
global_permissions.provisioning=Create Projects
global_permissions.provisioning.desc=Ability to initialize a project so its settings can be configured before the first analysis.



#------------------------------------------------------------------------------
#
# ORGANIZATIONS PERMISSIONS
#
#------------------------------------------------------------------------------

organizations_permissions.admin=Administer Organization
organizations_permissions.admin.desc=Ability to perform all administration functions for the organization.
organizations_permissions.profileadmin=Administer Quality Profiles
organizations_permissions.profileadmin.desc=Ability to perform any action on quality profiles.
organizations_permissions.gateadmin=Administer Quality Gates
organizations_permissions.gateadmin.desc=Ability to perform any action on quality gates.
organizations_permissions.scan=Execute Analysis
organizations_permissions.scan.desc=Ability to get all settings required to perform an analysis (including the secured settings like passwords) and to push analysis results to the SonarQube server.
organizations_permissions.provisioning=Create Projects
organizations_permissions.provisioning.desc=Ability to initialize a project so its settings can be configured before the first analysis.



#------------------------------------------------------------------------------
#
# PROJECTS PERMISSIONS

Loading…
Cancel
Save