Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configuration: Add an option to hide certain users in the UI #28942

Merged
merged 34 commits into from Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7bf8601
Add an option to hide certain users in the UI
AgnesToulet Nov 9, 2020
b68cf02
revert changes for admin users routes
AgnesToulet Nov 9, 2020
affa394
fix sqlstore function name
AgnesToulet Nov 9, 2020
403ba09
Improve slice management
AgnesToulet Nov 10, 2020
dff0bf2
Hidden users: convert slice to map
AgnesToulet Nov 10, 2020
a247aa7
filter with user logins instead of IDs
AgnesToulet Nov 10, 2020
22e0faa
put HiddenUsers in Cfg struct
AgnesToulet Nov 10, 2020
ec5e6d4
hide hidden users from dashboards/folders permissions list
AgnesToulet Nov 10, 2020
78b3f52
Update conf/defaults.ini
AgnesToulet Nov 10, 2020
11c48d8
fix params order
AgnesToulet Nov 10, 2020
85766f2
Merge branch 'config-hidden-users' of https://github.com/AgnesToulet/…
AgnesToulet Nov 10, 2020
ba41f68
fix tests
AgnesToulet Nov 10, 2020
69f5f88
Merge branch 'master' into config-hidden-users
AgnesToulet Nov 10, 2020
5c05906
fix dashboard/folder update with hidden user
AgnesToulet Nov 10, 2020
c6ae7a3
add team tests
AgnesToulet Nov 13, 2020
271c4c8
add dashboard and folder permissions tests
AgnesToulet Nov 13, 2020
f134875
Merge branch 'master' into config-hidden-users
AgnesToulet Nov 13, 2020
a14aed3
fixes after merge
AgnesToulet Nov 13, 2020
478fd94
fix tests
AgnesToulet Nov 13, 2020
30f7a70
Merge branch 'master' into config-hidden-users
AgnesToulet Nov 17, 2020
12e9164
API: add test for org users endpoints
AgnesToulet Nov 17, 2020
5df868a
update hidden users management for dashboard / folder permissions
AgnesToulet Nov 17, 2020
7da897b
Merge branch 'master' into config-hidden-users
AgnesToulet Nov 17, 2020
4d28116
improve dashboard / folder permissions tests
AgnesToulet Nov 17, 2020
319b968
Merge branch 'master' into config-hidden-users
AgnesToulet Nov 17, 2020
6661337
fixes after merge
AgnesToulet Nov 17, 2020
b6d7d44
Guardian: add hidden acl tests
AgnesToulet Nov 18, 2020
674a514
API: add team members tests
AgnesToulet Nov 18, 2020
868ff29
fix team sql syntax for postgres
AgnesToulet Nov 18, 2020
7461502
api tests update
AgnesToulet Nov 18, 2020
578647b
fix linter error
AgnesToulet Nov 18, 2020
e94c168
Merge branch 'master' into config-hidden-users
xlson Nov 24, 2020
9e91d73
fix tests errors after merge
AgnesToulet Nov 24, 2020
0f05c1a
Merge branch 'master' into config-hidden-users
xlson Nov 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions conf/defaults.ini
Expand Up @@ -296,6 +296,9 @@ editors_can_admin = false
# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes).
user_invite_max_lifetime_duration = 24h

# Enter a comma-separated list of usernames to hide them in the Grafana UI. These users are shown to Grafana admins and to themselves.
hidden_users =

[auth]
# Login cookie name
login_cookie_name = grafana_session
Expand Down
3 changes: 3 additions & 0 deletions conf/sample.ini
Expand Up @@ -295,6 +295,9 @@
# The duration in time a user invitation remains valid before expiring. This setting should be expressed as a duration. Examples: 6h (hours), 2d (days), 1w (week). Default is 24h (24 hours). The minimum supported duration is 15m (15 minutes).
;user_invite_max_lifetime_duration = 24h

# Enter a comma-separated list of users login to hide them in the Grafana UI. These users are shown to Grafana admins and themselves.
; hidden_users =

[auth]
# Login cookie name
;login_cookie_name = grafana_session
Expand Down
16 changes: 8 additions & 8 deletions pkg/api/api.go
Expand Up @@ -170,7 +170,7 @@ func (hs *HTTPServer) registerRoutes() {

// team without requirement of user to be org admin
apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) {
teamsRoute.Get("/:teamId", Wrap(GetTeamByID))
teamsRoute.Get("/:teamId", Wrap(hs.GetTeamByID))
teamsRoute.Get("/search", Wrap(hs.SearchTeams))
})

Expand All @@ -184,7 +184,7 @@ func (hs *HTTPServer) registerRoutes() {
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), Wrap(UpdateOrgCurrent))
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), Wrap(UpdateOrgAddressCurrent))
orgRoute.Get("/users", Wrap(GetOrgUsersForCurrentOrg))
orgRoute.Get("/users", Wrap(hs.GetOrgUsersForCurrentOrg))
orgRoute.Post("/users", quota("user"), bind(models.AddOrgUserCommand{}), Wrap(AddOrgUserToCurrentOrg))
orgRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), Wrap(UpdateOrgUserForCurrentOrg))
orgRoute.Delete("/users/:userId", Wrap(RemoveOrgUserForCurrentOrg))
Expand All @@ -201,7 +201,7 @@ func (hs *HTTPServer) registerRoutes() {

// current org without requirement of user to be org admin
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
orgRoute.Get("/users/lookup", Wrap(GetOrgUsersForCurrentOrgLookup))
orgRoute.Get("/users/lookup", Wrap(hs.GetOrgUsersForCurrentOrgLookup))
})

// create new org
Expand All @@ -216,7 +216,7 @@ func (hs *HTTPServer) registerRoutes() {
orgsRoute.Put("/", bind(dtos.UpdateOrgForm{}), Wrap(UpdateOrg))
orgsRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), Wrap(UpdateOrgAddress))
orgsRoute.Delete("/", Wrap(DeleteOrgByID))
orgsRoute.Get("/users", Wrap(GetOrgUsers))
orgsRoute.Get("/users", Wrap(hs.GetOrgUsers))
orgsRoute.Post("/users", bind(models.AddOrgUserCommand{}), Wrap(AddOrgUser))
orgsRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), Wrap(UpdateOrgUser))
orgsRoute.Delete("/users/:userId", Wrap(RemoveOrgUser))
Expand Down Expand Up @@ -287,8 +287,8 @@ func (hs *HTTPServer) registerRoutes() {
folderUidRoute.Delete("/", Wrap(DeleteFolder))

folderUidRoute.Group("/permissions", func(folderPermissionRoute routing.RouteRegister) {
folderPermissionRoute.Get("/", Wrap(GetFolderPermissionList))
folderPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), Wrap(UpdateFolderPermissions))
folderPermissionRoute.Get("/", Wrap(hs.GetFolderPermissionList))
folderPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), Wrap(hs.UpdateFolderPermissions))
})
})
})
Expand All @@ -314,8 +314,8 @@ func (hs *HTTPServer) registerRoutes() {
dashIdRoute.Post("/restore", bind(dtos.RestoreDashboardVersionCommand{}), Wrap(hs.RestoreDashboardVersion))

dashIdRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
dashboardPermissionRoute.Get("/", Wrap(GetDashboardPermissionList))
dashboardPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), Wrap(UpdateDashboardPermissions))
dashboardPermissionRoute.Get("/", Wrap(hs.GetDashboardPermissionList))
dashboardPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), Wrap(hs.UpdateDashboardPermissions))
})
})
})
Expand Down
1 change: 1 addition & 0 deletions pkg/api/common_test.go
Expand Up @@ -28,6 +28,7 @@ func loggedInUserScenarioWithRole(t *testing.T, desc string, method string, url
sc.context = c
sc.context.UserId = testUserID
sc.context.OrgId = testOrgID
sc.context.Login = testUserLogin
sc.context.OrgRole = role
if sc.handlerFunc != nil {
return sc.handlerFunc(sc.context)
Expand Down
19 changes: 16 additions & 3 deletions pkg/api/dashboard_permission.go
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/grafana/grafana/pkg/services/guardian"
)

func GetDashboardPermissionList(c *models.ReqContext) Response {
func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) Response {
dashID := c.ParamsInt64(":dashboardId")

_, rsp := getDashboardHelper(c.OrgId, "", dashID, "")
Expand All @@ -29,7 +29,12 @@ func GetDashboardPermissionList(c *models.ReqContext) Response {
return Error(500, "Failed to get dashboard permissions", err)
}

filteredAcls := make([]*models.DashboardAclInfoDTO, 0, len(acl))
for _, perm := range acl {
if dtos.IsHiddenUser(perm.UserLogin, c.SignedInUser, hs.Cfg) {
continue
}

perm.UserAvatarUrl = dtos.GetGravatarUrl(perm.UserEmail)

if perm.TeamId > 0 {
Expand All @@ -38,12 +43,14 @@ func GetDashboardPermissionList(c *models.ReqContext) Response {
if perm.Slug != "" {
perm.Url = models.GetDashboardFolderUrl(perm.IsFolder, perm.Uid, perm.Slug)
}

filteredAcls = append(filteredAcls, perm)
}

return JSON(200, acl)
return JSON(200, filteredAcls)
}

func UpdateDashboardPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) Response {
func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) Response {
if err := validatePermissionsUpdate(apiCmd); err != nil {
return Error(400, err.Error(), err)
}
Expand Down Expand Up @@ -76,6 +83,12 @@ func UpdateDashboardPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboar
})
}

hiddenACL, err := g.GetHiddenACL(hs.Cfg)
if err != nil {
return Error(500, "Error while retrieving hidden permissions", err)
}
cmd.Items = append(cmd.Items, hiddenACL...)

if okToUpdate, err := g.CheckPermissionBeforeUpdate(models.PERMISSION_ADMIN, cmd.Items); err != nil || !okToUpdate {
if err != nil {
if errors.Is(err, guardian.ErrGuardianPermissionExists) || errors.Is(err, guardian.ErrGuardianOverride) {
Expand Down