diff --git a/pkg/api/common_test.go b/pkg/api/common_test.go index 461a719fef0..2f5ace440ce 100644 --- a/pkg/api/common_test.go +++ b/pkg/api/common_test.go @@ -31,6 +31,7 @@ import ( "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/annotations/annotationstest" "github.com/grafana/grafana/pkg/services/auth/authtest" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/authn/authntest" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy" @@ -213,7 +214,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa } userAuthTokenSvc := authtest.NewFakeUserAuthTokenService() renderSvc := &fakeRenderService{} - authJWTSvc := models.NewFakeJWTService() + authJWTSvc := jwt.NewFakeJWTService() tracer := tracing.InitializeTracerForTest() authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginservice.LoginServiceMock{}, &usertest.FakeUserService{}, sqlStore) loginService := &logintest.LoginServiceFake{} diff --git a/pkg/cmd/grafana-cli/runner/wire.go b/pkg/cmd/grafana-cli/runner/wire.go index ce25050be66..21959dda2cf 100644 --- a/pkg/cmd/grafana-cli/runner/wire.go +++ b/pkg/cmd/grafana-cli/runner/wire.go @@ -7,10 +7,8 @@ import ( "context" "github.com/google/wire" - "github.com/grafana/grafana/pkg/tsdb/parca" - "github.com/grafana/grafana/pkg/tsdb/phlare" - sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" + "github.com/grafana/grafana/pkg/api" "github.com/grafana/grafana/pkg/api/avatar" "github.com/grafana/grafana/pkg/api/routing" @@ -33,7 +31,6 @@ import ( loginpkg "github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/login/social" "github.com/grafana/grafana/pkg/middleware/csrf" - "github.com/grafana/grafana/pkg/models" pluginDashboards "github.com/grafana/grafana/pkg/plugins/manager/dashboards" "github.com/grafana/grafana/pkg/registry/corekind" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -132,6 +129,8 @@ import ( "github.com/grafana/grafana/pkg/tsdb/mssql" "github.com/grafana/grafana/pkg/tsdb/mysql" "github.com/grafana/grafana/pkg/tsdb/opentsdb" + "github.com/grafana/grafana/pkg/tsdb/parca" + "github.com/grafana/grafana/pkg/tsdb/phlare" "github.com/grafana/grafana/pkg/tsdb/postgres" "github.com/grafana/grafana/pkg/tsdb/prometheus" "github.com/grafana/grafana/pkg/tsdb/tempo" @@ -209,7 +208,7 @@ var wireSet = wire.NewSet( pushhttp.ProvideService, contexthandler.ProvideService, jwt.ProvideService, - wire.Bind(new(models.JWTService), new(*jwt.AuthService)), + wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), diff --git a/pkg/middleware/middleware_jwt_auth_test.go b/pkg/middleware/middleware_jwt_auth_test.go index ab41f4d4abe..cc3b48c001a 100644 --- a/pkg/middleware/middleware_jwt_auth_test.go +++ b/pkg/middleware/middleware_jwt_auth_test.go @@ -5,11 +5,12 @@ import ( "errors" "testing" - "github.com/grafana/grafana/pkg/services/org" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/auth/jwt" + "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -61,9 +62,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with valid login claim", func(t *testing.T, sc *scenarioContext) { myUsername := "vladimir" var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myUsername, "foo-username": myUsername, }, nil @@ -88,9 +89,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { // nolint:gosec myToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ2bGFkaW1pckBleGFtcGxlLmNvbSIsImlhdCI6MTUxNjIzOTAyMiwiZm9vLXVzZXJuYW1lIjoidmxhZGltaXIiLCJuYW1lIjoiVmxhZGltaXIgRXhhbXBsZSIsImZvby1lbWFpbCI6InZsYWRpbWlyQGV4YW1wbGUuY29tIn0.MeNU1pCzRHGdQuu5ppeftxT31_2Le2kM1wd1GK2jExs" var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = myToken - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myUsername, "foo-username": myUsername, }, nil @@ -108,9 +109,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with valid email claim", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "foo-email": myEmail, }, nil @@ -128,9 +129,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with no user and auto_sign_up disabled", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "name": "Vladimir Example", "foo-email": myEmail, @@ -146,9 +147,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with no user and auto_sign_up enabled", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "name": "Vladimir Example", "foo-email": myEmail, @@ -167,9 +168,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token without a login claim", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": "baz", "foo": "bar", }, nil @@ -183,9 +184,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token without a email claim", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": "baz", "foo": "bar", }, nil @@ -199,9 +200,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with role", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "role": "Editor", }, nil @@ -217,9 +218,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with invalid role", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "role": "test", }, nil @@ -235,9 +236,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with invalid role in strict mode", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "role": "test", }, nil @@ -252,9 +253,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with grafana admin role not allowed", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "role": "GrafanaAdmin", }, nil @@ -271,9 +272,9 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Valid token with grafana admin role allowed", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token - return models.JWTClaims{ + return jwt.JWTClaims{ "sub": myEmail, "role": "GrafanaAdmin", }, nil @@ -290,7 +291,7 @@ func TestMiddlewareJWTAuth(t *testing.T) { middlewareScenario(t, "Invalid token", func(t *testing.T, sc *scenarioContext) { var verifiedToken string - sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) { + sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (jwt.JWTClaims, error) { verifiedToken = token return nil, errors.New("token is invalid") } diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 60d59fa12a1..cd522c12136 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -29,6 +29,7 @@ import ( "github.com/grafana/grafana/pkg/services/apikey/apikeytest" "github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtest" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/authn/authntest" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy" @@ -885,7 +886,7 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func( sc.m.Use(OrgRedirect(sc.cfg, sc.userService)) sc.userAuthTokenService = ctxHdlr.AuthTokenService.(*authtest.FakeUserAuthTokenService) - sc.jwtAuthService = ctxHdlr.JWTAuthService.(*models.FakeJWTService) + sc.jwtAuthService = ctxHdlr.JWTAuthService.(*jwt.FakeJWTService) sc.remoteCacheService = ctxHdlr.RemoteCache sc.defaultHandler = func(c *models.ReqContext) { @@ -928,7 +929,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *dbtest.Fake remoteCacheSvc := remotecache.NewFakeStore(t) userAuthTokenSvc := authtest.NewFakeUserAuthTokenService() renderSvc := &fakeRenderService{} - authJWTSvc := models.NewFakeJWTService() + authJWTSvc := jwt.NewFakeJWTService() tracer := tracing.InitializeTracerForTest() authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, userService, mockSQLStore) authenticator := &logintest.AuthenticatorFake{ExpectedUser: &user.User{}} diff --git a/pkg/middleware/testing.go b/pkg/middleware/testing.go index 7e858cfd845..2c27fcf7ae2 100644 --- a/pkg/middleware/testing.go +++ b/pkg/middleware/testing.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/apikey/apikeytest" "github.com/grafana/grafana/pkg/services/auth/authtest" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" "github.com/grafana/grafana/pkg/services/login/loginservice" @@ -37,7 +38,7 @@ type scenarioContext struct { defaultHandler web.Handler url string userAuthTokenService *authtest.FakeUserAuthTokenService - jwtAuthService *models.FakeJWTService + jwtAuthService *jwt.FakeJWTService remoteCacheService *remotecache.RemoteCache cfg *setting.Cfg sqlStore db.DB diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 4082ca6d624..54595f3f44a 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -6,6 +6,7 @@ package server import ( "github.com/google/wire" sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" + "github.com/grafana/grafana/pkg/api" "github.com/grafana/grafana/pkg/api/avatar" "github.com/grafana/grafana/pkg/api/routing" @@ -27,7 +28,6 @@ import ( loginpkg "github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/login/social" "github.com/grafana/grafana/pkg/middleware/csrf" - "github.com/grafana/grafana/pkg/models" pluginDashboards "github.com/grafana/grafana/pkg/plugins/manager/dashboards" "github.com/grafana/grafana/pkg/registry/corekind" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -230,7 +230,7 @@ var wireBasicSet = wire.NewSet( pushhttp.ProvideService, contexthandler.ProvideService, jwt.ProvideService, - wire.Bind(new(models.JWTService), new(*jwt.AuthService)), + wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), ngstore.ProvideDBStore, ngimage.ProvideDeleteExpiredService, ngalert.ProvideService, diff --git a/pkg/services/auth/auth.go b/pkg/services/auth/auth.go index e59e1fa6817..356e2426de1 100644 --- a/pkg/services/auth/auth.go +++ b/pkg/services/auth/auth.go @@ -6,9 +6,9 @@ import ( "fmt" "net" - "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models/usertoken" "github.com/grafana/grafana/pkg/registry" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/user" ) @@ -74,4 +74,4 @@ type UserTokenBackgroundService interface { registry.BackgroundService } -type JWTVerifierService = models.JWTService +type JWTVerifierService = jwt.JWTService diff --git a/pkg/services/auth/jwt/auth.go b/pkg/services/auth/jwt/auth.go index 28adad3a2ff..0edeb3f8506 100644 --- a/pkg/services/auth/jwt/auth.go +++ b/pkg/services/auth/jwt/auth.go @@ -10,7 +10,6 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/remotecache" - "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" ) @@ -66,7 +65,7 @@ func sanitizeJWT(jwtToken string) string { return strings.ReplaceAll(jwtToken, string(base64.StdPadding), "") } -func (s *AuthService) Verify(ctx context.Context, strToken string) (models.JWTClaims, error) { +func (s *AuthService) Verify(ctx context.Context, strToken string) (JWTClaims, error) { s.log.Debug("Parsing JSON Web Token") strToken = sanitizeJWT(strToken) @@ -85,7 +84,7 @@ func (s *AuthService) Verify(ctx context.Context, strToken string) (models.JWTCl s.log.Debug("Trying to verify JSON Web Token using a key") - var claims models.JWTClaims + var claims JWTClaims for _, key := range keys { if err = token.Claims(key, &claims); err == nil { break diff --git a/pkg/models/jwt.go b/pkg/services/auth/jwt/jwt.go similarity index 97% rename from pkg/models/jwt.go rename to pkg/services/auth/jwt/jwt.go index 66cad7ae709..d6f3d7d3689 100644 --- a/pkg/models/jwt.go +++ b/pkg/services/auth/jwt/jwt.go @@ -1,4 +1,4 @@ -package models +package jwt import ( "context" diff --git a/pkg/services/auth/jwt/validation.go b/pkg/services/auth/jwt/validation.go index 38a75dc2f31..e4a134b2d63 100644 --- a/pkg/services/auth/jwt/validation.go +++ b/pkg/services/auth/jwt/validation.go @@ -7,8 +7,6 @@ import ( "time" "gopkg.in/square/go-jose.v2/jwt" - - "github.com/grafana/grafana/pkg/models" ) func (s *AuthService) initClaimExpectations() error { @@ -54,7 +52,7 @@ func (s *AuthService) initClaimExpectations() error { return nil } -func (s *AuthService) validateClaims(claims models.JWTClaims) error { +func (s *AuthService) validateClaims(claims JWTClaims) error { var registeredClaims jwt.Claims for key, value := range claims { switch key { diff --git a/pkg/services/authn/clients/jwt_test.go b/pkg/services/authn/clients/jwt_test.go index 5a62067681c..80df9289092 100644 --- a/pkg/services/authn/clients/jwt_test.go +++ b/pkg/services/authn/clients/jwt_test.go @@ -12,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models/roletype" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/authn" "github.com/grafana/grafana/pkg/setting" ) @@ -21,9 +22,9 @@ func stringPtr(s string) *string { } func TestAuthenticateJWT(t *testing.T) { - jwtService := &models.FakeJWTService{ - VerifyProvider: func(context.Context, string) (models.JWTClaims, error) { - return models.JWTClaims{ + jwtService := &jwt.FakeJWTService{ + VerifyProvider: func(context.Context, string) (jwt.JWTClaims, error) { + return jwt.JWTClaims{ "sub": "1234567890", "email": "eai.doe@cor.po", "preferred_username": "eai-doe", @@ -86,9 +87,9 @@ func TestAuthenticateJWT(t *testing.T) { } func TestJWTClaimConfig(t *testing.T) { - jwtService := &models.FakeJWTService{ - VerifyProvider: func(context.Context, string) (models.JWTClaims, error) { - return models.JWTClaims{ + jwtService := &jwt.FakeJWTService{ + VerifyProvider: func(context.Context, string) (jwt.JWTClaims, error) { + return jwt.JWTClaims{ "sub": "1234567890", "email": "eai.doe@cor.po", "preferred_username": "eai-doe", @@ -197,7 +198,7 @@ func TestJWTClaimConfig(t *testing.T) { } func TestJWTTest(t *testing.T) { - jwtService := &models.FakeJWTService{} + jwtService := &jwt.FakeJWTService{} jwtHeaderName := "X-Forwarded-User" // #nosec G101 -- This is dummy/test token validFormatToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o" diff --git a/pkg/services/contexthandler/auth_proxy_test.go b/pkg/services/contexthandler/auth_proxy_test.go index 38b9f3e27dd..2f409ff256d 100644 --- a/pkg/services/contexthandler/auth_proxy_test.go +++ b/pkg/services/contexthandler/auth_proxy_test.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/auth/authtest" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/authn/authntest" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -85,7 +86,7 @@ func getContextHandler(t *testing.T) *ContextHandler { require.NoError(t, err) userAuthTokenSvc := authtest.NewFakeUserAuthTokenService() renderSvc := &fakeRenderService{} - authJWTSvc := models.NewFakeJWTService() + authJWTSvc := jwt.NewFakeJWTService() tracer := tracing.InitializeTracerForTest() loginService := loginservice.LoginServiceMock{ExpectedUser: &user.User{ID: userID}} diff --git a/pkg/services/contexthandler/contexthandler.go b/pkg/services/contexthandler/contexthandler.go index 8c04274892c..d2b306b3c99 100644 --- a/pkg/services/contexthandler/contexthandler.go +++ b/pkg/services/contexthandler/contexthandler.go @@ -23,6 +23,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/auth" + "github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/authn" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" @@ -45,7 +46,7 @@ const ( const ServiceName = "ContextHandler" -func ProvideService(cfg *setting.Cfg, tokenService auth.UserTokenService, jwtService models.JWTService, +func ProvideService(cfg *setting.Cfg, tokenService auth.UserTokenService, jwtService jwt.JWTService, remoteCache *remotecache.RemoteCache, renderService rendering.Service, sqlStore db.DB, tracer tracing.Tracer, authProxy *authproxy.AuthProxy, loginService login.Service, apiKeyService apikey.Service, authenticator loginpkg.Authenticator, userService user.Service,