Chore: use org service methods (#55768)

* Chore: use org service methods

* fix tests

* fix errors

* adjust func signatures for getbyname

* 💩

* Use the same fake service to get the user in AC and in HS

* Fix middleware test

* Fix more middleware test

* Fix api tests

Co-authored-by: gamab <gabi.mabs@gmail.com>
Co-authored-by: Ida Furjesova <ida.furjesova@grafana.com>
This commit is contained in:
Kat Yang 2022-10-04 14:48:02 -04:00 committed by GitHub
parent 169f1ab974
commit 7715672fb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 108 additions and 67 deletions

View File

@ -213,7 +213,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginservice.LoginServiceMock{}, &usertest.FakeUserService{}, sqlStore) authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginservice.LoginServiceMock{}, &usertest.FakeUserService{}, sqlStore)
loginService := &logintest.LoginServiceFake{} loginService := &logintest.LoginServiceFake{}
authenticator := &logintest.AuthenticatorFake{} authenticator := &logintest.AuthenticatorFake{}
ctxHdlr := contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, sqlStore, tracer, authProxy, loginService, nil, authenticator, usertest.NewUserServiceFake()) ctxHdlr := contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, sqlStore, tracer, authProxy, loginService, nil, authenticator, usertest.NewUserServiceFake(), orgtest.NewOrgServiceFake())
return ctxHdlr return ctxHdlr
} }
@ -379,6 +379,10 @@ func setupHTTPServerWithCfgDb(
var acService accesscontrol.Service var acService accesscontrol.Service
var userSvc user.Service var userSvc user.Service
userMock := usertest.NewUserServiceFake()
userMock.ExpectedUser = &user.User{ID: 1}
orgMock := orgtest.NewOrgServiceFake()
orgMock.ExpectedOrg = &org.Org{}
// Defining the accesscontrol service has to be done before registering routes // Defining the accesscontrol service has to be done before registering routes
if useFakeAccessControl { if useFakeAccessControl {
@ -388,7 +392,7 @@ func setupHTTPServerWithCfgDb(
} }
ac = acmock ac = acmock
acService = acmock acService = acmock
userSvc = &usertest.FakeUserService{} userSvc = userMock
} else { } else {
var err error var err error
acService, err = acimpl.ProvideService(cfg, db, routeRegister, localcache.ProvideService()) acService, err = acimpl.ProvideService(cfg, db, routeRegister, localcache.ProvideService())
@ -418,7 +422,7 @@ func setupHTTPServerWithCfgDb(
), ),
preferenceService: preftest.NewPreferenceServiceFake(), preferenceService: preftest.NewPreferenceServiceFake(),
userService: userSvc, userService: userSvc,
orgService: orgtest.NewOrgServiceFake(), orgService: orgMock,
teamService: teamService, teamService: teamService,
annotationsRepo: annotationstest.NewFakeAnnotationsRepo(), annotationsRepo: annotationstest.NewFakeAnnotationsRepo(),
} }

View File

@ -62,7 +62,7 @@ func (hs *HTTPServer) GetOrgByID(c *models.ReqContext) response.Response {
// 403: forbiddenError // 403: forbiddenError
// 500: internalServerError // 500: internalServerError
func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response {
org, err := hs.SQLStore.GetOrgByName(web.Params(c.Req)[":name"]) orga, err := hs.orgService.GetByName(c.Req.Context(), &org.GetOrgByNameQuery{Name: web.Params(c.Req)[":name"]})
if err != nil { if err != nil {
if errors.Is(err, models.ErrOrgNotFound) { if errors.Is(err, models.ErrOrgNotFound) {
return response.Error(http.StatusNotFound, "Organization not found", err) return response.Error(http.StatusNotFound, "Organization not found", err)
@ -71,15 +71,15 @@ func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response {
return response.Error(http.StatusInternalServerError, "Failed to get organization", err) return response.Error(http.StatusInternalServerError, "Failed to get organization", err)
} }
result := models.OrgDetailsDTO{ result := models.OrgDetailsDTO{
Id: org.Id, Id: orga.ID,
Name: org.Name, Name: orga.Name,
Address: models.Address{ Address: models.Address{
Address1: org.Address1, Address1: orga.Address1,
Address2: org.Address2, Address2: orga.Address2,
City: org.City, City: orga.City,
ZipCode: org.ZipCode, ZipCode: orga.ZipCode,
State: org.State, State: orga.State,
Country: org.Country, Country: orga.Country,
}, },
} }
@ -87,26 +87,27 @@ func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response {
} }
func (hs *HTTPServer) getOrgHelper(ctx context.Context, orgID int64) response.Response { func (hs *HTTPServer) getOrgHelper(ctx context.Context, orgID int64) response.Response {
query := models.GetOrgByIdQuery{Id: orgID} query := org.GetOrgByIdQuery{ID: orgID}
if err := hs.SQLStore.GetOrgById(ctx, &query); err != nil { res, err := hs.orgService.GetByID(ctx, &query)
if err != nil {
if errors.Is(err, models.ErrOrgNotFound) { if errors.Is(err, models.ErrOrgNotFound) {
return response.Error(http.StatusNotFound, "Organization not found", err) return response.Error(http.StatusNotFound, "Organization not found", err)
} }
return response.Error(http.StatusInternalServerError, "Failed to get organization", err) return response.Error(http.StatusInternalServerError, "Failed to get organization", err)
} }
org := query.Result orga := res
result := models.OrgDetailsDTO{ result := models.OrgDetailsDTO{
Id: org.Id, Id: orga.ID,
Name: org.Name, Name: orga.Name,
Address: models.Address{ Address: models.Address{
Address1: org.Address1, Address1: orga.Address1,
Address2: org.Address2, Address2: orga.Address2,
City: org.City, City: orga.City,
ZipCode: org.ZipCode, ZipCode: orga.ZipCode,
State: org.State, State: orga.State,
Country: org.Country, Country: orga.Country,
}, },
} }

View File

@ -5,6 +5,7 @@ import (
"testing" "testing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -39,6 +40,7 @@ func TestMiddlewareAuth(t *testing.T) {
middlewareScenario(t, "ReqSignIn true and NoAnonynmous true", func( middlewareScenario(t, "ReqSignIn true and NoAnonynmous true", func(
t *testing.T, sc *scenarioContext) { t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedOrg = &models.Org{Id: orgID, Name: "test"} sc.mockSQLStore.ExpectedOrg = &models.Org{Id: orgID, Name: "test"}
sc.orgService.ExpectedOrg = &org.Org{ID: orgID, Name: "test"}
sc.m.Get("/api/secure", ReqSignedInNoAnonymous, sc.defaultHandler) sc.m.Get("/api/secure", ReqSignedInNoAnonymous, sc.defaultHandler)
sc.fakeReq("GET", "/api/secure").exec() sc.fakeReq("GET", "/api/secure").exec()
@ -48,6 +50,7 @@ func TestMiddlewareAuth(t *testing.T) {
middlewareScenario(t, "ReqSignIn true and request with forceLogin in query string", func( middlewareScenario(t, "ReqSignIn true and request with forceLogin in query string", func(
t *testing.T, sc *scenarioContext) { t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedOrg = &models.Org{Id: orgID, Name: "test"} sc.mockSQLStore.ExpectedOrg = &models.Org{Id: orgID, Name: "test"}
sc.orgService.ExpectedOrg = &org.Org{ID: orgID, Name: "test"}
sc.m.Get("/secure", reqSignIn, sc.defaultHandler) sc.m.Get("/secure", reqSignIn, sc.defaultHandler)
sc.fakeReq("GET", "/secure?forceLogin=true").exec() sc.fakeReq("GET", "/secure?forceLogin=true").exec()
@ -61,6 +64,7 @@ func TestMiddlewareAuth(t *testing.T) {
middlewareScenario(t, "ReqSignIn true and request with same org provided in query string", func( middlewareScenario(t, "ReqSignIn true and request with same org provided in query string", func(
t *testing.T, sc *scenarioContext) { t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedOrg = &models.Org{Id: 1, Name: sc.cfg.AnonymousOrgName} sc.mockSQLStore.ExpectedOrg = &models.Org{Id: 1, Name: sc.cfg.AnonymousOrgName}
sc.orgService.ExpectedOrg = &org.Org{ID: 1, Name: sc.cfg.AnonymousOrgName}
org, err := sc.mockSQLStore.CreateOrgWithMember(sc.cfg.AnonymousOrgName, 1) org, err := sc.mockSQLStore.CreateOrgWithMember(sc.cfg.AnonymousOrgName, 1)
require.NoError(t, err) require.NoError(t, err)
@ -74,6 +78,7 @@ func TestMiddlewareAuth(t *testing.T) {
middlewareScenario(t, "ReqSignIn true and request with different org provided in query string", func( middlewareScenario(t, "ReqSignIn true and request with different org provided in query string", func(
t *testing.T, sc *scenarioContext) { t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedOrg = &models.Org{Id: 1, Name: sc.cfg.AnonymousOrgName} sc.mockSQLStore.ExpectedOrg = &models.Org{Id: 1, Name: sc.cfg.AnonymousOrgName}
sc.orgService.ExpectedOrg = &org.Org{ID: 1, Name: sc.cfg.AnonymousOrgName}
sc.m.Get("/secure", reqSignIn, sc.defaultHandler) sc.m.Get("/secure", reqSignIn, sc.defaultHandler)
sc.fakeReq("GET", "/secure?orgId=2").exec() sc.fakeReq("GET", "/secure?orgId=2").exec()

View File

@ -32,6 +32,7 @@ import (
"github.com/grafana/grafana/pkg/services/login/logintest" "github.com/grafana/grafana/pkg/services/login/logintest"
"github.com/grafana/grafana/pkg/services/navtree" "github.com/grafana/grafana/pkg/services/navtree"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@ -340,6 +341,7 @@ func TestMiddlewareContext(t *testing.T) {
middlewareScenario(t, "When anonymous access is enabled", func(t *testing.T, sc *scenarioContext) { middlewareScenario(t, "When anonymous access is enabled", func(t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedOrg = &models.Org{Id: 1, Name: sc.cfg.AnonymousOrgName} sc.mockSQLStore.ExpectedOrg = &models.Org{Id: 1, Name: sc.cfg.AnonymousOrgName}
sc.orgService.ExpectedOrg = &org.Org{ID: 1, Name: sc.cfg.AnonymousOrgName}
orga, err := sc.mockSQLStore.CreateOrgWithMember(sc.cfg.AnonymousOrgName, 1) orga, err := sc.mockSQLStore.CreateOrgWithMember(sc.cfg.AnonymousOrgName, 1)
require.NoError(t, err) require.NoError(t, err)
sc.fakeReq("GET", "/").exec() sc.fakeReq("GET", "/").exec()
@ -653,8 +655,9 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
sc.mockSQLStore = mockstore.NewSQLStoreMock() sc.mockSQLStore = mockstore.NewSQLStoreMock()
sc.loginService = &loginservice.LoginServiceMock{} sc.loginService = &loginservice.LoginServiceMock{}
sc.userService = usertest.NewUserServiceFake() sc.userService = usertest.NewUserServiceFake()
sc.orgService = orgtest.NewOrgServiceFake()
sc.apiKeyService = &apikeytest.Service{} sc.apiKeyService = &apikeytest.Service{}
ctxHdlr := getContextHandler(t, cfg, sc.mockSQLStore, sc.loginService, sc.apiKeyService, sc.userService) ctxHdlr := getContextHandler(t, cfg, sc.mockSQLStore, sc.loginService, sc.apiKeyService, sc.userService, sc.orgService)
sc.sqlStore = ctxHdlr.SQLStore sc.sqlStore = ctxHdlr.SQLStore
sc.contextHandler = ctxHdlr sc.contextHandler = ctxHdlr
sc.m.Use(ctxHdlr.Middleware) sc.m.Use(ctxHdlr.Middleware)
@ -687,7 +690,10 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
}) })
} }
func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *mockstore.SQLStoreMock, loginService *loginservice.LoginServiceMock, apiKeyService *apikeytest.Service, userService *usertest.FakeUserService) *contexthandler.ContextHandler { func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *mockstore.SQLStoreMock,
loginService *loginservice.LoginServiceMock, apiKeyService *apikeytest.Service,
userService *usertest.FakeUserService, orgService *orgtest.FakeOrgService,
) *contexthandler.ContextHandler {
t.Helper() t.Helper()
if cfg == nil { if cfg == nil {
@ -704,7 +710,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *mockstore.S
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, userService, mockSQLStore) authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, userService, mockSQLStore)
authenticator := &logintest.AuthenticatorFake{ExpectedUser: &user.User{}} authenticator := &logintest.AuthenticatorFake{ExpectedUser: &user.User{}}
return contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, mockSQLStore, tracer, authProxy, loginService, apiKeyService, authenticator, userService) return contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, mockSQLStore, tracer, authProxy, loginService, apiKeyService, authenticator, userService, orgService)
} }
type fakeRenderService struct { type fakeRenderService struct {

View File

@ -68,7 +68,7 @@ func recoveryScenario(t *testing.T, desc string, url string, fn scenarioFunc) {
sc.userAuthTokenService = auth.NewFakeUserAuthTokenService() sc.userAuthTokenService = auth.NewFakeUserAuthTokenService()
sc.remoteCacheService = remotecache.NewFakeStore(t) sc.remoteCacheService = remotecache.NewFakeStore(t)
contextHandler := getContextHandler(t, nil, nil, nil, nil, nil) contextHandler := getContextHandler(t, nil, nil, nil, nil, nil, nil)
sc.m.Use(contextHandler.Middleware) sc.m.Use(contextHandler.Middleware)
// mock out gc goroutine // mock out gc goroutine
sc.m.Use(OrgRedirect(cfg, sc.userService)) sc.m.Use(OrgRedirect(cfg, sc.userService))

View File

@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/login/loginservice" "github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/services/user/usertest"
@ -43,6 +44,7 @@ type scenarioContext struct {
loginService *loginservice.LoginServiceMock loginService *loginservice.LoginServiceMock
apiKeyService *apikeytest.Service apiKeyService *apikeytest.Service
userService *usertest.FakeUserService userService *usertest.FakeUserService
orgService *orgtest.FakeOrgService
req *http.Request req *http.Request
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/contexthandler/authproxy" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy"
"github.com/grafana/grafana/pkg/services/login/loginservice" "github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@ -96,12 +97,14 @@ func getContextHandler(t *testing.T) *ContextHandler {
}, nil }, nil
}, },
} }
orgService := orgtest.NewOrgServiceFake()
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, &userService, &FakeGetSignUserStore{}) authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, &userService, &FakeGetSignUserStore{})
authenticator := &fakeAuthenticator{} authenticator := &fakeAuthenticator{}
return ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, return ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc,
renderSvc, sqlStore, tracer, authProxy, loginService, nil, authenticator, &userService) renderSvc, sqlStore, tracer, authProxy, loginService, nil, authenticator,
&userService, orgService)
} }
type FakeGetSignUserStore struct { type FakeGetSignUserStore struct {

View File

@ -44,7 +44,7 @@ func ProvideService(cfg *setting.Cfg, tokenService models.UserTokenService, jwtS
remoteCache *remotecache.RemoteCache, renderService rendering.Service, sqlStore sqlstore.Store, remoteCache *remotecache.RemoteCache, renderService rendering.Service, sqlStore sqlstore.Store,
tracer tracing.Tracer, authProxy *authproxy.AuthProxy, loginService login.Service, tracer tracing.Tracer, authProxy *authproxy.AuthProxy, loginService login.Service,
apiKeyService apikey.Service, authenticator loginpkg.Authenticator, userService user.Service, apiKeyService apikey.Service, authenticator loginpkg.Authenticator, userService user.Service,
) *ContextHandler { orgService org.Service) *ContextHandler {
return &ContextHandler{ return &ContextHandler{
Cfg: cfg, Cfg: cfg,
AuthTokenService: tokenService, AuthTokenService: tokenService,
@ -58,6 +58,7 @@ func ProvideService(cfg *setting.Cfg, tokenService models.UserTokenService, jwtS
loginService: loginService, loginService: loginService,
apiKeyService: apiKeyService, apiKeyService: apiKeyService,
userService: userService, userService: userService,
orgService: orgService,
} }
} }
@ -75,6 +76,7 @@ type ContextHandler struct {
loginService login.Service loginService login.Service
apiKeyService apikey.Service apiKeyService apikey.Service
userService user.Service userService user.Service
orgService org.Service
// GetTime returns the current time. // GetTime returns the current time.
// Stubbable by tests. // Stubbable by tests.
GetTime func() time.Time GetTime func() time.Time
@ -184,7 +186,9 @@ func (h *ContextHandler) initContextWithAnonymousUser(reqContext *models.ReqCont
_, span := h.tracer.Start(reqContext.Req.Context(), "initContextWithAnonymousUser") _, span := h.tracer.Start(reqContext.Req.Context(), "initContextWithAnonymousUser")
defer span.End() defer span.End()
orga, err := h.SQLStore.GetOrgByName(h.Cfg.AnonymousOrgName) getOrg := org.GetOrgByNameQuery{Name: h.Cfg.AnonymousOrgName}
orga, err := h.orgService.GetByName(reqContext.Req.Context(), &getOrg)
if err != nil { if err != nil {
reqContext.Logger.Error("Anonymous access organization error.", "org_name", h.Cfg.AnonymousOrgName, "error", err) reqContext.Logger.Error("Anonymous access organization error.", "org_name", h.Cfg.AnonymousOrgName, "error", err)
return false return false
@ -194,7 +198,7 @@ func (h *ContextHandler) initContextWithAnonymousUser(reqContext *models.ReqCont
reqContext.AllowAnonymous = true reqContext.AllowAnonymous = true
reqContext.SignedInUser = &user.SignedInUser{IsAnonymous: true} reqContext.SignedInUser = &user.SignedInUser{IsAnonymous: true}
reqContext.OrgRole = org.RoleType(h.Cfg.AnonymousOrgRole) reqContext.OrgRole = org.RoleType(h.Cfg.AnonymousOrgRole)
reqContext.OrgID = orga.Id reqContext.OrgID = orga.ID
reqContext.OrgName = orga.Name reqContext.OrgName = orga.Name
return true return true
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/encryption" "github.com/grafana/grafana/pkg/services/encryption"
"github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/notifications"
"github.com/grafana/grafana/pkg/services/org"
) )
type Manager interface { type Manager interface {
@ -29,8 +30,8 @@ type SQLStore interface {
} }
// Provision alert notifiers // Provision alert notifiers
func Provision(ctx context.Context, configDirectory string, alertingService Manager, sqlstore SQLStore, encryptionService encryption.Internal, notificationService *notifications.NotificationService) error { func Provision(ctx context.Context, configDirectory string, alertingService Manager, orgService org.Service, sqlstore SQLStore, encryptionService encryption.Internal, notificationService *notifications.NotificationService) error {
dc := newNotificationProvisioner(sqlstore, alertingService, encryptionService, notificationService, log.New("provisioning.notifiers")) dc := newNotificationProvisioner(orgService, sqlstore, alertingService, encryptionService, notificationService, log.New("provisioning.notifiers"))
return dc.applyChanges(ctx, configDirectory) return dc.applyChanges(ctx, configDirectory)
} }
@ -40,9 +41,10 @@ type NotificationProvisioner struct {
cfgProvider *configReader cfgProvider *configReader
alertingManager Manager alertingManager Manager
sqlstore SQLStore sqlstore SQLStore
orgService org.Service
} }
func newNotificationProvisioner(store SQLStore, alertingManager Manager, encryptionService encryption.Internal, notifiationService *notifications.NotificationService, log log.Logger) NotificationProvisioner { func newNotificationProvisioner(orgService org.Service, store SQLStore, alertingManager Manager, encryptionService encryption.Internal, notifiationService *notifications.NotificationService, log log.Logger) NotificationProvisioner {
return NotificationProvisioner{ return NotificationProvisioner{
log: log, log: log,
alertingManager: alertingManager, alertingManager: alertingManager,
@ -52,7 +54,8 @@ func newNotificationProvisioner(store SQLStore, alertingManager Manager, encrypt
log: log, log: log,
orgStore: store, orgStore: store,
}, },
sqlstore: store, sqlstore: store,
orgService: orgService,
} }
} }
@ -73,11 +76,12 @@ func (dc *NotificationProvisioner) deleteNotifications(ctx context.Context, noti
dc.log.Info("Deleting alert notification", "name", notification.Name, "uid", notification.UID) dc.log.Info("Deleting alert notification", "name", notification.Name, "uid", notification.UID)
if notification.OrgID == 0 && notification.OrgName != "" { if notification.OrgID == 0 && notification.OrgName != "" {
getOrg := &models.GetOrgByNameQuery{Name: notification.OrgName} getOrg := org.GetOrgByNameQuery{Name: notification.OrgName}
if err := dc.sqlstore.GetOrgByNameHandler(ctx, getOrg); err != nil { res, err := dc.orgService.GetByName(ctx, &getOrg)
if err != nil {
return err return err
} }
notification.OrgID = getOrg.Result.Id notification.OrgID = res.ID
} else if notification.OrgID < 0 { } else if notification.OrgID < 0 {
notification.OrgID = 1 notification.OrgID = 1
} }
@ -102,11 +106,12 @@ func (dc *NotificationProvisioner) deleteNotifications(ctx context.Context, noti
func (dc *NotificationProvisioner) mergeNotifications(ctx context.Context, notificationToMerge []*notificationFromConfig) error { func (dc *NotificationProvisioner) mergeNotifications(ctx context.Context, notificationToMerge []*notificationFromConfig) error {
for _, notification := range notificationToMerge { for _, notification := range notificationToMerge {
if notification.OrgID == 0 && notification.OrgName != "" { if notification.OrgID == 0 && notification.OrgName != "" {
getOrg := &models.GetOrgByNameQuery{Name: notification.OrgName} getOrg := org.GetOrgByNameQuery{Name: notification.OrgName}
if err := dc.sqlstore.GetOrgByNameHandler(ctx, getOrg); err != nil { res, err := dc.orgService.GetByName(ctx, &getOrg)
if err != nil {
return err return err
} }
notification.OrgID = getOrg.Result.Id notification.OrgID = res.ID
} else if notification.OrgID < 0 { } else if notification.OrgID < 0 {
notification.OrgID = 1 notification.OrgID = 1
} }

View File

@ -12,6 +12,8 @@ import (
"github.com/grafana/grafana/pkg/services/alerting/notifiers" "github.com/grafana/grafana/pkg/services/alerting/notifiers"
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service" encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
"github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/notifications"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -34,6 +36,8 @@ func TestNotificationAsConfig(t *testing.T) {
var sqlStore *sqlstore.SQLStore var sqlStore *sqlstore.SQLStore
var ns *alerting.AlertNotificationService var ns *alerting.AlertNotificationService
logger := log.New("fake.log") logger := log.New("fake.log")
orgService := orgtest.NewOrgServiceFake()
orgService.ExpectedOrg = &org.Org{}
encryptionService := encryptionservice.SetupTestService(t) encryptionService := encryptionservice.SetupTestService(t)
@ -146,7 +150,7 @@ func TestNotificationAsConfig(t *testing.T) {
setup() setup()
fakeAlertNotification := &fakeAlertNotification{} fakeAlertNotification := &fakeAlertNotification{}
fakeAlertNotification.ExpectedAlertNotification = &models.AlertNotification{OrgId: 1} fakeAlertNotification.ExpectedAlertNotification = &models.AlertNotification{OrgId: 1}
dc := newNotificationProvisioner(sqlStore, fakeAlertNotification, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, fakeAlertNotification, encryptionService, nil, logger)
err := dc.applyChanges(context.Background(), twoNotificationsConfig) err := dc.applyChanges(context.Background(), twoNotificationsConfig)
if err != nil { if err != nil {
@ -172,7 +176,7 @@ func TestNotificationAsConfig(t *testing.T) {
require.Equal(t, len(notificationsQuery.Result), 1) require.Equal(t, len(notificationsQuery.Result), 1)
t.Run("should update one notification", func(t *testing.T) { t.Run("should update one notification", func(t *testing.T) {
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
err = dc.applyChanges(context.Background(), twoNotificationsConfig) err = dc.applyChanges(context.Background(), twoNotificationsConfig)
if err != nil { if err != nil {
t.Fatalf("applyChanges return an error %v", err) t.Fatalf("applyChanges return an error %v", err)
@ -182,7 +186,7 @@ func TestNotificationAsConfig(t *testing.T) {
t.Run("Two notifications with is_default", func(t *testing.T) { t.Run("Two notifications with is_default", func(t *testing.T) {
setup() setup()
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
err := dc.applyChanges(context.Background(), doubleNotificationsConfig) err := dc.applyChanges(context.Background(), doubleNotificationsConfig)
t.Run("should both be inserted", func(t *testing.T) { t.Run("should both be inserted", func(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
@ -217,7 +221,7 @@ func TestNotificationAsConfig(t *testing.T) {
require.Equal(t, len(notificationsQuery.Result), 2) require.Equal(t, len(notificationsQuery.Result), 2)
t.Run("should have two new notifications", func(t *testing.T) { t.Run("should have two new notifications", func(t *testing.T) {
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
err := dc.applyChanges(context.Background(), twoNotificationsConfig) err := dc.applyChanges(context.Background(), twoNotificationsConfig)
if err != nil { if err != nil {
t.Fatalf("applyChanges return an error %v", err) t.Fatalf("applyChanges return an error %v", err)
@ -247,7 +251,7 @@ func TestNotificationAsConfig(t *testing.T) {
err = ns.SQLStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd) err = ns.SQLStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
require.NoError(t, err) require.NoError(t, err)
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
err = dc.applyChanges(context.Background(), correctPropertiesWithOrgName) err = dc.applyChanges(context.Background(), correctPropertiesWithOrgName)
if err != nil { if err != nil {
t.Fatalf("applyChanges return an error %v", err) t.Fatalf("applyChanges return an error %v", err)
@ -256,7 +260,7 @@ func TestNotificationAsConfig(t *testing.T) {
t.Run("Config doesn't contain required field", func(t *testing.T) { t.Run("Config doesn't contain required field", func(t *testing.T) {
setup() setup()
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
err := dc.applyChanges(context.Background(), noRequiredFields) err := dc.applyChanges(context.Background(), noRequiredFields)
require.NotNil(t, err) require.NotNil(t, err)
@ -270,7 +274,7 @@ func TestNotificationAsConfig(t *testing.T) {
t.Run("Empty yaml file", func(t *testing.T) { t.Run("Empty yaml file", func(t *testing.T) {
t.Run("should have not changed repo", func(t *testing.T) { t.Run("should have not changed repo", func(t *testing.T) {
setup() setup()
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger) dc := newNotificationProvisioner(orgService, sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
err := dc.applyChanges(context.Background(), emptyFile) err := dc.applyChanges(context.Background(), emptyFile)
if err != nil { if err != nil {
t.Fatalf("applyChanges return an error %v", err) t.Fatalf("applyChanges return an error %v", err)

View File

@ -7,22 +7,19 @@ import (
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsettings"
) )
type Store interface {
GetOrgByNameHandler(ctx context.Context, query *models.GetOrgByNameQuery) error
}
// Provision scans a directory for provisioning config files // Provision scans a directory for provisioning config files
// and provisions the app in those files. // and provisions the app in those files.
func Provision(ctx context.Context, configDirectory string, store Store, pluginStore plugins.Store, pluginSettings pluginsettings.Service) error { func Provision(ctx context.Context, configDirectory string, pluginStore plugins.Store, pluginSettings pluginsettings.Service, orgService org.Service) error {
logger := log.New("provisioning.plugins") logger := log.New("provisioning.plugins")
ap := PluginProvisioner{ ap := PluginProvisioner{
log: logger, log: logger,
cfgProvider: newConfigReader(logger, pluginStore), cfgProvider: newConfigReader(logger, pluginStore),
store: store,
pluginSettings: pluginSettings, pluginSettings: pluginSettings,
orgService: orgService,
} }
return ap.applyChanges(ctx, configDirectory) return ap.applyChanges(ctx, configDirectory)
} }
@ -32,18 +29,19 @@ func Provision(ctx context.Context, configDirectory string, store Store, pluginS
type PluginProvisioner struct { type PluginProvisioner struct {
log log.Logger log log.Logger
cfgProvider configReader cfgProvider configReader
store Store
pluginSettings pluginsettings.Service pluginSettings pluginsettings.Service
orgService org.Service
} }
func (ap *PluginProvisioner) apply(ctx context.Context, cfg *pluginsAsConfig) error { func (ap *PluginProvisioner) apply(ctx context.Context, cfg *pluginsAsConfig) error {
for _, app := range cfg.Apps { for _, app := range cfg.Apps {
if app.OrgID == 0 && app.OrgName != "" { if app.OrgID == 0 && app.OrgName != "" {
getOrgQuery := &models.GetOrgByNameQuery{Name: app.OrgName} getOrgQuery := &org.GetOrgByNameQuery{Name: app.OrgName}
if err := ap.store.GetOrgByNameHandler(ctx, getOrgQuery); err != nil { res, err := ap.orgService.GetByName(ctx, getOrgQuery)
if err != nil {
return err return err
} }
app.OrgID = getOrgQuery.Result.Id app.OrgID = res.ID
} else if app.OrgID < 0 { } else if app.OrgID < 0 {
app.OrgID = 1 app.OrgID = 1
} }

View File

@ -5,6 +5,8 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsettings"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
@ -34,7 +36,9 @@ func TestPluginProvisioner(t *testing.T) {
} }
reader := &testConfigReader{result: cfg} reader := &testConfigReader{result: cfg}
store := &mockStore{} store := &mockStore{}
ap := PluginProvisioner{log: log.New("test"), cfgProvider: reader, store: store, pluginSettings: store} orgMock := orgtest.NewOrgServiceFake()
orgMock.ExpectedOrg = &org.Org{ID: 4}
ap := PluginProvisioner{log: log.New("test"), cfgProvider: reader, pluginSettings: store, orgService: orgMock}
err := ap.applyChanges(context.Background(), "") err := ap.applyChanges(context.Background(), "")
require.NoError(t, err) require.NoError(t, err)

View File

@ -18,6 +18,7 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/provisioning"
"github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/notifications"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsettings"
prov_alerting "github.com/grafana/grafana/pkg/services/provisioning/alerting" prov_alerting "github.com/grafana/grafana/pkg/services/provisioning/alerting"
"github.com/grafana/grafana/pkg/services/provisioning/dashboards" "github.com/grafana/grafana/pkg/services/provisioning/dashboards"
@ -49,6 +50,7 @@ func ProvideService(
searchService searchV2.SearchService, searchService searchV2.SearchService,
quotaService quota.Service, quotaService quota.Service,
secrectService secrets.Service, secrectService secrets.Service,
orgService org.Service,
) (*ProvisioningServiceImpl, error) { ) (*ProvisioningServiceImpl, error) {
s := &ProvisioningServiceImpl{ s := &ProvisioningServiceImpl{
Cfg: cfg, Cfg: cfg,
@ -72,6 +74,7 @@ func ProvideService(
quotaService: quotaService, quotaService: quotaService,
secretService: secrectService, secretService: secrectService,
log: log.New("provisioning"), log: log.New("provisioning"),
orgService: orgService,
} }
return s, nil return s, nil
} }
@ -103,9 +106,9 @@ func NewProvisioningServiceImpl() *ProvisioningServiceImpl {
// Used for testing purposes // Used for testing purposes
func newProvisioningServiceImpl( func newProvisioningServiceImpl(
newDashboardProvisioner dashboards.DashboardProvisionerFactory, newDashboardProvisioner dashboards.DashboardProvisionerFactory,
provisionNotifiers func(context.Context, string, notifiers.Manager, notifiers.SQLStore, encryption.Internal, *notifications.NotificationService) error, provisionNotifiers func(context.Context, string, notifiers.Manager, org.Service, notifiers.SQLStore, encryption.Internal, *notifications.NotificationService) error,
provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, utils.OrgStore) error, provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, utils.OrgStore) error,
provisionPlugins func(context.Context, string, plugins.Store, plugifaces.Store, pluginsettings.Service) error, provisionPlugins func(context.Context, string, plugifaces.Store, pluginsettings.Service, org.Service) error,
) *ProvisioningServiceImpl { ) *ProvisioningServiceImpl {
return &ProvisioningServiceImpl{ return &ProvisioningServiceImpl{
log: log.New("provisioning"), log: log.New("provisioning"),
@ -119,6 +122,7 @@ func newProvisioningServiceImpl(
type ProvisioningServiceImpl struct { type ProvisioningServiceImpl struct {
Cfg *setting.Cfg Cfg *setting.Cfg
SQLStore *sqlstore.SQLStore SQLStore *sqlstore.SQLStore
orgService org.Service
ac accesscontrol.AccessControl ac accesscontrol.AccessControl
pluginStore plugifaces.Store pluginStore plugifaces.Store
EncryptionService encryption.Internal EncryptionService encryption.Internal
@ -127,9 +131,9 @@ type ProvisioningServiceImpl struct {
pollingCtxCancel context.CancelFunc pollingCtxCancel context.CancelFunc
newDashboardProvisioner dashboards.DashboardProvisionerFactory newDashboardProvisioner dashboards.DashboardProvisionerFactory
dashboardProvisioner dashboards.DashboardProvisioner dashboardProvisioner dashboards.DashboardProvisioner
provisionNotifiers func(context.Context, string, notifiers.Manager, notifiers.SQLStore, encryption.Internal, *notifications.NotificationService) error provisionNotifiers func(context.Context, string, notifiers.Manager, org.Service, notifiers.SQLStore, encryption.Internal, *notifications.NotificationService) error
provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, utils.OrgStore) error provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, utils.OrgStore) error
provisionPlugins func(context.Context, string, plugins.Store, plugifaces.Store, pluginsettings.Service) error provisionPlugins func(context.Context, string, plugifaces.Store, pluginsettings.Service, org.Service) error
provisionAlerting func(context.Context, prov_alerting.ProvisionerConfig) error provisionAlerting func(context.Context, prov_alerting.ProvisionerConfig) error
mutex sync.Mutex mutex sync.Mutex
dashboardProvisioningService dashboardservice.DashboardProvisioningService dashboardProvisioningService dashboardservice.DashboardProvisioningService
@ -211,7 +215,7 @@ func (ps *ProvisioningServiceImpl) ProvisionDatasources(ctx context.Context) err
func (ps *ProvisioningServiceImpl) ProvisionPlugins(ctx context.Context) error { func (ps *ProvisioningServiceImpl) ProvisionPlugins(ctx context.Context) error {
appPath := filepath.Join(ps.Cfg.ProvisioningPath, "plugins") appPath := filepath.Join(ps.Cfg.ProvisioningPath, "plugins")
if err := ps.provisionPlugins(ctx, appPath, ps.SQLStore, ps.pluginStore, ps.pluginsSettings); err != nil { if err := ps.provisionPlugins(ctx, appPath, ps.pluginStore, ps.pluginsSettings, ps.orgService); err != nil {
err = fmt.Errorf("%v: %w", "app provisioning error", err) err = fmt.Errorf("%v: %w", "app provisioning error", err)
ps.log.Error("Failed to provision plugins", "error", err) ps.log.Error("Failed to provision plugins", "error", err)
return err return err
@ -221,7 +225,7 @@ func (ps *ProvisioningServiceImpl) ProvisionPlugins(ctx context.Context) error {
func (ps *ProvisioningServiceImpl) ProvisionNotifications(ctx context.Context) error { func (ps *ProvisioningServiceImpl) ProvisionNotifications(ctx context.Context) error {
alertNotificationsPath := filepath.Join(ps.Cfg.ProvisioningPath, "notifiers") alertNotificationsPath := filepath.Join(ps.Cfg.ProvisioningPath, "notifiers")
if err := ps.provisionNotifiers(ctx, alertNotificationsPath, ps.alertingService, ps.SQLStore, ps.EncryptionService, ps.NotificationService); err != nil { if err := ps.provisionNotifiers(ctx, alertNotificationsPath, ps.alertingService, ps.orgService, ps.SQLStore, ps.EncryptionService, ps.NotificationService); err != nil {
err = fmt.Errorf("%v: %w", "Alert notification provisioning error", err) err = fmt.Errorf("%v: %w", "Alert notification provisioning error", err)
ps.log.Error("Failed to provision alert notifications", "error", err) ps.log.Error("Failed to provision alert notifications", "error", err)
return err return err

View File

@ -148,14 +148,15 @@ func (s *StandardSearchService) getUser(ctx context.Context, backendUser *backen
var usr *user.SignedInUser var usr *user.SignedInUser
if s.cfg.AnonymousEnabled && backendUser.Email == "" && backendUser.Login == "" { if s.cfg.AnonymousEnabled && backendUser.Email == "" && backendUser.Login == "" {
orga, err := s.sql.GetOrgByName(s.cfg.AnonymousOrgName) getOrg := org.GetOrgByNameQuery{Name: s.cfg.AnonymousOrgName}
orga, err := s.orgService.GetByName(ctx, &getOrg)
if err != nil { if err != nil {
s.logger.Error("Anonymous access organization error.", "org_name", s.cfg.AnonymousOrgName, "error", err) s.logger.Error("Anonymous access organization error.", "org_name", s.cfg.AnonymousOrgName, "error", err)
return nil, err return nil, err
} }
usr = &user.SignedInUser{ usr = &user.SignedInUser{
OrgID: orga.Id, OrgID: orga.ID,
OrgName: orga.Name, OrgName: orga.Name,
OrgRole: org.RoleType(s.cfg.AnonymousOrgRole), OrgRole: org.RoleType(s.cfg.AnonymousOrgRole),
IsAnonymous: true, IsAnonymous: true,