From a14a5717cd31d3358d5ba09b36696caf08518546 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Tue, 31 Jan 2017 13:46:14 +0100 Subject: [PATCH] SONAR-8658 Create organization's permission templates page --- .../sonar-web/src/main/js/api/permissions.js | 42 +++++++++-------- .../components/nav/settings/SettingsNav.js | 18 ++++---- .../OrganizationPermissionTemplates.js | 46 +++++++++++++++++++ .../navigation/OrganizationNavigation.js | 8 +++- .../OrganizationNavigation-test.js.snap | 9 ++++ .../src/main/js/apps/organizations/routes.js | 2 + .../components/ActionsCell.js | 26 +++++++---- .../permission-templates/components/App.js | 8 +++- .../permission-templates/components/Header.js | 9 +++- .../permission-templates/components/Home.js | 3 ++ .../permission-templates/components/List.js | 5 +- .../components/ListItem.js | 3 ++ .../components/NameCell.js | 9 +++- .../components/Template.js | 26 +++++++---- .../components/TemplateHeader.js | 10 +++- .../permission-templates/views/CreateView.js | 8 +++- 16 files changed, 175 insertions(+), 57 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js diff --git a/server/sonar-web/src/main/js/api/permissions.js b/server/sonar-web/src/main/js/api/permissions.js index e4d7f9b9b09..f498c3612d9 100644 --- a/server/sonar-web/src/main/js/api/permissions.js +++ b/server/sonar-web/src/main/js/api/permissions.js @@ -71,9 +71,9 @@ export function revokePermissionFromGroup (projectKey, groupName, permission) { * Get list of permission templates * @returns {Promise} */ -export function getPermissionTemplates () { +export function getPermissionTemplates (organization) { const url = '/api/permissions/search_templates'; - return getJSON(url); + return organization ? getJSON(url, { organization }) : getJSON(url); } export const createPermissionTemplate = data => ( @@ -90,13 +90,13 @@ export const deletePermissionTemplate = data => ( /** * Set default permission template for a given qualifier - * @param {string} templateName + * @param {string} templateId * @param {string} qualifier * @returns {Promise} */ -export function setDefaultPermissionTemplate (templateName, qualifier) { +export function setDefaultPermissionTemplate (templateId, qualifier) { const url = '/api/permissions/set_default_template'; - const data = { templateName, qualifier }; + const data = { templateId, qualifier }; return post(url, data); } @@ -110,39 +110,37 @@ export function bulkApplyTemplate (data) { return post(url, data); } -export function grantTemplatePermissionToUser (templateName, login, permission) { +export function grantTemplatePermissionToUser (templateId, login, permission) { const url = '/api/permissions/add_user_to_template'; - const data = { templateName, login, permission }; + const data = { templateId, login, permission }; return post(url, data); } -export function revokeTemplatePermissionFromUser (templateName, login, permission) { +export function revokeTemplatePermissionFromUser (templateId, login, permission) { const url = '/api/permissions/remove_user_from_template'; - const data = { templateName, login, permission }; + const data = { templateId, login, permission }; return post(url, data); } -export function grantTemplatePermissionToGroup (templateName, groupName, permission) { +export function grantTemplatePermissionToGroup (data) { const url = '/api/permissions/add_group_to_template'; - const data = { templateName, groupName, permission }; return post(url, data); } -export function revokeTemplatePermissionFromGroup (templateName, groupName, permission) { +export function revokeTemplatePermissionFromGroup (data) { const url = '/api/permissions/remove_group_from_template'; - const data = { templateName, groupName, permission }; return post(url, data); } -export function addProjectCreatorToTemplate (templateName, permission) { +export function addProjectCreatorToTemplate (templateId, permission) { const url = '/api/permissions/add_project_creator_to_template'; - const data = { templateName, permission }; + const data = { templateId, permission }; return post(url, data); } -export function removeProjectCreatorFromTemplate (templateName, permission) { +export function removeProjectCreatorFromTemplate (templateId, permission) { const url = '/api/permissions/remove_project_creator_from_template'; - const data = { templateName, permission }; + const data = { templateId, permission }; return post(url, data); } @@ -194,7 +192,7 @@ export function getGlobalPermissionsGroups (query = '', permission = null) { return getJSON(url, data).then(r => r.groups); } -export function getPermissionTemplateUsers (templateId, query = '', permission = null) { +export function getPermissionTemplateUsers (templateId, query = '', permission = null, organization = null) { const url = '/api/permissions/template_users'; const data = { templateId, ps: PAGE_SIZE }; if (query) { @@ -203,10 +201,13 @@ export function getPermissionTemplateUsers (templateId, query = '', permission = if (permission) { data.permission = permission; } + if (organization) { + Object.assign(data, { organization }); + } return getJSON(url, data).then(r => r.users); } -export function getPermissionTemplateGroups (templateId, query = '', permission = null) { +export function getPermissionTemplateGroups (templateId, query = '', permission = null, organization = null) { const url = '/api/permissions/template_groups'; const data = { templateId, ps: PAGE_SIZE }; if (query) { @@ -215,5 +216,8 @@ export function getPermissionTemplateGroups (templateId, query = '', permission if (permission) { data.permission = permission; } + if (organization) { + Object.assign(data, { organization }); + } return getJSON(url, data).then(r => r.groups); } 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 417f89a1553..9879cec41d5 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 @@ -75,9 +75,9 @@ class SettingsNav extends React.Component {
@@ -138,11 +138,13 @@ class SettingsNav extends React.Component { {translate('global_permissions.page')} -
  • - - {translate('permission_templates')} - -
  • + {!this.props.customOrganizations && ( +
  • + + {translate('permission_templates')} + +
  • + )} diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js new file mode 100644 index 00000000000..614e2ec376a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js @@ -0,0 +1,46 @@ +/* + * 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 AppContainer from '../../permission-templates/components/AppContainer'; +import { getOrganizationByKey } from '../../../store/rootReducer'; +import type { Organization } from '../../../store/organizations/duck'; + +class OrganizationPermissionTemplates extends React.Component { + props: { + location: {}, + organization: Organization + }; + + render () { + return ( + + ); + } +} + +const mapStateToProps = (state, ownProps) => ({ + organization: getOrganizationByKey(state, ownProps.params.organizationKey) +}); + +export default connect(mapStateToProps)(OrganizationPermissionTemplates); 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 d9cfafeb5eb..8590e0e192f 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 @@ -25,7 +25,8 @@ import { translate } from '../../../helpers/l10n'; const ADMIN_PATHS = [ 'edit', 'groups', - 'delete' + 'delete', + 'permission_templates' ]; export default class OrganizationNavigation extends React.Component { @@ -56,6 +57,11 @@ export default class OrganizationNavigation extends React.Component { {translate('user_groups.page')} +
  • + + {translate('permission_templates')} + +
  • {translate('edit')} 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 cd5ffee80cf..af802f0809d 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 @@ -49,6 +49,15 @@ exports[`test admin 1`] = ` user_groups.page
  • +
  • + + permission_templates + +
  • + ); diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js b/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js index 88c034de322..1a0a97e38cf 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js @@ -30,6 +30,7 @@ import { setDefaultPermissionTemplate } from '../../../api/permissions'; export default class ActionsCell extends React.Component { static propTypes = { + organization: React.PropTypes.object, permissionTemplate: PermissionTemplateType.isRequired, topQualifiers: React.PropTypes.array.isRequired, refresh: CallbackType, @@ -57,7 +58,10 @@ export default class ActionsCell extends React.Component { new DeleteView({ model: new Backbone.Model(this.props.permissionTemplate) }).on('done', () => { - this.context.router.replace('/permission_templates'); + const pathname = this.props.organization ? + `/organizations/${this.props.organization.key}/permission_templates` : + '/permission_templates'; + this.context.router.replace(pathname); this.props.refresh(); }).render(); } @@ -65,7 +69,7 @@ export default class ActionsCell extends React.Component { setDefault (qualifier, e) { e.preventDefault(); setDefaultPermissionTemplate( - this.props.permissionTemplate.name, + this.props.permissionTemplate.id, qualifier ).then(this.props.refresh); } @@ -137,7 +141,11 @@ export default class ActionsCell extends React.Component { } render () { - const { permissionTemplate: t } = this.props; + const { permissionTemplate: t, organization } = this.props; + + const pathname = organization ? + `/organizations/${organization.key}/permission_templates` : + '/permission_templates'; return (
    @@ -151,12 +159,12 @@ export default class ActionsCell extends React.Component { {this.renderSetDefaultsControl()} {!this.props.fromDetails && ( -
  • - - {this.renderDropdownIcon()} - Edit Permissions - -
  • +
  • + + {this.renderDropdownIcon()} + Edit Permissions + +
  • )}
  • diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/App.js b/server/sonar-web/src/main/js/apps/permission-templates/components/App.js index 2263339753b..b5e494aa2ed 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/App.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/App.js @@ -30,6 +30,8 @@ import '../../permissions/styles.css'; export default class App extends React.Component { static propTypes = { + location: React.PropTypes.object.isRequired, + organization: React.PropTypes.object, topQualifiers: React.PropTypes.array.isRequired }; @@ -53,7 +55,9 @@ export default class App extends React.Component { } requestPermissions () { - return getPermissionTemplates().then(r => { + const { organization } = this.props; + const request = organization ? getPermissionTemplates(organization.key) : getPermissionTemplates(); + return request.then(r => { if (this.mounted) { const permissions = sortPermissions(r.permissions); const permissionTemplates = mergeDefaultsToTemplates( @@ -77,6 +81,7 @@ export default class App extends React.Component { const template = this.state.permissionTemplates.find(t => t.id === id); return (