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
53c74fa2
Commit
53c74fa2
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: refactor so that you can only delete teams if you are team admin
parent
a615b78f
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
53 additions
and
9 deletions
+53
-9
pkg/models/team.go
+1
-0
pkg/services/sqlstore/team.go
+15
-2
public/app/features/teams/TeamList.tsx
+5
-2
public/app/features/teams/__mocks__/teamMocks.ts
+2
-0
public/app/features/teams/__snapshots__/TeamList.test.tsx.snap
+7
-0
public/app/features/teams/state/navModel.ts
+2
-1
public/app/features/teams/state/selectors.ts
+18
-4
public/app/types/teams.ts
+3
-0
No files found.
pkg/models/team.go
View file @
53c74fa2
...
@@ -79,6 +79,7 @@ type TeamDTO struct {
...
@@ -79,6 +79,7 @@ type TeamDTO struct {
Email
string
`json:"email"`
Email
string
`json:"email"`
AvatarUrl
string
`json:"avatarUrl"`
AvatarUrl
string
`json:"avatarUrl"`
MemberCount
int64
`json:"memberCount"`
MemberCount
int64
`json:"memberCount"`
Permission
PermissionType
`json:"permission"`
}
}
type
SearchTeamQueryResult
struct
{
type
SearchTeamQueryResult
struct
{
...
...
pkg/services/sqlstore/team.go
View file @
53c74fa2
...
@@ -23,6 +23,18 @@ func init() {
...
@@ -23,6 +23,18 @@ func init() {
bus
.
AddHandler
(
"sql"
,
GetTeamMembers
)
bus
.
AddHandler
(
"sql"
,
GetTeamMembers
)
}
}
func
getTeamSearchSqlBase
()
string
{
return
`SELECT
team.id as id,
team.org_id,
team.name as name,
team.email as email,
(SELECT COUNT(*) from team_member where team_member.team_id = team.id) as member_count,
team_member.permission
FROM team as team
INNER JOIN team_member on team.id = team_member.team_id AND team_member.user_id = ? `
}
func
getTeamSelectSqlBase
()
string
{
func
getTeamSelectSqlBase
()
string
{
return
`SELECT
return
`SELECT
team.id as id,
team.id as id,
...
@@ -146,10 +158,11 @@ func SearchTeams(query *m.SearchTeamsQuery) error {
...
@@ -146,10 +158,11 @@ func SearchTeams(query *m.SearchTeamsQuery) error {
var
sql
bytes
.
Buffer
var
sql
bytes
.
Buffer
params
:=
make
([]
interface
{},
0
)
params
:=
make
([]
interface
{},
0
)
sql
.
WriteString
(
getTeamSelectSqlBase
())
if
query
.
UserIdFilter
>
0
{
if
query
.
UserIdFilter
>
0
{
sql
.
WriteString
(
`INNER JOIN team_member on team.id = team_member.team_id AND team_member.user_id = ?`
)
sql
.
WriteString
(
getTeamSearchSqlBase
()
)
params
=
append
(
params
,
query
.
UserIdFilter
)
params
=
append
(
params
,
query
.
UserIdFilter
)
}
else
{
sql
.
WriteString
(
getTeamSelectSqlBase
())
}
}
sql
.
WriteString
(
` WHERE team.org_id = ?`
)
sql
.
WriteString
(
` WHERE team.org_id = ?`
)
...
...
public/app/features/teams/TeamList.tsx
View file @
53c74fa2
...
@@ -6,7 +6,7 @@ import { DeleteButton } from '@grafana/ui';
...
@@ -6,7 +6,7 @@ import { DeleteButton } from '@grafana/ui';
import
EmptyListCTA
from
'app/core/components/EmptyListCTA/EmptyListCTA'
;
import
EmptyListCTA
from
'app/core/components/EmptyListCTA/EmptyListCTA'
;
import
{
NavModel
,
Team
,
OrgRole
}
from
'app/types'
;
import
{
NavModel
,
Team
,
OrgRole
}
from
'app/types'
;
import
{
loadTeams
,
deleteTeam
,
setSearchQuery
}
from
'./state/actions'
;
import
{
loadTeams
,
deleteTeam
,
setSearchQuery
}
from
'./state/actions'
;
import
{
getSearchQuery
,
getTeams
,
getTeamsCount
}
from
'./state/selectors'
;
import
{
getSearchQuery
,
getTeams
,
getTeamsCount
,
isPermissionTeamAdmin
}
from
'./state/selectors'
;
import
{
getNavModel
}
from
'app/core/selectors/navModel'
;
import
{
getNavModel
}
from
'app/core/selectors/navModel'
;
import
{
FilterInput
}
from
'app/core/components/FilterInput/FilterInput'
;
import
{
FilterInput
}
from
'app/core/components/FilterInput/FilterInput'
;
import
{
config
}
from
'app/core/config'
;
import
{
config
}
from
'app/core/config'
;
...
@@ -43,7 +43,10 @@ export class TeamList extends PureComponent<Props, any> {
...
@@ -43,7 +43,10 @@ export class TeamList extends PureComponent<Props, any> {
};
};
renderTeam
(
team
:
Team
)
{
renderTeam
(
team
:
Team
)
{
const
{
editorsCanAdmin
,
signedInUser
}
=
this
.
props
;
const
permission
=
team
.
permission
;
const
teamUrl
=
`org/teams/edit/
${
team
.
id
}
`
;
const
teamUrl
=
`org/teams/edit/
${
team
.
id
}
`
;
const
canDelete
=
isPermissionTeamAdmin
({
permission
,
editorsCanAdmin
,
signedInUser
});
return
(
return
(
<
tr
key=
{
team
.
id
}
>
<
tr
key=
{
team
.
id
}
>
...
@@ -62,7 +65,7 @@ export class TeamList extends PureComponent<Props, any> {
...
@@ -62,7 +65,7 @@ export class TeamList extends PureComponent<Props, any> {
<
a
href=
{
teamUrl
}
>
{
team
.
memberCount
}
</
a
>
<
a
href=
{
teamUrl
}
>
{
team
.
memberCount
}
</
a
>
</
td
>
</
td
>
<
td
className=
"text-right"
>
<
td
className=
"text-right"
>
<
DeleteButton
onConfirm=
{
()
=>
this
.
deleteTeam
(
team
)
}
/>
<
DeleteButton
onConfirm=
{
()
=>
this
.
deleteTeam
(
team
)
}
disabled=
{
!
canDelete
}
/>
</
td
>
</
td
>
</
tr
>
</
tr
>
);
);
...
...
public/app/features/teams/__mocks__/teamMocks.ts
View file @
53c74fa2
...
@@ -9,6 +9,7 @@ export const getMultipleMockTeams = (numberOfTeams: number): Team[] => {
...
@@ -9,6 +9,7 @@ export const getMultipleMockTeams = (numberOfTeams: number): Team[] => {
avatarUrl
:
'some/url/'
,
avatarUrl
:
'some/url/'
,
email
:
`test-
${
i
}
@test.com`
,
email
:
`test-
${
i
}
@test.com`
,
memberCount
:
i
,
memberCount
:
i
,
permission
:
TeamPermissionLevel
.
Member
,
});
});
}
}
...
@@ -22,6 +23,7 @@ export const getMockTeam = (): Team => {
...
@@ -22,6 +23,7 @@ export const getMockTeam = (): Team => {
avatarUrl
:
'some/url/'
,
avatarUrl
:
'some/url/'
,
email
:
'test@test.com'
,
email
:
'test@test.com'
,
memberCount
:
1
,
memberCount
:
1
,
permission
:
TeamPermissionLevel
.
Member
,
};
};
};
};
...
...
public/app/features/teams/__snapshots__/TeamList.test.tsx.snap
View file @
53c74fa2
...
@@ -133,6 +133,7 @@ exports[`Render should render teams table 1`] = `
...
@@ -133,6 +133,7 @@ exports[`Render should render teams table 1`] = `
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={false}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
@@ -183,6 +184,7 @@ exports[`Render should render teams table 1`] = `
...
@@ -183,6 +184,7 @@ exports[`Render should render teams table 1`] = `
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={false}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
@@ -233,6 +235,7 @@ exports[`Render should render teams table 1`] = `
...
@@ -233,6 +235,7 @@ exports[`Render should render teams table 1`] = `
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={false}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
@@ -283,6 +286,7 @@ exports[`Render should render teams table 1`] = `
...
@@ -283,6 +286,7 @@ exports[`Render should render teams table 1`] = `
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={false}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
@@ -333,6 +337,7 @@ exports[`Render should render teams table 1`] = `
...
@@ -333,6 +337,7 @@ exports[`Render should render teams table 1`] = `
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={false}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
@@ -458,6 +463,7 @@ exports[`Render when feature toggle editorsCanAdmin is turned on and signedin us
...
@@ -458,6 +463,7 @@ exports[`Render when feature toggle editorsCanAdmin is turned on and signedin us
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={true}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
@@ -583,6 +589,7 @@ exports[`Render when feature toggle editorsCanAdmin is turned on and signedin us
...
@@ -583,6 +589,7 @@ exports[`Render when feature toggle editorsCanAdmin is turned on and signedin us
className="text-right"
className="text-right"
>
>
<DeleteButton
<DeleteButton
disabled={true}
onConfirm={[Function]}
onConfirm={[Function]}
/>
/>
</td>
</td>
...
...
public/app/features/teams/state/navModel.ts
View file @
53c74fa2
import
{
Team
,
NavModelItem
,
NavModel
}
from
'app/types'
;
import
{
Team
,
NavModelItem
,
NavModel
,
TeamPermissionLevel
}
from
'app/types'
;
import
config
from
'app/core/config'
;
import
config
from
'app/core/config'
;
export
function
buildNavModel
(
team
:
Team
):
NavModelItem
{
export
function
buildNavModel
(
team
:
Team
):
NavModelItem
{
...
@@ -47,6 +47,7 @@ export function getTeamLoadingNav(pageName: string): NavModel {
...
@@ -47,6 +47,7 @@ export function getTeamLoadingNav(pageName: string): NavModel {
name
:
'Loading'
,
name
:
'Loading'
,
email
:
'loading'
,
email
:
'loading'
,
memberCount
:
0
,
memberCount
:
0
,
permission
:
TeamPermissionLevel
.
Member
,
});
});
let
node
:
NavModelItem
;
let
node
:
NavModelItem
;
...
...
public/app/features/teams/state/selectors.ts
View file @
53c74fa2
...
@@ -37,10 +37,24 @@ export interface Config {
...
@@ -37,10 +37,24 @@ export interface Config {
}
}
export
const
isSignedInUserTeamAdmin
=
(
config
:
Config
):
boolean
=>
{
export
const
isSignedInUserTeamAdmin
=
(
config
:
Config
):
boolean
=>
{
const
userInMembers
=
config
.
members
.
find
(
m
=>
m
.
userId
===
config
.
signedInUser
.
id
);
const
{
members
,
signedInUser
,
editorsCanAdmin
}
=
config
;
const
isAdmin
=
config
.
signedInUser
.
isGrafanaAdmin
||
config
.
signedInUser
.
orgRole
===
OrgRole
.
Admin
;
const
userInMembers
=
members
.
find
(
m
=>
m
.
userId
===
signedInUser
.
id
);
const
userIsTeamAdmin
=
userInMembers
&&
userInMembers
.
permission
===
TeamPermissionLevel
.
Admin
;
const
permission
=
userInMembers
?
userInMembers
.
permission
:
TeamPermissionLevel
.
Member
;
return
isPermissionTeamAdmin
({
permission
,
signedInUser
,
editorsCanAdmin
});
};
export
interface
PermissionConfig
{
permission
:
TeamPermissionLevel
;
editorsCanAdmin
:
boolean
;
signedInUser
:
User
;
}
export
const
isPermissionTeamAdmin
=
(
config
:
PermissionConfig
):
boolean
=>
{
const
{
permission
,
signedInUser
,
editorsCanAdmin
}
=
config
;
const
isAdmin
=
signedInUser
.
isGrafanaAdmin
||
signedInUser
.
orgRole
===
OrgRole
.
Admin
;
const
userIsTeamAdmin
=
permission
===
TeamPermissionLevel
.
Admin
;
const
isSignedInUserTeamAdmin
=
isAdmin
||
userIsTeamAdmin
;
const
isSignedInUserTeamAdmin
=
isAdmin
||
userIsTeamAdmin
;
return
isSignedInUserTeamAdmin
||
!
config
.
editorsCanAdmin
;
return
isSignedInUserTeamAdmin
||
!
editorsCanAdmin
;
};
};
public/app/types/teams.ts
View file @
53c74fa2
import
{
TeamPermissionLevel
}
from
'./acl'
;
export
interface
Team
{
export
interface
Team
{
id
:
number
;
id
:
number
;
name
:
string
;
name
:
string
;
avatarUrl
:
string
;
avatarUrl
:
string
;
email
:
string
;
email
:
string
;
memberCount
:
number
;
memberCount
:
number
;
permission
:
TeamPermissionLevel
;
}
}
export
interface
TeamMember
{
export
interface
TeamMember
{
...
...
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