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:
@@ -14,8 +14,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/middleware/cookies"
|
||||
|
||||
"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/setting"
|
||||
"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) {
|
||||
unauthorized(c, revokedErr)
|
||||
return
|
||||
@@ -111,7 +111,7 @@ func unauthorized(c *models.ReqContext, err error) {
|
||||
"message": "Unauthorized",
|
||||
}
|
||||
|
||||
var revokedErr *models.TokenRevokedError
|
||||
var revokedErr *usertoken.TokenRevokedError
|
||||
if errors.As(err, &revokedErr) {
|
||||
response["message"] = "Token revoked"
|
||||
response["error"] = map[string]interface{}{
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models/usertoken"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"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
|
||||
var (
|
||||
ErrUserTokenNotFound = errors.New("user token not found")
|
||||
)
|
||||
|
||||
type TokenRevokedError = usertoken.TokenRevokedError
|
||||
|
||||
// CreateTokenErr represents a token creation error; used in Enterprise
|
||||
type CreateTokenErr struct {
|
||||
StatusCode int
|
||||
InternalErr error
|
||||
ExternalErr string
|
||||
}
|
||||
|
||||
func (e *CreateTokenErr) Error() string {
|
||||
if e.InternalErr != nil {
|
||||
return e.InternalErr.Error()
|
||||
}
|
||||
return "failed to create token"
|
||||
}
|
||||
|
||||
type TokenExpiredError struct {
|
||||
UserID int64
|
||||
TokenID int64
|
||||
}
|
||||
|
||||
func (e *TokenExpiredError) Error() string { return "user token expired" }
|
||||
|
||||
type UserToken = usertoken.UserToken
|
||||
|
||||
type RevokeAuthTokenCmd struct {
|
||||
AuthTokenId int64 `json:"authTokenId"`
|
||||
}
|
||||
|
||||
// UserTokenService are used for generating and validating user tokens
|
||||
type UserTokenService interface {
|
||||
CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*UserToken, error)
|
||||
LookupToken(ctx context.Context, unhashedToken string) (*UserToken, error)
|
||||
TryRotateToken(ctx context.Context, token *UserToken, clientIP net.IP, userAgent string) (bool, error)
|
||||
RevokeToken(ctx context.Context, token *UserToken, soft bool) error
|
||||
RevokeAllUserTokens(ctx context.Context, userId int64) error
|
||||
GetUserToken(ctx context.Context, userId, userTokenId int64) (*UserToken, error)
|
||||
GetUserTokens(ctx context.Context, userId int64) ([]*UserToken, error)
|
||||
GetUserRevokedTokens(ctx context.Context, userId int64) ([]*UserToken, error)
|
||||
}
|
||||
|
||||
type UserTokenBackgroundService interface {
|
||||
registry.BackgroundService
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package authimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"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/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -42,10 +42,6 @@ type UserAuthTokenService struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
type ActiveTokenService interface {
|
||||
ActiveTokenCount(ctx context.Context, _ *quota.ScopeParameters) (*quota.Map, error)
|
||||
}
|
||||
|
||||
type ActiveAuthTokenService struct {
|
||||
cfg *setting.Cfg
|
||||
sqlStore db.DB
|
||||
@@ -63,7 +59,7 @@ func ProvideActiveAuthTokenService(cfg *setting.Cfg, sqlStore db.DB, quotaServic
|
||||
}
|
||||
|
||||
if err := quotaService.RegisterQuotaReporter("a.NewUsageReporter{
|
||||
TargetSrv: QuotaTargetSrv,
|
||||
TargetSrv: auth.QuotaTargetSrv,
|
||||
DefaultLimits: defaultLimits,
|
||||
Reporter: s.ActiveTokenCount,
|
||||
}); err != nil {
|
||||
@@ -86,7 +82,7 @@ func (a *ActiveAuthTokenService) ActiveTokenCount(ctx context.Context, _ *quota.
|
||||
return err
|
||||
})
|
||||
|
||||
tag, err := quota.NewTag(QuotaTargetSrv, QuotaTarget, quota.GlobalScope)
|
||||
tag, err := quota.NewTag(auth.QuotaTargetSrv, auth.QuotaTarget, quota.GlobalScope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -96,7 +92,7 @@ func (a *ActiveAuthTokenService) ActiveTokenCount(ctx context.Context, _ *quota.
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -138,13 +134,13 @@ func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *user.User,
|
||||
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)
|
||||
|
||||
var userToken models.UserToken
|
||||
var userToken auth.UserToken
|
||||
err = userAuthToken.toUserToken(&userToken)
|
||||
|
||||
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)
|
||||
var model userAuthToken
|
||||
var exists bool
|
||||
@@ -162,14 +158,14 @@ func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken st
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return nil, models.ErrUserTokenNotFound
|
||||
return nil, auth.ErrUserTokenNotFound
|
||||
}
|
||||
|
||||
ctxLogger := s.log.FromContext(ctx)
|
||||
|
||||
if model.RevokedAt > 0 {
|
||||
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,
|
||||
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() {
|
||||
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,
|
||||
TokenID: model.Id,
|
||||
}
|
||||
@@ -242,13 +238,13 @@ func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken st
|
||||
|
||||
model.UnhashedToken = unhashedToken
|
||||
|
||||
var userToken models.UserToken
|
||||
var userToken auth.UserToken
|
||||
err = model.toUserToken(&userToken)
|
||||
|
||||
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) {
|
||||
if token == nil {
|
||||
return false, nil
|
||||
@@ -328,9 +324,9 @@ func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *models
|
||||
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 {
|
||||
return models.ErrUserTokenNotFound
|
||||
return auth.ErrUserTokenNotFound
|
||||
}
|
||||
|
||||
model, err := userAuthTokenFromUserToken(token)
|
||||
@@ -361,7 +357,7 @@ func (s *UserAuthTokenService) RevokeToken(ctx context.Context, token *models.Us
|
||||
|
||||
if rowsAffected == 0 {
|
||||
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)
|
||||
@@ -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) {
|
||||
var result models.UserToken
|
||||
func (s *UserAuthTokenService) GetUserToken(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error) {
|
||||
var result auth.UserToken
|
||||
err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error {
|
||||
var token userAuthToken
|
||||
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 {
|
||||
return models.ErrUserTokenNotFound
|
||||
return auth.ErrUserTokenNotFound
|
||||
}
|
||||
|
||||
return token.toUserToken(&result)
|
||||
@@ -437,8 +433,8 @@ func (s *UserAuthTokenService) GetUserToken(ctx context.Context, userId, userTok
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64) ([]*models.UserToken, error) {
|
||||
result := []*models.UserToken{}
|
||||
func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
|
||||
result := []*auth.UserToken{}
|
||||
err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error {
|
||||
var tokens []*userAuthToken
|
||||
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 {
|
||||
var userToken models.UserToken
|
||||
var userToken auth.UserToken
|
||||
if err := token.toUserToken(&userToken); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -464,8 +460,8 @@ func (s *UserAuthTokenService) GetUserTokens(ctx context.Context, userId int64)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *UserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId int64) ([]*models.UserToken, error) {
|
||||
result := []*models.UserToken{}
|
||||
func (s *UserAuthTokenService) GetUserRevokedTokens(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
|
||||
result := []*auth.UserToken{}
|
||||
err := s.SQLStore.WithDbSession(ctx, func(dbSession *db.Session) error {
|
||||
var tokens []*userAuthToken
|
||||
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 {
|
||||
var userToken models.UserToken
|
||||
var userToken auth.UserToken
|
||||
if err := token.toUserToken(&userToken); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -507,7 +503,7 @@ func readQuotaConfig(cfg *setting.Cfg) (*quota.Map, error) {
|
||||
return limits, nil
|
||||
}
|
||||
|
||||
globalQuotaTag, err := quota.NewTag(QuotaTargetSrv, QuotaTarget, quota.GlobalScope)
|
||||
globalQuotaTag, err := quota.NewTag(auth.QuotaTargetSrv, auth.QuotaTarget, quota.GlobalScope)
|
||||
if err != nil {
|
||||
return limits, err
|
||||
}
|
||||
+13
-13
@@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package authimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"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/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -29,7 +29,7 @@ func TestUserAuthToken(t *testing.T) {
|
||||
defer func() { getTime = time.Now }()
|
||||
|
||||
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,
|
||||
net.ParseIP("192.168.10.11"), "some user agent")
|
||||
require.Nil(t, err)
|
||||
@@ -43,7 +43,7 @@ func TestUserAuthToken(t *testing.T) {
|
||||
t.Run("Can count active tokens", func(t *testing.T) {
|
||||
m, err := ctx.activeTokenService.ActiveTokenCount(context.Background(), "a.ScopeParameters{})
|
||||
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)
|
||||
count, ok := m.Get(tag)
|
||||
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) {
|
||||
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)
|
||||
})
|
||||
|
||||
@@ -90,13 +90,13 @@ func TestUserAuthToken(t *testing.T) {
|
||||
|
||||
t.Run("revoking nil token should return error", func(t *testing.T) {
|
||||
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) {
|
||||
userToken.Id = 1000
|
||||
err := ctx.tokenService.RevokeToken(context.Background(), userToken, false)
|
||||
require.Equal(t, models.ErrUserTokenNotFound, err)
|
||||
require.Equal(t, auth.ErrUserTokenNotFound, err)
|
||||
})
|
||||
|
||||
ctx = createTestContext(t)
|
||||
@@ -209,13 +209,13 @@ func TestUserAuthToken(t *testing.T) {
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
t.Run("should not find active token when expired", func(t *testing.T) {
|
||||
m, err := ctx.activeTokenService.ActiveTokenCount(context.Background(), "a.ScopeParameters{})
|
||||
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)
|
||||
count, ok := m.Get(tag)
|
||||
require.True(t, ok)
|
||||
@@ -247,7 +247,7 @@ func TestUserAuthToken(t *testing.T) {
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
})
|
||||
@@ -274,7 +274,7 @@ func TestUserAuthToken(t *testing.T) {
|
||||
model, err := ctx.getAuthTokenByID(userToken.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
var tok models.UserToken
|
||||
var tok auth.UserToken
|
||||
err = model.toUserToken(&tok)
|
||||
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) {
|
||||
ut := models.UserToken{
|
||||
ut := auth.UserToken{
|
||||
Id: 1,
|
||||
UserId: 2,
|
||||
AuthToken: "a",
|
||||
@@ -524,7 +524,7 @@ func TestUserAuthToken(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
uatMap := uatJSON.MustMap()
|
||||
|
||||
var ut models.UserToken
|
||||
var ut auth.UserToken
|
||||
err = uat.toUserToken(&ut)
|
||||
require.Nil(t, err)
|
||||
utBytes, err := json.Marshal(ut)
|
||||
@@ -1,10 +1,9 @@
|
||||
package auth
|
||||
package authimpl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
)
|
||||
|
||||
type userAuthToken struct {
|
||||
@@ -23,13 +22,13 @@ type userAuthToken struct {
|
||||
UnhashedToken string `xorm:"-"`
|
||||
}
|
||||
|
||||
func userAuthTokenFromUserToken(ut *models.UserToken) (*userAuthToken, error) {
|
||||
func userAuthTokenFromUserToken(ut *auth.UserToken) (*userAuthToken, error) {
|
||||
var uat userAuthToken
|
||||
err := uat.fromUserToken(ut)
|
||||
return &uat, err
|
||||
}
|
||||
|
||||
func (uat *userAuthToken) fromUserToken(ut *models.UserToken) error {
|
||||
func (uat *userAuthToken) fromUserToken(ut *auth.UserToken) error {
|
||||
if uat == nil {
|
||||
return fmt.Errorf("needs pointer to userAuthToken struct")
|
||||
}
|
||||
@@ -51,7 +50,7 @@ func (uat *userAuthToken) fromUserToken(ut *models.UserToken) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (uat *userAuthToken) toUserToken(ut *models.UserToken) error {
|
||||
func (uat *userAuthToken) toUserToken(ut *auth.UserToken) error {
|
||||
if uat == nil {
|
||||
return fmt.Errorf("needs pointer to userAuthToken struct")
|
||||
}
|
||||
@@ -72,8 +71,3 @@ func (uat *userAuthToken) toUserToken(ut *models.UserToken) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
QuotaTargetSrv quota.TargetSrv = "auth"
|
||||
QuotaTarget quota.Target = "session"
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package authimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package authimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package authtest
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,42 +6,43 @@ import (
|
||||
"time"
|
||||
|
||||
"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/user"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
type FakeUserAuthTokenService struct {
|
||||
CreateTokenProvider func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error)
|
||||
TryRotateTokenProvider func(ctx context.Context, token *models.UserToken, clientIP net.IP, userAgent string) (bool, error)
|
||||
LookupTokenProvider func(ctx context.Context, unhashedToken string) (*models.UserToken, error)
|
||||
RevokeTokenProvider func(ctx context.Context, token *models.UserToken, soft bool) error
|
||||
CreateTokenProvider func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*auth.UserToken, error)
|
||||
TryRotateTokenProvider func(ctx context.Context, token *auth.UserToken, clientIP net.IP, userAgent string) (bool, error)
|
||||
LookupTokenProvider func(ctx context.Context, unhashedToken string) (*auth.UserToken, error)
|
||||
RevokeTokenProvider func(ctx context.Context, token *auth.UserToken, soft bool) error
|
||||
RevokeAllUserTokensProvider func(ctx context.Context, userId int64) error
|
||||
ActiveAuthTokenCount func(ctx context.Context) (int64, error)
|
||||
GetUserTokenProvider func(ctx context.Context, userId, userTokenId int64) (*models.UserToken, error)
|
||||
GetUserTokensProvider func(ctx context.Context, userId int64) ([]*models.UserToken, error)
|
||||
GetUserRevokedTokensProvider func(ctx context.Context, userId int64) ([]*models.UserToken, error)
|
||||
GetUserTokenProvider func(ctx context.Context, userId, userTokenId int64) (*auth.UserToken, error)
|
||||
GetUserTokensProvider func(ctx context.Context, userId int64) ([]*auth.UserToken, error)
|
||||
GetUserRevokedTokensProvider func(ctx context.Context, userId int64) ([]*auth.UserToken, error)
|
||||
BatchRevokedTokenProvider func(ctx context.Context, userIds []int64) error
|
||||
}
|
||||
|
||||
func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
|
||||
return &FakeUserAuthTokenService{
|
||||
CreateTokenProvider: func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
|
||||
return &models.UserToken{
|
||||
CreateTokenProvider: func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*auth.UserToken, error) {
|
||||
return &auth.UserToken{
|
||||
UserId: 0,
|
||||
UnhashedToken: "",
|
||||
}, 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
|
||||
},
|
||||
LookupTokenProvider: func(ctx context.Context, unhashedToken string) (*models.UserToken, error) {
|
||||
return &models.UserToken{
|
||||
LookupTokenProvider: func(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
|
||||
return &auth.UserToken{
|
||||
UserId: 0,
|
||||
UnhashedToken: "",
|
||||
}, 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
|
||||
},
|
||||
RevokeAllUserTokensProvider: func(ctx context.Context, userId int64) error {
|
||||
@@ -53,10 +54,10 @@ func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
|
||||
ActiveAuthTokenCount: func(ctx context.Context) (int64, error) {
|
||||
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
|
||||
},
|
||||
GetUserTokensProvider: func(ctx context.Context, userId int64) ([]*models.UserToken, error) {
|
||||
GetUserTokensProvider: func(ctx context.Context, userId int64) ([]*auth.UserToken, error) {
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
@@ -68,20 +69,20 @@ func (s *FakeUserAuthTokenService) Init() error {
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -93,15 +94,15 @@ func (s *FakeUserAuthTokenService) ActiveTokenCount(ctx context.Context) (int64,
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"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/login/loginservice"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||
@@ -80,7 +80,7 @@ func getContextHandler(t *testing.T) *ContextHandler {
|
||||
cfg.AuthProxyHeaderProperty = "username"
|
||||
remoteCacheSvc, err := remotecache.ProvideService(cfg, sqlStore)
|
||||
require.NoError(t, err)
|
||||
userAuthTokenSvc := auth.NewFakeUserAuthTokenService()
|
||||
userAuthTokenSvc := authtest.NewFakeUserAuthTokenService()
|
||||
renderSvc := &fakeRenderService{}
|
||||
authJWTSvc := models.NewFakeJWTService()
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
|
||||
@@ -44,7 +44,7 @@ const (
|
||||
|
||||
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,
|
||||
tracer tracing.Tracer, authProxy *authproxy.AuthProxy, loginService login.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.
|
||||
type ContextHandler struct {
|
||||
Cfg *setting.Cfg
|
||||
AuthTokenService models.UserTokenService
|
||||
AuthTokenService auth.UserTokenService
|
||||
JWTAuthService models.JWTService
|
||||
RemoteCache *remotecache.RemoteCache
|
||||
RenderService rendering.Service
|
||||
@@ -474,7 +474,7 @@ func (h *ContextHandler) initContextWithToken(reqContext *models.ReqContext, org
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
return false
|
||||
@@ -506,8 +506,8 @@ func (h *ContextHandler) deleteInvalidCookieEndOfRequestFunc(reqContext *models.
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ContextHandler) rotateEndOfRequestFunc(reqContext *models.ReqContext, authTokenService models.UserTokenService,
|
||||
token *models.UserToken) web.BeforeFunc {
|
||||
func (h *ContextHandler) rotateEndOfRequestFunc(reqContext *models.ReqContext, authTokenService auth.UserTokenService,
|
||||
token *auth.UserToken) web.BeforeFunc {
|
||||
return func(w web.ResponseWriter) {
|
||||
// if response has already been written, skip.
|
||||
if w.Written() {
|
||||
|
||||
@@ -7,14 +7,16 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"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/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDontRotateTokensOnCancelledRequests(t *testing.T) {
|
||||
@@ -25,15 +27,15 @@ func TestDontRotateTokensOnCancelledRequests(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
tryRotateCallCount := 0
|
||||
uts := &auth.FakeUserAuthTokenService{
|
||||
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP net.IP,
|
||||
uts := &authtest.FakeUserAuthTokenService{
|
||||
TryRotateTokenProvider: func(ctx context.Context, token *auth.UserToken, clientIP net.IP,
|
||||
userAgent string) (bool, error) {
|
||||
tryRotateCallCount++
|
||||
return false, nil
|
||||
},
|
||||
}
|
||||
|
||||
token := &models.UserToken{AuthToken: "oldtoken"}
|
||||
token := &auth.UserToken{AuthToken: "oldtoken"}
|
||||
|
||||
fn := ctxHdlr.rotateEndOfRequestFunc(reqContext, uts, token)
|
||||
cancel()
|
||||
@@ -48,8 +50,8 @@ func TestTokenRotationAtEndOfRequest(t *testing.T) {
|
||||
reqContext, rr, err := initTokenRotationScenario(context.Background(), t, ctxHdlr)
|
||||
require.NoError(t, err)
|
||||
|
||||
uts := &auth.FakeUserAuthTokenService{
|
||||
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP net.IP,
|
||||
uts := &authtest.FakeUserAuthTokenService{
|
||||
TryRotateTokenProvider: func(ctx context.Context, token *auth.UserToken, clientIP net.IP,
|
||||
userAgent string) (bool, error) {
|
||||
newToken, err := util.RandomHex(16)
|
||||
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)
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
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"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@@ -45,7 +46,7 @@ func TestAlertingProxy_createProxyContext(t *testing.T) {
|
||||
Req: &http.Request{},
|
||||
},
|
||||
SignedInUser: &user.SignedInUser{},
|
||||
UserToken: &models.UserToken{},
|
||||
UserToken: &auth.UserToken{},
|
||||
IsSignedIn: rand.Int63()%2 == 1,
|
||||
IsRenderCall: rand.Int63()%2 == 1,
|
||||
AllowAnonymous: rand.Int63()%2 == 1,
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/auth/authimpl"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"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) {
|
||||
_, err := apikeyimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
|
||||
require.NoError(t, err)
|
||||
_, err = auth.ProvideActiveAuthTokenService(sqlStore.Cfg, sqlStore, quotaService)
|
||||
_, err = authimpl.ProvideActiveAuthTokenService(sqlStore.Cfg, sqlStore, quotaService)
|
||||
require.NoError(t, err)
|
||||
_, err = dashboardStore.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user