aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/quality-profiles/details
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2017-09-25 16:00:06 +0200
committerStas Vilchik <stas.vilchik@sonarsource.com>2017-10-02 17:18:15 +0200
commit77d3e365acbfd9095efe4458c643a9e8ccdada13 (patch)
tree8b19a0ace2cb8b2ce57005b62eec498c17d72866 /server/sonar-web/src/main/js/apps/quality-profiles/details
parent7c42d81e08599b315076118e961361a96df62323 (diff)
downloadsonarqube-77d3e365acbfd9095efe4458c643a9e8ccdada13.tar.gz
sonarqube-77d3e365acbfd9095efe4458c643a9e8ccdada13.zip
SONAR-1330 Allow only authorized actions on the Quality Profiles page
Diffstat (limited to 'server/sonar-web/src/main/js/apps/quality-profiles/details')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx11
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileDetails-test.tsx53
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx22
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileDetails-test.tsx.snap133
8 files changed, 210 insertions, 33 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.tsx
index 59566996434..524a148dadd 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileDetails.tsx
@@ -26,7 +26,6 @@ import ProfilePermissions from './ProfilePermissions';
import { Exporter, Profile } from '../types';
interface Props {
- canAdmin: boolean;
exporters: Exporter[];
onRequestFail: (reasong: any) => void;
organization: string | null;
@@ -36,18 +35,17 @@ interface Props {
}
export default function ProfileDetails(props: Props) {
+ const { profile } = props;
return (
<div>
<div className="quality-profile-grid">
<div className="quality-profile-grid-left">
<ProfileRules {...props} />
<ProfileExporters {...props} />
- {props.canAdmin &&
- !props.profile.isBuiltIn && (
- <ProfilePermissions
- organization={props.organization || undefined}
- profile={props.profile}
- />
+ {profile.actions &&
+ profile.actions.edit &&
+ !profile.isBuiltIn && (
+ <ProfilePermissions organization={props.organization || undefined} profile={profile} />
)}
</div>
<div className="quality-profile-grid-right">
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.tsx
index d0091653d08..5b04d60fdd4 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileHeader.tsx
@@ -33,7 +33,6 @@ import {
import { Profile } from '../types';
interface Props {
- canAdmin: boolean;
onRequestFail: (reasong: any) => void;
profile: Profile;
organization: string | null;
@@ -113,7 +112,6 @@ export default class ProfileHeader extends React.PureComponent<Props> {
{translate('actions')} <i className="icon-dropdown" />
</button>
<ProfileActions
- canAdmin={this.props.canAdmin}
onRequestFail={this.props.onRequestFail}
organization={organization}
profile={profile}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.tsx
index 1e71f1bd612..77f8a92a7f1 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileInheritance.tsx
@@ -26,7 +26,6 @@ import { getProfileInheritance } from '../../../api/quality-profiles';
import { Profile } from '../types';
interface Props {
- canAdmin: boolean;
onRequestFail: (reason: any) => void;
organization: string | null;
profile: Profile;
@@ -120,8 +119,9 @@ export default class ProfileInheritance extends React.PureComponent<Props, State
return (
<div className="boxed-group quality-profile-inheritance">
- {this.props.canAdmin &&
- !this.props.profile.isBuiltIn && (
+ {profile.actions &&
+ profile.actions.edit &&
+ !profile.isBuiltIn && (
<div className="boxed-group-actions">
<button className="pull-right js-change-parent" onClick={this.handleChangeParentClick}>
{translate('quality_profiles.change_parent')}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx
index ca284571441..b809abd6a6f 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileProjects.tsx
@@ -26,7 +26,6 @@ import { translate } from '../../../helpers/l10n';
import { Profile } from '../types';
interface Props {
- canAdmin: boolean;
organization: string | null;
profile: Profile;
updateProfiles: () => Promise<void>;
@@ -127,10 +126,12 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
}
render() {
+ const { profile } = this.props;
return (
<div className="boxed-group quality-profile-projects">
- {this.props.canAdmin &&
- !this.props.profile.isDefault && (
+ {profile.actions &&
+ profile.actions.edit &&
+ !profile.isDefault && (
<div className="boxed-group-actions">
<button className="js-change-projects" onClick={this.handleChangeClick}>
{translate('quality_profiles.change_projects')}
@@ -145,7 +146,7 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
<div className="boxed-group-inner">
{this.state.loading ? (
<i className="spinner" />
- ) : this.props.profile.isDefault ? (
+ ) : profile.isDefault ? (
this.renderDefault()
) : (
this.renderProjects()
@@ -156,7 +157,7 @@ export default class ProfileProjects extends React.PureComponent<Props, State> {
<ChangeProjectsForm
onClose={this.closeForm}
organization={this.props.organization}
- profile={this.props.profile}
+ profile={profile}
/>
)}
</div>
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.tsx
index b9ee6c91fac..a036a636f62 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/ProfileRules.tsx
@@ -33,7 +33,6 @@ import { Profile } from '../types';
const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL'];
interface Props {
- canAdmin: boolean;
organization: string | null;
profile: Profile;
}
@@ -181,7 +180,8 @@ export default class ProfileRules extends React.PureComponent<Props, State> {
</tbody>
</table>
- {this.props.canAdmin &&
+ {profile.actions &&
+ profile.actions.edit &&
!profile.isBuiltIn && (
<div className="text-right big-spacer-top">
<Link to={activateMoreUrl} className="button js-activate-rules">
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileDetails-test.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileDetails-test.tsx
new file mode 100644
index 00000000000..f799c8e3f28
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileDetails-test.tsx
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import ProfileDetails from '../ProfileDetails';
+import { Profile } from '../../types';
+
+it('renders without permissions', () => {
+ expect(
+ shallow(
+ <ProfileDetails
+ exporters={[]}
+ onRequestFail={jest.fn()}
+ organization="org"
+ profile={{} as Profile}
+ profiles={[]}
+ updateProfiles={jest.fn()}
+ />
+ )
+ ).toMatchSnapshot();
+});
+
+it('renders with edit permission', () => {
+ expect(
+ shallow(
+ <ProfileDetails
+ exporters={[]}
+ onRequestFail={jest.fn()}
+ organization="org"
+ profile={{ actions: { edit: true } } as Profile}
+ profiles={[]}
+ updateProfiles={jest.fn()}
+ />
+ )
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx
index 9b282b2e2a1..95a3665df08 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfileRules-test.tsx
@@ -40,6 +40,8 @@ const PROFILE = {
rulesUpdatedAt: '2017-06-28T12:58:44+0000'
};
+const EDITABLE_PROFILE = { ...PROFILE, actions: { edit: true } };
+
const apiResponseAll = {
total: 243,
facets: [
@@ -81,7 +83,7 @@ const apiResponseActive = {
});
it('should render the quality profiles rules with sonarway comparison', () => {
- const wrapper = shallow(<ProfileRules canAdmin={false} organization="foo" profile={PROFILE} />);
+ const wrapper = shallow(<ProfileRules organization="foo" profile={PROFILE} />);
const instance = wrapper.instance() as any;
instance.mounted = true;
instance.loadRules();
@@ -93,16 +95,15 @@ it('should render the quality profiles rules with sonarway comparison', () => {
});
it('should show a button to activate more rules for admins', () => {
- const wrapper = shallow(<ProfileRules canAdmin={true} organization="foo" profile={PROFILE} />);
+ const wrapper = shallow(<ProfileRules organization="foo" profile={EDITABLE_PROFILE} />);
expect(wrapper.find('.js-activate-rules')).toMatchSnapshot();
});
it('should show a deprecated rules warning message', () => {
const wrapper = shallow(
<ProfileRules
- canAdmin={true}
organization="foo"
- profile={{ ...PROFILE, activeDeprecatedRuleCount: 8 }}
+ profile={{ ...EDITABLE_PROFILE, activeDeprecatedRuleCount: 8 }}
/>
);
expect(wrapper.find('ProfileRulesDeprecatedWarning')).toMatchSnapshot();
@@ -110,14 +111,7 @@ it('should show a deprecated rules warning message', () => {
it('should not show a button to activate more rules on built in profiles', () => {
const wrapper = shallow(
- <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
- );
- expect(wrapper.find('.js-activate-rules')).toHaveLength(0);
-});
-
-it('should not show a button to activate more rules on built in profiles', () => {
- const wrapper = shallow(
- <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
+ <ProfileRules organization={null} profile={{ ...EDITABLE_PROFILE, isBuiltIn: true }} />
);
expect(wrapper.find('.js-activate-rules')).toHaveLength(0);
});
@@ -125,7 +119,7 @@ it('should not show a button to activate more rules on built in profiles', () =>
it('should not show sonarway comparison for built in profiles', () => {
(apiQP as any).getQualityProfile = jest.fn(() => Promise.resolve());
const wrapper = shallow(
- <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
+ <ProfileRules organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
);
const instance = wrapper.instance() as any;
instance.mounted = true;
@@ -147,7 +141,7 @@ it('should not show sonarway comparison if there is no missing rules', () => {
}
})
);
- const wrapper = shallow(<ProfileRules canAdmin={true} organization={null} profile={PROFILE} />);
+ const wrapper = shallow(<ProfileRules organization={null} profile={PROFILE} />);
const instance = wrapper.instance() as any;
instance.mounted = true;
instance.loadRules();
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileDetails-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileDetails-test.tsx.snap
new file mode 100644
index 00000000000..85f0f92c7a5
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/__snapshots__/ProfileDetails-test.tsx.snap
@@ -0,0 +1,133 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders with edit permission 1`] = `
+<div>
+ <div
+ className="quality-profile-grid"
+ >
+ <div
+ className="quality-profile-grid-left"
+ >
+ <ProfileRules
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={
+ Object {
+ "actions": Object {
+ "edit": true,
+ },
+ }
+ }
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ <ProfileExporters
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={
+ Object {
+ "actions": Object {
+ "edit": true,
+ },
+ }
+ }
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ <ProfilePermissions
+ organization="org"
+ profile={
+ Object {
+ "actions": Object {
+ "edit": true,
+ },
+ }
+ }
+ />
+ </div>
+ <div
+ className="quality-profile-grid-right"
+ >
+ <ProfileInheritance
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={
+ Object {
+ "actions": Object {
+ "edit": true,
+ },
+ }
+ }
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ <ProfileProjects
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={
+ Object {
+ "actions": Object {
+ "edit": true,
+ },
+ }
+ }
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ </div>
+ </div>
+</div>
+`;
+
+exports[`renders without permissions 1`] = `
+<div>
+ <div
+ className="quality-profile-grid"
+ >
+ <div
+ className="quality-profile-grid-left"
+ >
+ <ProfileRules
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={Object {}}
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ <ProfileExporters
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={Object {}}
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ </div>
+ <div
+ className="quality-profile-grid-right"
+ >
+ <ProfileInheritance
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={Object {}}
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ <ProfileProjects
+ exporters={Array []}
+ onRequestFail={[Function]}
+ organization="org"
+ profile={Object {}}
+ profiles={Array []}
+ updateProfiles={[Function]}
+ />
+ </div>
+ </div>
+</div>
+`;