Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
13ed1049
Commit
13ed1049
authored
Mar 14, 2019
by
Hugo Häggmark
Committed by
Leonard Gram
Mar 19, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
teams: hide tabs settings and groupsync for non team admins
parent
d1481cac
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
215 additions
and
109 deletions
+215
-109
public/app/features/teams/TeamMembers.test.tsx
+0
-82
public/app/features/teams/TeamMembers.tsx
+7
-15
public/app/features/teams/TeamPages.test.tsx
+51
-1
public/app/features/teams/TeamPages.tsx
+24
-8
public/app/features/teams/__snapshots__/TeamPages.test.tsx.snap
+22
-0
public/app/features/teams/state/selectors.test.ts
+94
-2
public/app/features/teams/state/selectors.ts
+17
-1
No files found.
public/app/features/teams/TeamMembers.test.tsx
View file @
13ed1049
...
...
@@ -74,86 +74,4 @@ describe('Functions', () => {
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
);
});
});
});
});
public/app/features/teams/TeamMembers.tsx
View file @
13ed1049
...
...
@@ -3,9 +3,9 @@ import { connect } from 'react-redux';
import
SlideDown
from
'app/core/components/Animations/SlideDown'
;
import
{
UserPicker
}
from
'app/core/components/Select/UserPicker'
;
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
{
getSearchMemberQuery
,
getTeamMembers
}
from
'./state/selectors'
;
import
{
getSearchMemberQuery
,
getTeamMembers
,
isSignedInUserTeamAdmin
}
from
'./state/selectors'
;
import
{
FilterInput
}
from
'app/core/components/FilterInput/FilterInput'
;
import
{
WithFeatureToggle
}
from
'app/core/components/WithFeatureToggle'
;
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
()
{
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
(
<
div
>
<
div
className=
"page-action-bar"
>
...
...
@@ -100,7 +92,7 @@ export class TeamMembers extends PureComponent<Props, State> {
<
button
className=
"btn btn-primary pull-right"
onClick=
{
this
.
onToggleAdding
}
disabled=
{
isAdding
||
!
this
.
isSignedInUserTeamAdmin
()
}
disabled=
{
isAdding
||
!
isTeamAdmin
}
>
Add member
</
button
>
...
...
@@ -145,7 +137,7 @@ export class TeamMembers extends PureComponent<Props, State> {
member=
{
member
}
syncEnabled=
{
syncEnabled
}
editorsCanAdmin=
{
editorsCanAdmin
}
signedInUserIsTeamAdmin=
{
this
.
isSignedInUserTeamAdmin
()
}
signedInUserIsTeamAdmin=
{
isTeamAdmin
}
/>
))
}
</
tbody
>
...
...
public/app/features/teams/TeamPages.test.tsx
View file @
13ed1049
import
React
from
'react'
;
import
{
shallow
}
from
'enzyme'
;
import
{
TeamPages
,
Props
}
from
'./TeamPages'
;
import
{
NavModel
,
Team
}
from
'../../types'
;
import
{
NavModel
,
Team
,
TeamMember
,
OrgRole
}
from
'../../types'
;
import
{
getMockTeam
}
from
'./__mocks__/teamMocks'
;
import
{
User
}
from
'app/core/services/context_srv'
;
jest
.
mock
(
'app/core/config'
,
()
=>
({
buildInfo
:
{
isEnterprise
:
true
},
...
...
@@ -15,6 +16,13 @@ const setup = (propOverrides?: object) => {
loadTeam
:
jest
.
fn
(),
pageName
:
'members'
,
team
:
{}
as
Team
,
members
:
[]
as
TeamMember
[],
editorsCanAdmin
:
false
,
signedInUser
:
{
id
:
1
,
isGrafanaAdmin
:
false
,
orgRole
:
OrgRole
.
Viewer
,
}
as
User
,
};
Object
.
assign
(
props
,
propOverrides
);
...
...
@@ -65,4 +73,46 @@ describe('Render', () => {
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
();
});
});
});
public/app/features/teams/TeamPages.tsx
View file @
13ed1049
...
...
@@ -7,12 +7,13 @@ import Page from 'app/core/components/Page/Page';
import
TeamMembers
from
'./TeamMembers'
;
import
TeamSettings
from
'./TeamSettings'
;
import
TeamGroupSync
from
'./TeamGroupSync'
;
import
{
NavModel
,
Team
}
from
'app/types'
;
import
{
NavModel
,
Team
,
TeamMember
}
from
'app/types'
;
import
{
loadTeam
}
from
'./state/actions'
;
import
{
getTeam
}
from
'./state/selectors'
;
import
{
getTeam
,
getTeamMembers
,
isSignedInUserTeamAdmin
}
from
'./state/selectors'
;
import
{
getTeamLoadingNav
}
from
'./state/navModel'
;
import
{
getNavModel
}
from
'app/core/selectors/navModel'
;
import
{
getRouteParamsId
,
getRouteParamsPage
}
from
'../../core/selectors/location'
;
import
{
contextSrv
,
User
}
from
'app/core/services/context_srv'
;
export
interface
Props
{
team
:
Team
;
...
...
@@ -20,6 +21,9 @@ export interface Props {
teamId
:
number
;
pageName
:
string
;
navModel
:
NavModel
;
members
?:
TeamMember
[];
editorsCanAdmin
?:
boolean
;
signedInUser
?:
User
;
}
interface
State
{
...
...
@@ -61,7 +65,15 @@ export class TeamPages extends PureComponent<Props, State> {
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
currentPage
=
this
.
getCurrentPage
();
...
...
@@ -70,21 +82,22 @@ export class TeamPages extends PureComponent<Props, State> {
return
<
TeamMembers
syncEnabled=
{
isSyncEnabled
}
/>;
case
PageTypes
.
Settings
:
return
<
TeamSettings
/>;
return
isSignedInUserTeamAdmin
&&
<
TeamSettings
/>;
case
PageTypes
.
GroupSync
:
return
isSyncEnabled
&&
<
TeamGroupSync
/>;
return
isS
ignedInUserTeamAdmin
&&
isS
yncEnabled
&&
<
TeamGroupSync
/>;
}
return
null
;
}
render
()
{
const
{
team
,
navModel
}
=
this
.
props
;
const
{
team
,
navModel
,
members
,
editorsCanAdmin
,
signedInUser
}
=
this
.
props
;
const
isTeamAdmin
=
isSignedInUserTeamAdmin
({
members
,
editorsCanAdmin
,
signedInUser
});
return
(
<
Page
navModel=
{
navModel
}
>
<
Page
navModel=
{
this
.
hideTabsFromNonTeamAdmin
(
navModel
,
isTeamAdmin
)
}
>
<
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
>
);
...
...
@@ -101,6 +114,9 @@ function mapStateToProps(state) {
teamId
:
teamId
,
pageName
:
pageName
,
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,
};
}
...
...
public/app/features/teams/__snapshots__/TeamPages.test.tsx.snap
View file @
13ed1049
...
...
@@ -47,3 +47,25 @@ exports[`Render should render settings and preferences page 1`] = `
</PageContents>
</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>
`;
public/app/features/teams/state/selectors.test.ts
View file @
13ed1049
import
{
getTeam
,
getTeamMembers
,
getTeams
}
from
'./selectors'
;
import
{
getTeam
,
getTeamMembers
,
getTeams
,
isSignedInUserTeamAdmin
,
Config
}
from
'./selectors'
;
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
(
'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
);
});
});
});
public/app/features/teams/state/selectors.ts
View file @
13ed1049
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
getSearchMemberQuery
=
(
state
:
TeamState
)
=>
state
.
searchMemberQuery
;
...
...
@@ -28,3 +29,18 @@ export const getTeamMembers = (state: TeamState) => {
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
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment