mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Migrate to Wire for dependency injection (#32289)
Fixes #30144 Co-authored-by: dsotirakis <sotirakis.dim@gmail.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> Co-authored-by: Ida Furjesova <ida.furjesova@grafana.com> Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com> Co-authored-by: Will Browne <wbrowne@users.noreply.github.com> Co-authored-by: Leon Sorokin <leeoniya@gmail.com> Co-authored-by: Andrej Ocenas <mr.ocenas@gmail.com> Co-authored-by: spinillos <selenepinillos@gmail.com> Co-authored-by: Karl Persson <kalle.persson@grafana.com> Co-authored-by: Leonard Gram <leo@xlson.com>
This commit is contained in:
44
pkg/api/apierrors/folder.go
Normal file
44
pkg/api/apierrors/folder.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package apierrors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// ToFolderErrorResponse returns a different response status according to the folder error type
|
||||
func ToFolderErrorResponse(err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
return response.Error(dashboardErr.StatusCode, err.Error(), err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderTitleEmpty) ||
|
||||
errors.Is(err, models.ErrDashboardTypeMismatch) ||
|
||||
errors.Is(err, models.ErrDashboardInvalidUid) ||
|
||||
errors.Is(err, models.ErrDashboardUidTooLong) ||
|
||||
errors.Is(err, models.ErrFolderContainsAlertRules) {
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderAccessDenied) {
|
||||
return response.Error(403, "Access denied", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
return response.JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderSameNameExists) ||
|
||||
errors.Is(err, models.ErrFolderWithSameUIDExists) {
|
||||
return response.Error(409, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderVersionMismatch) {
|
||||
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
|
||||
}
|
||||
|
||||
return response.Error(500, "Folder API error", err)
|
||||
}
|
||||
@@ -7,23 +7,23 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/fs"
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/auth/jwt"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
func loggedInUserScenario(t *testing.T, desc string, url string, fn scenarioFunc) {
|
||||
@@ -168,35 +168,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa
|
||||
userAuthTokenSvc := auth.NewFakeUserAuthTokenService()
|
||||
renderSvc := &fakeRenderService{}
|
||||
authJWTSvc := models.NewFakeJWTService()
|
||||
ctxHdlr := &contexthandler.ContextHandler{}
|
||||
|
||||
err := registry.BuildServiceGraph([]interface{}{cfg}, []*registry.Descriptor{
|
||||
{
|
||||
Name: sqlstore.ServiceName,
|
||||
Instance: sqlStore,
|
||||
},
|
||||
{
|
||||
Name: remotecache.ServiceName,
|
||||
Instance: remoteCacheSvc,
|
||||
},
|
||||
{
|
||||
Name: auth.ServiceName,
|
||||
Instance: userAuthTokenSvc,
|
||||
},
|
||||
{
|
||||
Name: rendering.ServiceName,
|
||||
Instance: renderSvc,
|
||||
},
|
||||
{
|
||||
Name: jwt.ServiceName,
|
||||
Instance: authJWTSvc,
|
||||
},
|
||||
{
|
||||
Name: contexthandler.ServiceName,
|
||||
Instance: ctxHdlr,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ctxHdlr := contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, sqlStore)
|
||||
|
||||
return ctxHdlr
|
||||
}
|
||||
@@ -236,6 +208,9 @@ func setupAccessControlScenarioContext(t *testing.T, cfg *setting.Cfg, url strin
|
||||
hs := &HTTPServer{
|
||||
Cfg: cfg,
|
||||
RouteRegister: routing.NewRouteRegister(),
|
||||
QuotaService: "a.QuotaService{
|
||||
Cfg: cfg,
|
||||
},
|
||||
AccessControl: accesscontrolmock.New().WithPermissions(permissions),
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/live"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -86,10 +87,8 @@ type testState struct {
|
||||
}
|
||||
|
||||
func newTestLive(t *testing.T) *live.GrafanaLive {
|
||||
gLive := live.NewGrafanaLive()
|
||||
gLive.RouteRegister = routing.NewRouteRegister()
|
||||
gLive.Cfg = &setting.Cfg{AppURL: "http://localhost:3000/"}
|
||||
err := gLive.Init()
|
||||
cfg := &setting.Cfg{AppURL: "http://localhost:3000/"}
|
||||
gLive, err := live.ProvideService(nil, cfg, routing.NewRouteRegister(), nil, nil, nil, nil, sqlstore.InitTestDB(t))
|
||||
require.NoError(t, err)
|
||||
return gLive
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ func GetDataSourceIdByName(c *models.ReqContext) response.Response {
|
||||
// /api/datasources/:id/resources/*
|
||||
func (hs *HTTPServer) CallDatasourceResource(c *models.ReqContext) {
|
||||
datasourceID := c.ParamsInt64(":id")
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
ds, err := hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
c.JsonApiErr(403, "Access denied to datasource", err)
|
||||
@@ -431,7 +431,7 @@ func convertModelToDtos(ds *models.DataSource) dtos.DataSource {
|
||||
func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Response {
|
||||
datasourceID := c.ParamsInt64("id")
|
||||
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
ds, err := hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
return response.Error(403, "Access denied to datasource", err)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -19,7 +20,7 @@ func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response {
|
||||
folders, err := s.GetFolders(c.QueryInt64("limit"), c.QueryInt64("page"))
|
||||
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
result := make([]dtos.FolderSearchHit, 0)
|
||||
@@ -39,7 +40,7 @@ func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
folder, err := s.GetFolderByUID(c.Params(":uid"))
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
|
||||
@@ -50,7 +51,7 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
folder, err := s.GetFolderByID(c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
|
||||
@@ -61,7 +62,7 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolder
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
folder, err := s.CreateFolder(cmd.Title, cmd.Uid)
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
if hs.Cfg.EditorsCanAdmin {
|
||||
@@ -79,7 +80,7 @@ func (hs *HTTPServer) UpdateFolder(c *models.ReqContext, cmd models.UpdateFolder
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
err := s.UpdateFolder(c.Params(":uid"), &cmd)
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(cmd.Result.Id, c.OrgId, c.SignedInUser)
|
||||
@@ -93,12 +94,12 @@ func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { //
|
||||
if errors.Is(err, libraryelements.ErrFolderHasConnectedLibraryElements) {
|
||||
return response.Error(403, "Folder could not be deleted because it contains library elements in use", err)
|
||||
}
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
f, err := s.DeleteFolder(c.Params(":uid"), c.QueryBool("forceDeleteRules"))
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
@@ -138,38 +139,3 @@ func toFolderDto(ctx context.Context, g guardian.DashboardGuardian, folder *mode
|
||||
Version: folder.Version,
|
||||
}
|
||||
}
|
||||
|
||||
// ToFolderErrorResponse returns a different response status according to the folder error type
|
||||
func ToFolderErrorResponse(err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
return response.Error(dashboardErr.StatusCode, err.Error(), err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderTitleEmpty) ||
|
||||
errors.Is(err, models.ErrDashboardTypeMismatch) ||
|
||||
errors.Is(err, models.ErrDashboardInvalidUid) ||
|
||||
errors.Is(err, models.ErrDashboardUidTooLong) ||
|
||||
errors.Is(err, models.ErrFolderContainsAlertRules) {
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderAccessDenied) {
|
||||
return response.Error(403, "Access denied", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
return response.JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderSameNameExists) ||
|
||||
errors.Is(err, models.ErrFolderWithSameUIDExists) {
|
||||
return response.Error(409, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderVersionMismatch) {
|
||||
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
|
||||
}
|
||||
|
||||
return response.Error(500, "Folder API error", err)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -17,13 +18,13 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
|
||||
folder, err := s.GetFolderByUID(c.Params(":uid"))
|
||||
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
|
||||
|
||||
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
|
||||
return ToFolderErrorResponse(models.ErrFolderAccessDenied)
|
||||
return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied)
|
||||
}
|
||||
|
||||
acl, err := g.GetAcl()
|
||||
@@ -64,17 +65,17 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
folder, err := s.GetFolderByUID(c.Params(":uid"))
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
|
||||
canAdmin, err := g.CanAdmin()
|
||||
if err != nil {
|
||||
return ToFolderErrorResponse(err)
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
if !canAdmin {
|
||||
return ToFolderErrorResponse(models.ErrFolderAccessDenied)
|
||||
return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied)
|
||||
}
|
||||
|
||||
var items []*models.DashboardAcl
|
||||
|
||||
@@ -14,6 +14,10 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/services/cleanup"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements"
|
||||
"github.com/grafana/grafana/pkg/services/librarypanels"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
@@ -24,15 +28,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
_ "github.com/grafana/grafana/pkg/plugins/backendplugin/manager"
|
||||
"github.com/grafana/grafana/pkg/plugins/plugincontext"
|
||||
"github.com/grafana/grafana/pkg/plugins/plugindashboards"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
@@ -58,14 +63,6 @@ import (
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Register(®istry.Descriptor{
|
||||
Name: "HTTPServer",
|
||||
Instance: &HTTPServer{},
|
||||
InitPriority: registry.High,
|
||||
})
|
||||
}
|
||||
|
||||
type HTTPServer struct {
|
||||
log log.Logger
|
||||
macaron *macaron.Macaron
|
||||
@@ -73,49 +70,128 @@ type HTTPServer struct {
|
||||
httpSrv *http.Server
|
||||
middlewares []macaron.Handler
|
||||
|
||||
PluginContextProvider *plugincontext.Provider `inject:""`
|
||||
RouteRegister routing.RouteRegister `inject:""`
|
||||
Bus bus.Bus `inject:""`
|
||||
RenderService rendering.Service `inject:""`
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
SettingsProvider setting.Provider `inject:""`
|
||||
HooksService *hooks.HooksService `inject:""`
|
||||
CacheService *localcache.CacheService `inject:""`
|
||||
DatasourceCache datasources.CacheService `inject:""`
|
||||
AuthTokenService models.UserTokenService `inject:""`
|
||||
QuotaService *quota.QuotaService `inject:""`
|
||||
RemoteCacheService *remotecache.RemoteCache `inject:""`
|
||||
ProvisioningService provisioning.ProvisioningService `inject:""`
|
||||
Login login.Service `inject:""`
|
||||
License models.Licensing `inject:""`
|
||||
AccessControl accesscontrol.AccessControl `inject:""`
|
||||
BackendPluginManager backendplugin.Manager `inject:""`
|
||||
DataProxy *datasourceproxy.DatasourceProxyService `inject:""`
|
||||
PluginRequestValidator models.PluginRequestValidator `inject:""`
|
||||
PluginManager plugins.Manager `inject:""`
|
||||
SearchService *search.SearchService `inject:""`
|
||||
ShortURLService shorturls.Service `inject:""`
|
||||
Live *live.GrafanaLive `inject:""`
|
||||
LivePushGateway *pushhttp.Gateway `inject:""`
|
||||
ContextHandler *contexthandler.ContextHandler `inject:""`
|
||||
SQLStore *sqlstore.SQLStore `inject:""`
|
||||
DataService *tsdb.Service `inject:""`
|
||||
PluginDashboardService *plugindashboards.Service `inject:""`
|
||||
AlertEngine *alerting.AlertEngine `inject:""`
|
||||
LoadSchemaService *schemaloader.SchemaLoaderService `inject:""`
|
||||
LibraryPanelService librarypanels.Service `inject:""`
|
||||
LibraryElementService libraryelements.Service `inject:""`
|
||||
SocialService social.Service `inject:""`
|
||||
OAuthTokenService *oauthtoken.Service `inject:""`
|
||||
UsageStatsService usagestats.UsageStats
|
||||
PluginContextProvider *plugincontext.Provider
|
||||
RouteRegister routing.RouteRegister
|
||||
Bus bus.Bus
|
||||
RenderService rendering.Service
|
||||
Cfg *setting.Cfg
|
||||
SettingsProvider setting.Provider
|
||||
HooksService *hooks.HooksService
|
||||
CacheService *localcache.CacheService
|
||||
DataSourceCache datasources.CacheService
|
||||
AuthTokenService models.UserTokenService
|
||||
QuotaService *quota.QuotaService
|
||||
RemoteCacheService *remotecache.RemoteCache
|
||||
ProvisioningService provisioning.ProvisioningService
|
||||
Login login.Service
|
||||
License models.Licensing
|
||||
AccessControl accesscontrol.AccessControl
|
||||
BackendPluginManager backendplugin.Manager
|
||||
DataProxy *datasourceproxy.DataSourceProxyService
|
||||
PluginRequestValidator models.PluginRequestValidator
|
||||
PluginManager plugins.Manager
|
||||
SearchService *search.SearchService
|
||||
ShortURLService shorturls.Service
|
||||
Live *live.GrafanaLive
|
||||
LivePushGateway *pushhttp.Gateway
|
||||
ContextHandler *contexthandler.ContextHandler
|
||||
SQLStore *sqlstore.SQLStore
|
||||
DataService *tsdb.Service
|
||||
AlertEngine *alerting.AlertEngine
|
||||
LoadSchemaService *schemaloader.SchemaLoaderService
|
||||
AlertNG *ngalert.AlertNG
|
||||
LibraryPanelService librarypanels.Service
|
||||
LibraryElementService libraryelements.Service
|
||||
notificationService *notifications.NotificationService
|
||||
SocialService social.Service
|
||||
OAuthTokenService oauthtoken.OAuthTokenService
|
||||
Listener net.Listener
|
||||
cleanUpService *cleanup.CleanUpService
|
||||
tracingService *tracing.TracingService
|
||||
internalMetricsSvc *metrics.InternalMetricsService
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) Init() error {
|
||||
hs.log = log.New("http.server")
|
||||
type ServerOptions struct {
|
||||
Listener net.Listener
|
||||
}
|
||||
|
||||
hs.macaron = hs.newMacaron()
|
||||
func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routing.RouteRegister, bus bus.Bus,
|
||||
renderService rendering.Service, licensing models.Licensing, hooksService *hooks.HooksService,
|
||||
cacheService *localcache.CacheService, sqlStore *sqlstore.SQLStore,
|
||||
dataService *tsdb.Service, alertEngine *alerting.AlertEngine,
|
||||
usageStatsService *usagestats.UsageStatsService, pluginRequestValidator models.PluginRequestValidator,
|
||||
pluginManager plugins.Manager, backendPM backendplugin.Manager, settingsProvider setting.Provider,
|
||||
dataSourceCache datasources.CacheService, userTokenService models.UserTokenService,
|
||||
cleanUpService *cleanup.CleanUpService, shortURLService shorturls.Service,
|
||||
remoteCache *remotecache.RemoteCache, provisioningService provisioning.ProvisioningService,
|
||||
loginService login.Service, accessControl accesscontrol.AccessControl,
|
||||
dataSourceProxy *datasourceproxy.DataSourceProxyService, searchService *search.SearchService,
|
||||
live *live.GrafanaLive, livePushGateway *pushhttp.Gateway, plugCtxProvider *plugincontext.Provider,
|
||||
contextHandler *contexthandler.ContextHandler,
|
||||
schemaService *schemaloader.SchemaLoaderService, alertNG *ngalert.AlertNG,
|
||||
libraryPanelService librarypanels.Service, libraryElementService libraryelements.Service,
|
||||
notificationService *notifications.NotificationService, tracingService *tracing.TracingService,
|
||||
internalMetricsSvc *metrics.InternalMetricsService, quotaService *quota.QuotaService,
|
||||
socialService social.Service, oauthTokenService oauthtoken.OAuthTokenService) (*HTTPServer, error) {
|
||||
macaron.Env = cfg.Env
|
||||
m := macaron.New()
|
||||
// automatically set HEAD for every GET
|
||||
m.SetAutoHead(true)
|
||||
|
||||
hs := &HTTPServer{
|
||||
Cfg: cfg,
|
||||
RouteRegister: routeRegister,
|
||||
Bus: bus,
|
||||
RenderService: renderService,
|
||||
License: licensing,
|
||||
HooksService: hooksService,
|
||||
CacheService: cacheService,
|
||||
SQLStore: sqlStore,
|
||||
DataService: dataService,
|
||||
AlertEngine: alertEngine,
|
||||
UsageStatsService: usageStatsService,
|
||||
PluginRequestValidator: pluginRequestValidator,
|
||||
PluginManager: pluginManager,
|
||||
BackendPluginManager: backendPM,
|
||||
SettingsProvider: settingsProvider,
|
||||
DataSourceCache: dataSourceCache,
|
||||
AuthTokenService: userTokenService,
|
||||
cleanUpService: cleanUpService,
|
||||
ShortURLService: shortURLService,
|
||||
RemoteCacheService: remoteCache,
|
||||
ProvisioningService: provisioningService,
|
||||
Login: loginService,
|
||||
AccessControl: accessControl,
|
||||
DataProxy: dataSourceProxy,
|
||||
SearchService: searchService,
|
||||
Live: live,
|
||||
LivePushGateway: livePushGateway,
|
||||
PluginContextProvider: plugCtxProvider,
|
||||
ContextHandler: contextHandler,
|
||||
LoadSchemaService: schemaService,
|
||||
AlertNG: alertNG,
|
||||
LibraryPanelService: libraryPanelService,
|
||||
LibraryElementService: libraryElementService,
|
||||
QuotaService: quotaService,
|
||||
notificationService: notificationService,
|
||||
tracingService: tracingService,
|
||||
internalMetricsSvc: internalMetricsSvc,
|
||||
log: log.New("http.server"),
|
||||
macaron: m,
|
||||
Listener: opts.Listener,
|
||||
SocialService: socialService,
|
||||
OAuthTokenService: oauthTokenService,
|
||||
}
|
||||
if hs.Listener != nil {
|
||||
hs.log.Debug("Using provided listener")
|
||||
}
|
||||
hs.registerRoutes()
|
||||
return hs.declareFixedRoles()
|
||||
|
||||
if err := hs.declareFixedRoles(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hs, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AddMiddleware(middleware macaron.Handler) {
|
||||
@@ -304,16 +380,6 @@ func (hs *HTTPServer) configureHttp2() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) newMacaron() *macaron.Macaron {
|
||||
macaron.Env = hs.Cfg.Env
|
||||
m := macaron.New()
|
||||
|
||||
// automatically set HEAD for every GET
|
||||
m.SetAutoHead(true)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) applyRoutes() {
|
||||
// start with middlewares & static routes
|
||||
hs.addMiddlewaresAndStaticRoutes()
|
||||
|
||||
@@ -52,7 +52,7 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
|
||||
// So only the datasource from the first query is needed. As all requests
|
||||
// should be the same data source.
|
||||
if i == 0 {
|
||||
ds, err = hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
ds, err = hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
return hs.handleGetDataSourceError(err, datasourceID)
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func (hs *HTTPServer) handleExpressions(c *models.ReqContext, reqDTO dtos.Metric
|
||||
if name != expr.DatasourceName {
|
||||
// Expression requests have everything in one request, so need to check
|
||||
// all data source queries for possible permission / not found issues.
|
||||
if _, err = hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache); err != nil {
|
||||
if _, err = hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache); err != nil {
|
||||
return hs.handleGetDataSourceError(err, datasourceID)
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricReque
|
||||
return response.Error(http.StatusBadRequest, "Query missing datasourceId", nil)
|
||||
}
|
||||
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceId, c.SignedInUser, c.SkipCache)
|
||||
ds, err := hs.DataSourceCache.GetDatasource(datasourceId, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
return hs.handleGetDataSourceError(err, datasourceId)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
@@ -50,13 +52,17 @@ type RouteRegister interface {
|
||||
|
||||
type RegisterNamedMiddleware func(name string) macaron.Handler
|
||||
|
||||
func ProvideRegister(cfg *setting.Cfg) *RouteRegisterImpl {
|
||||
return NewRouteRegister(middleware.ProvideRouteOperationName, middleware.RequestMetrics(cfg))
|
||||
}
|
||||
|
||||
// NewRouteRegister creates a new RouteRegister with all middlewares sent as params
|
||||
func NewRouteRegister(namedMiddleware ...RegisterNamedMiddleware) RouteRegister {
|
||||
return &routeRegister{
|
||||
prefix: "",
|
||||
routes: []route{},
|
||||
subfixHandlers: []macaron.Handler{},
|
||||
namedMiddleware: namedMiddleware,
|
||||
func NewRouteRegister(namedMiddlewares ...RegisterNamedMiddleware) *RouteRegisterImpl {
|
||||
return &RouteRegisterImpl{
|
||||
prefix: "",
|
||||
routes: []route{},
|
||||
subfixHandlers: []macaron.Handler{},
|
||||
namedMiddlewares: namedMiddlewares,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,15 +72,15 @@ type route struct {
|
||||
handlers []macaron.Handler
|
||||
}
|
||||
|
||||
type routeRegister struct {
|
||||
prefix string
|
||||
subfixHandlers []macaron.Handler
|
||||
namedMiddleware []RegisterNamedMiddleware
|
||||
routes []route
|
||||
groups []*routeRegister
|
||||
type RouteRegisterImpl struct {
|
||||
prefix string
|
||||
subfixHandlers []macaron.Handler
|
||||
namedMiddlewares []RegisterNamedMiddleware
|
||||
routes []route
|
||||
groups []*RouteRegisterImpl
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Reset() {
|
||||
func (rr *RouteRegisterImpl) Reset() {
|
||||
if rr == nil {
|
||||
return
|
||||
}
|
||||
@@ -84,7 +90,7 @@ func (rr *routeRegister) Reset() {
|
||||
rr.subfixHandlers = nil
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Insert(pattern string, fn func(RouteRegister), handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Insert(pattern string, fn func(RouteRegister), handlers ...macaron.Handler) {
|
||||
// loop over all groups at current level
|
||||
for _, g := range rr.groups {
|
||||
// apply routes if the prefix matches the pattern
|
||||
@@ -100,19 +106,19 @@ func (rr *routeRegister) Insert(pattern string, fn func(RouteRegister), handlers
|
||||
}
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Group(pattern string, fn func(rr RouteRegister), handlers ...macaron.Handler) {
|
||||
group := &routeRegister{
|
||||
prefix: rr.prefix + pattern,
|
||||
subfixHandlers: append(rr.subfixHandlers, handlers...),
|
||||
routes: []route{},
|
||||
namedMiddleware: rr.namedMiddleware,
|
||||
func (rr *RouteRegisterImpl) Group(pattern string, fn func(rr RouteRegister), handlers ...macaron.Handler) {
|
||||
group := &RouteRegisterImpl{
|
||||
prefix: rr.prefix + pattern,
|
||||
subfixHandlers: append(rr.subfixHandlers, handlers...),
|
||||
routes: []route{},
|
||||
namedMiddlewares: rr.namedMiddlewares,
|
||||
}
|
||||
|
||||
fn(group)
|
||||
rr.groups = append(rr.groups, group)
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Register(router Router) {
|
||||
func (rr *RouteRegisterImpl) Register(router Router) {
|
||||
for _, r := range rr.routes {
|
||||
// GET requests have to be added to macaron routing using Get()
|
||||
// Otherwise HEAD requests will not be allowed.
|
||||
@@ -129,11 +135,11 @@ func (rr *routeRegister) Register(router Router) {
|
||||
}
|
||||
}
|
||||
|
||||
func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) route(pattern, method string, handlers ...macaron.Handler) {
|
||||
h := make([]macaron.Handler, 0)
|
||||
fullPattern := rr.prefix + pattern
|
||||
|
||||
for _, fn := range rr.namedMiddleware {
|
||||
for _, fn := range rr.namedMiddlewares {
|
||||
h = append(h, fn(fullPattern))
|
||||
}
|
||||
|
||||
@@ -153,26 +159,26 @@ func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handl
|
||||
})
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Get(pattern string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Get(pattern string, handlers ...macaron.Handler) {
|
||||
rr.route(pattern, http.MethodGet, handlers...)
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Post(pattern string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Post(pattern string, handlers ...macaron.Handler) {
|
||||
rr.route(pattern, http.MethodPost, handlers...)
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Delete(pattern string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Delete(pattern string, handlers ...macaron.Handler) {
|
||||
rr.route(pattern, http.MethodDelete, handlers...)
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Put(pattern string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Put(pattern string, handlers ...macaron.Handler) {
|
||||
rr.route(pattern, http.MethodPut, handlers...)
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Patch(pattern string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Patch(pattern string, handlers ...macaron.Handler) {
|
||||
rr.route(pattern, http.MethodPatch, handlers...)
|
||||
}
|
||||
|
||||
func (rr *routeRegister) Any(pattern string, handlers ...macaron.Handler) {
|
||||
func (rr *RouteRegisterImpl) Any(pattern string, handlers ...macaron.Handler) {
|
||||
rr.route(pattern, "*", handlers...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user