mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
teams: hide tabs settings and groupsync for non team admins
This commit is contained in:
committed by
Leonard Gram
parent
d1481cac50
commit
13ed10495a
@@ -74,86 +74,4 @@ describe('Functions', () => {
|
|||||||
|
|
||||||
expect(instance.props.addTeamMember).toHaveBeenCalledWith(1);
|
expect(instance.props.addTeamMember).toHaveBeenCalledWith(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isSignedInUserTeamAdmin', () => {
|
|
||||||
describe('when feature toggle editorsCanAdmin is turned off', () => {
|
|
||||||
it('should return true', () => {
|
|
||||||
const { instance } = setup({ editorsCanAdmin: false });
|
|
||||||
|
|
||||||
const result = instance.isSignedInUserTeamAdmin();
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when feature toggle editorsCanAdmin is turned on', () => {
|
|
||||||
it('should return true if signed in user is grafanaAdmin', () => {
|
|
||||||
const members = getMockTeamMembers(5, 5);
|
|
||||||
const { instance } = setup({
|
|
||||||
members,
|
|
||||||
editorsCanAdmin: true,
|
|
||||||
signedInUser: {
|
|
||||||
id: signedInUserId,
|
|
||||||
isGrafanaAdmin: true,
|
|
||||||
orgRole: OrgRole.Viewer,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = instance.isSignedInUserTeamAdmin();
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if signed in user is org admin', () => {
|
|
||||||
const members = getMockTeamMembers(5, 5);
|
|
||||||
const { instance } = setup({
|
|
||||||
members,
|
|
||||||
editorsCanAdmin: true,
|
|
||||||
signedInUser: {
|
|
||||||
id: signedInUserId,
|
|
||||||
isGrafanaAdmin: false,
|
|
||||||
orgRole: OrgRole.Admin,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = instance.isSignedInUserTeamAdmin();
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if signed in user is team admin', () => {
|
|
||||||
const members = getMockTeamMembers(5, signedInUserId);
|
|
||||||
const { instance } = setup({
|
|
||||||
members,
|
|
||||||
editorsCanAdmin: true,
|
|
||||||
signedInUser: {
|
|
||||||
id: signedInUserId,
|
|
||||||
isGrafanaAdmin: false,
|
|
||||||
orgRole: OrgRole.Viewer,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = instance.isSignedInUserTeamAdmin();
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if signed in user is not grafanaAdmin, org admin or team admin', () => {
|
|
||||||
const members = getMockTeamMembers(5, 5);
|
|
||||||
const { instance } = setup({
|
|
||||||
members,
|
|
||||||
editorsCanAdmin: true,
|
|
||||||
signedInUser: {
|
|
||||||
id: signedInUserId,
|
|
||||||
isGrafanaAdmin: false,
|
|
||||||
orgRole: OrgRole.Viewer,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = instance.isSignedInUserTeamAdmin();
|
|
||||||
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { connect } from 'react-redux';
|
|||||||
import SlideDown from 'app/core/components/Animations/SlideDown';
|
import SlideDown from 'app/core/components/Animations/SlideDown';
|
||||||
import { UserPicker } from 'app/core/components/Select/UserPicker';
|
import { UserPicker } from 'app/core/components/Select/UserPicker';
|
||||||
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
||||||
import { TeamMember, User, TeamPermissionLevel, OrgRole } from 'app/types';
|
import { TeamMember, User } from 'app/types';
|
||||||
import { loadTeamMembers, addTeamMember, setSearchMemberQuery } from './state/actions';
|
import { loadTeamMembers, addTeamMember, setSearchMemberQuery } from './state/actions';
|
||||||
import { getSearchMemberQuery, getTeamMembers } from './state/selectors';
|
import { getSearchMemberQuery, getTeamMembers, isSignedInUserTeamAdmin } from './state/selectors';
|
||||||
import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
|
import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
|
||||||
import { WithFeatureToggle } from 'app/core/components/WithFeatureToggle';
|
import { WithFeatureToggle } from 'app/core/components/WithFeatureToggle';
|
||||||
import { config } from 'app/core/config';
|
import { config } from 'app/core/config';
|
||||||
@@ -69,19 +69,11 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isSignedInUserTeamAdmin = (): boolean => {
|
|
||||||
const { members, editorsCanAdmin, signedInUser } = this.props;
|
|
||||||
const userInMembers = members.find(m => m.userId === signedInUser.id);
|
|
||||||
const isAdmin = signedInUser.isGrafanaAdmin || signedInUser.orgRole === OrgRole.Admin;
|
|
||||||
const userIsTeamAdmin = userInMembers && userInMembers.permission === TeamPermissionLevel.Admin;
|
|
||||||
const isSignedInUserTeamAdmin = isAdmin || userIsTeamAdmin;
|
|
||||||
|
|
||||||
return isSignedInUserTeamAdmin || !editorsCanAdmin;
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isAdding } = this.state;
|
const { isAdding } = this.state;
|
||||||
const { searchMemberQuery, members, syncEnabled, editorsCanAdmin } = this.props;
|
const { searchMemberQuery, members, syncEnabled, editorsCanAdmin, signedInUser } = this.props;
|
||||||
|
const isTeamAdmin = isSignedInUserTeamAdmin({ members, editorsCanAdmin, signedInUser });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="page-action-bar">
|
<div className="page-action-bar">
|
||||||
@@ -100,7 +92,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
<button
|
<button
|
||||||
className="btn btn-primary pull-right"
|
className="btn btn-primary pull-right"
|
||||||
onClick={this.onToggleAdding}
|
onClick={this.onToggleAdding}
|
||||||
disabled={isAdding || !this.isSignedInUserTeamAdmin()}
|
disabled={isAdding || !isTeamAdmin}
|
||||||
>
|
>
|
||||||
Add member
|
Add member
|
||||||
</button>
|
</button>
|
||||||
@@ -145,7 +137,7 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
member={member}
|
member={member}
|
||||||
syncEnabled={syncEnabled}
|
syncEnabled={syncEnabled}
|
||||||
editorsCanAdmin={editorsCanAdmin}
|
editorsCanAdmin={editorsCanAdmin}
|
||||||
signedInUserIsTeamAdmin={this.isSignedInUserTeamAdmin()}
|
signedInUserIsTeamAdmin={isTeamAdmin}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { TeamPages, Props } from './TeamPages';
|
import { TeamPages, Props } from './TeamPages';
|
||||||
import { NavModel, Team } from '../../types';
|
import { NavModel, Team, TeamMember, OrgRole } from '../../types';
|
||||||
import { getMockTeam } from './__mocks__/teamMocks';
|
import { getMockTeam } from './__mocks__/teamMocks';
|
||||||
|
import { User } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
jest.mock('app/core/config', () => ({
|
jest.mock('app/core/config', () => ({
|
||||||
buildInfo: { isEnterprise: true },
|
buildInfo: { isEnterprise: true },
|
||||||
@@ -15,6 +16,13 @@ const setup = (propOverrides?: object) => {
|
|||||||
loadTeam: jest.fn(),
|
loadTeam: jest.fn(),
|
||||||
pageName: 'members',
|
pageName: 'members',
|
||||||
team: {} as Team,
|
team: {} as Team,
|
||||||
|
members: [] as TeamMember[],
|
||||||
|
editorsCanAdmin: false,
|
||||||
|
signedInUser: {
|
||||||
|
id: 1,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Viewer,
|
||||||
|
} as User,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(props, propOverrides);
|
Object.assign(props, propOverrides);
|
||||||
@@ -65,4 +73,46 @@ describe('Render', () => {
|
|||||||
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when feature toggle editorsCanAdmin is turned on', () => {
|
||||||
|
it('should render settings page if user is team admin', () => {
|
||||||
|
const { wrapper } = setup({
|
||||||
|
team: getMockTeam(),
|
||||||
|
pageName: 'settings',
|
||||||
|
preferences: {
|
||||||
|
homeDashboardId: 1,
|
||||||
|
theme: 'Default',
|
||||||
|
timezone: 'Default',
|
||||||
|
},
|
||||||
|
editorsCanAdmin: true,
|
||||||
|
signedInUser: {
|
||||||
|
id: 1,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Admin,
|
||||||
|
} as User,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render settings page if user is team member', () => {
|
||||||
|
const { wrapper } = setup({
|
||||||
|
team: getMockTeam(),
|
||||||
|
pageName: 'settings',
|
||||||
|
preferences: {
|
||||||
|
homeDashboardId: 1,
|
||||||
|
theme: 'Default',
|
||||||
|
timezone: 'Default',
|
||||||
|
},
|
||||||
|
editorsCanAdmin: true,
|
||||||
|
signedInUser: {
|
||||||
|
id: 1,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Viewer,
|
||||||
|
} as User,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import Page from 'app/core/components/Page/Page';
|
|||||||
import TeamMembers from './TeamMembers';
|
import TeamMembers from './TeamMembers';
|
||||||
import TeamSettings from './TeamSettings';
|
import TeamSettings from './TeamSettings';
|
||||||
import TeamGroupSync from './TeamGroupSync';
|
import TeamGroupSync from './TeamGroupSync';
|
||||||
import { NavModel, Team } from 'app/types';
|
import { NavModel, Team, TeamMember } from 'app/types';
|
||||||
import { loadTeam } from './state/actions';
|
import { loadTeam } from './state/actions';
|
||||||
import { getTeam } from './state/selectors';
|
import { getTeam, getTeamMembers, isSignedInUserTeamAdmin } from './state/selectors';
|
||||||
import { getTeamLoadingNav } from './state/navModel';
|
import { getTeamLoadingNav } from './state/navModel';
|
||||||
import { getNavModel } from 'app/core/selectors/navModel';
|
import { getNavModel } from 'app/core/selectors/navModel';
|
||||||
import { getRouteParamsId, getRouteParamsPage } from '../../core/selectors/location';
|
import { getRouteParamsId, getRouteParamsPage } from '../../core/selectors/location';
|
||||||
|
import { contextSrv, User } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
team: Team;
|
team: Team;
|
||||||
@@ -20,6 +21,9 @@ export interface Props {
|
|||||||
teamId: number;
|
teamId: number;
|
||||||
pageName: string;
|
pageName: string;
|
||||||
navModel: NavModel;
|
navModel: NavModel;
|
||||||
|
members?: TeamMember[];
|
||||||
|
editorsCanAdmin?: boolean;
|
||||||
|
signedInUser?: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@@ -61,7 +65,15 @@ export class TeamPages extends PureComponent<Props, State> {
|
|||||||
return _.includes(pages, currentPage) ? currentPage : pages[0];
|
return _.includes(pages, currentPage) ? currentPage : pages[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPage() {
|
hideTabsFromNonTeamAdmin = (navModel: NavModel, isSignedInUserTeamAdmin: boolean) => {
|
||||||
|
if (!isSignedInUserTeamAdmin && navModel.main && navModel.main.children) {
|
||||||
|
navModel.main.children = navModel.main.children.filter(navItem => navItem.text === 'Members');
|
||||||
|
}
|
||||||
|
|
||||||
|
return navModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderPage(isSignedInUserTeamAdmin: boolean) {
|
||||||
const { isSyncEnabled } = this.state;
|
const { isSyncEnabled } = this.state;
|
||||||
const currentPage = this.getCurrentPage();
|
const currentPage = this.getCurrentPage();
|
||||||
|
|
||||||
@@ -70,21 +82,22 @@ export class TeamPages extends PureComponent<Props, State> {
|
|||||||
return <TeamMembers syncEnabled={isSyncEnabled} />;
|
return <TeamMembers syncEnabled={isSyncEnabled} />;
|
||||||
|
|
||||||
case PageTypes.Settings:
|
case PageTypes.Settings:
|
||||||
return <TeamSettings />;
|
return isSignedInUserTeamAdmin && <TeamSettings />;
|
||||||
case PageTypes.GroupSync:
|
case PageTypes.GroupSync:
|
||||||
return isSyncEnabled && <TeamGroupSync />;
|
return isSignedInUserTeamAdmin && isSyncEnabled && <TeamGroupSync />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { team, navModel } = this.props;
|
const { team, navModel, members, editorsCanAdmin, signedInUser } = this.props;
|
||||||
|
const isTeamAdmin = isSignedInUserTeamAdmin({ members, editorsCanAdmin, signedInUser });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page navModel={navModel}>
|
<Page navModel={this.hideTabsFromNonTeamAdmin(navModel, isTeamAdmin)}>
|
||||||
<Page.Contents isLoading={this.state.isLoading}>
|
<Page.Contents isLoading={this.state.isLoading}>
|
||||||
{team && Object.keys(team).length !== 0 && this.renderPage()}
|
{team && Object.keys(team).length !== 0 && this.renderPage(isTeamAdmin)}
|
||||||
</Page.Contents>
|
</Page.Contents>
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
@@ -101,6 +114,9 @@ function mapStateToProps(state) {
|
|||||||
teamId: teamId,
|
teamId: teamId,
|
||||||
pageName: pageName,
|
pageName: pageName,
|
||||||
team: getTeam(state.team, teamId),
|
team: getTeam(state.team, teamId),
|
||||||
|
members: getTeamMembers(state.team),
|
||||||
|
editorsCanAdmin: config.editorsCanAdmin, // this makes the feature toggle mockable/controllable from tests,
|
||||||
|
signedInUser: contextSrv.user, // this makes the feature toggle mockable/controllable from tests,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,3 +47,25 @@ exports[`Render should render settings and preferences page 1`] = `
|
|||||||
</PageContents>
|
</PageContents>
|
||||||
</Page>
|
</Page>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Render when feature toggle editorsCanAdmin is turned on should not render settings page if user is team member 1`] = `
|
||||||
|
<Page
|
||||||
|
navModel={Object {}}
|
||||||
|
>
|
||||||
|
<PageContents
|
||||||
|
isLoading={true}
|
||||||
|
/>
|
||||||
|
</Page>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Render when feature toggle editorsCanAdmin is turned on should render settings page if user is team admin 1`] = `
|
||||||
|
<Page
|
||||||
|
navModel={Object {}}
|
||||||
|
>
|
||||||
|
<PageContents
|
||||||
|
isLoading={true}
|
||||||
|
>
|
||||||
|
<Connect(TeamSettings) />
|
||||||
|
</PageContents>
|
||||||
|
</Page>
|
||||||
|
`;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { getTeam, getTeamMembers, getTeams } from './selectors';
|
import { getTeam, getTeamMembers, getTeams, isSignedInUserTeamAdmin, Config } from './selectors';
|
||||||
import { getMockTeam, getMockTeamMembers, getMultipleMockTeams } from '../__mocks__/teamMocks';
|
import { getMockTeam, getMockTeamMembers, getMultipleMockTeams } from '../__mocks__/teamMocks';
|
||||||
import { Team, TeamGroup, TeamsState, TeamState } from '../../../types';
|
import { Team, TeamGroup, TeamsState, TeamState, OrgRole } from '../../../types';
|
||||||
|
import { User } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
describe('Teams selectors', () => {
|
describe('Teams selectors', () => {
|
||||||
describe('Get teams', () => {
|
describe('Get teams', () => {
|
||||||
@@ -55,3 +56,94 @@ describe('Team selectors', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const signedInUserId = 1;
|
||||||
|
|
||||||
|
const setup = (configOverrides?: Partial<Config>) => {
|
||||||
|
const defaultConfig: Config = {
|
||||||
|
editorsCanAdmin: false,
|
||||||
|
members: getMockTeamMembers(5, 5),
|
||||||
|
signedInUser: {
|
||||||
|
id: signedInUserId,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Viewer,
|
||||||
|
} as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
return { ...defaultConfig, ...configOverrides };
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('isSignedInUserTeamAdmin', () => {
|
||||||
|
describe('when feature toggle editorsCanAdmin is turned off', () => {
|
||||||
|
it('should return true', () => {
|
||||||
|
const config = setup();
|
||||||
|
|
||||||
|
const result = isSignedInUserTeamAdmin(config);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when feature toggle editorsCanAdmin is turned on', () => {
|
||||||
|
it('should return true if signed in user is grafanaAdmin', () => {
|
||||||
|
const config = setup({
|
||||||
|
editorsCanAdmin: true,
|
||||||
|
signedInUser: {
|
||||||
|
id: signedInUserId,
|
||||||
|
isGrafanaAdmin: true,
|
||||||
|
orgRole: OrgRole.Viewer,
|
||||||
|
} as User,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = isSignedInUserTeamAdmin(config);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if signed in user is org admin', () => {
|
||||||
|
const config = setup({
|
||||||
|
editorsCanAdmin: true,
|
||||||
|
signedInUser: {
|
||||||
|
id: signedInUserId,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Admin,
|
||||||
|
} as User,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = isSignedInUserTeamAdmin(config);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if signed in user is team admin', () => {
|
||||||
|
const config = setup({
|
||||||
|
members: getMockTeamMembers(5, signedInUserId),
|
||||||
|
editorsCanAdmin: true,
|
||||||
|
signedInUser: {
|
||||||
|
id: signedInUserId,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Viewer,
|
||||||
|
} as User,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = isSignedInUserTeamAdmin(config);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if signed in user is not grafanaAdmin, org admin or team admin', () => {
|
||||||
|
const config = setup({
|
||||||
|
editorsCanAdmin: true,
|
||||||
|
signedInUser: {
|
||||||
|
id: signedInUserId,
|
||||||
|
isGrafanaAdmin: false,
|
||||||
|
orgRole: OrgRole.Viewer,
|
||||||
|
} as User,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = isSignedInUserTeamAdmin(config);
|
||||||
|
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Team, TeamsState, TeamState } from 'app/types';
|
import { Team, TeamsState, TeamState, TeamMember, OrgRole, TeamPermissionLevel } from 'app/types';
|
||||||
|
import { User } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
export const getSearchQuery = (state: TeamsState) => state.searchQuery;
|
export const getSearchQuery = (state: TeamsState) => state.searchQuery;
|
||||||
export const getSearchMemberQuery = (state: TeamState) => state.searchMemberQuery;
|
export const getSearchMemberQuery = (state: TeamState) => state.searchMemberQuery;
|
||||||
@@ -28,3 +29,18 @@ export const getTeamMembers = (state: TeamState) => {
|
|||||||
return regex.test(member.login) || regex.test(member.email);
|
return regex.test(member.login) || regex.test(member.email);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface Config {
|
||||||
|
members: TeamMember[];
|
||||||
|
editorsCanAdmin: boolean;
|
||||||
|
signedInUser: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isSignedInUserTeamAdmin = (config: Config): boolean => {
|
||||||
|
const userInMembers = config.members.find(m => m.userId === config.signedInUser.id);
|
||||||
|
const isAdmin = config.signedInUser.isGrafanaAdmin || config.signedInUser.orgRole === OrgRole.Admin;
|
||||||
|
const userIsTeamAdmin = userInMembers && userInMembers.permission === TeamPermissionLevel.Admin;
|
||||||
|
const isSignedInUserTeamAdmin = isAdmin || userIsTeamAdmin;
|
||||||
|
|
||||||
|
return isSignedInUserTeamAdmin || !config.editorsCanAdmin;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user