aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2017-02-01 17:01:57 +0100
committerStas Vilchik <stas-vilchik@users.noreply.github.com>2017-02-03 11:54:45 +0100
commit63d06f0b44b99b0ca814d590b1487265db998bc3 (patch)
tree1c9775e48bc959bd357b58dc7a479ba8217e4273 /server
parentaf070afc92b4b36ae75727af3377b4107a0a0203 (diff)
downloadsonarqube-63d06f0b44b99b0ca814d590b1487265db998bc3.tar.gz
sonarqube-63d06f0b44b99b0ca814d590b1487265db998bc3.zip
SONAR-8729 Create organization's permissions page
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js12
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js43
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js6
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/navigation/__tests__/__snapshots__/OrganizationNavigation-test.js.snap9
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/routes.js2
-rw-r--r--server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js36
-rw-r--r--server/sonar-web/src/main/js/apps/permissions/global/components/App.js7
-rw-r--r--server/sonar-web/src/main/js/apps/permissions/global/store/actions.js34
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,