From 96aa4ae19f1b33ebf4b993b811acbecbc04800bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Tue, 12 Mar 2019 13:46:52 +0100 Subject: [PATCH] teams: remov permission select for non admin users --- .../sidemenu/BottomNavLinks.test.tsx | 1 + public/app/core/services/context_srv.ts | 1 + .../app/features/teams/TeamMembers.test.tsx | 88 +- public/app/features/teams/TeamMembers.tsx | 53 +- .../__snapshots__/TeamMembers.test.tsx.snap | 1664 +++++++++++++---- 5 files changed, 1452 insertions(+), 355 deletions(-) diff --git a/public/app/core/components/sidemenu/BottomNavLinks.test.tsx b/public/app/core/components/sidemenu/BottomNavLinks.test.tsx index b52e5311dc5..5ba4503da13 100644 --- a/public/app/core/components/sidemenu/BottomNavLinks.test.tsx +++ b/public/app/core/components/sidemenu/BottomNavLinks.test.tsx @@ -12,6 +12,7 @@ const setup = (propOverrides?: object) => { { link: {}, user: { + id: 1, isGrafanaAdmin: false, isSignedIn: false, orgCount: 2, diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts index e3b10f129d1..214c7efb782 100644 --- a/public/app/core/services/context_srv.ts +++ b/public/app/core/services/context_srv.ts @@ -3,6 +3,7 @@ import _ from 'lodash'; import coreModule from 'app/core/core_module'; export class User { + id: number; isGrafanaAdmin: any; isSignedIn: any; orgRole: any; diff --git a/public/app/features/teams/TeamMembers.test.tsx b/public/app/features/teams/TeamMembers.test.tsx index f30e0c56325..64609f1fd79 100644 --- a/public/app/features/teams/TeamMembers.test.tsx +++ b/public/app/features/teams/TeamMembers.test.tsx @@ -4,8 +4,25 @@ import { TeamMembers, Props, State } from './TeamMembers'; import { TeamMember, TeamPermissionLevel } from '../../types'; import { getMockTeamMember, getMockTeamMembers } from './__mocks__/teamMocks'; import { SelectOptionItem } from '@grafana/ui'; +import { contextSrv } from 'app/core/services/context_srv'; -const setup = (propOverrides?: object) => { +jest.mock('app/core/services/context_srv', () => ({ + contextSrv: { + isGrafanaAdmin: false, + hasRole: role => false, + user: { id: 1 }, + }, +})); + +const originalContextSrv = contextSrv; + +interface SetupProps { + propOverrides?: object; + isGrafanaAdmin?: boolean; + isOrgAdmin?: boolean; +} + +const setup = (setupProps: SetupProps) => { const props: Props = { members: [] as TeamMember[], searchMemberQuery: '', @@ -15,9 +32,13 @@ const setup = (propOverrides?: object) => { removeTeamMember: jest.fn(), updateTeamMember: jest.fn(), syncEnabled: false, + editorsCanAdmin: false, }; - Object.assign(props, propOverrides); + contextSrv.isGrafanaAdmin = setupProps.isGrafanaAdmin || false; + contextSrv.hasRole = role => setupProps.isOrgAdmin || false; + + Object.assign(props, setupProps.propOverrides); const wrapper = shallow(); const instance = wrapper.instance() as TeamMembers; @@ -29,15 +50,22 @@ const setup = (propOverrides?: object) => { }; describe('Render', () => { + beforeEach(() => { + contextSrv.isGrafanaAdmin = originalContextSrv.isGrafanaAdmin; + contextSrv.hasRole = originalContextSrv.hasRole; + }); + it('should render component', () => { - const { wrapper } = setup(); + const { wrapper } = setup({}); expect(wrapper).toMatchSnapshot(); }); it('should render team members', () => { const { wrapper } = setup({ - members: getMockTeamMembers(5), + propOverrides: { + members: getMockTeamMembers(5), + }, }); expect(wrapper).toMatchSnapshot(); @@ -45,18 +73,58 @@ describe('Render', () => { it('should render team members when sync enabled', () => { const { wrapper } = setup({ - members: getMockTeamMembers(5), - syncEnabled: true, + propOverrides: { + members: getMockTeamMembers(5), + syncEnabled: true, + }, }); expect(wrapper).toMatchSnapshot(); }); + + describe('when feature toggle editorsCanAdmin is turned on', () => { + it('should render permissions select if user is Grafana Admin', () => { + const members = getMockTeamMembers(5); + members[4].permission = TeamPermissionLevel.Admin; + const { wrapper } = setup({ + propOverrides: { members, editorsCanAdmin: true }, + isGrafanaAdmin: true, + isOrgAdmin: false, + }); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render permissions select if user is Org Admin', () => { + const members = getMockTeamMembers(5); + members[4].permission = TeamPermissionLevel.Admin; + const { wrapper } = setup({ + propOverrides: { members, editorsCanAdmin: true }, + isGrafanaAdmin: false, + isOrgAdmin: true, + }); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render permissions select if user is team admin', () => { + const members = getMockTeamMembers(5); + members[0].permission = TeamPermissionLevel.Admin; + const { wrapper } = setup({ + propOverrides: { members, editorsCanAdmin: true }, + isGrafanaAdmin: false, + isOrgAdmin: false, + }); + + expect(wrapper).toMatchSnapshot(); + }); + }); }); describe('Functions', () => { describe('on search member query change', () => { it('it should call setSearchMemberQuery', () => { - const { instance } = setup(); + const { instance } = setup({}); instance.onSearchQueryChange('member'); @@ -65,7 +133,7 @@ describe('Functions', () => { }); describe('on remove member', () => { - const { instance } = setup(); + const { instance } = setup({}); const mockTeamMember = getMockTeamMember(); instance.onRemoveMember(mockTeamMember); @@ -74,7 +142,7 @@ describe('Functions', () => { }); describe('on add user to team', () => { - const { wrapper, instance } = setup(); + const { wrapper, instance } = setup({}); const state = wrapper.state() as State; state.newTeamMember = { @@ -90,7 +158,7 @@ describe('Functions', () => { }); describe('on update permision for user in team', () => { - const { instance } = setup(); + const { instance } = setup({}); const permission = TeamPermissionLevel.Admin; const item: SelectOptionItem = { value: permission }; const member: TeamMember = { diff --git a/public/app/features/teams/TeamMembers.tsx b/public/app/features/teams/TeamMembers.tsx index bcb2f3fab4b..89ad24f9c58 100644 --- a/public/app/features/teams/TeamMembers.tsx +++ b/public/app/features/teams/TeamMembers.tsx @@ -4,7 +4,7 @@ import SlideDown from 'app/core/components/Animations/SlideDown'; import { UserPicker } from 'app/core/components/Select/UserPicker'; import { DeleteButton, Select, SelectOptionItem } from '@grafana/ui'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; -import { TeamMember, User, teamsPermissionLevels } from 'app/types'; +import { TeamMember, User, teamsPermissionLevels, TeamPermissionLevel, OrgRole } from 'app/types'; import { loadTeamMembers, addTeamMember, @@ -16,6 +16,7 @@ import { getSearchMemberQuery, getTeamMembers } from './state/selectors'; import { FilterInput } from 'app/core/components/FilterInput/FilterInput'; import { WithFeatureToggle } from 'app/core/components/WithFeatureToggle'; import { config } from 'app/core/config'; +import { contextSrv } from 'app/core/services/context_srv'; export interface Props { members: TeamMember[]; @@ -26,6 +27,7 @@ export interface Props { setSearchMemberQuery: typeof setSearchMemberQuery; updateTeamMember: typeof updateTeamMember; syncEnabled: boolean; + editorsCanAdmin?: boolean; } export interface State { @@ -37,6 +39,7 @@ export class TeamMembers extends PureComponent { constructor(props) { super(props); this.state = { isAdding: false, newTeamMember: null }; + this.renderPermissionsSelect = this.renderPermissionsSelect.bind(this); } componentDidMount() { @@ -85,6 +88,35 @@ export class TeamMembers extends PureComponent { this.props.updateTeamMember(updatedTeamMember); }; + renderPermissionsSelect(member: TeamMember) { + const { members, editorsCanAdmin } = this.props; + const userInMembers = members.find(m => m.userId === contextSrv.user.id); + const isUserTeamAdmin = + contextSrv.isGrafanaAdmin || contextSrv.hasRole(OrgRole.Admin) + ? true + : userInMembers && userInMembers.permission === TeamPermissionLevel.Admin; + const value = teamsPermissionLevels.find(dp => dp.value === member.permission); + + return ( + + +
+ {isUserTeamAdmin && ( + this.onPermissionChange(item, member)} - className="gf-form-select-box__control--menu-right" - value={teamsPermissionLevels.find(dp => dp.value === member.permission)} - /> -
- -
+ {this.renderPermissionsSelect(member)} {syncEnabled && this.renderLabels(member.labels)} this.onRemoveMember(member)} /> @@ -116,7 +136,7 @@ export class TeamMembers extends PureComponent { render() { const { isAdding } = this.state; - const { searchMemberQuery, members, syncEnabled } = this.props; + const { searchMemberQuery, members, syncEnabled, editorsCanAdmin } = this.props; return (
@@ -161,7 +181,7 @@ export class TeamMembers extends PureComponent { Name Email - + Permission {syncEnabled && } @@ -180,6 +200,7 @@ function mapStateToProps(state) { return { members: getTeamMembers(state.team), searchMemberQuery: getSearchMemberQuery(state.team), + editorsCanAdmin: config.editorsCanAdmin, // this makes the feature toggle mockable/controllable from tests, }; } diff --git a/public/app/features/teams/__snapshots__/TeamMembers.test.tsx.snap b/public/app/features/teams/__snapshots__/TeamMembers.test.tsx.snap index 01d7b40ec61..d8540ed0615 100644 --- a/public/app/features/teams/__snapshots__/TeamMembers.test.tsx.snap +++ b/public/app/features/teams/__snapshots__/TeamMembers.test.tsx.snap @@ -201,41 +201,9 @@ exports[`Render should render team members 1`] = `
- + + Member +
@@ -341,41 +277,9 @@ exports[`Render should render team members 1`] = `
- + + Member +
@@ -481,41 +353,9 @@ exports[`Render should render team members 1`] = `
- + + Member +
@@ -730,41 +538,9 @@ exports[`Render should render team members when sync enabled 1`] = `
- + + Member +
@@ -902,41 +646,9 @@ exports[`Render should render team members when sync enabled 1`] = `
- +
+ + + + + + + + + + + + testUser-3 + + + test@test.com + + + +
+ +
+ +
+ + + + + + + + + + testUser-5 + + + test@test.com + + + +
+ +
+ +
+ + + + + + + + + + testUser-2 + + + test@test.com + + + +
+ +
+ +
+ + + + + + + + + + testUser-4 + + + test@test.com + + + +
+ +
+ +
+ + + + + + +
+
+`; + +exports[`Render when feature toggle editorsCanAdmin is turned on should render permissions select if user is team admin 1`] = ` +
+
+
+ +
+
+ +
+ +
+ +
+ Add team member +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Name + + Email + + Permission + +
+ + + testUser-1 + + test@test.com + +
+
+ +
+ + + testUser-2 + + test@test.com + +
+
+ +
+ + + testUser-3 + + test@test.com + +
+
+ +
+ + + testUser-4 + + test@test.com + +
+
+ +
+ + + testUser-5 + + test@test.com + +
+