mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Access control: Make Admin/Users UI working with the permissions (#33176)
* API: authorize admin/users views * Render admin/users components based on user's permissions * Add LDAP permissions (required by admin/user page) * Extend default admin role by LDAP permissions * Show/hide LDAP debug views * Render LDAP debug page if user has access * Authorize LDAP debug view * fix permissions definitions * Add LDAP page permissions * remove ambiguous permissions check * Hide logout buttons in sessions table * Add org/users permissions * Use org permissions for managing user roles in orgs * Apply permissions to org/users * Apply suggestions from review * Fix tests * remove scopes from the frontend * Tweaks according to review * Handle /invites endpoints
This commit is contained in:
@@ -58,9 +58,9 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
r.Get("/datasources/", reqOrgAdmin, hs.Index)
|
||||
r.Get("/datasources/new", reqOrgAdmin, hs.Index)
|
||||
r.Get("/datasources/edit/*", reqOrgAdmin, hs.Index)
|
||||
r.Get("/org/users", reqOrgAdmin, hs.Index)
|
||||
r.Get("/org/users", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersRead, accesscontrol.ScopeOrgCurrentUsersAll), hs.Index)
|
||||
r.Get("/org/users/new", reqOrgAdmin, hs.Index)
|
||||
r.Get("/org/users/invite", reqOrgAdmin, hs.Index)
|
||||
r.Get("/org/users/invite", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersAdd, accesscontrol.ScopeOrgCurrentUsersAll), hs.Index)
|
||||
r.Get("/org/teams", reqCanAccessTeams, hs.Index)
|
||||
r.Get("/org/teams/*", reqCanAccessTeams, hs.Index)
|
||||
r.Get("/org/apikeys/", reqOrgAdmin, hs.Index)
|
||||
@@ -68,13 +68,13 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
r.Get("/configuration", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/settings", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/users", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/users/create", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/users/edit/:id", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/users", authorize(reqGrafanaAdmin, accesscontrol.ActionUsersRead, accesscontrol.ScopeUsersAll), hs.Index)
|
||||
r.Get("/admin/users/create", authorize(reqGrafanaAdmin, accesscontrol.ActionUsersCreate), hs.Index)
|
||||
r.Get("/admin/users/edit/:id", authorize(reqGrafanaAdmin, accesscontrol.ActionUsersRead), hs.Index)
|
||||
r.Get("/admin/orgs", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/stats", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/ldap", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin/ldap", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPStatusRead), hs.Index)
|
||||
|
||||
r.Get("/styleguide", reqSignedIn, hs.Index)
|
||||
|
||||
@@ -201,22 +201,23 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// current org
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrgCurrent))
|
||||
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddressCurrent))
|
||||
orgRoute.Get("/users", routing.Wrap(hs.GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Post("/users", quota("user"), bind(models.AddOrgUserCommand{}), routing.Wrap(AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), routing.Wrap(UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Delete("/users/:userId", routing.Wrap(RemoveOrgUserForCurrentOrg))
|
||||
const orgScope = `org:current/users:{{ index . ":userId" }}`
|
||||
orgRoute.Put("/", reqOrgAdmin, bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrgCurrent))
|
||||
orgRoute.Put("/address", reqOrgAdmin, bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddressCurrent))
|
||||
orgRoute.Get("/users", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersRead, accesscontrol.ScopeOrgCurrentUsersAll), routing.Wrap(hs.GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Post("/users", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersAdd, accesscontrol.ScopeOrgCurrentUsersAll), quota("user"), bind(models.AddOrgUserCommand{}), routing.Wrap(AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersRoleUpdate, orgScope), bind(models.UpdateOrgUserCommand{}), routing.Wrap(UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Delete("/users/:userId", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersRemove, orgScope), routing.Wrap(RemoveOrgUserForCurrentOrg))
|
||||
|
||||
// invites
|
||||
orgRoute.Get("/invites", routing.Wrap(GetPendingOrgInvites))
|
||||
orgRoute.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), routing.Wrap(AddOrgInvite))
|
||||
orgRoute.Patch("/invites/:code/revoke", routing.Wrap(RevokeInvite))
|
||||
orgRoute.Get("/invites", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersAdd, accesscontrol.ScopeOrgCurrentUsersAll), routing.Wrap(GetPendingOrgInvites))
|
||||
orgRoute.Post("/invites", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersAdd, accesscontrol.ScopeOrgCurrentUsersAll), quota("user"), bind(dtos.AddInviteForm{}), routing.Wrap(AddOrgInvite))
|
||||
orgRoute.Patch("/invites/:code/revoke", authorize(reqOrgAdmin, accesscontrol.ActionOrgUsersAdd, accesscontrol.ScopeOrgCurrentUsersAll), routing.Wrap(RevokeInvite))
|
||||
|
||||
// prefs
|
||||
orgRoute.Get("/preferences", routing.Wrap(GetOrgPreferences))
|
||||
orgRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), routing.Wrap(UpdateOrgPreferences))
|
||||
}, reqOrgAdmin)
|
||||
orgRoute.Get("/preferences", reqOrgAdmin, routing.Wrap(GetOrgPreferences))
|
||||
orgRoute.Put("/preferences", reqOrgAdmin, bind(dtos.UpdatePrefsCmd{}), routing.Wrap(UpdateOrgPreferences))
|
||||
})
|
||||
|
||||
// current org without requirement of user to be org admin
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
@@ -231,17 +232,19 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// orgs (admin routes)
|
||||
apiRoute.Group("/orgs/:orgId", func(orgsRoute routing.RouteRegister) {
|
||||
orgsRoute.Get("/", routing.Wrap(GetOrgByID))
|
||||
orgsRoute.Put("/", bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrg))
|
||||
orgsRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddress))
|
||||
orgsRoute.Delete("/", routing.Wrap(DeleteOrgByID))
|
||||
orgsRoute.Get("/users", routing.Wrap(hs.GetOrgUsers))
|
||||
orgsRoute.Post("/users", bind(models.AddOrgUserCommand{}), routing.Wrap(AddOrgUser))
|
||||
orgsRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), routing.Wrap(UpdateOrgUser))
|
||||
orgsRoute.Delete("/users/:userId", routing.Wrap(RemoveOrgUser))
|
||||
orgsRoute.Get("/quotas", routing.Wrap(GetOrgQuotas))
|
||||
orgsRoute.Put("/quotas/:target", bind(models.UpdateOrgQuotaCmd{}), routing.Wrap(UpdateOrgQuota))
|
||||
}, reqGrafanaAdmin)
|
||||
const orgScope = `org:{{ index . ":orgId" }}/users:*`
|
||||
const orgUsersScope = `org:{{ index . ":orgId" }}/users:{{ index . ":userId" }}`
|
||||
orgsRoute.Get("/", reqGrafanaAdmin, routing.Wrap(GetOrgByID))
|
||||
orgsRoute.Put("/", reqGrafanaAdmin, bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrg))
|
||||
orgsRoute.Put("/address", reqGrafanaAdmin, bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddress))
|
||||
orgsRoute.Delete("/", reqGrafanaAdmin, routing.Wrap(DeleteOrgByID))
|
||||
orgsRoute.Get("/users", authorize(reqGrafanaAdmin, accesscontrol.ActionOrgUsersRead, orgScope), routing.Wrap(hs.GetOrgUsers))
|
||||
orgsRoute.Post("/users", authorize(reqGrafanaAdmin, accesscontrol.ActionOrgUsersAdd, orgScope), bind(models.AddOrgUserCommand{}), routing.Wrap(AddOrgUser))
|
||||
orgsRoute.Patch("/users/:userId", authorize(reqGrafanaAdmin, accesscontrol.ActionOrgUsersRoleUpdate, orgUsersScope), bind(models.UpdateOrgUserCommand{}), routing.Wrap(UpdateOrgUser))
|
||||
orgsRoute.Delete("/users/:userId", authorize(reqGrafanaAdmin, accesscontrol.ActionOrgUsersRemove, orgUsersScope), routing.Wrap(RemoveOrgUser))
|
||||
orgsRoute.Get("/quotas", reqGrafanaAdmin, routing.Wrap(GetOrgQuotas))
|
||||
orgsRoute.Put("/quotas/:target", reqGrafanaAdmin, bind(models.UpdateOrgQuotaCmd{}), routing.Wrap(UpdateOrgQuota))
|
||||
})
|
||||
|
||||
// orgs (admin routes)
|
||||
apiRoute.Group("/orgs/name/:name", func(orgsRoute routing.RouteRegister) {
|
||||
@@ -425,19 +428,19 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// admin api
|
||||
r.Group("/api/admin", func(adminRoute routing.RouteRegister) {
|
||||
adminRoute.Get("/settings", routing.Wrap(AdminGetSettings))
|
||||
adminRoute.Get("/stats", routing.Wrap(AdminGetStats))
|
||||
adminRoute.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), routing.Wrap(PauseAllAlerts))
|
||||
adminRoute.Get("/settings", reqGrafanaAdmin, routing.Wrap(AdminGetSettings))
|
||||
adminRoute.Get("/stats", reqGrafanaAdmin, routing.Wrap(AdminGetStats))
|
||||
adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, bind(dtos.PauseAllAlertsCommand{}), routing.Wrap(PauseAllAlerts))
|
||||
|
||||
adminRoute.Post("/provisioning/dashboards/reload", routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
adminRoute.Post("/provisioning/datasources/reload", routing.Wrap(hs.AdminProvisioningReloadDatasources))
|
||||
adminRoute.Post("/provisioning/notifications/reload", routing.Wrap(hs.AdminProvisioningReloadNotifications))
|
||||
adminRoute.Post("/ldap/reload", routing.Wrap(hs.ReloadLDAPCfg))
|
||||
adminRoute.Post("/ldap/sync/:id", routing.Wrap(hs.PostSyncUserWithLDAP))
|
||||
adminRoute.Get("/ldap/:username", routing.Wrap(hs.GetUserFromLDAP))
|
||||
adminRoute.Get("/ldap/status", routing.Wrap(hs.GetLDAPStatus))
|
||||
}, reqGrafanaAdmin)
|
||||
adminRoute.Post("/provisioning/dashboards/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
adminRoute.Post("/provisioning/datasources/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadDatasources))
|
||||
adminRoute.Post("/provisioning/notifications/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadNotifications))
|
||||
adminRoute.Post("/ldap/reload", reqGrafanaAdmin, routing.Wrap(hs.ReloadLDAPCfg))
|
||||
adminRoute.Post("/ldap/sync/:id", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPUsersSync), routing.Wrap(hs.PostSyncUserWithLDAP))
|
||||
adminRoute.Get("/ldap/:username", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPUsersRead), routing.Wrap(hs.GetUserFromLDAP))
|
||||
adminRoute.Get("/ldap/status", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPStatusRead), routing.Wrap(hs.GetLDAPStatus))
|
||||
})
|
||||
|
||||
// Administering users
|
||||
r.Group("/api/admin/users", func(adminUserRoute routing.RouteRegister) {
|
||||
|
||||
Reference in New Issue
Block a user