Auth: Refactor auth package (#58920)

* Auth: move interface to its own file

* Auth: move to test package

* Auth: move quota consts to auth file

* Auth: move service to impl package

* Auth: move interfaces and related models to auth package

* Auth: Create sub package and type alias to avoid circular dependency
This commit is contained in:
Karl Persson 2022-11-18 09:56:06 +01:00 committed by GitHub
parent ea27eca147
commit fef1e1d5bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 245 additions and 221 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
@ -416,7 +417,7 @@ func (hs *HTTPServer) AdminGetUserAuthTokens(c *models.ReqContext) response.Resp
// 404: notFoundError // 404: notFoundError
// 500: internalServerError // 500: internalServerError
func (hs *HTTPServer) AdminRevokeUserAuthToken(c *models.ReqContext) response.Response { func (hs *HTTPServer) AdminRevokeUserAuthToken(c *models.ReqContext) response.Response {
cmd := models.RevokeAuthTokenCmd{} cmd := auth.RevokeAuthTokenCmd{}
if err := web.Bind(c.Req, &cmd); err != nil { if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err) return response.Error(http.StatusBadRequest, "bad request data", err)
} }
@ -476,7 +477,7 @@ type AdminLogoutUserParams struct {
type AdminRevokeUserAuthTokenParams struct { type AdminRevokeUserAuthTokenParams struct {
// in:body // in:body
// required:true // required:true
Body models.RevokeAuthTokenCmd `json:"body"` Body auth.RevokeAuthTokenCmd `json:"body"`
// in:path // in:path
// required:true // required:true
UserID int64 `json:"user_id"` UserID int64 `json:"user_id"`
@ -508,5 +509,5 @@ type AdminCreateUserResponseResponse struct {
// swagger:response adminGetUserAuthTokensResponse // swagger:response adminGetUserAuthTokensResponse
type AdminGetUserAuthTokensResponse struct { type AdminGetUserAuthTokensResponse struct {
// in:body // in:body
Body []*models.UserToken `json:"body"` Body []*auth.UserToken `json:"body"`
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/login/loginservice" "github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/services/login/logintest" "github.com/grafana/grafana/pkg/services/login/logintest"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
@ -65,7 +66,7 @@ func TestAdminAPIEndpoint(t *testing.T) {
}) })
t.Run("When a server admin attempts to revoke an auth token for a non-existing user", func(t *testing.T) { t.Run("When a server admin attempts to revoke an auth token for a non-existing user", func(t *testing.T) {
cmd := models.RevokeAuthTokenCmd{AuthTokenId: 2} cmd := auth.RevokeAuthTokenCmd{AuthTokenId: 2}
mockUser := usertest.NewUserServiceFake() mockUser := usertest.NewUserServiceFake()
mockUser.ExpectedError = user.ErrUserNotFound mockUser.ExpectedError = user.ErrUserNotFound
adminRevokeUserAuthTokenScenario(t, "Should return not found when calling POST on", adminRevokeUserAuthTokenScenario(t, "Should return not found when calling POST on",
@ -263,7 +264,7 @@ func putAdminScenario(t *testing.T, desc string, url string, routePattern string
func adminLogoutUserScenario(t *testing.T, desc string, url string, routePattern string, fn scenarioFunc, userService *usertest.FakeUserService) { func adminLogoutUserScenario(t *testing.T, desc string, url string, routePattern string, fn scenarioFunc, userService *usertest.FakeUserService) {
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: auth.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
userService: userService, userService: userService,
} }
@ -285,9 +286,9 @@ func adminLogoutUserScenario(t *testing.T, desc string, url string, routePattern
}) })
} }
func adminRevokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePattern string, cmd models.RevokeAuthTokenCmd, fn scenarioFunc, userService user.Service) { func adminRevokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePattern string, cmd auth.RevokeAuthTokenCmd, fn scenarioFunc, userService user.Service) {
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: fakeAuthTokenService, AuthTokenService: fakeAuthTokenService,
@ -315,7 +316,7 @@ func adminRevokeUserAuthTokenScenario(t *testing.T, desc string, url string, rou
func adminGetUserAuthTokensScenario(t *testing.T, desc string, url string, routePattern string, fn scenarioFunc, userService *usertest.FakeUserService) { func adminGetUserAuthTokensScenario(t *testing.T, desc string, url string, routePattern string, fn scenarioFunc, userService *usertest.FakeUserService) {
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: fakeAuthTokenService, AuthTokenService: fakeAuthTokenService,
@ -341,7 +342,7 @@ func adminGetUserAuthTokensScenario(t *testing.T, desc string, url string, route
func adminDisableUserScenario(t *testing.T, desc string, action string, url string, routePattern string, fn scenarioFunc) { func adminDisableUserScenario(t *testing.T, desc string, action string, url string, routePattern string, fn scenarioFunc) {
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
authInfoService := &logintest.AuthInfoServiceFake{} authInfoService := &logintest.AuthInfoServiceFake{}

View File

@ -28,7 +28,7 @@ import (
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/annotations/annotationstest" "github.com/grafana/grafana/pkg/services/annotations/annotationstest"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/contexthandler/authproxy" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
@ -181,7 +181,7 @@ type scenarioContext struct {
defaultHandler web.Handler defaultHandler web.Handler
req *http.Request req *http.Request
url string url string
userAuthTokenService *auth.FakeUserAuthTokenService userAuthTokenService *authtest.FakeUserAuthTokenService
sqlStore sqlstore.Store sqlStore sqlstore.Store
authInfoService *logintest.AuthInfoServiceFake authInfoService *logintest.AuthInfoServiceFake
dashboardVersionService dashver.Service dashboardVersionService dashver.Service
@ -207,7 +207,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa
cfg.RemoteCacheOptions = &setting.RemoteCacheOptions{ cfg.RemoteCacheOptions = &setting.RemoteCacheOptions{
Name: "database", Name: "database",
} }
userAuthTokenSvc := auth.NewFakeUserAuthTokenService() userAuthTokenSvc := authtest.NewFakeUserAuthTokenService()
renderSvc := &fakeRenderService{} renderSvc := &fakeRenderService{}
authJWTSvc := models.NewFakeJWTService() authJWTSvc := models.NewFakeJWTService()
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()

View File

@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/middleware/csrf" "github.com/grafana/grafana/pkg/middleware/csrf"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/oauthtoken"
"github.com/grafana/grafana/pkg/services/querylibrary" "github.com/grafana/grafana/pkg/services/querylibrary"
@ -120,7 +121,7 @@ type HTTPServer struct {
navTreeService navtree.Service navTreeService navtree.Service
CacheService *localcache.CacheService CacheService *localcache.CacheService
DataSourceCache datasources.CacheService DataSourceCache datasources.CacheService
AuthTokenService models.UserTokenService AuthTokenService auth.UserTokenService
QuotaService quota.Service QuotaService quota.Service
RemoteCacheService *remotecache.RemoteCache RemoteCacheService *remotecache.RemoteCache
ProvisioningService provisioning.ProvisioningService ProvisioningService provisioning.ProvisioningService
@ -220,7 +221,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
pluginRequestValidator models.PluginRequestValidator, pluginStaticRouteResolver plugins.StaticRouteResolver, pluginRequestValidator models.PluginRequestValidator, pluginStaticRouteResolver plugins.StaticRouteResolver,
pluginDashboardService plugindashboards.Service, pluginStore plugins.Store, pluginClient plugins.Client, pluginDashboardService plugindashboards.Service, pluginStore plugins.Store, pluginClient plugins.Client,
pluginErrorResolver plugins.ErrorResolver, pluginInstaller plugins.Installer, settingsProvider setting.Provider, pluginErrorResolver plugins.ErrorResolver, pluginInstaller plugins.Installer, settingsProvider setting.Provider,
dataSourceCache datasources.CacheService, userTokenService models.UserTokenService, dataSourceCache datasources.CacheService, userTokenService auth.UserTokenService,
cleanUpService *cleanup.CleanUpService, shortURLService shorturls.Service, queryHistoryService queryhistory.Service, correlationsService correlations.Service, cleanUpService *cleanup.CleanUpService, shortURLService shorturls.Service, queryHistoryService queryhistory.Service, correlationsService correlations.Service,
thumbService thumbs.Service, remoteCache *remotecache.RemoteCache, provisioningService provisioning.ProvisioningService, thumbService thumbs.Service, remoteCache *remotecache.RemoteCache, provisioningService provisioning.ProvisioningService,
loginService login.Service, authenticator loginpkg.Authenticator, accessControl accesscontrol.AccessControl, loginService login.Service, authenticator loginpkg.Authenticator, accessControl accesscontrol.AccessControl,

View File

@ -15,7 +15,7 @@ import (
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/ldap" "github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/login/loginservice" "github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/services/login/logintest" "github.com/grafana/grafana/pkg/services/login/logintest"
@ -379,7 +379,7 @@ func postSyncUserWithLDAPContext(t *testing.T, requestURL string, preHook func(*
hs := &HTTPServer{ hs := &HTTPServer{
Cfg: sc.cfg, Cfg: sc.cfg,
AuthTokenService: auth.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
Login: loginservice.LoginServiceMock{}, Login: loginservice.LoginServiceMock{},
authInfoService: sc.authInfoService, authInfoService: sc.authInfoService,
userService: userService, userService: userService,

View File

@ -16,6 +16,7 @@ import (
"github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/login"
"github.com/grafana/grafana/pkg/middleware/cookies" "github.com/grafana/grafana/pkg/middleware/cookies"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth"
loginService "github.com/grafana/grafana/pkg/services/login" loginService "github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@ -227,7 +228,7 @@ func (hs *HTTPServer) LoginPost(c *models.ReqContext) response.Response {
err = hs.loginUserWithUser(usr, c) err = hs.loginUserWithUser(usr, c)
if err != nil { if err != nil {
var createTokenErr *models.CreateTokenErr var createTokenErr *auth.CreateTokenErr
if errors.As(err, &createTokenErr) { if errors.As(err, &createTokenErr) {
resp = response.Error(createTokenErr.StatusCode, createTokenErr.ExternalErr, createTokenErr.InternalErr) resp = response.Error(createTokenErr.StatusCode, createTokenErr.ExternalErr, createTokenErr.InternalErr)
} else { } else {
@ -299,7 +300,7 @@ func (hs *HTTPServer) Logout(c *models.ReqContext) {
} }
err := hs.AuthTokenService.RevokeToken(c.Req.Context(), c.UserToken, false) err := hs.AuthTokenService.RevokeToken(c.Req.Context(), c.UserToken, false)
if err != nil && !errors.Is(err, models.ErrUserTokenNotFound) { if err != nil && !errors.Is(err, auth.ErrUserTokenNotFound) {
hs.log.Error("failed to revoke auth token", "error", err) hs.log.Error("failed to revoke auth token", "error", err)
} }
@ -370,7 +371,7 @@ func (hs *HTTPServer) samlSingleLogoutEnabled() bool {
} }
func getLoginExternalError(err error) string { func getLoginExternalError(err error) string {
var createTokenErr *models.CreateTokenErr var createTokenErr *auth.CreateTokenErr
if errors.As(err, &createTokenErr) { if errors.As(err, &createTokenErr) {
return createTokenErr.ExternalErr return createTokenErr.ExternalErr
} }

View File

@ -12,8 +12,6 @@ import (
"strings" "strings"
"testing" "testing"
loginservice "github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/navtree"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -25,9 +23,11 @@ import (
"github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/login"
"github.com/grafana/grafana/pkg/login/social" "github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/hooks" "github.com/grafana/grafana/pkg/services/hooks"
"github.com/grafana/grafana/pkg/services/licensing" "github.com/grafana/grafana/pkg/services/licensing"
loginservice "github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/navtree"
"github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/secrets/fakes" "github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -323,7 +323,7 @@ func TestLoginPostRedirect(t *testing.T) {
Cfg: setting.NewCfg(), Cfg: setting.NewCfg(),
HooksService: &hooks.HooksService{}, HooksService: &hooks.HooksService{},
License: &licensing.OSSLicensingService{}, License: &licensing.OSSLicensingService{},
AuthTokenService: auth.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
} }
hs.Cfg.CookieSecure = true hs.Cfg.CookieSecure = true
@ -564,7 +564,7 @@ func setupAuthProxyLoginTest(t *testing.T, enableLoginToken bool) *scenarioConte
Cfg: sc.cfg, Cfg: sc.cfg,
SettingsProvider: &setting.OSSImpl{Cfg: sc.cfg}, SettingsProvider: &setting.OSSImpl{Cfg: sc.cfg},
License: &licensing.OSSLicensingService{}, License: &licensing.OSSLicensingService{},
AuthTokenService: auth.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
log: log.New("hello"), log: log.New("hello"),
SocialService: &mockSocialService{}, SocialService: &mockSocialService{},
} }
@ -602,7 +602,7 @@ func TestLoginPostRunLokingHook(t *testing.T) {
log: log.New("test"), log: log.New("test"),
Cfg: setting.NewCfg(), Cfg: setting.NewCfg(),
License: &licensing.OSSLicensingService{}, License: &licensing.OSSLicensingService{},
AuthTokenService: auth.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
HooksService: hookService, HooksService: hookService,
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
@ -43,7 +44,7 @@ func (hs *HTTPServer) GetUserAuthTokens(c *models.ReqContext) response.Response
// 403: forbiddenError // 403: forbiddenError
// 500: internalServerError // 500: internalServerError
func (hs *HTTPServer) RevokeUserAuthToken(c *models.ReqContext) response.Response { func (hs *HTTPServer) RevokeUserAuthToken(c *models.ReqContext) response.Response {
cmd := models.RevokeAuthTokenCmd{} cmd := auth.RevokeAuthTokenCmd{}
if err := web.Bind(c.Req, &cmd); err != nil { if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err) return response.Error(http.StatusBadRequest, "bad request data", err)
} }
@ -143,7 +144,7 @@ func (hs *HTTPServer) getUserAuthTokensInternal(c *models.ReqContext, userID int
return response.JSON(http.StatusOK, result) return response.JSON(http.StatusOK, result)
} }
func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID int64, cmd models.RevokeAuthTokenCmd) response.Response { func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID int64, cmd auth.RevokeAuthTokenCmd) response.Response {
userQuery := user.GetUserByIDQuery{ID: userID} userQuery := user.GetUserByIDQuery{ID: userID}
_, err := hs.userService.GetByID(c.Req.Context(), &userQuery) _, err := hs.userService.GetByID(c.Req.Context(), &userQuery)
if err != nil { if err != nil {
@ -155,7 +156,7 @@ func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID i
token, err := hs.AuthTokenService.GetUserToken(c.Req.Context(), userID, cmd.AuthTokenId) token, err := hs.AuthTokenService.GetUserToken(c.Req.Context(), userID, cmd.AuthTokenId)
if err != nil { if err != nil {
if errors.Is(err, models.ErrUserTokenNotFound) { if errors.Is(err, auth.ErrUserTokenNotFound) {
return response.Error(404, "User auth token not found", err) return response.Error(404, "User auth token not found", err)
} }
return response.Error(500, "Failed to get user auth token", err) return response.Error(500, "Failed to get user auth token", err)
@ -167,7 +168,7 @@ func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID i
err = hs.AuthTokenService.RevokeToken(c.Req.Context(), token, false) err = hs.AuthTokenService.RevokeToken(c.Req.Context(), token, false)
if err != nil { if err != nil {
if errors.Is(err, models.ErrUserTokenNotFound) { if errors.Is(err, auth.ErrUserTokenNotFound) {
return response.Error(404, "User auth token not found", err) return response.Error(404, "User auth token not found", err)
} }
return response.Error(500, "Failed to revoke user auth token", err) return response.Error(500, "Failed to revoke user auth token", err)
@ -182,11 +183,11 @@ func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID i
type RevokeUserAuthTokenParams struct { type RevokeUserAuthTokenParams struct {
// in:body // in:body
// required:true // required:true
Body models.RevokeAuthTokenCmd `json:"body"` Body auth.RevokeAuthTokenCmd `json:"body"`
} }
// swagger:response getUserAuthTokensResponse // swagger:response getUserAuthTokensResponse
type GetUserAuthTokensResponse struct { type GetUserAuthTokensResponse struct {
// in:body // in:body
Body []*models.UserToken `json:"body"` Body []*auth.UserToken `json:"body"`
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/services/user/usertest"
@ -20,7 +21,7 @@ import (
func TestUserTokenAPIEndpoint(t *testing.T) { func TestUserTokenAPIEndpoint(t *testing.T) {
userMock := usertest.NewUserServiceFake() userMock := usertest.NewUserServiceFake()
t.Run("When current user attempts to revoke an auth token for a non-existing user", func(t *testing.T) { t.Run("When current user attempts to revoke an auth token for a non-existing user", func(t *testing.T) {
cmd := models.RevokeAuthTokenCmd{AuthTokenId: 2} cmd := auth.RevokeAuthTokenCmd{AuthTokenId: 2}
userMock.ExpectedError = user.ErrUserNotFound userMock.ExpectedError = user.ErrUserNotFound
revokeUserAuthTokenScenario(t, "Should return not found when calling POST on", "/api/user/revoke-auth-token", revokeUserAuthTokenScenario(t, "Should return not found when calling POST on", "/api/user/revoke-auth-token",
"/api/user/revoke-auth-token", cmd, 200, func(sc *scenarioContext) { "/api/user/revoke-auth-token", cmd, 200, func(sc *scenarioContext) {
@ -59,15 +60,15 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
}) })
t.Run("When revoke an auth token for a user", func(t *testing.T) { t.Run("When revoke an auth token for a user", func(t *testing.T) {
cmd := models.RevokeAuthTokenCmd{AuthTokenId: 2} cmd := auth.RevokeAuthTokenCmd{AuthTokenId: 2}
token := &models.UserToken{Id: 1} token := &auth.UserToken{Id: 1}
mockUser := &usertest.FakeUserService{ mockUser := &usertest.FakeUserService{
ExpectedUser: &user.User{ID: 200}, ExpectedUser: &user.User{ID: 200},
} }
revokeUserAuthTokenInternalScenario(t, "Should be successful", cmd, 200, token, func(sc *scenarioContext) { revokeUserAuthTokenInternalScenario(t, "Should be successful", cmd, 200, token, func(sc *scenarioContext) {
sc.userAuthTokenService.GetUserTokenProvider = func(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error) { sc.userAuthTokenService.GetUserTokenProvider = func(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error) {
return &models.UserToken{Id: 2}, nil return &auth.UserToken{Id: 2}, nil
} }
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec() sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
assert.Equal(t, 200, sc.resp.Code) assert.Equal(t, 200, sc.resp.Code)
@ -75,11 +76,11 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
}) })
t.Run("When revoke the active auth token used by himself", func(t *testing.T) { t.Run("When revoke the active auth token used by himself", func(t *testing.T) {
cmd := models.RevokeAuthTokenCmd{AuthTokenId: 2} cmd := auth.RevokeAuthTokenCmd{AuthTokenId: 2}
token := &models.UserToken{Id: 2} token := &auth.UserToken{Id: 2}
mockUser := usertest.NewUserServiceFake() mockUser := usertest.NewUserServiceFake()
revokeUserAuthTokenInternalScenario(t, "Should not be successful", cmd, testUserID, token, func(sc *scenarioContext) { revokeUserAuthTokenInternalScenario(t, "Should not be successful", cmd, testUserID, token, func(sc *scenarioContext) {
sc.userAuthTokenService.GetUserTokenProvider = func(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error) { sc.userAuthTokenService.GetUserTokenProvider = func(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error) {
return token, nil return token, nil
} }
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec() sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
@ -88,10 +89,10 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
}) })
t.Run("When gets auth tokens for a user", func(t *testing.T) { t.Run("When gets auth tokens for a user", func(t *testing.T) {
currentToken := &models.UserToken{Id: 1} currentToken := &auth.UserToken{Id: 1}
mockUser := usertest.NewUserServiceFake() mockUser := usertest.NewUserServiceFake()
getUserAuthTokensInternalScenario(t, "Should be successful", currentToken, func(sc *scenarioContext) { getUserAuthTokensInternalScenario(t, "Should be successful", currentToken, func(sc *scenarioContext) {
tokens := []*models.UserToken{ tokens := []*auth.UserToken{
{ {
Id: 1, Id: 1,
ClientIp: "127.0.0.1", ClientIp: "127.0.0.1",
@ -107,7 +108,7 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
SeenAt: 0, SeenAt: 0,
}, },
} }
sc.userAuthTokenService.GetUserTokensProvider = func(ctx context.Context, userId int64) ([]*models.UserToken, error) { sc.userAuthTokenService.GetUserTokensProvider = func(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
return tokens, nil return tokens, nil
} }
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
@ -145,10 +146,10 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
}) })
} }
func revokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePattern string, cmd models.RevokeAuthTokenCmd, func revokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePattern string, cmd auth.RevokeAuthTokenCmd,
userId int64, fn scenarioFunc, userService user.Service) { userId int64, fn scenarioFunc, userService user.Service) {
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: fakeAuthTokenService, AuthTokenService: fakeAuthTokenService,
@ -175,7 +176,7 @@ func revokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePat
func getUserAuthTokensScenario(t *testing.T, desc string, url string, routePattern string, userId int64, fn scenarioFunc, userService user.Service) { func getUserAuthTokensScenario(t *testing.T, desc string, url string, routePattern string, userId int64, fn scenarioFunc, userService user.Service) {
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: fakeAuthTokenService, AuthTokenService: fakeAuthTokenService,
@ -202,7 +203,7 @@ func getUserAuthTokensScenario(t *testing.T, desc string, url string, routePatte
func logoutUserFromAllDevicesInternalScenario(t *testing.T, desc string, userId int64, fn scenarioFunc, userService user.Service) { func logoutUserFromAllDevicesInternalScenario(t *testing.T, desc string, userId int64, fn scenarioFunc, userService user.Service) {
t.Run(desc, func(t *testing.T) { t.Run(desc, func(t *testing.T) {
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: auth.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
userService: userService, userService: userService,
} }
@ -222,10 +223,10 @@ func logoutUserFromAllDevicesInternalScenario(t *testing.T, desc string, userId
}) })
} }
func revokeUserAuthTokenInternalScenario(t *testing.T, desc string, cmd models.RevokeAuthTokenCmd, userId int64, func revokeUserAuthTokenInternalScenario(t *testing.T, desc string, cmd auth.RevokeAuthTokenCmd, userId int64,
token *models.UserToken, fn scenarioFunc, userService user.Service) { token *auth.UserToken, fn scenarioFunc, userService user.Service) {
t.Run(desc, func(t *testing.T) { t.Run(desc, func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: fakeAuthTokenService, AuthTokenService: fakeAuthTokenService,
@ -248,9 +249,9 @@ func revokeUserAuthTokenInternalScenario(t *testing.T, desc string, cmd models.R
}) })
} }
func getUserAuthTokensInternalScenario(t *testing.T, desc string, token *models.UserToken, fn scenarioFunc, userService user.Service) { func getUserAuthTokensInternalScenario(t *testing.T, desc string, token *auth.UserToken, fn scenarioFunc, userService user.Service) {
t.Run(desc, func(t *testing.T) { t.Run(desc, func(t *testing.T) {
fakeAuthTokenService := auth.NewFakeUserAuthTokenService() fakeAuthTokenService := authtest.NewFakeUserAuthTokenService()
hs := HTTPServer{ hs := HTTPServer{
AuthTokenService: fakeAuthTokenService, AuthTokenService: fakeAuthTokenService,

View File

@ -7,6 +7,7 @@ import (
"context" "context"
"github.com/google/wire" "github.com/google/wire"
"github.com/grafana/grafana/pkg/services/auth/authimpl"
"github.com/grafana/grafana/pkg/tsdb/parca" "github.com/grafana/grafana/pkg/tsdb/parca"
"github.com/grafana/grafana/pkg/tsdb/phlare" "github.com/grafana/grafana/pkg/tsdb/phlare"
@ -253,8 +254,8 @@ var wireSet = wire.NewSet(
influxdb.ProvideService, influxdb.ProvideService,
wire.Bind(new(social.Service), new(*social.SocialService)), wire.Bind(new(social.Service), new(*social.SocialService)),
oauthtoken.ProvideService, oauthtoken.ProvideService,
auth.ProvideActiveAuthTokenService, authimpl.ProvideActiveAuthTokenService,
wire.Bind(new(auth.ActiveTokenService), new(*auth.ActiveAuthTokenService)), wire.Bind(new(auth.ActiveTokenService), new(*authimpl.ActiveAuthTokenService)),
wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)),
tempo.ProvideService, tempo.ProvideService,
loki.ProvideService, loki.ProvideService,

View File

@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl" "github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authimpl"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions" "github.com/grafana/grafana/pkg/services/datasources/permissions"
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service" datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
@ -48,9 +49,9 @@ var wireExtsSet = wire.NewSet(
wire.Bind(new(setting.Provider), new(*setting.OSSImpl)), wire.Bind(new(setting.Provider), new(*setting.OSSImpl)),
osskmsproviders.ProvideService, osskmsproviders.ProvideService,
wire.Bind(new(kmsproviders.Service), new(osskmsproviders.Service)), wire.Bind(new(kmsproviders.Service), new(osskmsproviders.Service)),
auth.ProvideUserAuthTokenService, authimpl.ProvideUserAuthTokenService,
wire.Bind(new(models.UserTokenService), new(*auth.UserAuthTokenService)), wire.Bind(new(auth.UserTokenService), new(*authimpl.UserAuthTokenService)),
wire.Bind(new(models.UserTokenBackgroundService), new(*auth.UserAuthTokenService)), wire.Bind(new(auth.UserTokenBackgroundService), new(*authimpl.UserAuthTokenService)),
acimpl.ProvideService, acimpl.ProvideService,
wire.Bind(new(accesscontrol.Service), new(*acimpl.Service)), wire.Bind(new(accesscontrol.Service), new(*acimpl.Service)),
wire.Bind(new(accesscontrol.RoleRegistry), new(*acimpl.Service)), wire.Bind(new(accesscontrol.RoleRegistry), new(*acimpl.Service)),

View File

@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/middleware/cookies" "github.com/grafana/grafana/pkg/middleware/cookies"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/team" "github.com/grafana/grafana/pkg/services/team"
@ -42,7 +43,7 @@ func notAuthorized(c *models.ReqContext) {
c.Redirect(setting.AppSubUrl + "/login") c.Redirect(setting.AppSubUrl + "/login")
} }
func tokenRevoked(c *models.ReqContext, err *models.TokenRevokedError) { func tokenRevoked(c *models.ReqContext, err *auth.TokenRevokedError) {
if c.IsApiRequest() { if c.IsApiRequest() {
c.JSON(401, map[string]interface{}{ c.JSON(401, map[string]interface{}{
"message": "Token revoked", "message": "Token revoked",
@ -117,7 +118,7 @@ func Auth(options *AuthOptions) web.Handler {
requireLogin := !c.AllowAnonymous || forceLogin || options.ReqNoAnonynmous requireLogin := !c.AllowAnonymous || forceLogin || options.ReqNoAnonynmous
if !c.IsSignedIn && options.ReqSignedIn && requireLogin { if !c.IsSignedIn && options.ReqSignedIn && requireLogin {
var revokedErr *models.TokenRevokedError var revokedErr *auth.TokenRevokedError
if errors.As(c.LookupTokenErr, &revokedErr) { if errors.As(c.LookupTokenErr, &revokedErr) {
tokenRevoked(c, revokedErr) tokenRevoked(c, revokedErr)
return return

View File

@ -28,6 +28,7 @@ import (
"github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/apikey/apikeytest" "github.com/grafana/grafana/pkg/services/apikey/apikeytest"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/contexthandler/authproxy" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
@ -264,8 +265,8 @@ func TestMiddlewareContext(t *testing.T) {
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: userID, UserId: userID,
UnhashedToken: unhashedToken, UnhashedToken: unhashedToken,
}, nil }, nil
@ -288,14 +289,14 @@ func TestMiddlewareContext(t *testing.T) {
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: userID, UserId: userID,
UnhashedToken: "", UnhashedToken: "",
}, nil }, nil
} }
sc.userAuthTokenService.TryRotateTokenProvider = func(ctx context.Context, userToken *models.UserToken, sc.userAuthTokenService.TryRotateTokenProvider = func(ctx context.Context, userToken *auth.UserToken,
clientIP net.IP, userAgent string) (bool, error) { clientIP net.IP, userAgent string) (bool, error) {
userToken.UnhashedToken = "rotated" userToken.UnhashedToken = "rotated"
return true, nil return true, nil
@ -371,8 +372,8 @@ func TestMiddlewareContext(t *testing.T) {
middlewareScenario(t, "Invalid/expired auth token in cookie", func(t *testing.T, sc *scenarioContext) { middlewareScenario(t, "Invalid/expired auth token in cookie", func(t *testing.T, sc *scenarioContext) {
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return nil, models.ErrUserTokenNotFound return nil, auth.ErrUserTokenNotFound
} }
sc.fakeReq("GET", "/").exec() sc.fakeReq("GET", "/").exec()
@ -391,8 +392,8 @@ func TestMiddlewareContext(t *testing.T) {
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.oauthTokenService.ExpectedAuthUser = &models.UserAuth{UserId: userID, OAuthExpiry: fakeGetTime()().Add(11 * time.Second)} sc.oauthTokenService.ExpectedAuthUser = &models.UserAuth{UserId: userID, OAuthExpiry: fakeGetTime()().Add(11 * time.Second)}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: userID, UserId: userID,
UnhashedToken: unhashedToken, UnhashedToken: unhashedToken,
}, nil }, nil
@ -424,8 +425,8 @@ func TestMiddlewareContext(t *testing.T) {
OAuthRefreshToken: "refresh_token"} OAuthRefreshToken: "refresh_token"}
sc.oauthTokenService.ExpectedErrors = map[string]error{"TryTokenRefresh": errors.New("error")} sc.oauthTokenService.ExpectedErrors = map[string]error{"TryTokenRefresh": errors.New("error")}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: userID, UserId: userID,
UnhashedToken: unhashedToken, UnhashedToken: unhashedToken,
}, nil }, nil
@ -454,8 +455,8 @@ func TestMiddlewareContext(t *testing.T) {
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.oauthTokenService.ExpectedAuthUser = &models.UserAuth{UserId: userID, OAuthExpiry: fakeGetTime()().Add(-5 * time.Second), OAuthRefreshToken: "refreshtoken"} sc.oauthTokenService.ExpectedAuthUser = &models.UserAuth{UserId: userID, OAuthExpiry: fakeGetTime()().Add(-5 * time.Second), OAuthRefreshToken: "refreshtoken"}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: userID, UserId: userID,
UnhashedToken: unhashedToken, UnhashedToken: unhashedToken,
}, nil }, nil
@ -481,8 +482,8 @@ func TestMiddlewareContext(t *testing.T) {
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.oauthTokenService.ExpectedAuthUser = &models.UserAuth{UserId: userID} sc.oauthTokenService.ExpectedAuthUser = &models.UserAuth{UserId: userID}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: userID, UserId: userID,
UnhashedToken: unhashedToken, UnhashedToken: unhashedToken,
}, nil }, nil
@ -819,14 +820,14 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
sc.userService = usertest.NewUserServiceFake() sc.userService = usertest.NewUserServiceFake()
sc.orgService = orgtest.NewOrgServiceFake() sc.orgService = orgtest.NewOrgServiceFake()
sc.apiKeyService = &apikeytest.Service{} sc.apiKeyService = &apikeytest.Service{}
sc.oauthTokenService = &auth.FakeOAuthTokenService{} sc.oauthTokenService = &authtest.FakeOAuthTokenService{}
ctxHdlr := getContextHandler(t, cfg, sc.mockSQLStore, sc.loginService, sc.apiKeyService, sc.userService, sc.orgService, sc.oauthTokenService) ctxHdlr := getContextHandler(t, cfg, sc.mockSQLStore, sc.loginService, sc.apiKeyService, sc.userService, sc.orgService, sc.oauthTokenService)
sc.sqlStore = ctxHdlr.SQLStore sc.sqlStore = ctxHdlr.SQLStore
sc.contextHandler = ctxHdlr sc.contextHandler = ctxHdlr
sc.m.Use(ctxHdlr.Middleware) sc.m.Use(ctxHdlr.Middleware)
sc.m.Use(OrgRedirect(sc.cfg, sc.userService)) sc.m.Use(OrgRedirect(sc.cfg, sc.userService))
sc.userAuthTokenService = ctxHdlr.AuthTokenService.(*auth.FakeUserAuthTokenService) sc.userAuthTokenService = ctxHdlr.AuthTokenService.(*authtest.FakeUserAuthTokenService)
sc.jwtAuthService = ctxHdlr.JWTAuthService.(*models.FakeJWTService) sc.jwtAuthService = ctxHdlr.JWTAuthService.(*models.FakeJWTService)
sc.remoteCacheService = ctxHdlr.RemoteCache sc.remoteCacheService = ctxHdlr.RemoteCache
@ -856,7 +857,7 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *dbtest.FakeDB, func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *dbtest.FakeDB,
loginService *loginservice.LoginServiceMock, apiKeyService *apikeytest.Service, loginService *loginservice.LoginServiceMock, apiKeyService *apikeytest.Service,
userService *usertest.FakeUserService, orgService *orgtest.FakeOrgService, userService *usertest.FakeUserService, orgService *orgtest.FakeOrgService,
oauthTokenService *auth.FakeOAuthTokenService, oauthTokenService *authtest.FakeOAuthTokenService,
) *contexthandler.ContextHandler { ) *contexthandler.ContextHandler {
t.Helper() t.Helper()
@ -868,7 +869,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *dbtest.Fake
} }
remoteCacheSvc := remotecache.NewFakeStore(t) remoteCacheSvc := remotecache.NewFakeStore(t)
userAuthTokenSvc := auth.NewFakeUserAuthTokenService() userAuthTokenSvc := authtest.NewFakeUserAuthTokenService()
renderSvc := &fakeRenderService{} renderSvc := &fakeRenderService{}
authJWTSvc := models.NewFakeJWTService() authJWTSvc := models.NewFakeJWTService()
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()

View File

@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
) )
@ -48,8 +48,8 @@ func TestOrgRedirectMiddleware(t *testing.T) {
middlewareScenario(t, tc.desc, func(t *testing.T, sc *scenarioContext) { middlewareScenario(t, tc.desc, func(t *testing.T, sc *scenarioContext) {
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 1, UserID: 12} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 1, UserID: 12}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: 0, UserId: 0,
UnhashedToken: "", UnhashedToken: "",
}, nil }, nil
@ -68,8 +68,8 @@ func TestOrgRedirectMiddleware(t *testing.T) {
sc.userService.ExpectedSetUsingOrgError = fmt.Errorf("") sc.userService.ExpectedSetUsingOrgError = fmt.Errorf("")
sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 1, UserID: 12} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 1, UserID: 12}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: 12, UserId: 12,
UnhashedToken: "", UnhashedToken: "",
}, nil }, nil

View File

@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -55,8 +55,8 @@ func TestMiddlewareQuota(t *testing.T) {
setUp := func(sc *scenarioContext) { setUp := func(sc *scenarioContext) {
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: 12} sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: 12}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: 12, UserId: 12,
UnhashedToken: "", UnhashedToken: "",
}, nil }, nil

View File

@ -10,7 +10,7 @@ import (
"github.com/grafana/grafana/pkg/infra/remotecache" "github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
@ -65,7 +65,7 @@ func recoveryScenario(t *testing.T, desc string, url string, fn scenarioFunc) {
sc.m.Use(AddDefaultResponseHeaders(cfg)) sc.m.Use(AddDefaultResponseHeaders(cfg))
sc.m.UseMiddleware(web.Renderer(viewsPath, "[[", "]]")) sc.m.UseMiddleware(web.Renderer(viewsPath, "[[", "]]"))
sc.userAuthTokenService = auth.NewFakeUserAuthTokenService() sc.userAuthTokenService = authtest.NewFakeUserAuthTokenService()
sc.remoteCacheService = remotecache.NewFakeStore(t) sc.remoteCacheService = remotecache.NewFakeStore(t)
contextHandler := getContextHandler(t, nil, nil, nil, nil, nil, nil, nil) contextHandler := getContextHandler(t, nil, nil, nil, nil, nil, nil, nil)

View File

@ -13,7 +13,7 @@ import (
"github.com/grafana/grafana/pkg/infra/remotecache" "github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/apikey/apikeytest" "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/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
"github.com/grafana/grafana/pkg/services/login/loginservice" "github.com/grafana/grafana/pkg/services/login/loginservice"
@ -36,7 +36,7 @@ type scenarioContext struct {
handlerFunc handlerFunc handlerFunc handlerFunc
defaultHandler web.Handler defaultHandler web.Handler
url string url string
userAuthTokenService *auth.FakeUserAuthTokenService userAuthTokenService *authtest.FakeUserAuthTokenService
jwtAuthService *models.FakeJWTService jwtAuthService *models.FakeJWTService
remoteCacheService *remotecache.RemoteCache remoteCacheService *remotecache.RemoteCache
cfg *setting.Cfg cfg *setting.Cfg
@ -46,7 +46,7 @@ type scenarioContext struct {
loginService *loginservice.LoginServiceMock loginService *loginservice.LoginServiceMock
apiKeyService *apikeytest.Service apiKeyService *apikeytest.Service
userService *usertest.FakeUserService userService *usertest.FakeUserService
oauthTokenService *auth.FakeOAuthTokenService oauthTokenService *authtest.FakeOAuthTokenService
orgService *orgtest.FakeOrgService orgService *orgtest.FakeOrgService
req *http.Request req *http.Request

View File

@ -5,6 +5,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -15,7 +16,7 @@ import (
type ReqContext struct { type ReqContext struct {
*web.Context *web.Context
*user.SignedInUser *user.SignedInUser
UserToken *UserToken UserToken *usertoken.UserToken
IsSignedIn bool IsSignedIn bool
IsRenderCall bool IsRenderCall bool

View File

@ -0,0 +1,26 @@
package usertoken
type TokenRevokedError struct {
UserID int64
TokenID int64
MaxConcurrentSessions int64
}
func (e *TokenRevokedError) Error() string { return "user token revoked" }
// UserToken represents a user token
type UserToken struct {
Id int64
UserId int64
AuthToken string
PrevAuthToken string
UserAgent string
ClientIp string
AuthTokenSeen bool
SeenAt int64
RotatedAt int64
CreatedAt int64
UpdatedAt int64
RevokedAt int64
UnhashedToken string
}

View File

@ -7,10 +7,10 @@ import (
"github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/tracing"
uss "github.com/grafana/grafana/pkg/infra/usagestats/service" uss "github.com/grafana/grafana/pkg/infra/usagestats/service"
"github.com/grafana/grafana/pkg/infra/usagestats/statscollector" "github.com/grafana/grafana/pkg/infra/usagestats/statscollector"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins/manager/process" "github.com/grafana/grafana/pkg/plugins/manager/process"
"github.com/grafana/grafana/pkg/registry" "github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/cleanup" "github.com/grafana/grafana/pkg/services/cleanup"
"github.com/grafana/grafana/pkg/services/dashboardsnapshots" "github.com/grafana/grafana/pkg/services/dashboardsnapshots"
"github.com/grafana/grafana/pkg/services/grpcserver" "github.com/grafana/grafana/pkg/services/grpcserver"
@ -38,7 +38,7 @@ import (
func ProvideBackgroundServiceRegistry( func ProvideBackgroundServiceRegistry(
httpServer *api.HTTPServer, ng *ngalert.AlertNG, cleanup *cleanup.CleanUpService, live *live.GrafanaLive, httpServer *api.HTTPServer, ng *ngalert.AlertNG, cleanup *cleanup.CleanUpService, live *live.GrafanaLive,
pushGateway *pushhttp.Gateway, notifications *notifications.NotificationService, processManager *process.Manager, pushGateway *pushhttp.Gateway, notifications *notifications.NotificationService, processManager *process.Manager,
rendering *rendering.RenderingService, tokenService models.UserTokenBackgroundService, tracing tracing.Tracer, rendering *rendering.RenderingService, tokenService auth.UserTokenBackgroundService, tracing tracing.Tracer,
provisioning *provisioning.ProvisioningServiceImpl, alerting *alerting.AlertEngine, usageStats *uss.UsageStats, provisioning *provisioning.ProvisioningServiceImpl, alerting *alerting.AlertEngine, usageStats *uss.UsageStats,
statsCollector *statscollector.Service, grafanaUpdateChecker *updatechecker.GrafanaService, statsCollector *statscollector.Service, grafanaUpdateChecker *updatechecker.GrafanaService,
pluginsUpdateChecker *updatechecker.PluginsService, metrics *metrics.InternalMetricsService, pluginsUpdateChecker *updatechecker.PluginsService, metrics *metrics.InternalMetricsService,

View File

@ -49,6 +49,7 @@ import (
"github.com/grafana/grafana/pkg/services/annotations/annotationsimpl" "github.com/grafana/grafana/pkg/services/annotations/annotationsimpl"
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl" "github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authimpl"
"github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/auth/jwt"
"github.com/grafana/grafana/pkg/services/cleanup" "github.com/grafana/grafana/pkg/services/cleanup"
"github.com/grafana/grafana/pkg/services/comments" "github.com/grafana/grafana/pkg/services/comments"
@ -271,8 +272,8 @@ var wireBasicSet = wire.NewSet(
influxdb.ProvideService, influxdb.ProvideService,
wire.Bind(new(social.Service), new(*social.SocialService)), wire.Bind(new(social.Service), new(*social.SocialService)),
oauthtoken.ProvideService, oauthtoken.ProvideService,
auth.ProvideActiveAuthTokenService, authimpl.ProvideActiveAuthTokenService,
wire.Bind(new(auth.ActiveTokenService), new(*auth.ActiveAuthTokenService)), wire.Bind(new(auth.ActiveTokenService), new(*authimpl.ActiveAuthTokenService)),
wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)),
tempo.ProvideService, tempo.ProvideService,
loki.ProvideService, loki.ProvideService,

View File

@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl" "github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authimpl"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions" "github.com/grafana/grafana/pkg/services/datasources/permissions"
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service" datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
@ -39,9 +40,9 @@ import (
) )
var wireExtsBasicSet = wire.NewSet( var wireExtsBasicSet = wire.NewSet(
auth.ProvideUserAuthTokenService, authimpl.ProvideUserAuthTokenService,
wire.Bind(new(models.UserTokenService), new(*auth.UserAuthTokenService)), wire.Bind(new(auth.UserTokenService), new(*authimpl.UserAuthTokenService)),
wire.Bind(new(models.UserTokenBackgroundService), new(*auth.UserAuthTokenService)), wire.Bind(new(auth.UserTokenBackgroundService), new(*authimpl.UserAuthTokenService)),
licensing.ProvideService, licensing.ProvideService,
wire.Bind(new(models.Licensing), new(*licensing.OSSLicensingService)), wire.Bind(new(models.Licensing), new(*licensing.OSSLicensingService)),
setting.ProvideProvider, setting.ProvideProvider,

View File

@ -14,8 +14,8 @@ import (
"time" "time"
"github.com/grafana/grafana/pkg/middleware/cookies" "github.com/grafana/grafana/pkg/middleware/cookies"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
@ -41,7 +41,7 @@ func Middleware(ac AccessControl) func(web.Handler, Evaluator) web.Handler {
} }
} }
var revokedErr *models.TokenRevokedError var revokedErr *usertoken.TokenRevokedError
if errors.As(c.LookupTokenErr, &revokedErr) { if errors.As(c.LookupTokenErr, &revokedErr) {
unauthorized(c, revokedErr) unauthorized(c, revokedErr)
return return
@ -111,7 +111,7 @@ func unauthorized(c *models.ReqContext, err error) {
"message": "Unauthorized", "message": "Unauthorized",
} }
var revokedErr *models.TokenRevokedError var revokedErr *usertoken.TokenRevokedError
if errors.As(err, &revokedErr) { if errors.As(err, &revokedErr) {
response["message"] = "Token revoked" response["message"] = "Token revoked"
response["error"] = map[string]interface{}{ response["error"] = map[string]interface{}{

View File

@ -1,19 +1,32 @@
package models package auth
import ( import (
"context" "context"
"errors" "errors"
"net" "net"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/registry" "github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
) )
const (
QuotaTargetSrv quota.TargetSrv = "auth"
QuotaTarget quota.Target = "session"
)
type ActiveTokenService interface {
ActiveTokenCount(ctx context.Context, _ *quota.ScopeParameters) (*quota.Map, error)
}
// Typed errors // Typed errors
var ( var (
ErrUserTokenNotFound = errors.New("user token not found") ErrUserTokenNotFound = errors.New("user token not found")
) )
type TokenRevokedError = usertoken.TokenRevokedError
// CreateTokenErr represents a token creation error; used in Enterprise // CreateTokenErr represents a token creation error; used in Enterprise
type CreateTokenErr struct { type CreateTokenErr struct {
StatusCode int StatusCode int
@ -35,30 +48,7 @@ type TokenExpiredError struct {
func (e *TokenExpiredError) Error() string { return "user token expired" } func (e *TokenExpiredError) Error() string { return "user token expired" }
type TokenRevokedError struct { type UserToken = usertoken.UserToken
UserID int64
TokenID int64
MaxConcurrentSessions int64
}
func (e *TokenRevokedError) Error() string { return "user token revoked" }
// UserToken represents a user token
type UserToken struct {
Id int64
UserId int64
AuthToken string
PrevAuthToken string
UserAgent string
ClientIp string
AuthTokenSeen bool
SeenAt int64
RotatedAt int64
CreatedAt int64
UpdatedAt int64
RevokedAt int64
UnhashedToken string
}
type RevokeAuthTokenCmd struct { type RevokeAuthTokenCmd struct {
AuthTokenId int64 `json:"authTokenId"` AuthTokenId int64 `json:"authTokenId"`

View File

@ -1,4 +1,4 @@
package auth package authimpl
import ( import (
"context" "context"
@ -11,7 +11,7 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/serverlock" "github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -42,10 +42,6 @@ type UserAuthTokenService struct {
log log.Logger log log.Logger
} }
type ActiveTokenService interface {
ActiveTokenCount(ctx context.Context, _ *quota.ScopeParameters) (*quota.Map, error)
}
type ActiveAuthTokenService struct { type ActiveAuthTokenService struct {
cfg *setting.Cfg cfg *setting.Cfg
sqlStore db.DB sqlStore db.DB
@ -63,7 +59,7 @@ func ProvideActiveAuthTokenService(cfg *setting.Cfg, sqlStore db.DB, quotaServic
} }
if err := quotaService.RegisterQuotaReporter(&quota.NewUsageReporter{ if err := quotaService.RegisterQuotaReporter(&quota.NewUsageReporter{
TargetSrv: QuotaTargetSrv, TargetSrv: auth.QuotaTargetSrv,
DefaultLimits: defaultLimits, DefaultLimits: defaultLimits,
Reporter: s.ActiveTokenCount, Reporter: s.ActiveTokenCount,
}); err != nil { }); err != nil {
@ -86,7 +82,7 @@ func (a *ActiveAuthTokenService) ActiveTokenCount(ctx context.Context, _ *quota.
return err return err
}) })
tag, err := quota.NewTag(QuotaTargetSrv, QuotaTarget, quota.GlobalScope) tag, err := quota.NewTag(auth.QuotaTargetSrv, auth.QuotaTarget, quota.GlobalScope)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -96,7 +92,7 @@ func (a *ActiveAuthTokenService) ActiveTokenCount(ctx context.Context, _ *quota.
return u, err return u, err
} }
func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) { func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*auth.UserToken, error) {
token, err := util.RandomHex(16) token, err := util.RandomHex(16)
if err != nil { if err != nil {
return nil, err return nil, err
@ -138,13 +134,13 @@ func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *user.User,
ctxLogger := s.log.FromContext(ctx) ctxLogger := s.log.FromContext(ctx)
ctxLogger.Debug("user auth token created", "tokenId", userAuthToken.Id, "userId", userAuthToken.UserId, "clientIP", userAuthToken.ClientIp, "userAgent", userAuthToken.UserAgent, "authToken", userAuthToken.AuthToken) ctxLogger.Debug("user auth token created", "tokenId", userAuthToken.Id, "userId", userAuthToken.UserId, "clientIP", userAuthToken.ClientIp, "userAgent", userAuthToken.UserAgent, "authToken", userAuthToken.AuthToken)
var userToken models.UserToken var userToken auth.UserToken
err = userAuthToken.toUserToken(&userToken) err = userAuthToken.toUserToken(&userToken)
return &userToken, err return &userToken, err
} }
func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken string) (*models.UserToken, error) { func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
hashedToken := hashToken(unhashedToken) hashedToken := hashToken(unhashedToken)
var model userAuthToken var model userAuthToken
var exists bool var exists bool
@ -162,14 +158,14 @@ func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken st
} }
if !exists { if !exists {
return nil, models.ErrUserTokenNotFound return nil, auth.ErrUserTokenNotFound
} }
ctxLogger := s.log.FromContext(ctx) ctxLogger := s.log.FromContext(ctx)
if model.RevokedAt > 0 { if model.RevokedAt > 0 {
ctxLogger.Debug("user token has been revoked", "user ID", model.UserId, "token ID", model.Id) ctxLogger.Debug("user token has been revoked", "user ID", model.UserId, "token ID", model.Id)
return nil, &models.TokenRevokedError{ return nil, &auth.TokenRevokedError{
UserID: model.UserId, UserID: model.UserId,
TokenID: model.Id, TokenID: model.Id,
} }
@ -177,7 +173,7 @@ func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken st
if model.CreatedAt <= s.createdAfterParam() || model.RotatedAt <= s.rotatedAfterParam() { if model.CreatedAt <= s.createdAfterParam() || model.RotatedAt <= s.rotatedAfterParam() {
ctxLogger.Debug("user token has expired", "user ID", model.UserId, "token ID", model.Id) ctxLogger.Debug("user token has expired", "user ID", model.UserId, "token ID", model.Id)
return nil, &models.TokenExpiredError{ return nil, &auth.TokenExpiredError{
UserID: model.UserId, UserID: model.UserId,
TokenID: model.Id, TokenID: model.Id,
} }
@ -242,13 +238,13 @@ func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken st
model.UnhashedToken = unhashedToken model.UnhashedToken = unhashedToken
var userToken models.UserToken var userToken auth.UserToken
err = model.toUserToken(&userToken) err = model.toUserToken(&userToken)
return &userToken, err return &userToken, err
} }
func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *models.UserToken, func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *auth.UserToken,
clientIP net.IP, userAgent string) (bool, error) { clientIP net.IP, userAgent string) (bool, error) {
if token == nil { if token == nil {
return false, nil return false, nil
@ -328,9 +324,9 @@ func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *models
return false, nil return false, nil
} }
func (s *UserAuthTokenService) RevokeToken(ctx context.Context, token *models.UserToken, soft bool) error { func (s *UserAuthTokenService) RevokeToken(ctx context.Context, token *auth.UserToken, soft bool) error {
if token == nil { if token == nil {
return models.ErrUserTokenNotFound return auth.ErrUserTokenNotFound
} }
model, err := userAuthTokenFromUserToken(token) model, err := userAuthTokenFromUserToken(token)
@ -361,7 +357,7 @@ func (s *UserAuthTokenService) RevokeToken(ctx context.Context, token *models.Us
if rowsAffected == 0 { if rowsAffected == 0 {
ctxLogger.Debug("user auth token not found/revoked", "tokenId", model.Id, "userId", model.UserId, "clientIP", model.ClientIp, "userAgent", model.UserAgent) ctxLogger.Debug("user auth token not found/revoked", "tokenId", model.Id, "userId", model.UserId, "clientIP", model.ClientIp, "userAgent", model.UserAgent)
return models.ErrUserTokenNotFound return auth.ErrUserTokenNotFound
} }
ctxLogger.Debug("user auth token revoked", "tokenId", model.Id, "userId", model.UserId, "clientIP", model.ClientIp, "userAgent", model.UserAgent, "soft", soft) ctxLogger.Debug("user auth token revoked", "tokenId", model.Id, "userId", model.UserId, "clientIP", model.ClientIp, "userAgent", model.UserAgent, "soft", soft)
@ -418,8 +414,8 @@ func (s *UserAuthTokenService) BatchRevokeAllUserTokens(ctx context.Context, use
}) })
} }
func (s *UserAuthTokenService) GetUserToken(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error) { func (s *UserAuthTokenService) GetUserToken(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error) {
var result models.UserToken var result auth.UserToken
err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error { err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error {
var token userAuthToken var token userAuthToken
exists, err := dbSession.Where("id = ? AND user_id = ?", userTokenId, userId).Get(&token) exists, err := dbSession.Where("id = ? AND user_id = ?", userTokenId, userId).Get(&token)
@ -428,7 +424,7 @@ func (s *UserAuthTokenService) GetUserToken(ctx context.Context, userId, userTok
} }
if !exists { if !exists {
return models.ErrUserTokenNotFound return auth.ErrUserTokenNotFound
} }
return token.toUserToken(&result) return token.toUserToken(&result)
@ -437,8 +433,8 @@ func (s *UserAuthTokenService) GetUserToken(ctx context.Context, userId, userTok
return &result, err return &result, err
} }
func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64) ([]*models.UserToken, error) { func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
result := []*models.UserToken{} result := []*auth.UserToken{}
err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error { err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error {
var tokens []*userAuthToken var tokens []*userAuthToken
err := dbSession.Where("user_id = ? AND created_at > ? AND rotated_at > ? AND revoked_at = 0", err := dbSession.Where("user_id = ? AND created_at > ? AND rotated_at > ? AND revoked_at = 0",
@ -451,7 +447,7 @@ func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64)
} }
for _, token := range tokens { for _, token := range tokens {
var userToken models.UserToken var userToken auth.UserToken
if err := token.toUserToken(&userToken); err != nil { if err := token.toUserToken(&userToken); err != nil {
return err return err
} }
@ -464,8 +460,8 @@ func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64)
return result, err return result, err
} }
func (s *UserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId int64) ([]*models.UserToken, error) { func (s *UserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
result := []*models.UserToken{} result := []*auth.UserToken{}
err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error { err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error {
var tokens []*userAuthToken var tokens []*userAuthToken
err := dbSession.Where("user_id = ? AND revoked_at > 0", userId).Find(&tokens) err := dbSession.Where("user_id = ? AND revoked_at > 0", userId).Find(&tokens)
@ -474,7 +470,7 @@ func (s *UserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId
} }
for _, token := range tokens { for _, token := range tokens {
var userToken models.UserToken var userToken auth.UserToken
if err := token.toUserToken(&userToken); err != nil { if err := token.toUserToken(&userToken); err != nil {
return err return err
} }
@ -507,7 +503,7 @@ func readQuotaConfig(cfg *setting.Cfg) (*quota.Map, error) {
return limits, nil return limits, nil
} }
globalQuotaTag, err := quota.NewTag(QuotaTargetSrv, QuotaTarget, quota.GlobalScope) globalQuotaTag, err := quota.NewTag(auth.QuotaTargetSrv, auth.QuotaTarget, quota.GlobalScope)
if err != nil { if err != nil {
return limits, err return limits, err
} }

View File

@ -1,4 +1,4 @@
package auth package authimpl
import ( import (
"context" "context"
@ -8,12 +8,12 @@ import (
"testing" "testing"
"time" "time"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"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/services/quota" "github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -29,7 +29,7 @@ func TestUserAuthToken(t *testing.T) {
defer func() { getTime = time.Now }() defer func() { getTime = time.Now }()
t.Run("When creating token", func(t *testing.T) { t.Run("When creating token", func(t *testing.T) {
createToken := func() *models.UserToken { createToken := func() *auth.UserToken {
userToken, err := ctx.tokenService.CreateToken(context.Background(), user, userToken, err := ctx.tokenService.CreateToken(context.Background(), user,
net.ParseIP("192.168.10.11"), "some user agent") net.ParseIP("192.168.10.11"), "some user agent")
require.Nil(t, err) require.Nil(t, err)
@ -43,7 +43,7 @@ func TestUserAuthToken(t *testing.T) {
t.Run("Can count active tokens", func(t *testing.T) { t.Run("Can count active tokens", func(t *testing.T) {
m, err := ctx.activeTokenService.ActiveTokenCount(context.Background(), &quota.ScopeParameters{}) m, err := ctx.activeTokenService.ActiveTokenCount(context.Background(), &quota.ScopeParameters{})
require.Nil(t, err) require.Nil(t, err)
tag, err := quota.NewTag(QuotaTargetSrv, QuotaTarget, quota.GlobalScope) tag, err := quota.NewTag(auth.QuotaTargetSrv, auth.QuotaTarget, quota.GlobalScope)
require.NoError(t, err) require.NoError(t, err)
count, ok := m.Get(tag) count, ok := m.Get(tag)
require.True(t, ok) require.True(t, ok)
@ -65,7 +65,7 @@ func TestUserAuthToken(t *testing.T) {
t.Run("When lookup hashed token should return user auth token not found error", func(t *testing.T) { t.Run("When lookup hashed token should return user auth token not found error", func(t *testing.T) {
userToken, err := ctx.tokenService.LookupToken(context.Background(), userToken.AuthToken) userToken, err := ctx.tokenService.LookupToken(context.Background(), userToken.AuthToken)
require.Equal(t, models.ErrUserTokenNotFound, err) require.Equal(t, auth.ErrUserTokenNotFound, err)
require.Nil(t, userToken) require.Nil(t, userToken)
}) })
@ -90,13 +90,13 @@ func TestUserAuthToken(t *testing.T) {
t.Run("revoking nil token should return error", func(t *testing.T) { t.Run("revoking nil token should return error", func(t *testing.T) {
err := ctx.tokenService.RevokeToken(context.Background(), nil, false) err := ctx.tokenService.RevokeToken(context.Background(), nil, false)
require.Equal(t, models.ErrUserTokenNotFound, err) require.Equal(t, auth.ErrUserTokenNotFound, err)
}) })
t.Run("revoking non-existing token should return error", func(t *testing.T) { t.Run("revoking non-existing token should return error", func(t *testing.T) {
userToken.Id = 1000 userToken.Id = 1000
err := ctx.tokenService.RevokeToken(context.Background(), userToken, false) err := ctx.tokenService.RevokeToken(context.Background(), userToken, false)
require.Equal(t, models.ErrUserTokenNotFound, err) require.Equal(t, auth.ErrUserTokenNotFound, err)
}) })
ctx = createTestContext(t) ctx = createTestContext(t)
@ -209,13 +209,13 @@ func TestUserAuthToken(t *testing.T) {
} }
notGood, err := ctx.tokenService.LookupToken(context.Background(), userToken.UnhashedToken) notGood, err := ctx.tokenService.LookupToken(context.Background(), userToken.UnhashedToken)
require.Equal(t, reflect.TypeOf(err), reflect.TypeOf(&models.TokenExpiredError{})) require.Equal(t, reflect.TypeOf(err), reflect.TypeOf(&auth.TokenExpiredError{}))
require.Nil(t, notGood) require.Nil(t, notGood)
t.Run("should not find active token when expired", func(t *testing.T) { t.Run("should not find active token when expired", func(t *testing.T) {
m, err := ctx.activeTokenService.ActiveTokenCount(context.Background(), &quota.ScopeParameters{}) m, err := ctx.activeTokenService.ActiveTokenCount(context.Background(), &quota.ScopeParameters{})
require.Nil(t, err) require.Nil(t, err)
tag, err := quota.NewTag(QuotaTargetSrv, QuotaTarget, quota.GlobalScope) tag, err := quota.NewTag(auth.QuotaTargetSrv, auth.QuotaTarget, quota.GlobalScope)
require.NoError(t, err) require.NoError(t, err)
count, ok := m.Get(tag) count, ok := m.Get(tag)
require.True(t, ok) require.True(t, ok)
@ -247,7 +247,7 @@ func TestUserAuthToken(t *testing.T) {
} }
notGood, err := ctx.tokenService.LookupToken(context.Background(), userToken.UnhashedToken) notGood, err := ctx.tokenService.LookupToken(context.Background(), userToken.UnhashedToken)
require.Equal(t, reflect.TypeOf(err), reflect.TypeOf(&models.TokenExpiredError{})) require.Equal(t, reflect.TypeOf(err), reflect.TypeOf(&auth.TokenExpiredError{}))
require.Nil(t, notGood) require.Nil(t, notGood)
}) })
}) })
@ -274,7 +274,7 @@ func TestUserAuthToken(t *testing.T) {
model, err := ctx.getAuthTokenByID(userToken.Id) model, err := ctx.getAuthTokenByID(userToken.Id)
require.Nil(t, err) require.Nil(t, err)
var tok models.UserToken var tok auth.UserToken
err = model.toUserToken(&tok) err = model.toUserToken(&tok)
require.Nil(t, err) require.Nil(t, err)
@ -471,7 +471,7 @@ func TestUserAuthToken(t *testing.T) {
}) })
t.Run("When populating userAuthToken from UserToken should copy all properties", func(t *testing.T) { t.Run("When populating userAuthToken from UserToken should copy all properties", func(t *testing.T) {
ut := models.UserToken{ ut := auth.UserToken{
Id: 1, Id: 1,
UserId: 2, UserId: 2,
AuthToken: "a", AuthToken: "a",
@ -524,7 +524,7 @@ func TestUserAuthToken(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
uatMap := uatJSON.MustMap() uatMap := uatJSON.MustMap()
var ut models.UserToken var ut auth.UserToken
err = uat.toUserToken(&ut) err = uat.toUserToken(&ut)
require.Nil(t, err) require.Nil(t, err)
utBytes, err := json.Marshal(ut) utBytes, err := json.Marshal(ut)

View File

@ -1,10 +1,9 @@
package auth package authimpl
import ( import (
"fmt" "fmt"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/quota"
) )
type userAuthToken struct { type userAuthToken struct {
@ -23,13 +22,13 @@ type userAuthToken struct {
UnhashedToken string `xorm:"-"` UnhashedToken string `xorm:"-"`
} }
func userAuthTokenFromUserToken(ut *models.UserToken) (*userAuthToken, error) { func userAuthTokenFromUserToken(ut *auth.UserToken) (*userAuthToken, error) {
var uat userAuthToken var uat userAuthToken
err := uat.fromUserToken(ut) err := uat.fromUserToken(ut)
return &uat, err return &uat, err
} }
func (uat *userAuthToken) fromUserToken(ut *models.UserToken) error { func (uat *userAuthToken) fromUserToken(ut *auth.UserToken) error {
if uat == nil { if uat == nil {
return fmt.Errorf("needs pointer to userAuthToken struct") return fmt.Errorf("needs pointer to userAuthToken struct")
} }
@ -51,7 +50,7 @@ func (uat *userAuthToken) fromUserToken(ut *models.UserToken) error {
return nil return nil
} }
func (uat *userAuthToken) toUserToken(ut *models.UserToken) error { func (uat *userAuthToken) toUserToken(ut *auth.UserToken) error {
if uat == nil { if uat == nil {
return fmt.Errorf("needs pointer to userAuthToken struct") return fmt.Errorf("needs pointer to userAuthToken struct")
} }
@ -72,8 +71,3 @@ func (uat *userAuthToken) toUserToken(ut *models.UserToken) error {
return nil return nil
} }
const (
QuotaTargetSrv quota.TargetSrv = "auth"
QuotaTarget quota.Target = "session"
)

View File

@ -1,4 +1,4 @@
package auth package authimpl
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package auth package authimpl
import ( import (
"context" "context"

View File

@ -1,4 +1,4 @@
package auth package authtest
import ( import (
"context" "context"
@ -6,42 +6,43 @@ import (
"time" "time"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
type FakeUserAuthTokenService struct { type FakeUserAuthTokenService struct {
CreateTokenProvider func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) CreateTokenProvider func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*auth.UserToken, error)
TryRotateTokenProvider func(ctx context.Context, token *models.UserToken, clientIP net.IP, userAgent string) (bool, error) TryRotateTokenProvider func(ctx context.Context, token *auth.UserToken, clientIP net.IP, userAgent string) (bool, error)
LookupTokenProvider func(ctx context.Context, unhashedToken string) (*models.UserToken, error) LookupTokenProvider func(ctx context.Context, unhashedToken string) (*auth.UserToken, error)
RevokeTokenProvider func(ctx context.Context, token *models.UserToken, soft bool) error RevokeTokenProvider func(ctx context.Context, token *auth.UserToken, soft bool) error
RevokeAllUserTokensProvider func(ctx context.Context, userId int64) error RevokeAllUserTokensProvider func(ctx context.Context, userId int64) error
ActiveAuthTokenCount func(ctx context.Context) (int64, error) ActiveAuthTokenCount func(ctx context.Context) (int64, error)
GetUserTokenProvider func(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error) GetUserTokenProvider func(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error)
GetUserTokensProvider func(ctx context.Context, userId int64) ([]*models.UserToken, error) GetUserTokensProvider func(ctx context.Context, userId int64) ([]*auth.UserToken, error)
GetUserRevokedTokensProvider func(ctx context.Context, userId int64) ([]*models.UserToken, error) GetUserRevokedTokensProvider func(ctx context.Context, userId int64) ([]*auth.UserToken, error)
BatchRevokedTokenProvider func(ctx context.Context, userIds []int64) error BatchRevokedTokenProvider func(ctx context.Context, userIds []int64) error
} }
func NewFakeUserAuthTokenService() *FakeUserAuthTokenService { func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
return &FakeUserAuthTokenService{ return &FakeUserAuthTokenService{
CreateTokenProvider: func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) { CreateTokenProvider: func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: 0, UserId: 0,
UnhashedToken: "", UnhashedToken: "",
}, nil }, nil
}, },
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP net.IP, userAgent string) (bool, error) { TryRotateTokenProvider: func(ctx context.Context, token *auth.UserToken, clientIP net.IP, userAgent string) (bool, error) {
return false, nil return false, nil
}, },
LookupTokenProvider: func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { LookupTokenProvider: func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return &models.UserToken{ return &auth.UserToken{
UserId: 0, UserId: 0,
UnhashedToken: "", UnhashedToken: "",
}, nil }, nil
}, },
RevokeTokenProvider: func(ctx context.Context, token *models.UserToken, soft bool) error { RevokeTokenProvider: func(ctx context.Context, token *auth.UserToken, soft bool) error {
return nil return nil
}, },
RevokeAllUserTokensProvider: func(ctx context.Context, userId int64) error { RevokeAllUserTokensProvider: func(ctx context.Context, userId int64) error {
@ -53,10 +54,10 @@ func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
ActiveAuthTokenCount: func(ctx context.Context) (int64, error) { ActiveAuthTokenCount: func(ctx context.Context) (int64, error) {
return 10, nil return 10, nil
}, },
GetUserTokenProvider: func(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error) { GetUserTokenProvider: func(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error) {
return nil, nil return nil, nil
}, },
GetUserTokensProvider: func(ctx context.Context, userId int64) ([]*models.UserToken, error) { GetUserTokensProvider: func(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
return nil, nil return nil, nil
}, },
} }
@ -68,20 +69,20 @@ func (s *FakeUserAuthTokenService) Init() error {
return nil return nil
} }
func (s *FakeUserAuthTokenService) CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) { func (s *FakeUserAuthTokenService) CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*auth.UserToken, error) {
return s.CreateTokenProvider(context.Background(), user, clientIP, userAgent) return s.CreateTokenProvider(context.Background(), user, clientIP, userAgent)
} }
func (s *FakeUserAuthTokenService) LookupToken(ctx context.Context, unhashedToken string) (*models.UserToken, error) { func (s *FakeUserAuthTokenService) LookupToken(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
return s.LookupTokenProvider(context.Background(), unhashedToken) return s.LookupTokenProvider(context.Background(), unhashedToken)
} }
func (s *FakeUserAuthTokenService) TryRotateToken(ctx context.Context, token *models.UserToken, clientIP net.IP, func (s *FakeUserAuthTokenService) TryRotateToken(ctx context.Context, token *auth.UserToken, clientIP net.IP,
userAgent string) (bool, error) { userAgent string) (bool, error) {
return s.TryRotateTokenProvider(context.Background(), token, clientIP, userAgent) return s.TryRotateTokenProvider(context.Background(), token, clientIP, userAgent)
} }
func (s *FakeUserAuthTokenService) RevokeToken(ctx context.Context, token *models.UserToken, soft bool) error { func (s *FakeUserAuthTokenService) RevokeToken(ctx context.Context, token *auth.UserToken, soft bool) error {
return s.RevokeTokenProvider(context.Background(), token, soft) return s.RevokeTokenProvider(context.Background(), token, soft)
} }
@ -93,15 +94,15 @@ func (s *FakeUserAuthTokenService) ActiveTokenCount(ctx context.Context) (int64,
return s.ActiveAuthTokenCount(context.Background()) return s.ActiveAuthTokenCount(context.Background())
} }
func (s *FakeUserAuthTokenService) GetUserToken(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error) { func (s *FakeUserAuthTokenService) GetUserToken(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error) {
return s.GetUserTokenProvider(context.Background(), userId, userTokenId) return s.GetUserTokenProvider(context.Background(), userId, userTokenId)
} }
func (s *FakeUserAuthTokenService) GetUserTokens(ctx context.Context, userId int64) ([]*models.UserToken, error) { func (s *FakeUserAuthTokenService) GetUserTokens(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
return s.GetUserTokensProvider(context.Background(), userId) return s.GetUserTokensProvider(context.Background(), userId)
} }
func (s *FakeUserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId int64) ([]*models.UserToken, error) { func (s *FakeUserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
return s.GetUserRevokedTokensProvider(context.Background(), userId) return s.GetUserRevokedTokensProvider(context.Background(), userId)
} }

View File

@ -13,7 +13,7 @@ import (
"github.com/grafana/grafana/pkg/infra/remotecache" "github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtest"
"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/org/orgtest"
@ -80,7 +80,7 @@ func getContextHandler(t *testing.T) *ContextHandler {
cfg.AuthProxyHeaderProperty = "username" cfg.AuthProxyHeaderProperty = "username"
remoteCacheSvc, err := remotecache.ProvideService(cfg, sqlStore) remoteCacheSvc, err := remotecache.ProvideService(cfg, sqlStore)
require.NoError(t, err) require.NoError(t, err)
userAuthTokenSvc := auth.NewFakeUserAuthTokenService() userAuthTokenSvc := authtest.NewFakeUserAuthTokenService()
renderSvc := &fakeRenderService{} renderSvc := &fakeRenderService{}
authJWTSvc := models.NewFakeJWTService() authJWTSvc := models.NewFakeJWTService()
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()

View File

@ -44,7 +44,7 @@ const (
const ServiceName = "ContextHandler" const ServiceName = "ContextHandler"
func ProvideService(cfg *setting.Cfg, tokenService models.UserTokenService, jwtService models.JWTService, func ProvideService(cfg *setting.Cfg, tokenService auth.UserTokenService, jwtService models.JWTService,
remoteCache *remotecache.RemoteCache, renderService rendering.Service, sqlStore db.DB, remoteCache *remotecache.RemoteCache, renderService rendering.Service, sqlStore db.DB,
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,
@ -77,7 +77,7 @@ func ProvideService(cfg *setting.Cfg, tokenService models.UserTokenService, jwtS
// ContextHandler is a middleware. // ContextHandler is a middleware.
type ContextHandler struct { type ContextHandler struct {
Cfg *setting.Cfg Cfg *setting.Cfg
AuthTokenService models.UserTokenService AuthTokenService auth.UserTokenService
JWTAuthService models.JWTService JWTAuthService models.JWTService
RemoteCache *remotecache.RemoteCache RemoteCache *remotecache.RemoteCache
RenderService rendering.Service RenderService rendering.Service
@ -474,7 +474,7 @@ func (h *ContextHandler) initContextWithToken(reqContext *models.ReqContext, org
} }
err = h.AuthTokenService.RevokeToken(ctx, token, false) err = h.AuthTokenService.RevokeToken(ctx, token, false)
if err != nil && !errors.Is(err, models.ErrUserTokenNotFound) { if err != nil && !errors.Is(err, auth.ErrUserTokenNotFound) {
reqContext.Logger.Error("failed to revoke auth token", "error", err) reqContext.Logger.Error("failed to revoke auth token", "error", err)
} }
return false return false
@ -506,8 +506,8 @@ func (h *ContextHandler) deleteInvalidCookieEndOfRequestFunc(reqContext *models.
} }
} }
func (h *ContextHandler) rotateEndOfRequestFunc(reqContext *models.ReqContext, authTokenService models.UserTokenService, func (h *ContextHandler) rotateEndOfRequestFunc(reqContext *models.ReqContext, authTokenService auth.UserTokenService,
token *models.UserToken) web.BeforeFunc { token *auth.UserToken) web.BeforeFunc {
return func(w web.ResponseWriter) { return func(w web.ResponseWriter) {
// if response has already been written, skip. // if response has already been written, skip.
if w.Written() { if w.Written() {

View File

@ -7,14 +7,16 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
"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/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestDontRotateTokensOnCancelledRequests(t *testing.T) { func TestDontRotateTokensOnCancelledRequests(t *testing.T) {
@ -25,15 +27,15 @@ func TestDontRotateTokensOnCancelledRequests(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
tryRotateCallCount := 0 tryRotateCallCount := 0
uts := &auth.FakeUserAuthTokenService{ uts := &authtest.FakeUserAuthTokenService{
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP net.IP, TryRotateTokenProvider: func(ctx context.Context, token *auth.UserToken, clientIP net.IP,
userAgent string) (bool, error) { userAgent string) (bool, error) {
tryRotateCallCount++ tryRotateCallCount++
return false, nil return false, nil
}, },
} }
token := &models.UserToken{AuthToken: "oldtoken"} token := &auth.UserToken{AuthToken: "oldtoken"}
fn := ctxHdlr.rotateEndOfRequestFunc(reqContext, uts, token) fn := ctxHdlr.rotateEndOfRequestFunc(reqContext, uts, token)
cancel() cancel()
@ -48,8 +50,8 @@ func TestTokenRotationAtEndOfRequest(t *testing.T) {
reqContext, rr, err := initTokenRotationScenario(context.Background(), t, ctxHdlr) reqContext, rr, err := initTokenRotationScenario(context.Background(), t, ctxHdlr)
require.NoError(t, err) require.NoError(t, err)
uts := &auth.FakeUserAuthTokenService{ uts := &authtest.FakeUserAuthTokenService{
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP net.IP, TryRotateTokenProvider: func(ctx context.Context, token *auth.UserToken, clientIP net.IP,
userAgent string) (bool, error) { userAgent string) (bool, error) {
newToken, err := util.RandomHex(16) newToken, err := util.RandomHex(16)
require.NoError(t, err) require.NoError(t, err)
@ -58,7 +60,7 @@ func TestTokenRotationAtEndOfRequest(t *testing.T) {
}, },
} }
token := &models.UserToken{AuthToken: "oldtoken"} token := &auth.UserToken{AuthToken: "oldtoken"}
ctxHdlr.rotateEndOfRequestFunc(reqContext, uts, token)(reqContext.Resp) ctxHdlr.rotateEndOfRequestFunc(reqContext, uts, token)(reqContext.Resp)

View File

@ -12,6 +12,7 @@ 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"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/auth"
models2 "github.com/grafana/grafana/pkg/services/ngalert/models" models2 "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@ -45,7 +46,7 @@ func TestAlertingProxy_createProxyContext(t *testing.T) {
Req: &http.Request{}, Req: &http.Request{},
}, },
SignedInUser: &user.SignedInUser{}, SignedInUser: &user.SignedInUser{},
UserToken: &models.UserToken{}, UserToken: &auth.UserToken{},
IsSignedIn: rand.Int63()%2 == 1, IsSignedIn: rand.Int63()%2 == 1,
IsRenderCall: rand.Int63()%2 == 1, IsRenderCall: rand.Int63()%2 == 1,
AllowAnonymous: rand.Int63()%2 == 1, AllowAnonymous: rand.Int63()%2 == 1,

View File

@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl" "github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/authimpl"
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database" dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
@ -464,7 +465,7 @@ func getQuotaBySrvTargetScope(t *testing.T, quotaService quota.Service, srv quot
func setupEnv(t *testing.T, sqlStore *sqlstore.SQLStore, b bus.Bus, quotaService quota.Service) { func setupEnv(t *testing.T, sqlStore *sqlstore.SQLStore, b bus.Bus, quotaService quota.Service) {
_, err := apikeyimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService) _, err := apikeyimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err) require.NoError(t, err)
_, err = auth.ProvideActiveAuthTokenService(sqlStore.Cfg, sqlStore, quotaService) _, err = authimpl.ProvideActiveAuthTokenService(sqlStore.Cfg, sqlStore, quotaService)
require.NoError(t, err) require.NoError(t, err)
_, err = dashboardStore.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService) _, err = dashboardStore.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
require.NoError(t, err) require.NoError(t, err)