RBAC: Remove legacy ac from authorization middleware (#68898)

remove legacy AC fallback from RBAC middleware, and some unused auth logic
This commit is contained in:
Ieva
2023-05-24 09:49:42 +01:00
committed by GitHub
parent 323cbe1997
commit 4980b64274
21 changed files with 214 additions and 437 deletions

View File

@ -36,7 +36,6 @@ import (
ac "github.com/grafana/grafana/pkg/services/accesscontrol" ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/correlations" "github.com/grafana/grafana/pkg/services/correlations"
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
@ -61,11 +60,8 @@ func (hs *HTTPServer) registerRoutes() {
reqGrafanaAdmin := middleware.ReqGrafanaAdmin reqGrafanaAdmin := middleware.ReqGrafanaAdmin
reqEditorRole := middleware.ReqEditorRole reqEditorRole := middleware.ReqEditorRole
reqOrgAdmin := middleware.ReqOrgAdmin reqOrgAdmin := middleware.ReqOrgAdmin
reqOrgAdminDashOrFolderAdminOrTeamAdmin := middleware.OrgAdminDashOrFolderAdminOrTeamAdmin(hs.SQLStore, hs.DashboardService, hs.teamService)
reqCanAccessTeams := middleware.AdminOrEditorAndFeatureEnabled(hs.Cfg.EditorsCanAdmin)
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg) reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg) redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
ensureEditorOrViewerCanEdit := middleware.EnsureEditorOrViewerCanEdit(hs.Cfg)
authorize := ac.Middleware(hs.AccessControl) authorize := ac.Middleware(hs.AccessControl)
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService) authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService)
quota := middleware.Quota(hs.QuotaService) quota := middleware.Quota(hs.QuotaService)
@ -85,32 +81,32 @@ func (hs *HTTPServer) registerRoutes() {
r.Get("/profile/password", reqSignedInNoAnonymous, hs.Index) r.Get("/profile/password", reqSignedInNoAnonymous, hs.Index)
r.Get("/.well-known/change-password", redirectToChangePassword) r.Get("/.well-known/change-password", redirectToChangePassword)
r.Get("/profile/switch-org/:id", reqSignedInNoAnonymous, hs.ChangeActiveOrgAndRedirectToHome) r.Get("/profile/switch-org/:id", reqSignedInNoAnonymous, hs.ChangeActiveOrgAndRedirectToHome)
r.Get("/org/", authorize(reqOrgAdmin, ac.OrgPreferencesAccessEvaluator), hs.Index) r.Get("/org/", authorize(ac.OrgPreferencesAccessEvaluator), hs.Index)
r.Get("/org/new", authorizeInOrg(reqGrafanaAdmin, ac.UseGlobalOrg, ac.OrgsCreateAccessEvaluator), hs.Index) r.Get("/org/new", authorizeInOrg(ac.UseGlobalOrg, ac.OrgsCreateAccessEvaluator), hs.Index)
r.Get("/datasources/", authorize(reqOrgAdmin, datasources.ConfigurationPageAccess), hs.Index) r.Get("/datasources/", authorize(datasources.ConfigurationPageAccess), hs.Index)
r.Get("/datasources/new", authorize(reqOrgAdmin, datasources.NewPageAccess), hs.Index) r.Get("/datasources/new", authorize(datasources.NewPageAccess), hs.Index)
r.Get("/datasources/edit/*", authorize(reqOrgAdmin, datasources.EditPageAccess), hs.Index) r.Get("/datasources/edit/*", authorize(datasources.EditPageAccess), hs.Index)
r.Get("/datasources/correlations", authorize(reqOrgAdmin, correlations.ConfigurationPageAccess), hs.Index) r.Get("/datasources/correlations", authorize(correlations.ConfigurationPageAccess), hs.Index)
r.Get("/org/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), hs.Index) r.Get("/org/users", authorize(ac.EvalPermission(ac.ActionOrgUsersRead)), hs.Index)
r.Get("/org/users/new", reqOrgAdmin, hs.Index) r.Get("/org/users/new", reqOrgAdmin, hs.Index)
r.Get("/org/users/invite", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd)), hs.Index) r.Get("/org/users/invite", authorize(ac.EvalPermission(ac.ActionOrgUsersAdd)), hs.Index)
r.Get("/org/teams", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsRead)), hs.Index) r.Get("/org/teams", authorize(ac.EvalPermission(ac.ActionTeamsRead)), hs.Index)
r.Get("/org/teams/edit/*", authorize(reqCanAccessTeams, ac.TeamsEditAccessEvaluator), hs.Index) r.Get("/org/teams/edit/*", authorize(ac.TeamsEditAccessEvaluator), hs.Index)
r.Get("/org/teams/new", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsCreate)), hs.Index) r.Get("/org/teams/new", authorize(ac.EvalPermission(ac.ActionTeamsCreate)), hs.Index)
r.Get("/org/serviceaccounts", authorize(reqOrgAdmin, ac.EvalPermission(serviceaccounts.ActionRead)), hs.Index) r.Get("/org/serviceaccounts", authorize(ac.EvalPermission(serviceaccounts.ActionRead)), hs.Index)
r.Get("/org/serviceaccounts/:serviceAccountId", authorize(reqOrgAdmin, ac.EvalPermission(serviceaccounts.ActionRead)), hs.Index) r.Get("/org/serviceaccounts/:serviceAccountId", authorize(ac.EvalPermission(serviceaccounts.ActionRead)), hs.Index)
r.Get("/org/apikeys/", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionAPIKeyRead)), hs.Index) r.Get("/org/apikeys/", authorize(ac.EvalPermission(ac.ActionAPIKeyRead)), hs.Index)
r.Get("/dashboard/import/", reqSignedIn, hs.Index) r.Get("/dashboard/import/", reqSignedIn, hs.Index)
r.Get("/configuration", reqGrafanaAdmin, hs.Index) r.Get("/configuration", reqGrafanaAdmin, hs.Index)
r.Get("/admin", reqOrgAdmin, hs.Index) r.Get("/admin", reqOrgAdmin, hs.Index)
r.Get("/admin/settings", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead, ac.ScopeSettingsAll)), hs.Index) r.Get("/admin/settings", authorize(ac.EvalPermission(ac.ActionSettingsRead, ac.ScopeSettingsAll)), hs.Index)
r.Get("/admin/users", authorize(reqSignedIn, ac.EvalAny(ac.EvalPermission(ac.ActionOrgUsersRead), ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll))), hs.Index) r.Get("/admin/users", authorize(ac.EvalAny(ac.EvalPermission(ac.ActionOrgUsersRead), ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll))), hs.Index)
r.Get("/admin/users/create", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersCreate)), hs.Index) r.Get("/admin/users/create", authorize(ac.EvalPermission(ac.ActionUsersCreate)), hs.Index)
r.Get("/admin/users/edit/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead)), hs.Index) r.Get("/admin/users/edit/:id", authorize(ac.EvalPermission(ac.ActionUsersRead)), hs.Index)
r.Get("/admin/orgs", authorizeInOrg(reqGrafanaAdmin, ac.UseGlobalOrg, ac.OrgsAccessEvaluator), hs.Index) r.Get("/admin/orgs", authorizeInOrg(ac.UseGlobalOrg, ac.OrgsAccessEvaluator), hs.Index)
r.Get("/admin/orgs/edit/:id", authorizeInOrg(reqGrafanaAdmin, ac.UseGlobalOrg, ac.OrgsAccessEvaluator), hs.Index) r.Get("/admin/orgs/edit/:id", authorizeInOrg(ac.UseGlobalOrg, ac.OrgsAccessEvaluator), hs.Index)
r.Get("/admin/stats", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionServerStatsRead)), hs.Index) r.Get("/admin/stats", authorize(ac.EvalPermission(ac.ActionServerStatsRead)), hs.Index)
r.Get("/admin/ldap", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionLDAPStatusRead)), hs.Index) r.Get("/admin/ldap", authorize(ac.EvalPermission(ac.ActionLDAPStatusRead)), hs.Index)
if hs.Features.IsEnabled(featuremgmt.FlagStorage) { if hs.Features.IsEnabled(featuremgmt.FlagStorage) {
r.Get("/admin/storage", reqSignedIn, hs.Index) r.Get("/admin/storage", reqSignedIn, hs.Index)
r.Get("/admin/storage/*", reqSignedIn, hs.Index) r.Get("/admin/storage/*", reqSignedIn, hs.Index)
@ -126,18 +122,18 @@ func (hs *HTTPServer) registerRoutes() {
r.Get("/plugins/:id/edit", middleware.CanAdminPlugins(hs.Cfg), hs.Index) // deprecated r.Get("/plugins/:id/edit", middleware.CanAdminPlugins(hs.Cfg), hs.Index) // deprecated
r.Get("/plugins/:id/page/:page", middleware.CanAdminPlugins(hs.Cfg), hs.Index) r.Get("/plugins/:id/page/:page", middleware.CanAdminPlugins(hs.Cfg), hs.Index)
r.Get("/connections/datasources", authorize(reqOrgAdmin, datasources.ConfigurationPageAccess), hs.Index) r.Get("/connections/datasources", authorize(datasources.ConfigurationPageAccess), hs.Index)
r.Get("/connections/datasources/new", authorize(reqOrgAdmin, datasources.NewPageAccess), hs.Index) r.Get("/connections/datasources/new", authorize(datasources.NewPageAccess), hs.Index)
r.Get("/connections/datasources/edit/*", authorize(reqOrgAdmin, datasources.EditPageAccess), hs.Index) r.Get("/connections/datasources/edit/*", authorize(datasources.EditPageAccess), hs.Index)
r.Get("/connections", authorize(reqOrgAdmin, datasources.ConfigurationPageAccess), hs.Index) r.Get("/connections", authorize(datasources.ConfigurationPageAccess), hs.Index)
r.Get("/connections/add-new-connection", authorize(reqOrgAdmin, datasources.ConfigurationPageAccess), hs.Index) r.Get("/connections/add-new-connection", authorize(datasources.ConfigurationPageAccess), hs.Index)
r.Get("/connections/datasources/:id", middleware.CanAdminPlugins(hs.Cfg), hs.Index) r.Get("/connections/datasources/:id", middleware.CanAdminPlugins(hs.Cfg), hs.Index)
r.Get("/connections/datasources/:id/page/:page", middleware.CanAdminPlugins(hs.Cfg), hs.Index) r.Get("/connections/datasources/:id/page/:page", middleware.CanAdminPlugins(hs.Cfg), hs.Index)
// App Root Page // App Root Page
appPluginIDScope := pluginaccesscontrol.ScopeProvider.GetResourceScope(ac.Parameter(":id")) appPluginIDScope := pluginaccesscontrol.ScopeProvider.GetResourceScope(ac.Parameter(":id"))
r.Get("/a/:id/*", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, appPluginIDScope)), hs.Index) r.Get("/a/:id/*", authorize(ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, appPluginIDScope)), hs.Index)
r.Get("/a/:id", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, appPluginIDScope)), hs.Index) r.Get("/a/:id", authorize(ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, appPluginIDScope)), hs.Index)
r.Get("/d/:uid/:slug", reqSignedIn, redirectFromLegacyPanelEditURL, hs.Index) r.Get("/d/:uid/:slug", reqSignedIn, redirectFromLegacyPanelEditURL, hs.Index)
r.Get("/d/:uid", reqSignedIn, redirectFromLegacyPanelEditURL, hs.Index) r.Get("/d/:uid", reqSignedIn, redirectFromLegacyPanelEditURL, hs.Index)
@ -165,12 +161,7 @@ func (hs *HTTPServer) registerRoutes() {
) )
} }
r.Get("/explore", authorize(func(c *contextmodel.ReqContext) { r.Get("/explore", authorize(ac.EvalPermission(ac.ActionDatasourcesExplore)), hs.Index)
if f, ok := reqSignedIn.(func(c *contextmodel.ReqContext)); ok {
f(c)
}
ensureEditorOrViewerCanEdit(c)
}, ac.EvalPermission(ac.ActionDatasourcesExplore)), hs.Index)
r.Get("/playlists/", reqSignedIn, hs.Index) r.Get("/playlists/", reqSignedIn, hs.Index)
r.Get("/playlists/*", reqSignedIn, hs.Index) r.Get("/playlists/*", reqSignedIn, hs.Index)
@ -220,7 +211,7 @@ func (hs *HTTPServer) registerRoutes() {
if hs.License.FeatureEnabled("saml") && hs.Features.IsEnabled(featuremgmt.FlagAuthenticationConfigUI) { if hs.License.FeatureEnabled("saml") && hs.Features.IsEnabled(featuremgmt.FlagAuthenticationConfigUI) {
// TODO change the scope when we extend the auth UI to more providers // TODO change the scope when we extend the auth UI to more providers
r.Get("/admin/authentication/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsWrite, ac.ScopeSettingsSAML)), hs.Index) r.Get("/admin/authentication/", authorize(ac.EvalPermission(ac.ActionSettingsWrite, ac.ScopeSettingsSAML)), hs.Index)
} }
// authed api // authed api
@ -260,40 +251,40 @@ func (hs *HTTPServer) registerRoutes() {
apiRoute.Group("/users", func(usersRoute routing.RouteRegister) { apiRoute.Group("/users", func(usersRoute routing.RouteRegister) {
userIDScope := ac.Scope("global.users", "id", ac.Parameter(":id")) userIDScope := ac.Scope("global.users", "id", ac.Parameter(":id"))
usersRoute.Get("/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead)), routing.Wrap(hs.searchUsersService.SearchUsers)) usersRoute.Get("/", authorize(ac.EvalPermission(ac.ActionUsersRead)), routing.Wrap(hs.searchUsersService.SearchUsers))
usersRoute.Get("/search", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead)), routing.Wrap(hs.searchUsersService.SearchUsersWithPaging)) usersRoute.Get("/search", authorize(ac.EvalPermission(ac.ActionUsersRead)), routing.Wrap(hs.searchUsersService.SearchUsersWithPaging))
usersRoute.Get("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserByID)) usersRoute.Get("/:id", authorize(ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserByID))
usersRoute.Get("/:id/teams", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserTeams)) usersRoute.Get("/:id/teams", authorize(ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserTeams))
usersRoute.Get("/:id/orgs", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserOrgList)) usersRoute.Get("/:id/orgs", authorize(ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserOrgList))
// query parameters /users/lookup?loginOrEmail=admin@example.com // query parameters /users/lookup?loginOrEmail=admin@example.com
usersRoute.Get("/lookup", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll)), routing.Wrap(hs.GetUserByLoginOrEmail)) usersRoute.Get("/lookup", authorize(ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll)), routing.Wrap(hs.GetUserByLoginOrEmail))
usersRoute.Put("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), routing.Wrap(hs.UpdateUser)) usersRoute.Put("/:id", authorize(ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), routing.Wrap(hs.UpdateUser))
usersRoute.Post("/:id/using/:orgId", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), routing.Wrap(hs.UpdateUserActiveOrg)) usersRoute.Post("/:id/using/:orgId", authorize(ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), routing.Wrap(hs.UpdateUserActiveOrg))
}) })
// team (admin permission required) // team (admin permission required)
apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) { apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) {
teamsRoute.Post("/", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsCreate)), routing.Wrap(hs.CreateTeam)) teamsRoute.Post("/", authorize(ac.EvalPermission(ac.ActionTeamsCreate)), routing.Wrap(hs.CreateTeam))
teamsRoute.Put("/:teamId", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.UpdateTeam)) teamsRoute.Put("/:teamId", authorize(ac.EvalPermission(ac.ActionTeamsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.UpdateTeam))
teamsRoute.Delete("/:teamId", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsDelete, ac.ScopeTeamsID)), routing.Wrap(hs.DeleteTeamByID)) teamsRoute.Delete("/:teamId", authorize(ac.EvalPermission(ac.ActionTeamsDelete, ac.ScopeTeamsID)), routing.Wrap(hs.DeleteTeamByID))
teamsRoute.Get("/:teamId/members", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsPermissionsRead, ac.ScopeTeamsID)), routing.Wrap(hs.GetTeamMembers)) teamsRoute.Get("/:teamId/members", authorize(ac.EvalPermission(ac.ActionTeamsPermissionsRead, ac.ScopeTeamsID)), routing.Wrap(hs.GetTeamMembers))
teamsRoute.Post("/:teamId/members", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsPermissionsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.AddTeamMember)) teamsRoute.Post("/:teamId/members", authorize(ac.EvalPermission(ac.ActionTeamsPermissionsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.AddTeamMember))
teamsRoute.Put("/:teamId/members/:userId", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsPermissionsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.UpdateTeamMember)) teamsRoute.Put("/:teamId/members/:userId", authorize(ac.EvalPermission(ac.ActionTeamsPermissionsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.UpdateTeamMember))
teamsRoute.Delete("/:teamId/members/:userId", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsPermissionsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.RemoveTeamMember)) teamsRoute.Delete("/:teamId/members/:userId", authorize(ac.EvalPermission(ac.ActionTeamsPermissionsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.RemoveTeamMember))
teamsRoute.Get("/:teamId/preferences", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsRead, ac.ScopeTeamsID)), routing.Wrap(hs.GetTeamPreferences)) teamsRoute.Get("/:teamId/preferences", authorize(ac.EvalPermission(ac.ActionTeamsRead, ac.ScopeTeamsID)), routing.Wrap(hs.GetTeamPreferences))
teamsRoute.Put("/:teamId/preferences", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.UpdateTeamPreferences)) teamsRoute.Put("/:teamId/preferences", authorize(ac.EvalPermission(ac.ActionTeamsWrite, ac.ScopeTeamsID)), routing.Wrap(hs.UpdateTeamPreferences))
}) })
// team without requirement of user to be org admin // team without requirement of user to be org admin
apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) { apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) {
teamsRoute.Get("/:teamId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionTeamsRead, ac.ScopeTeamsID)), routing.Wrap(hs.GetTeamByID)) teamsRoute.Get("/:teamId", authorize(ac.EvalPermission(ac.ActionTeamsRead, ac.ScopeTeamsID)), routing.Wrap(hs.GetTeamByID))
teamsRoute.Get("/search", authorize(reqSignedIn, ac.EvalPermission(ac.ActionTeamsRead)), routing.Wrap(hs.SearchTeams)) teamsRoute.Get("/search", authorize(ac.EvalPermission(ac.ActionTeamsRead)), routing.Wrap(hs.SearchTeams))
}) })
// org information available to all users. // org information available to all users.
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) { apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
orgRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.GetCurrentOrg)) orgRoute.Get("/", authorize(ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.GetCurrentOrg))
orgRoute.Get("/quotas", authorize(reqSignedIn, ac.EvalPermission(ac.ActionOrgsQuotasRead)), routing.Wrap(hs.GetCurrentOrgQuotas)) orgRoute.Get("/quotas", authorize(ac.EvalPermission(ac.ActionOrgsQuotasRead)), routing.Wrap(hs.GetCurrentOrgQuotas))
}) })
if hs.Features.IsEnabled(featuremgmt.FlagStorage) { if hs.Features.IsEnabled(featuremgmt.FlagStorage) {
@ -313,23 +304,23 @@ func (hs *HTTPServer) registerRoutes() {
// current org // current org
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) { apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
userIDScope := ac.Scope("users", "id", ac.Parameter(":userId")) userIDScope := ac.Scope("users", "id", ac.Parameter(":userId"))
orgRoute.Put("/", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateCurrentOrg)) orgRoute.Put("/", authorize(ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateCurrentOrg))
orgRoute.Put("/address", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateCurrentOrgAddress)) orgRoute.Put("/address", authorize(ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateCurrentOrgAddress))
orgRoute.Get("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.GetOrgUsersForCurrentOrg)) orgRoute.Get("/users", authorize(ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.GetOrgUsersForCurrentOrg))
orgRoute.Get("/users/search", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.SearchOrgUsersWithPaging)) orgRoute.Get("/users/search", authorize(ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.SearchOrgUsersWithPaging))
orgRoute.Post("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), quota(user.QuotaTargetSrv), quota(org.QuotaTargetSrv), routing.Wrap(hs.AddOrgUserToCurrentOrg)) orgRoute.Post("/users", authorize(ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), quota(user.QuotaTargetSrv), quota(org.QuotaTargetSrv), routing.Wrap(hs.AddOrgUserToCurrentOrg))
orgRoute.Patch("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersWrite, userIDScope)), routing.Wrap(hs.UpdateOrgUserForCurrentOrg)) orgRoute.Patch("/users/:userId", authorize(ac.EvalPermission(ac.ActionOrgUsersWrite, userIDScope)), routing.Wrap(hs.UpdateOrgUserForCurrentOrg))
orgRoute.Delete("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUserForCurrentOrg)) orgRoute.Delete("/users/:userId", authorize(ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUserForCurrentOrg))
// invites // invites
orgRoute.Get("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd)), routing.Wrap(hs.GetPendingOrgInvites)) orgRoute.Get("/invites", authorize(ac.EvalPermission(ac.ActionOrgUsersAdd)), routing.Wrap(hs.GetPendingOrgInvites))
orgRoute.Post("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd)), quota(user.QuotaTargetSrv), quota(user.QuotaTargetSrv), routing.Wrap(hs.AddOrgInvite)) orgRoute.Post("/invites", authorize(ac.EvalPermission(ac.ActionOrgUsersAdd)), quota(user.QuotaTargetSrv), quota(user.QuotaTargetSrv), routing.Wrap(hs.AddOrgInvite))
orgRoute.Patch("/invites/:code/revoke", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd)), routing.Wrap(hs.RevokeInvite)) orgRoute.Patch("/invites/:code/revoke", authorize(ac.EvalPermission(ac.ActionOrgUsersAdd)), routing.Wrap(hs.RevokeInvite))
// prefs // prefs
orgRoute.Get("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgsPreferencesRead)), routing.Wrap(hs.GetOrgPreferences)) orgRoute.Get("/preferences", authorize(ac.EvalPermission(ac.ActionOrgsPreferencesRead)), routing.Wrap(hs.GetOrgPreferences))
orgRoute.Put("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgsPreferencesWrite)), routing.Wrap(hs.UpdateOrgPreferences)) orgRoute.Put("/preferences", authorize(ac.EvalPermission(ac.ActionOrgsPreferencesWrite)), routing.Wrap(hs.UpdateOrgPreferences))
orgRoute.Patch("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgsPreferencesWrite)), routing.Wrap(hs.PatchOrgPreferences)) orgRoute.Patch("/preferences", authorize(ac.EvalPermission(ac.ActionOrgsPreferencesWrite)), routing.Wrap(hs.PatchOrgPreferences))
}) })
// current org without requirement of user to be org admin // current org without requirement of user to be org admin
@ -346,40 +337,40 @@ func (hs *HTTPServer) registerRoutes() {
ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite), ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite),
) )
} }
orgRoute.Get("/users/lookup", authorize(reqOrgAdminDashOrFolderAdminOrTeamAdmin, lookupEvaluator()), routing.Wrap(hs.GetOrgUsersForCurrentOrgLookup)) orgRoute.Get("/users/lookup", authorize(lookupEvaluator()), routing.Wrap(hs.GetOrgUsersForCurrentOrgLookup))
}) })
// create new org // create new org
apiRoute.Post("/orgs", authorizeInOrg(reqSignedIn, ac.UseGlobalOrg, ac.EvalPermission(ac.ActionOrgsCreate)), quota(org.QuotaTargetSrv), routing.Wrap(hs.CreateOrg)) apiRoute.Post("/orgs", authorizeInOrg(ac.UseGlobalOrg, ac.EvalPermission(ac.ActionOrgsCreate)), quota(org.QuotaTargetSrv), routing.Wrap(hs.CreateOrg))
// search all orgs // search all orgs
apiRoute.Get("/orgs", authorizeInOrg(reqGrafanaAdmin, ac.UseGlobalOrg, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.SearchOrgs)) apiRoute.Get("/orgs", authorizeInOrg(ac.UseGlobalOrg, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.SearchOrgs))
// orgs (admin routes) // orgs (admin routes)
apiRoute.Group("/orgs/:orgId", func(orgsRoute routing.RouteRegister) { apiRoute.Group("/orgs/:orgId", func(orgsRoute routing.RouteRegister) {
userIDScope := ac.Scope("users", "id", ac.Parameter(":userId")) userIDScope := ac.Scope("users", "id", ac.Parameter(":userId"))
orgsRoute.Get("/", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.GetOrgByID)) orgsRoute.Get("/", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.GetOrgByID))
orgsRoute.Put("/", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateOrg)) orgsRoute.Put("/", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateOrg))
orgsRoute.Put("/address", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateOrgAddress)) orgsRoute.Put("/address", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsWrite)), routing.Wrap(hs.UpdateOrgAddress))
orgsRoute.Delete("/", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsDelete)), routing.Wrap(hs.DeleteOrgByID)) orgsRoute.Delete("/", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsDelete)), routing.Wrap(hs.DeleteOrgByID))
orgsRoute.Get("/users", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.GetOrgUsers)) orgsRoute.Get("/users", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.GetOrgUsers))
orgsRoute.Get("/users/search", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.SearchOrgUsers)) orgsRoute.Get("/users/search", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.SearchOrgUsers))
orgsRoute.Post("/users", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), routing.Wrap(hs.AddOrgUser)) orgsRoute.Post("/users", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), routing.Wrap(hs.AddOrgUser))
orgsRoute.Patch("/users/:userId", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersWrite, userIDScope)), routing.Wrap(hs.UpdateOrgUser)) orgsRoute.Patch("/users/:userId", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersWrite, userIDScope)), routing.Wrap(hs.UpdateOrgUser))
orgsRoute.Delete("/users/:userId", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUser)) orgsRoute.Delete("/users/:userId", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUser))
orgsRoute.Get("/quotas", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsQuotasRead)), routing.Wrap(hs.GetOrgQuotas)) orgsRoute.Get("/quotas", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsQuotasRead)), routing.Wrap(hs.GetOrgQuotas))
orgsRoute.Put("/quotas/:target", authorizeInOrg(reqGrafanaAdmin, ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsQuotasWrite)), routing.Wrap(hs.UpdateOrgQuota)) orgsRoute.Put("/quotas/:target", authorizeInOrg(ac.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgsQuotasWrite)), routing.Wrap(hs.UpdateOrgQuota))
}) })
// orgs (admin routes) // orgs (admin routes)
apiRoute.Get("/orgs/name/:name/", authorizeInOrg(reqGrafanaAdmin, ac.UseGlobalOrg, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.GetOrgByName)) apiRoute.Get("/orgs/name/:name/", authorizeInOrg(ac.UseGlobalOrg, ac.EvalPermission(ac.ActionOrgsRead)), routing.Wrap(hs.GetOrgByName))
// auth api keys // auth api keys
apiRoute.Group("/auth/keys", func(keysRoute routing.RouteRegister) { apiRoute.Group("/auth/keys", func(keysRoute routing.RouteRegister) {
apikeyIDScope := ac.Scope("apikeys", "id", ac.Parameter(":id")) apikeyIDScope := ac.Scope("apikeys", "id", ac.Parameter(":id"))
keysRoute.Get("/", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionAPIKeyRead)), routing.Wrap(hs.GetAPIKeys)) keysRoute.Get("/", authorize(ac.EvalPermission(ac.ActionAPIKeyRead)), routing.Wrap(hs.GetAPIKeys))
keysRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionAPIKeyCreate)), quota(string(apikey.QuotaTargetSrv)), routing.Wrap(hs.AddAPIKey)) keysRoute.Post("/", authorize(ac.EvalPermission(ac.ActionAPIKeyCreate)), quota(string(apikey.QuotaTargetSrv)), routing.Wrap(hs.AddAPIKey))
keysRoute.Delete("/:id", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionAPIKeyDelete, apikeyIDScope)), routing.Wrap(hs.DeleteAPIKey)) keysRoute.Delete("/:id", authorize(ac.EvalPermission(ac.ActionAPIKeyDelete, apikeyIDScope)), routing.Wrap(hs.DeleteAPIKey))
}) })
// Preferences // Preferences
@ -392,17 +383,17 @@ func (hs *HTTPServer) registerRoutes() {
idScope := datasources.ScopeProvider.GetResourceScope(ac.Parameter(":id")) idScope := datasources.ScopeProvider.GetResourceScope(ac.Parameter(":id"))
uidScope := datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid")) uidScope := datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid"))
nameScope := datasources.ScopeProvider.GetResourceScopeName(ac.Parameter(":name")) nameScope := datasources.ScopeProvider.GetResourceScopeName(ac.Parameter(":name"))
datasourceRoute.Get("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSources)) datasourceRoute.Get("/", authorize(ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSources))
datasourceRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionCreate)), quota(string(datasources.QuotaTargetSrv)), routing.Wrap(hs.AddDataSource)) datasourceRoute.Post("/", authorize(ac.EvalPermission(datasources.ActionCreate)), quota(string(datasources.QuotaTargetSrv)), routing.Wrap(hs.AddDataSource))
datasourceRoute.Put("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, idScope)), routing.Wrap(hs.UpdateDataSourceByID)) datasourceRoute.Put("/:id", authorize(ac.EvalPermission(datasources.ActionWrite, idScope)), routing.Wrap(hs.UpdateDataSourceByID))
datasourceRoute.Put("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(hs.UpdateDataSourceByUID)) datasourceRoute.Put("/uid/:uid", authorize(ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(hs.UpdateDataSourceByUID))
datasourceRoute.Delete("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDelete, idScope)), routing.Wrap(hs.DeleteDataSourceById)) datasourceRoute.Delete("/:id", authorize(ac.EvalPermission(datasources.ActionDelete, idScope)), routing.Wrap(hs.DeleteDataSourceById))
datasourceRoute.Delete("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDelete, uidScope)), routing.Wrap(hs.DeleteDataSourceByUID)) datasourceRoute.Delete("/uid/:uid", authorize(ac.EvalPermission(datasources.ActionDelete, uidScope)), routing.Wrap(hs.DeleteDataSourceByUID))
datasourceRoute.Delete("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDelete, nameScope)), routing.Wrap(hs.DeleteDataSourceByName)) datasourceRoute.Delete("/name/:name", authorize(ac.EvalPermission(datasources.ActionDelete, nameScope)), routing.Wrap(hs.DeleteDataSourceByName))
datasourceRoute.Get("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead, idScope)), routing.Wrap(hs.GetDataSourceById)) datasourceRoute.Get("/:id", authorize(ac.EvalPermission(datasources.ActionRead, idScope)), routing.Wrap(hs.GetDataSourceById))
datasourceRoute.Get("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead, uidScope)), routing.Wrap(hs.GetDataSourceByUID)) datasourceRoute.Get("/uid/:uid", authorize(ac.EvalPermission(datasources.ActionRead, uidScope)), routing.Wrap(hs.GetDataSourceByUID))
datasourceRoute.Get("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead, nameScope)), routing.Wrap(hs.GetDataSourceByName)) datasourceRoute.Get("/name/:name", authorize(ac.EvalPermission(datasources.ActionRead, nameScope)), routing.Wrap(hs.GetDataSourceByName))
datasourceRoute.Get("/id/:name", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionIDRead, nameScope)), routing.Wrap(hs.GetDataSourceIdByName)) datasourceRoute.Get("/id/:name", authorize(ac.EvalPermission(datasources.ActionIDRead, nameScope)), routing.Wrap(hs.GetDataSourceIdByName))
}) })
pluginIDScope := pluginaccesscontrol.ScopeProvider.GetResourceScope(ac.Parameter(":pluginId")) pluginIDScope := pluginaccesscontrol.ScopeProvider.GetResourceScope(ac.Parameter(":pluginId"))
@ -410,96 +401,96 @@ func (hs *HTTPServer) registerRoutes() {
apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(hs.GetPluginSettingByID)) // RBAC check performed in handler for App Plugins apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(hs.GetPluginSettingByID)) // RBAC check performed in handler for App Plugins
apiRoute.Get("/plugins/:pluginId/markdown/:name", routing.Wrap(hs.GetPluginMarkdown)) apiRoute.Get("/plugins/:pluginId/markdown/:name", routing.Wrap(hs.GetPluginMarkdown))
apiRoute.Get("/plugins/:pluginId/health", routing.Wrap(hs.CheckHealth)) apiRoute.Get("/plugins/:pluginId/health", routing.Wrap(hs.CheckHealth))
apiRoute.Any("/plugins/:pluginId/resources", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.CallResource) apiRoute.Any("/plugins/:pluginId/resources", authorize(ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.CallResource)
apiRoute.Any("/plugins/:pluginId/resources/*", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.CallResource) apiRoute.Any("/plugins/:pluginId/resources/*", authorize(ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.CallResource)
apiRoute.Get("/plugins/errors", routing.Wrap(hs.GetPluginErrorsList)) apiRoute.Get("/plugins/errors", routing.Wrap(hs.GetPluginErrorsList))
apiRoute.Any("/plugin-proxy/:pluginId/*", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest) apiRoute.Any("/plugin-proxy/:pluginId/*", authorize(ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest)
apiRoute.Any("/plugin-proxy/:pluginId", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest) apiRoute.Any("/plugin-proxy/:pluginId", authorize(ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest)
if hs.Cfg.PluginAdminEnabled && !hs.Cfg.PluginAdminExternalManageEnabled { if hs.Cfg.PluginAdminEnabled && !hs.Cfg.PluginAdminExternalManageEnabled {
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) { apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
pluginRoute.Post("/:pluginId/install", authorize(reqGrafanaAdmin, ac.EvalPermission(pluginaccesscontrol.ActionInstall)), routing.Wrap(hs.InstallPlugin)) pluginRoute.Post("/:pluginId/install", authorize(ac.EvalPermission(pluginaccesscontrol.ActionInstall)), routing.Wrap(hs.InstallPlugin))
pluginRoute.Post("/:pluginId/uninstall", authorize(reqGrafanaAdmin, ac.EvalPermission(pluginaccesscontrol.ActionInstall)), routing.Wrap(hs.UninstallPlugin)) pluginRoute.Post("/:pluginId/uninstall", authorize(ac.EvalPermission(pluginaccesscontrol.ActionInstall)), routing.Wrap(hs.UninstallPlugin))
}) })
} }
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) { apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
pluginRoute.Get("/:pluginId/dashboards/", reqOrgAdmin, routing.Wrap(hs.GetPluginDashboards)) pluginRoute.Get("/:pluginId/dashboards/", reqOrgAdmin, routing.Wrap(hs.GetPluginDashboards))
pluginRoute.Post("/:pluginId/settings", authorize(reqOrgAdmin, ac.EvalPermission(pluginaccesscontrol.ActionWrite, pluginIDScope)), routing.Wrap(hs.UpdatePluginSetting)) pluginRoute.Post("/:pluginId/settings", authorize(ac.EvalPermission(pluginaccesscontrol.ActionWrite, pluginIDScope)), routing.Wrap(hs.UpdatePluginSetting))
pluginRoute.Get("/:pluginId/metrics", reqOrgAdmin, routing.Wrap(hs.CollectPluginMetrics)) pluginRoute.Get("/:pluginId/metrics", reqOrgAdmin, routing.Wrap(hs.CollectPluginMetrics))
}) })
apiRoute.Get("/frontend/settings/", hs.GetFrontendSettings) apiRoute.Get("/frontend/settings/", hs.GetFrontendSettings)
apiRoute.Any("/datasources/proxy/:id/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest) apiRoute.Any("/datasources/proxy/:id/*", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest)
apiRoute.Any("/datasources/proxy/uid/:uid/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequestWithUID) apiRoute.Any("/datasources/proxy/uid/:uid/*", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequestWithUID)
apiRoute.Any("/datasources/proxy/:id", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest) apiRoute.Any("/datasources/proxy/:id", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest)
apiRoute.Any("/datasources/proxy/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequestWithUID) apiRoute.Any("/datasources/proxy/uid/:uid", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequestWithUID)
// Deprecated: use /datasources/uid/:uid/resources API instead. // Deprecated: use /datasources/uid/:uid/resources API instead.
apiRoute.Any("/datasources/:id/resources", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource) apiRoute.Any("/datasources/:id/resources", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource)
apiRoute.Any("/datasources/uid/:uid/resources", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResourceWithUID) apiRoute.Any("/datasources/uid/:uid/resources", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResourceWithUID)
// Deprecated: use /datasources/uid/:uid/resources/* API instead. // Deprecated: use /datasources/uid/:uid/resources/* API instead.
apiRoute.Any("/datasources/:id/resources/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource) apiRoute.Any("/datasources/:id/resources/*", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource)
apiRoute.Any("/datasources/uid/:uid/resources/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResourceWithUID) apiRoute.Any("/datasources/uid/:uid/resources/*", authorize(ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResourceWithUID)
// Deprecated: use /datasources/uid/:uid/health API instead. // Deprecated: use /datasources/uid/:uid/health API instead.
apiRoute.Any("/datasources/:id/health", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealth)) apiRoute.Any("/datasources/:id/health", authorize(ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealth))
apiRoute.Any("/datasources/uid/:uid/health", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealthWithUID)) apiRoute.Any("/datasources/uid/:uid/health", authorize(ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealthWithUID))
// Folders // Folders
apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) { apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) {
idScope := dashboards.ScopeFoldersProvider.GetResourceScope(ac.Parameter(":id")) idScope := dashboards.ScopeFoldersProvider.GetResourceScope(ac.Parameter(":id"))
uidScope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(ac.Parameter(":uid")) uidScope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(ac.Parameter(":uid"))
folderRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersRead)), routing.Wrap(hs.GetFolders)) folderRoute.Get("/", authorize(ac.EvalPermission(dashboards.ActionFoldersRead)), routing.Wrap(hs.GetFolders))
folderRoute.Get("/id/:id", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersRead, idScope)), routing.Wrap(hs.GetFolderByID)) folderRoute.Get("/id/:id", authorize(ac.EvalPermission(dashboards.ActionFoldersRead, idScope)), routing.Wrap(hs.GetFolderByID))
folderRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersCreate)), routing.Wrap(hs.CreateFolder)) folderRoute.Post("/", authorize(ac.EvalPermission(dashboards.ActionFoldersCreate)), routing.Wrap(hs.CreateFolder))
folderRoute.Group("/:uid", func(folderUidRoute routing.RouteRegister) { folderRoute.Group("/:uid", func(folderUidRoute routing.RouteRegister) {
folderUidRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersRead, uidScope)), routing.Wrap(hs.GetFolderByUID)) folderUidRoute.Get("/", authorize(ac.EvalPermission(dashboards.ActionFoldersRead, uidScope)), routing.Wrap(hs.GetFolderByUID))
folderUidRoute.Put("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersWrite, uidScope)), routing.Wrap(hs.UpdateFolder)) folderUidRoute.Put("/", authorize(ac.EvalPermission(dashboards.ActionFoldersWrite, uidScope)), routing.Wrap(hs.UpdateFolder))
folderUidRoute.Post("/move", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersWrite, uidScope)), routing.Wrap(hs.MoveFolder)) folderUidRoute.Post("/move", authorize(ac.EvalPermission(dashboards.ActionFoldersWrite, uidScope)), routing.Wrap(hs.MoveFolder))
folderUidRoute.Delete("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersDelete, uidScope)), routing.Wrap(hs.DeleteFolder)) folderUidRoute.Delete("/", authorize(ac.EvalPermission(dashboards.ActionFoldersDelete, uidScope)), routing.Wrap(hs.DeleteFolder))
folderUidRoute.Get("/counts", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersRead, uidScope)), routing.Wrap(hs.GetFolderDescendantCounts)) folderUidRoute.Get("/counts", authorize(ac.EvalPermission(dashboards.ActionFoldersRead, uidScope)), routing.Wrap(hs.GetFolderDescendantCounts))
folderUidRoute.Group("/permissions", func(folderPermissionRoute routing.RouteRegister) { folderUidRoute.Group("/permissions", func(folderPermissionRoute routing.RouteRegister) {
folderPermissionRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersPermissionsRead, uidScope)), routing.Wrap(hs.GetFolderPermissionList)) folderPermissionRoute.Get("/", authorize(ac.EvalPermission(dashboards.ActionFoldersPermissionsRead, uidScope)), routing.Wrap(hs.GetFolderPermissionList))
folderPermissionRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersPermissionsWrite, uidScope)), routing.Wrap(hs.UpdateFolderPermissions)) folderPermissionRoute.Post("/", authorize(ac.EvalPermission(dashboards.ActionFoldersPermissionsWrite, uidScope)), routing.Wrap(hs.UpdateFolderPermissions))
}) })
}) })
}) })
// Dashboard // Dashboard
apiRoute.Group("/dashboards", func(dashboardRoute routing.RouteRegister) { apiRoute.Group("/dashboards", func(dashboardRoute routing.RouteRegister) {
dashboardRoute.Get("/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsRead)), routing.Wrap(hs.GetDashboard)) dashboardRoute.Get("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsRead)), routing.Wrap(hs.GetDashboard))
dashboardRoute.Delete("/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsDelete)), routing.Wrap(hs.DeleteDashboardByUID)) dashboardRoute.Delete("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsDelete)), routing.Wrap(hs.DeleteDashboardByUID))
dashboardRoute.Group("/uid/:uid", func(dashUidRoute routing.RouteRegister) { dashboardRoute.Group("/uid/:uid", func(dashUidRoute routing.RouteRegister) {
dashUidRoute.Get("/versions", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersions)) dashUidRoute.Get("/versions", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersions))
dashUidRoute.Post("/restore", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.RestoreDashboardVersion)) dashUidRoute.Post("/restore", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.RestoreDashboardVersion))
dashUidRoute.Get("/versions/:id", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion)) dashUidRoute.Get("/versions/:id", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion))
dashUidRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) { dashUidRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
dashboardPermissionRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList)) dashboardPermissionRoute.Get("/", authorize(ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList))
dashboardPermissionRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite)), routing.Wrap(hs.UpdateDashboardPermissions)) dashboardPermissionRoute.Post("/", authorize(ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite)), routing.Wrap(hs.UpdateDashboardPermissions))
}) })
}) })
dashboardRoute.Post("/calculate-diff", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.CalculateDashboardDiff)) dashboardRoute.Post("/calculate-diff", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.CalculateDashboardDiff))
dashboardRoute.Post("/validate", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.ValidateDashboard)) dashboardRoute.Post("/validate", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.ValidateDashboard))
dashboardRoute.Post("/trim", routing.Wrap(hs.TrimDashboard)) dashboardRoute.Post("/trim", routing.Wrap(hs.TrimDashboard))
dashboardRoute.Post("/db", authorize(reqSignedIn, ac.EvalAny(ac.EvalPermission(dashboards.ActionDashboardsCreate), ac.EvalPermission(dashboards.ActionDashboardsWrite))), routing.Wrap(hs.PostDashboard)) dashboardRoute.Post("/db", authorize(ac.EvalAny(ac.EvalPermission(dashboards.ActionDashboardsCreate), ac.EvalPermission(dashboards.ActionDashboardsWrite))), routing.Wrap(hs.PostDashboard))
dashboardRoute.Get("/home", routing.Wrap(hs.GetHomeDashboard)) dashboardRoute.Get("/home", routing.Wrap(hs.GetHomeDashboard))
dashboardRoute.Get("/tags", hs.GetDashboardTags) dashboardRoute.Get("/tags", hs.GetDashboardTags)
// Deprecated: used to convert internal IDs to UIDs // Deprecated: used to convert internal IDs to UIDs
dashboardRoute.Get("/ids/:ids", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsRead)), hs.GetDashboardUIDs) dashboardRoute.Get("/ids/:ids", authorize(ac.EvalPermission(dashboards.ActionDashboardsRead)), hs.GetDashboardUIDs)
// Deprecated: use /uid/:uid API instead. // Deprecated: use /uid/:uid API instead.
dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute routing.RouteRegister) { dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute routing.RouteRegister) {
dashIdRoute.Get("/versions", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersions)) dashIdRoute.Get("/versions", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersions))
dashIdRoute.Get("/versions/:id", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion)) dashIdRoute.Get("/versions/:id", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion))
dashIdRoute.Post("/restore", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.RestoreDashboardVersion)) dashIdRoute.Post("/restore", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.RestoreDashboardVersion))
dashIdRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) { dashIdRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
dashboardPermissionRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList)) dashboardPermissionRoute.Get("/", authorize(ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList))
dashboardPermissionRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite)), routing.Wrap(hs.UpdateDashboardPermissions)) dashboardPermissionRoute.Post("/", authorize(ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite)), routing.Wrap(hs.UpdateDashboardPermissions))
}) })
}) })
}) })
@ -526,7 +517,7 @@ func (hs *HTTPServer) registerRoutes() {
// metrics // metrics
// DataSource w/ expressions // DataSource w/ expressions
apiRoute.Post("/ds/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.QueryMetricsV2)) apiRoute.Post("/ds/query", authorize(ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.QueryMetricsV2))
apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) { apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) {
alertsRoute.Post("/test", routing.Wrap(hs.AlertTest)) alertsRoute.Post("/test", routing.Wrap(hs.AlertTest))
@ -564,17 +555,17 @@ func (hs *HTTPServer) registerRoutes() {
orgRoute.Get("/lookup", routing.Wrap(hs.GetAlertNotificationLookup)) orgRoute.Get("/lookup", routing.Wrap(hs.GetAlertNotificationLookup))
}) })
apiRoute.Get("/annotations", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsRead)), routing.Wrap(hs.GetAnnotations)) apiRoute.Get("/annotations", authorize(ac.EvalPermission(ac.ActionAnnotationsRead)), routing.Wrap(hs.GetAnnotations))
apiRoute.Post("/annotations/mass-delete", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionAnnotationsDelete)), routing.Wrap(hs.MassDeleteAnnotations)) apiRoute.Post("/annotations/mass-delete", authorize(ac.EvalPermission(ac.ActionAnnotationsDelete)), routing.Wrap(hs.MassDeleteAnnotations))
apiRoute.Group("/annotations", func(annotationsRoute routing.RouteRegister) { apiRoute.Group("/annotations", func(annotationsRoute routing.RouteRegister) {
annotationsRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsCreate)), routing.Wrap(hs.PostAnnotation)) annotationsRoute.Post("/", authorize(ac.EvalPermission(ac.ActionAnnotationsCreate)), routing.Wrap(hs.PostAnnotation))
annotationsRoute.Get("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsRead, ac.ScopeAnnotationsID)), routing.Wrap(hs.GetAnnotationByID)) annotationsRoute.Get("/:annotationId", authorize(ac.EvalPermission(ac.ActionAnnotationsRead, ac.ScopeAnnotationsID)), routing.Wrap(hs.GetAnnotationByID))
annotationsRoute.Delete("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsDelete, ac.ScopeAnnotationsID)), routing.Wrap(hs.DeleteAnnotationByID)) annotationsRoute.Delete("/:annotationId", authorize(ac.EvalPermission(ac.ActionAnnotationsDelete, ac.ScopeAnnotationsID)), routing.Wrap(hs.DeleteAnnotationByID))
annotationsRoute.Put("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsWrite, ac.ScopeAnnotationsID)), routing.Wrap(hs.UpdateAnnotation)) annotationsRoute.Put("/:annotationId", authorize(ac.EvalPermission(ac.ActionAnnotationsWrite, ac.ScopeAnnotationsID)), routing.Wrap(hs.UpdateAnnotation))
annotationsRoute.Patch("/:annotationId", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsWrite, ac.ScopeAnnotationsID)), routing.Wrap(hs.PatchAnnotation)) annotationsRoute.Patch("/:annotationId", authorize(ac.EvalPermission(ac.ActionAnnotationsWrite, ac.ScopeAnnotationsID)), routing.Wrap(hs.PatchAnnotation))
annotationsRoute.Post("/graphite", authorize(reqEditorRole, ac.EvalPermission(ac.ActionAnnotationsCreate, ac.ScopeAnnotationsTypeOrganization)), routing.Wrap(hs.PostGraphiteAnnotation)) annotationsRoute.Post("/graphite", authorize(ac.EvalPermission(ac.ActionAnnotationsCreate, ac.ScopeAnnotationsTypeOrganization)), routing.Wrap(hs.PostGraphiteAnnotation))
annotationsRoute.Get("/tags", authorize(reqSignedIn, ac.EvalPermission(ac.ActionAnnotationsRead)), routing.Wrap(hs.GetAnnotationTags)) annotationsRoute.Get("/tags", authorize(ac.EvalPermission(ac.ActionAnnotationsRead)), routing.Wrap(hs.GetAnnotationTags))
}) })
apiRoute.Post("/frontend-metrics", routing.Wrap(hs.PostFrontendMetrics)) apiRoute.Post("/frontend-metrics", routing.Wrap(hs.PostFrontendMetrics))
@ -600,9 +591,9 @@ func (hs *HTTPServer) registerRoutes() {
// admin api // admin api
r.Group("/api/admin", func(adminRoute routing.RouteRegister) { r.Group("/api/admin", func(adminRoute routing.RouteRegister) {
// There is additional filter which will ensure that user sees only settings that they are allowed to see, so we don't need provide additional scope here for ActionSettingsRead. // There is additional filter which will ensure that user sees only settings that they are allowed to see, so we don't need provide additional scope here for ActionSettingsRead.
adminRoute.Get("/settings", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetSettings)) adminRoute.Get("/settings", authorize(ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetSettings))
adminRoute.Get("/settings-verbose", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetVerboseSettings)) adminRoute.Get("/settings-verbose", authorize(ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetVerboseSettings))
adminRoute.Get("/stats", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionServerStatsRead)), routing.Wrap(hs.AdminGetStats)) adminRoute.Get("/stats", authorize(ac.EvalPermission(ac.ActionServerStatsRead)), routing.Wrap(hs.AdminGetStats))
adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, routing.Wrap(hs.PauseAllAlerts(setting.AlertingEnabled))) adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, routing.Wrap(hs.PauseAllAlerts(setting.AlertingEnabled)))
adminRoute.Post("/encryption/rotate-data-keys", reqGrafanaAdmin, routing.Wrap(hs.AdminRotateDataEncryptionKeys)) adminRoute.Post("/encryption/rotate-data-keys", reqGrafanaAdmin, routing.Wrap(hs.AdminRotateDataEncryptionKeys))
@ -613,29 +604,29 @@ func (hs *HTTPServer) registerRoutes() {
adminRoute.Post("/encryption/migrate-secrets/from-plugin", reqGrafanaAdmin, routing.Wrap(hs.AdminMigrateSecretsFromPlugin)) adminRoute.Post("/encryption/migrate-secrets/from-plugin", reqGrafanaAdmin, routing.Wrap(hs.AdminMigrateSecretsFromPlugin))
adminRoute.Post("/encryption/delete-secretsmanagerplugin-secrets", reqGrafanaAdmin, routing.Wrap(hs.AdminDeleteAllSecretsManagerPluginSecrets)) adminRoute.Post("/encryption/delete-secretsmanagerplugin-secrets", reqGrafanaAdmin, routing.Wrap(hs.AdminDeleteAllSecretsManagerPluginSecrets))
adminRoute.Post("/provisioning/dashboards/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersDashboards)), routing.Wrap(hs.AdminProvisioningReloadDashboards)) adminRoute.Post("/provisioning/dashboards/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersDashboards)), routing.Wrap(hs.AdminProvisioningReloadDashboards))
adminRoute.Post("/provisioning/plugins/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersPlugins)), routing.Wrap(hs.AdminProvisioningReloadPlugins)) adminRoute.Post("/provisioning/plugins/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersPlugins)), routing.Wrap(hs.AdminProvisioningReloadPlugins))
adminRoute.Post("/provisioning/datasources/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersDatasources)), routing.Wrap(hs.AdminProvisioningReloadDatasources)) adminRoute.Post("/provisioning/datasources/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersDatasources)), routing.Wrap(hs.AdminProvisioningReloadDatasources))
adminRoute.Post("/provisioning/notifications/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersNotifications)), routing.Wrap(hs.AdminProvisioningReloadNotifications)) adminRoute.Post("/provisioning/notifications/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersNotifications)), routing.Wrap(hs.AdminProvisioningReloadNotifications))
adminRoute.Post("/provisioning/alerting/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersAlertRules)), routing.Wrap(hs.AdminProvisioningReloadAlerting)) adminRoute.Post("/provisioning/alerting/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersAlertRules)), routing.Wrap(hs.AdminProvisioningReloadAlerting))
}, reqSignedIn) }, reqSignedIn)
// Administering users // Administering users
r.Group("/api/admin/users", func(adminUserRoute routing.RouteRegister) { r.Group("/api/admin/users", func(adminUserRoute routing.RouteRegister) {
userIDScope := ac.Scope("global.users", "id", ac.Parameter(":id")) userIDScope := ac.Scope("global.users", "id", ac.Parameter(":id"))
adminUserRoute.Post("/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(hs.AdminCreateUser)) adminUserRoute.Post("/", authorize(ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(hs.AdminCreateUser))
adminUserRoute.Put("/:id/password", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPasswordUpdate, userIDScope)), routing.Wrap(hs.AdminUpdateUserPassword)) adminUserRoute.Put("/:id/password", authorize(ac.EvalPermission(ac.ActionUsersPasswordUpdate, userIDScope)), routing.Wrap(hs.AdminUpdateUserPassword))
adminUserRoute.Put("/:id/permissions", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPermissionsUpdate, userIDScope)), routing.Wrap(hs.AdminUpdateUserPermissions)) adminUserRoute.Put("/:id/permissions", authorize(ac.EvalPermission(ac.ActionUsersPermissionsUpdate, userIDScope)), routing.Wrap(hs.AdminUpdateUserPermissions))
adminUserRoute.Delete("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersDelete, userIDScope)), routing.Wrap(hs.AdminDeleteUser)) adminUserRoute.Delete("/:id", authorize(ac.EvalPermission(ac.ActionUsersDelete, userIDScope)), routing.Wrap(hs.AdminDeleteUser))
adminUserRoute.Post("/:id/disable", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersDisable, userIDScope)), routing.Wrap(hs.AdminDisableUser)) adminUserRoute.Post("/:id/disable", authorize(ac.EvalPermission(ac.ActionUsersDisable, userIDScope)), routing.Wrap(hs.AdminDisableUser))
adminUserRoute.Post("/:id/enable", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersEnable, userIDScope)), routing.Wrap(hs.AdminEnableUser)) adminUserRoute.Post("/:id/enable", authorize(ac.EvalPermission(ac.ActionUsersEnable, userIDScope)), routing.Wrap(hs.AdminEnableUser))
adminUserRoute.Get("/:id/quotas", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersQuotasList, userIDScope)), routing.Wrap(hs.GetUserQuotas)) adminUserRoute.Get("/:id/quotas", authorize(ac.EvalPermission(ac.ActionUsersQuotasList, userIDScope)), routing.Wrap(hs.GetUserQuotas))
adminUserRoute.Put("/:id/quotas/:target", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersQuotasUpdate, userIDScope)), routing.Wrap(hs.UpdateUserQuota)) adminUserRoute.Put("/:id/quotas/:target", authorize(ac.EvalPermission(ac.ActionUsersQuotasUpdate, userIDScope)), routing.Wrap(hs.UpdateUserQuota))
adminUserRoute.Post("/:id/logout", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersLogout, userIDScope)), routing.Wrap(hs.AdminLogoutUser)) adminUserRoute.Post("/:id/logout", authorize(ac.EvalPermission(ac.ActionUsersLogout, userIDScope)), routing.Wrap(hs.AdminLogoutUser))
adminUserRoute.Get("/:id/auth-tokens", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersAuthTokenList, userIDScope)), routing.Wrap(hs.AdminGetUserAuthTokens)) adminUserRoute.Get("/:id/auth-tokens", authorize(ac.EvalPermission(ac.ActionUsersAuthTokenList, userIDScope)), routing.Wrap(hs.AdminGetUserAuthTokens))
adminUserRoute.Post("/:id/revoke-auth-token", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersAuthTokenUpdate, userIDScope)), routing.Wrap(hs.AdminRevokeUserAuthToken)) adminUserRoute.Post("/:id/revoke-auth-token", authorize(ac.EvalPermission(ac.ActionUsersAuthTokenUpdate, userIDScope)), routing.Wrap(hs.AdminRevokeUserAuthToken))
}, reqSignedIn) }, reqSignedIn)
// rendering // rendering

View File

@ -5,7 +5,6 @@ import (
"github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
) )
@ -16,7 +15,7 @@ func (uss *UsageStats) registerAPIEndpoints() {
authorize := accesscontrol.Middleware(uss.accesscontrol) authorize := accesscontrol.Middleware(uss.accesscontrol)
uss.RouteRegister.Group(rootUrl, func(subrouter routing.RouteRegister) { uss.RouteRegister.Group(rootUrl, func(subrouter routing.RouteRegister) {
subrouter.Get("/usage-report-preview", authorize(middleware.ReqGrafanaAdmin, accesscontrol.EvalPermission(ActionRead)), routing.Wrap(uss.getUsageReportPreview)) subrouter.Get("/usage-report-preview", authorize(accesscontrol.EvalPermission(ActionRead)), routing.Wrap(uss.getUsageReportPreview))
}) })
} }

View File

@ -8,16 +8,12 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/middleware/cookies" "github.com/grafana/grafana/pkg/middleware/cookies"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/authn" "github.com/grafana/grafana/pkg/services/authn"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/services/team"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
@ -90,14 +86,6 @@ func removeForceLoginParams(str string) string {
return forceLoginParamsRegexp.ReplaceAllString(str, "") return forceLoginParamsRegexp.ReplaceAllString(str, "")
} }
func EnsureEditorOrViewerCanEdit(cfg *setting.Cfg) func(c *contextmodel.ReqContext) {
return func(c *contextmodel.ReqContext) {
if !c.SignedInUser.HasRole(org.RoleEditor) && !cfg.ViewersCanEdit {
accessForbidden(c)
}
}
}
func CanAdminPlugins(cfg *setting.Cfg) func(c *contextmodel.ReqContext) { func CanAdminPlugins(cfg *setting.Cfg) func(c *contextmodel.ReqContext) {
return func(c *contextmodel.ReqContext) { return func(c *contextmodel.ReqContext) {
if !pluginaccesscontrol.ReqCanAdminPlugins(cfg)(c) { if !pluginaccesscontrol.ReqCanAdminPlugins(cfg)(c) {
@ -156,25 +144,6 @@ func Auth(options *AuthOptions) web.Handler {
} }
} }
// AdminOrEditorAndFeatureEnabled creates a middleware that allows
// access if the signed in user is either an Org Admin or if they
// are an Org Editor and the feature flag is enabled.
// Intended for when feature flags open up access to APIs that
// are otherwise only available to admins.
func AdminOrEditorAndFeatureEnabled(enabled bool) web.Handler {
return func(c *contextmodel.ReqContext) {
if c.OrgRole == org.RoleAdmin {
return
}
if c.OrgRole == org.RoleEditor && enabled {
return
}
accessForbidden(c)
}
}
// SnapshotPublicModeOrSignedIn creates a middleware that allows access // SnapshotPublicModeOrSignedIn creates a middleware that allows access
// if snapshot public mode is enabled or if user is signed in. // if snapshot public mode is enabled or if user is signed in.
func SnapshotPublicModeOrSignedIn(cfg *setting.Cfg) web.Handler { func SnapshotPublicModeOrSignedIn(cfg *setting.Cfg) web.Handler {
@ -218,33 +187,3 @@ func shouldForceLogin(c *contextmodel.ReqContext) bool {
return forceLogin return forceLogin
} }
func OrgAdminDashOrFolderAdminOrTeamAdmin(ss db.DB, ds dashboards.DashboardService, ts team.Service) func(c *contextmodel.ReqContext) {
return func(c *contextmodel.ReqContext) {
if c.OrgRole == org.RoleAdmin {
return
}
hasAdminPermissionInDashOrFoldersQuery := folder.HasAdminPermissionInDashboardsOrFoldersQuery{SignedInUser: c.SignedInUser}
hasAdminPermissionInDashOrFoldersQueryResult, err := ds.HasAdminPermissionInDashboardsOrFolders(c.Req.Context(), &hasAdminPermissionInDashOrFoldersQuery)
if err != nil {
c.JsonApiErr(500, "Failed to check if user is a folder admin", err)
}
if hasAdminPermissionInDashOrFoldersQueryResult {
return
}
isAdminOfTeamsQuery := team.IsAdminOfTeamsQuery{SignedInUser: c.SignedInUser}
isAdminOfTeamsQueryResult, err := ts.IsAdminOfTeams(c.Req.Context(), &isAdminOfTeamsQuery)
if err != nil {
c.JsonApiErr(500, "Failed to check if user is a team admin", err)
}
if isAdminOfTeamsQueryResult {
return
}
accessForbidden(c)
}
}

View File

@ -38,10 +38,8 @@ func (api *AccessControlAPI) RegisterAPIEndpoints() {
rr.Get("/user/permissions", middleware.ReqSignedIn, routing.Wrap(api.getUserPermissions)) rr.Get("/user/permissions", middleware.ReqSignedIn, routing.Wrap(api.getUserPermissions))
if api.features.IsEnabled(featuremgmt.FlagAccessControlOnCall) { if api.features.IsEnabled(featuremgmt.FlagAccessControlOnCall) {
userIDScope := ac.Scope("users", "id", ac.Parameter(":userID")) userIDScope := ac.Scope("users", "id", ac.Parameter(":userID"))
rr.Get("/users/permissions/search", authorize(middleware.ReqSignedIn, rr.Get("/users/permissions/search", authorize(ac.EvalPermission(ac.ActionUsersPermissionsRead)), routing.Wrap(api.searchUsersPermissions))
ac.EvalPermission(ac.ActionUsersPermissionsRead)), routing.Wrap(api.searchUsersPermissions)) rr.Get("/user/:userID/permissions/search", authorize(ac.EvalPermission(ac.ActionUsersPermissionsRead, userIDScope)), routing.Wrap(api.searchUserPermissions))
rr.Get("/user/:userID/permissions/search", authorize(middleware.ReqSignedIn,
ac.EvalPermission(ac.ActionUsersPermissionsRead, userIDScope)), routing.Wrap(api.searchUserPermissions))
} }
}) })
} }

View File

@ -24,12 +24,8 @@ import (
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
func Middleware(ac AccessControl) func(web.Handler, Evaluator) web.Handler { func Middleware(ac AccessControl) func(Evaluator) web.Handler {
return func(fallback web.Handler, evaluator Evaluator) web.Handler { return func(evaluator Evaluator) web.Handler {
if ac.IsDisabled() {
return fallback
}
return func(c *contextmodel.ReqContext) { return func(c *contextmodel.ReqContext) {
if c.AllowAnonymous { if c.AllowAnonymous {
forceLogin, _ := strconv.ParseBool(c.Req.URL.Query().Get("forceLogin")) // ignoring error, assuming false for non-true values is ok. forceLogin, _ := strconv.ParseBool(c.Req.URL.Query().Get("forceLogin")) // ignoring error, assuming false for non-true values is ok.
@ -180,12 +176,8 @@ type userCache interface {
GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error)
} }
func AuthorizeInOrgMiddleware(ac AccessControl, service Service, cache userCache) func(web.Handler, OrgIDGetter, Evaluator) web.Handler { func AuthorizeInOrgMiddleware(ac AccessControl, service Service, cache userCache) func(OrgIDGetter, Evaluator) web.Handler {
return func(fallback web.Handler, getTargetOrg OrgIDGetter, evaluator Evaluator) web.Handler { return func(getTargetOrg OrgIDGetter, evaluator Evaluator) web.Handler {
if ac.IsDisabled() {
return fallback
}
return func(c *contextmodel.ReqContext) { return func(c *contextmodel.ReqContext) {
// using a copy of the user not to modify the signedInUser, yet perform the permission evaluation in another org // using a copy of the user not to modify the signedInUser, yet perform the permission evaluation in another org
userCopy := *(c.SignedInUser) userCopy := *(c.SignedInUser)

View File

@ -18,7 +18,6 @@ import (
type middlewareTestCase struct { type middlewareTestCase struct {
desc string desc string
expectFallback bool
expectEndpoint bool expectEndpoint bool
evaluator accesscontrol.Evaluator evaluator accesscontrol.Evaluator
ac accesscontrol.AccessControl ac accesscontrol.AccessControl
@ -26,19 +25,12 @@ type middlewareTestCase struct {
func TestMiddleware(t *testing.T) { func TestMiddleware(t *testing.T) {
tests := []middlewareTestCase{ tests := []middlewareTestCase{
{
desc: "should use fallback if access control is disabled",
ac: mock.New().WithDisabled(),
expectFallback: true,
expectEndpoint: true,
},
{ {
desc: "should pass middleware for correct permissions", desc: "should pass middleware for correct permissions",
ac: mock.New().WithPermissions( ac: mock.New().WithPermissions(
[]accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}},
), ),
evaluator: accesscontrol.EvalPermission("users:read", "users:*"), evaluator: accesscontrol.EvalPermission("users:read", "users:*"),
expectFallback: false,
expectEndpoint: true, expectEndpoint: true,
}, },
{ {
@ -47,23 +39,17 @@ func TestMiddleware(t *testing.T) {
[]accesscontrol.Permission{{Action: "users:read", Scope: "users:1"}}, []accesscontrol.Permission{{Action: "users:read", Scope: "users:1"}},
), ),
evaluator: accesscontrol.EvalPermission("users:read", "users:*"), evaluator: accesscontrol.EvalPermission("users:read", "users:*"),
expectFallback: false,
expectEndpoint: false, expectEndpoint: false,
}, },
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.desc, func(t *testing.T) { t.Run(test.desc, func(t *testing.T) {
fallbackCalled := false
fallback := func(c *contextmodel.ReqContext) {
fallbackCalled = true
}
server := web.New() server := web.New()
server.UseMiddleware(web.Renderer("../../public/views", "[[", "]]")) server.UseMiddleware(web.Renderer("../../public/views", "[[", "]]"))
server.Use(contextProvider()) server.Use(contextProvider())
server.Use(accesscontrol.Middleware(test.ac)(fallback, test.evaluator)) server.Use(accesscontrol.Middleware(test.ac)(test.evaluator))
endpointCalled := false endpointCalled := false
server.Get("/", func(c *contextmodel.ReqContext) { server.Get("/", func(c *contextmodel.ReqContext) {
@ -77,7 +63,6 @@ func TestMiddleware(t *testing.T) {
server.ServeHTTP(recorder, request) server.ServeHTTP(recorder, request)
assert.Equal(t, test.expectFallback, fallbackCalled)
assert.Equal(t, test.expectEndpoint, endpointCalled) assert.Equal(t, test.expectEndpoint, endpointCalled)
}) })
} }
@ -111,7 +96,7 @@ func TestMiddleware_forceLogin(t *testing.T) {
c.IsSignedIn = false c.IsSignedIn = false
})) }))
server.Use( server.Use(
accesscontrol.Middleware(ac)(nil, accesscontrol.EvalPermission("endpoint:read", "endpoint:1")), accesscontrol.Middleware(ac)(accesscontrol.EvalPermission("endpoint:read", "endpoint:1")),
) )
request, err := http.NewRequest(http.MethodGet, tc.url, nil) request, err := http.NewRequest(http.MethodGet, tc.url, nil)

View File

@ -32,7 +32,6 @@ func newApi(ac accesscontrol.AccessControl, router routing.RouteRegister, manage
func (a *api) registerEndpoints() { func (a *api) registerEndpoints() {
auth := accesscontrol.Middleware(a.ac) auth := accesscontrol.Middleware(a.ac)
disable := disableMiddleware(a.ac.IsDisabled())
licenseMW := a.service.options.LicenseMW licenseMW := a.service.options.LicenseMW
if licenseMW == nil { if licenseMW == nil {
licenseMW = nopMiddleware licenseMW = nopMiddleware
@ -42,17 +41,17 @@ func (a *api) registerEndpoints() {
actionRead := fmt.Sprintf("%s.permissions:read", a.service.options.Resource) actionRead := fmt.Sprintf("%s.permissions:read", a.service.options.Resource)
actionWrite := fmt.Sprintf("%s.permissions:write", a.service.options.Resource) actionWrite := fmt.Sprintf("%s.permissions:write", a.service.options.Resource)
scope := accesscontrol.Scope(a.service.options.Resource, a.service.options.ResourceAttribute, accesscontrol.Parameter(":resourceID")) scope := accesscontrol.Scope(a.service.options.Resource, a.service.options.ResourceAttribute, accesscontrol.Parameter(":resourceID"))
r.Get("/description", auth(disable, accesscontrol.EvalPermission(actionRead)), routing.Wrap(a.getDescription)) r.Get("/description", auth(accesscontrol.EvalPermission(actionRead)), routing.Wrap(a.getDescription))
r.Get("/:resourceID", auth(disable, accesscontrol.EvalPermission(actionRead, scope)), routing.Wrap(a.getPermissions)) r.Get("/:resourceID", auth(accesscontrol.EvalPermission(actionRead, scope)), routing.Wrap(a.getPermissions))
r.Post("/:resourceID", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setPermissions)) r.Post("/:resourceID", licenseMW, auth(accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setPermissions))
if a.service.options.Assignments.Users { if a.service.options.Assignments.Users {
r.Post("/:resourceID/users/:userID", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setUserPermission)) r.Post("/:resourceID/users/:userID", licenseMW, auth(accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setUserPermission))
} }
if a.service.options.Assignments.Teams { if a.service.options.Assignments.Teams {
r.Post("/:resourceID/teams/:teamID", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setTeamPermission)) r.Post("/:resourceID/teams/:teamID", licenseMW, auth(accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setTeamPermission))
} }
if a.service.options.Assignments.BuiltInRoles { if a.service.options.Assignments.BuiltInRoles {
r.Post("/:resourceID/builtInRoles/:builtInRole", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setBuiltinRolePermission)) r.Post("/:resourceID/builtInRoles/:builtInRole", licenseMW, auth(accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setBuiltinRolePermission))
} }
}) })
} }

View File

@ -1,19 +1,7 @@
package resourcepermissions package resourcepermissions
import ( import (
"net/http"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/web"
) )
func disableMiddleware(shouldDisable bool) web.Handler {
return func(c *contextmodel.ReqContext) {
if shouldDisable {
c.Resp.WriteHeader(http.StatusNotFound)
return
}
}
}
func nopMiddleware(c *contextmodel.ReqContext) {} func nopMiddleware(c *contextmodel.ReqContext) {}

View File

@ -17,16 +17,16 @@ func (s *CorrelationsService) registerAPIEndpoints() {
uidScope := datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid")) uidScope := datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid"))
authorize := ac.Middleware(s.AccessControl) authorize := ac.Middleware(s.AccessControl)
s.RouteRegister.Get("/api/datasources/correlations", middleware.ReqSignedIn, authorize(middleware.ReqSignedIn, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationsHandler)) s.RouteRegister.Get("/api/datasources/correlations", middleware.ReqSignedIn, authorize(ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationsHandler))
s.RouteRegister.Group("/api/datasources/uid/:uid/correlations", func(entities routing.RouteRegister) { s.RouteRegister.Group("/api/datasources/uid/:uid/correlations", func(entities routing.RouteRegister) {
entities.Get("/", authorize(middleware.ReqSignedIn, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationsBySourceUIDHandler)) entities.Get("/", authorize(ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationsBySourceUIDHandler))
entities.Post("/", authorize(middleware.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.createHandler)) entities.Post("/", authorize(ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.createHandler))
entities.Group("/:correlationUID", func(entities routing.RouteRegister) { entities.Group("/:correlationUID", func(entities routing.RouteRegister) {
entities.Get("/", authorize(middleware.ReqSignedIn, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationHandler)) entities.Get("/", authorize(ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationHandler))
entities.Delete("/", authorize(middleware.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.deleteHandler)) entities.Delete("/", authorize(ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.deleteHandler))
entities.Patch("/", authorize(middleware.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.updateHandler)) entities.Patch("/", authorize(ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.updateHandler))
}) })
}, middleware.ReqSignedIn) }, middleware.ReqSignedIn)
} }

View File

@ -38,7 +38,7 @@ func (api *ImportDashboardAPI) RegisterAPIEndpoints(routeRegister routing.RouteR
routeRegister.Group("/api/dashboards", func(route routing.RouteRegister) { routeRegister.Group("/api/dashboards", func(route routing.RouteRegister) {
route.Post( route.Post(
"/import", "/import",
authorize(middleware.ReqSignedIn, accesscontrol.EvalPermission(dashboards.ActionDashboardsCreate)), authorize(accesscontrol.EvalPermission(dashboards.ActionDashboardsCreate)),
routing.Wrap(api.ImportDashboard), routing.Wrap(api.ImportDashboard),
) )
}, middleware.ReqSignedIn) }, middleware.ReqSignedIn)

View File

@ -56,13 +56,12 @@ func ProvideService(cfg *setting.Cfg, router routing.RouteRegister, accessContro
} }
authorize := ac.Middleware(accessControl) authorize := ac.Middleware(accessControl)
reqGrafanaAdmin := middleware.ReqGrafanaAdmin
router.Group("/api/admin", func(adminRoute routing.RouteRegister) { router.Group("/api/admin", func(adminRoute routing.RouteRegister) {
adminRoute.Post("/ldap/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionLDAPConfigReload)), routing.Wrap(s.ReloadLDAPCfg)) adminRoute.Post("/ldap/reload", authorize(ac.EvalPermission(ac.ActionLDAPConfigReload)), routing.Wrap(s.ReloadLDAPCfg))
adminRoute.Post("/ldap/sync/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionLDAPUsersSync)), routing.Wrap(s.PostSyncUserWithLDAP)) adminRoute.Post("/ldap/sync/:id", authorize(ac.EvalPermission(ac.ActionLDAPUsersSync)), routing.Wrap(s.PostSyncUserWithLDAP))
adminRoute.Get("/ldap/:username", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionLDAPUsersRead)), routing.Wrap(s.GetUserFromLDAP)) adminRoute.Get("/ldap/:username", authorize(ac.EvalPermission(ac.ActionLDAPUsersRead)), routing.Wrap(s.GetUserFromLDAP))
adminRoute.Get("/ldap/status", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionLDAPStatusRead)), routing.Wrap(s.GetLDAPStatus)) adminRoute.Get("/ldap/status", authorize(ac.EvalPermission(ac.ActionLDAPStatusRead)), routing.Wrap(s.GetLDAPStatus))
}, middleware.ReqSignedIn) }, middleware.ReqSignedIn)
if cfg.LDAPAuthEnabled { if cfg.LDAPAuthEnabled {

View File

@ -24,17 +24,6 @@ func (api *API) authorize(method, path string) web.Handler {
authorize := ac.Middleware(api.AccessControl) authorize := ac.Middleware(api.AccessControl)
var eval ac.Evaluator = nil var eval ac.Evaluator = nil
// Most routes follow this general authorization approach as a fallback. Exceptions are overridden directly in the below block.
var fallback web.Handler
switch method {
case http.MethodPost, http.MethodPut, http.MethodDelete:
fallback = middleware.ReqEditorRole
case http.MethodGet:
fallback = middleware.ReqSignedIn
default:
fallback = middleware.ReqSignedIn
}
switch method + path { switch method + path {
// Alert Rules // Alert Rules
@ -50,7 +39,6 @@ func (api *API) authorize(method, path string) web.Handler {
case http.MethodGet + "/api/ruler/grafana/api/v1/rules": case http.MethodGet + "/api/ruler/grafana/api/v1/rules":
eval = ac.EvalPermission(ac.ActionAlertingRuleRead) eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
case http.MethodPost + "/api/ruler/grafana/api/v1/rules/{Namespace}": case http.MethodPost + "/api/ruler/grafana/api/v1/rules/{Namespace}":
fallback = middleware.ReqSignedIn // if RBAC is disabled then we need to delegate permission check to folder because its permissions can allow editing for Viewer role
scope := dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace")) scope := dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace"))
// more granular permissions are enforced by the handler via "authorizeRuleChanges" // more granular permissions are enforced by the handler via "authorizeRuleChanges"
eval = ac.EvalAny( eval = ac.EvalAny(
@ -60,7 +48,6 @@ func (api *API) authorize(method, path string) web.Handler {
) )
// Grafana rule state history paths // Grafana rule state history paths
case http.MethodGet + "/api/v1/rules/history": case http.MethodGet + "/api/v1/rules/history":
fallback = middleware.ReqSignedIn
eval = ac.EvalPermission(ac.ActionAlertingRuleRead) eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
// Grafana, Prometheus-compatible Paths // Grafana, Prometheus-compatible Paths
@ -69,16 +56,13 @@ func (api *API) authorize(method, path string) web.Handler {
// Grafana Rules Testing Paths // Grafana Rules Testing Paths
case http.MethodPost + "/api/v1/rule/test/grafana": case http.MethodPost + "/api/v1/rule/test/grafana":
fallback = middleware.ReqSignedIn
// additional authorization is done in the request handler // additional authorization is done in the request handler
eval = ac.EvalPermission(ac.ActionAlertingRuleRead) eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
// Grafana Rules Testing Paths // Grafana Rules Testing Paths
case http.MethodPost + "/api/v1/rule/backtest": case http.MethodPost + "/api/v1/rule/backtest":
fallback = middleware.ReqSignedIn
// additional authorization is done in the request handler // additional authorization is done in the request handler
eval = ac.EvalPermission(ac.ActionAlertingRuleRead) eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
case http.MethodPost + "/api/v1/eval": case http.MethodPost + "/api/v1/eval":
fallback = middleware.ReqSignedIn
// additional authorization is done in the request handler // additional authorization is done in the request handler
eval = ac.EvalPermission(ac.ActionAlertingRuleRead) eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
@ -102,7 +86,6 @@ func (api *API) authorize(method, path string) web.Handler {
// Lotex Rules testing // Lotex Rules testing
case http.MethodPost + "/api/v1/rule/test/{DatasourceUID}": case http.MethodPost + "/api/v1/rule/test/{DatasourceUID}":
fallback = middleware.ReqSignedIn
eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID")))
// Alert Instances and Silences // Alert Instances and Silences
@ -156,10 +139,8 @@ func (api *API) authorize(method, path string) web.Handler {
case http.MethodDelete + "/api/alertmanager/grafana/config/api/v1/alerts": // reset alertmanager config to the default case http.MethodDelete + "/api/alertmanager/grafana/config/api/v1/alerts": // reset alertmanager config to the default
eval = ac.EvalPermission(ac.ActionAlertingNotificationsWrite) eval = ac.EvalPermission(ac.ActionAlertingNotificationsWrite)
case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/alerts": case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/alerts":
fallback = middleware.ReqEditorRole
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
case http.MethodGet + "/api/alertmanager/grafana/config/history": case http.MethodGet + "/api/alertmanager/grafana/config/history":
fallback = middleware.ReqEditorRole
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
case http.MethodGet + "/api/alertmanager/grafana/api/v2/status": case http.MethodGet + "/api/alertmanager/grafana/api/v2/status":
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
@ -171,10 +152,8 @@ func (api *API) authorize(method, path string) web.Handler {
case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/receivers": case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/receivers":
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test": case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test":
fallback = middleware.ReqEditorRole
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/templates/test": case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/templates/test":
fallback = middleware.ReqSignedIn
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
// External Alertmanager Paths // External Alertmanager Paths
@ -217,7 +196,6 @@ func (api *API) authorize(method, path string) web.Handler {
http.MethodGet + "/api/v1/provisioning/alert-rules/{UID}/export", http.MethodGet + "/api/v1/provisioning/alert-rules/{UID}/export",
http.MethodGet + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}", http.MethodGet + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}",
http.MethodGet + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}/export": http.MethodGet + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}/export":
fallback = middleware.ReqOrgAdmin
eval = ac.EvalPermission(ac.ActionAlertingProvisioningRead) // organization scope eval = ac.EvalPermission(ac.ActionAlertingProvisioningRead) // organization scope
case http.MethodPut + "/api/v1/provisioning/policies", case http.MethodPut + "/api/v1/provisioning/policies",
@ -234,12 +212,11 @@ func (api *API) authorize(method, path string) web.Handler {
http.MethodPut + "/api/v1/provisioning/alert-rules/{UID}", http.MethodPut + "/api/v1/provisioning/alert-rules/{UID}",
http.MethodDelete + "/api/v1/provisioning/alert-rules/{UID}", http.MethodDelete + "/api/v1/provisioning/alert-rules/{UID}",
http.MethodPut + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}": http.MethodPut + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}":
fallback = middleware.ReqOrgAdmin
eval = ac.EvalPermission(ac.ActionAlertingProvisioningWrite) // organization scope eval = ac.EvalPermission(ac.ActionAlertingProvisioningWrite) // organization scope
} }
if eval != nil { if eval != nil {
return authorize(fallback, eval) return authorize(eval)
} }
panic(fmt.Sprintf("no authorization handler for method [%s] of endpoint [%s]", method, path)) panic(fmt.Sprintf("no authorization handler for method [%s] of endpoint [%s]", method, path))

View File

@ -68,22 +68,22 @@ func (api *Api) RegisterAPIEndpoints() {
// Get public dashboard // Get public dashboard
api.RouteRegister.Get("/api/dashboards/uid/:dashboardUid/public-dashboards", api.RouteRegister.Get("/api/dashboards/uid/:dashboardUid/public-dashboards",
auth(middleware.ReqSignedIn, accesscontrol.EvalPermission(dashboards.ActionDashboardsRead, uidScope)), auth(accesscontrol.EvalPermission(dashboards.ActionDashboardsRead, uidScope)),
routing.Wrap(api.GetPublicDashboard)) routing.Wrap(api.GetPublicDashboard))
// Create Public Dashboard // Create Public Dashboard
api.RouteRegister.Post("/api/dashboards/uid/:dashboardUid/public-dashboards", api.RouteRegister.Post("/api/dashboards/uid/:dashboardUid/public-dashboards",
auth(middleware.ReqOrgAdmin, accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)), auth(accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)),
routing.Wrap(api.CreatePublicDashboard)) routing.Wrap(api.CreatePublicDashboard))
// Update Public Dashboard // Update Public Dashboard
api.RouteRegister.Put("/api/dashboards/uid/:dashboardUid/public-dashboards/:uid", api.RouteRegister.Put("/api/dashboards/uid/:dashboardUid/public-dashboards/:uid",
auth(middleware.ReqOrgAdmin, accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)), auth(accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)),
routing.Wrap(api.UpdatePublicDashboard)) routing.Wrap(api.UpdatePublicDashboard))
// Delete Public dashboard // Delete Public dashboard
api.RouteRegister.Delete("/api/dashboards/uid/:dashboardUid/public-dashboards/:uid", api.RouteRegister.Delete("/api/dashboards/uid/:dashboardUid/public-dashboards/:uid",
auth(middleware.ReqOrgAdmin, accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)), auth(accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)),
routing.Wrap(api.DeletePublicDashboard)) routing.Wrap(api.DeletePublicDashboard))
} }

View File

@ -9,7 +9,6 @@ import (
"github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/apikey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
@ -68,26 +67,16 @@ func NewServiceAccountsAPI(
func (api *ServiceAccountsAPI) RegisterAPIEndpoints() { func (api *ServiceAccountsAPI) RegisterAPIEndpoints() {
auth := accesscontrol.Middleware(api.accesscontrol) auth := accesscontrol.Middleware(api.accesscontrol)
api.RouterRegister.Group("/api/serviceaccounts", func(serviceAccountsRoute routing.RouteRegister) { api.RouterRegister.Group("/api/serviceaccounts", func(serviceAccountsRoute routing.RouteRegister) {
serviceAccountsRoute.Get("/search", auth(middleware.ReqOrgAdmin, serviceAccountsRoute.Get("/search", auth(accesscontrol.EvalPermission(serviceaccounts.ActionRead)), routing.Wrap(api.SearchOrgServiceAccountsWithPaging))
accesscontrol.EvalPermission(serviceaccounts.ActionRead)), routing.Wrap(api.SearchOrgServiceAccountsWithPaging)) serviceAccountsRoute.Post("/", auth(accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.CreateServiceAccount))
serviceAccountsRoute.Post("/", auth(middleware.ReqOrgAdmin, serviceAccountsRoute.Get("/:serviceAccountId", auth(accesscontrol.EvalPermission(serviceaccounts.ActionRead, serviceaccounts.ScopeID)), routing.Wrap(api.RetrieveServiceAccount))
accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.CreateServiceAccount)) serviceAccountsRoute.Patch("/:serviceAccountId", auth(accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.UpdateServiceAccount))
serviceAccountsRoute.Get("/:serviceAccountId", auth(middleware.ReqOrgAdmin, serviceAccountsRoute.Delete("/:serviceAccountId", auth(accesscontrol.EvalPermission(serviceaccounts.ActionDelete, serviceaccounts.ScopeID)), routing.Wrap(api.DeleteServiceAccount))
accesscontrol.EvalPermission(serviceaccounts.ActionRead, serviceaccounts.ScopeID)), routing.Wrap(api.RetrieveServiceAccount)) serviceAccountsRoute.Get("/:serviceAccountId/tokens", auth(accesscontrol.EvalPermission(serviceaccounts.ActionRead, serviceaccounts.ScopeID)), routing.Wrap(api.ListTokens))
serviceAccountsRoute.Patch("/:serviceAccountId", auth(middleware.ReqOrgAdmin, serviceAccountsRoute.Post("/:serviceAccountId/tokens", auth(accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.CreateToken))
accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.UpdateServiceAccount)) serviceAccountsRoute.Delete("/:serviceAccountId/tokens/:tokenId", auth(accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.DeleteToken))
serviceAccountsRoute.Delete("/:serviceAccountId", auth(middleware.ReqOrgAdmin, serviceAccountsRoute.Post("/migrate", auth(accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.MigrateApiKeysToServiceAccounts))
accesscontrol.EvalPermission(serviceaccounts.ActionDelete, serviceaccounts.ScopeID)), routing.Wrap(api.DeleteServiceAccount)) serviceAccountsRoute.Post("/migrate/:keyId", auth(accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.ConvertToServiceAccount))
serviceAccountsRoute.Get("/:serviceAccountId/tokens", auth(middleware.ReqOrgAdmin,
accesscontrol.EvalPermission(serviceaccounts.ActionRead, serviceaccounts.ScopeID)), routing.Wrap(api.ListTokens))
serviceAccountsRoute.Post("/:serviceAccountId/tokens", auth(middleware.ReqOrgAdmin,
accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.CreateToken))
serviceAccountsRoute.Delete("/:serviceAccountId/tokens/:tokenId", auth(middleware.ReqOrgAdmin,
accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.DeleteToken))
serviceAccountsRoute.Post("/migrate", auth(middleware.ReqOrgAdmin,
accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.MigrateApiKeysToServiceAccounts))
serviceAccountsRoute.Post("/migrate/:keyId", auth(middleware.ReqOrgAdmin,
accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.ConvertToServiceAccount))
}) })
} }

View File

@ -9,8 +9,6 @@ import (
grafanaApi "github.com/grafana/grafana/pkg/api" grafanaApi "github.com/grafana/grafana/pkg/api"
"github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models/roletype"
ac "github.com/grafana/grafana/pkg/services/accesscontrol" ac "github.com/grafana/grafana/pkg/services/accesscontrol"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/supportbundles" "github.com/grafana/grafana/pkg/services/supportbundles"
@ -22,30 +20,20 @@ const rootUrl = "/api/support-bundles"
func (s *Service) registerAPIEndpoints(httpServer *grafanaApi.HTTPServer, routeRegister routing.RouteRegister) { func (s *Service) registerAPIEndpoints(httpServer *grafanaApi.HTTPServer, routeRegister routing.RouteRegister) {
authorize := ac.Middleware(s.accessControl) authorize := ac.Middleware(s.accessControl)
orgRoleMiddleware := middleware.ReqGrafanaAdmin
if !s.serverAdminOnly {
orgRoleMiddleware = middleware.RoleAuth(roletype.RoleAdmin)
}
supportBundlePageAccess := ac.EvalAny( supportBundlePageAccess := ac.EvalAny(
ac.EvalPermission(ActionRead), ac.EvalPermission(ActionRead),
ac.EvalPermission(ActionCreate), ac.EvalPermission(ActionCreate),
) )
routeRegister.Get("/support-bundles", authorize(orgRoleMiddleware, supportBundlePageAccess), httpServer.Index) routeRegister.Get("/support-bundles", authorize(supportBundlePageAccess), httpServer.Index)
routeRegister.Get("/support-bundles/create", authorize(orgRoleMiddleware, ac.EvalPermission(ActionCreate)), httpServer.Index) routeRegister.Get("/support-bundles/create", authorize(ac.EvalPermission(ActionCreate)), httpServer.Index)
routeRegister.Group(rootUrl, func(subrouter routing.RouteRegister) { routeRegister.Group(rootUrl, func(subrouter routing.RouteRegister) {
subrouter.Get("/", authorize(orgRoleMiddleware, subrouter.Get("/", authorize(ac.EvalPermission(ActionRead)), routing.Wrap(s.handleList))
ac.EvalPermission(ActionRead)), routing.Wrap(s.handleList)) subrouter.Post("/", authorize(ac.EvalPermission(ActionCreate)), routing.Wrap(s.handleCreate))
subrouter.Post("/", authorize(orgRoleMiddleware, subrouter.Get("/:uid", authorize(ac.EvalPermission(ActionRead)), s.handleDownload)
ac.EvalPermission(ActionCreate)), routing.Wrap(s.handleCreate)) subrouter.Delete("/:uid", authorize(ac.EvalPermission(ActionDelete)), s.handleRemove)
subrouter.Get("/:uid", authorize(orgRoleMiddleware, subrouter.Get("/collectors", authorize(ac.EvalPermission(ActionCreate)), routing.Wrap(s.handleGetCollectors))
ac.EvalPermission(ActionRead)), s.handleDownload)
subrouter.Delete("/:uid", authorize(orgRoleMiddleware,
ac.EvalPermission(ActionDelete)), s.handleRemove)
subrouter.Get("/collectors", authorize(orgRoleMiddleware,
ac.EvalPermission(ActionCreate)), routing.Wrap(s.handleGetCollectors))
}) })
} }

View File

@ -98,10 +98,6 @@ type SearchTeamQueryResult struct {
PerPage int `json:"perPage"` PerPage int `json:"perPage"`
} }
type IsAdminOfTeamsQuery struct {
SignedInUser *user.SignedInUser
}
// TeamMember model // TeamMember model
type TeamMember struct { type TeamMember struct {
ID int64 `xorm:"pk autoincr 'id'"` ID int64 `xorm:"pk autoincr 'id'"`

View File

@ -20,5 +20,4 @@ type Service interface {
RemoveUsersMemberships(tx context.Context, userID int64) error RemoveUsersMemberships(tx context.Context, userID int64) error
GetUserTeamMemberships(ctx context.Context, orgID, userID int64, external bool) ([]*TeamMemberDTO, error) GetUserTeamMemberships(ctx context.Context, orgID, userID int64, external bool) ([]*TeamMemberDTO, error)
GetTeamMembers(ctx context.Context, query *GetTeamMembersQuery) ([]*TeamMemberDTO, error) GetTeamMembers(ctx context.Context, query *GetTeamMembersQuery) ([]*TeamMemberDTO, error)
IsAdminOfTeams(ctx context.Context, query *IsAdminOfTeamsQuery) (bool, error)
} }

View File

@ -30,7 +30,6 @@ type store interface {
RemoveMember(ctx context.Context, cmd *team.RemoveTeamMemberCommand) error RemoveMember(ctx context.Context, cmd *team.RemoveTeamMemberCommand) error
GetMemberships(ctx context.Context, orgID, userID int64, external bool) ([]*team.TeamMemberDTO, error) GetMemberships(ctx context.Context, orgID, userID int64, external bool) ([]*team.TeamMemberDTO, error)
GetMembers(ctx context.Context, query *team.GetTeamMembersQuery) ([]*team.TeamMemberDTO, error) GetMembers(ctx context.Context, query *team.GetTeamMembersQuery) ([]*team.TeamMemberDTO, error)
IsAdmin(ctx context.Context, query *team.IsAdminOfTeamsQuery) (bool, error)
} }
type xormStore struct { type xormStore struct {
@ -558,36 +557,3 @@ func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMemb
} }
return queryResult, nil return queryResult, nil
} }
func (ss *xormStore) IsAdmin(ctx context.Context, query *team.IsAdminOfTeamsQuery) (bool, error) {
queryResult := false
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
sql := `SELECT COUNT(team.id) AS count
FROM team
INNER JOIN team_member ON team_member.team_id = team.id
WHERE team.org_id = ?
AND team_member.user_id = ?
AND team_member.permission = ?`
params := []interface{}{
query.SignedInUser.OrgID,
query.SignedInUser.UserID,
dashboards.PERMISSION_ADMIN,
}
type teamCount struct {
Count int64
}
resp := make([]*teamCount, 0)
if err := sess.SQL(sql, params...).Find(&resp); err != nil {
return err
}
queryResult = len(resp) > 0 && resp[0].Count > 0
return nil
})
return queryResult, err
}

View File

@ -319,26 +319,6 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
require.Equal(t, len(permQueryResult), 0) require.Equal(t, len(permQueryResult), 0)
}) })
t.Run("Should be able to return if user is admin of teams or not", func(t *testing.T) {
sqlStore = db.InitTestDB(t)
setup()
groupId := team2.ID
err := teamSvc.AddTeamMember(userIds[0], testOrgID, groupId, false, 0)
require.NoError(t, err)
err = teamSvc.AddTeamMember(userIds[1], testOrgID, groupId, false, dashboards.PERMISSION_ADMIN)
require.NoError(t, err)
query := &team.IsAdminOfTeamsQuery{SignedInUser: &user.SignedInUser{OrgID: testOrgID, UserID: userIds[0]}}
queryResult, err := teamSvc.IsAdminOfTeams(context.Background(), query)
require.NoError(t, err)
require.False(t, queryResult)
query = &team.IsAdminOfTeamsQuery{SignedInUser: &user.SignedInUser{OrgID: testOrgID, UserID: userIds[1]}}
queryResult, err = teamSvc.IsAdminOfTeams(context.Background(), query)
require.NoError(t, err)
require.True(t, queryResult)
})
t.Run("Should not return hidden users in team member count", func(t *testing.T) { t.Run("Should not return hidden users in team member count", func(t *testing.T) {
sqlStore = db.InitTestDB(t) sqlStore = db.InitTestDB(t)
setup() setup()

View File

@ -68,7 +68,3 @@ func (s *Service) GetUserTeamMemberships(ctx context.Context, orgID, userID int6
func (s *Service) GetTeamMembers(ctx context.Context, query *team.GetTeamMembersQuery) ([]*team.TeamMemberDTO, error) { func (s *Service) GetTeamMembers(ctx context.Context, query *team.GetTeamMembersQuery) ([]*team.TeamMemberDTO, error) {
return s.store.GetMembers(ctx, query) return s.store.GetMembers(ctx, query)
} }
func (s *Service) IsAdminOfTeams(ctx context.Context, query *team.IsAdminOfTeamsQuery) (bool, error) {
return s.store.IsAdmin(ctx, query)
}

View File

@ -72,7 +72,3 @@ func (s *FakeService) GetUserTeamMemberships(ctx context.Context, orgID, userID
func (s *FakeService) GetTeamMembers(ctx context.Context, query *team.GetTeamMembersQuery) ([]*team.TeamMemberDTO, error) { func (s *FakeService) GetTeamMembers(ctx context.Context, query *team.GetTeamMembersQuery) ([]*team.TeamMemberDTO, error) {
return s.ExpectedMembers, s.ExpectedError return s.ExpectedMembers, s.ExpectedError
} }
func (s *FakeService) IsAdminOfTeams(ctx context.Context, query *team.IsAdminOfTeamsQuery) (bool, error) {
return s.ExpectedIsAdmin, s.ExpectedError
}