Split Create User (#50502)

* Split Create User

* Use new create user and User from package user

* Add service to wire

* Making create user work

* Replace user from user pkg

* One more

* Move Insert to orguser Service/Store

* Remove unnecessary conversion

* Cleaunp

* Fix Get User and add fakes

* Fixing get org id for user logic, adding fakes and other adjustments

* Add some tests for ourguser service and store

* Fix insert org logic

* Add comment about deprecation

* Fix after merge with main

* Move orguser service/store to org service/store

* Remove orguser from wire

* Unimplement new Create user and use User from pkg user

* Fix wire generation

* Fix lint

* Fix lint - use only User and CrateUserCommand from user pkg

* Remove User and CreateUserCommand from models

* Fix lint 2
This commit is contained in:
idafurjes
2022-06-28 14:32:25 +02:00
committed by GitHub
parent 2429fe1c70
commit 6c43eb0b4d
105 changed files with 1524 additions and 701 deletions
@@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
type getUserPermissionsTestCase struct {
@@ -81,7 +82,7 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
user, team := createUserAndTeam(t, sql, tt.orgID)
for _, id := range tt.userPermissions {
_, err := store.SetUserResourcePermission(context.Background(), tt.orgID, accesscontrol.User{ID: user.Id}, types.SetResourcePermissionCommand{
_, err := store.SetUserResourcePermission(context.Background(), tt.orgID, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"},
Resource: "dashboards",
ResourceID: id,
@@ -119,7 +120,7 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
permissions, err := store.GetUserPermissions(context.Background(), accesscontrol.GetUserPermissionsQuery{
OrgID: tt.orgID,
UserID: user.Id,
UserID: user.ID,
Roles: roles,
Actions: tt.actions,
})
@@ -130,19 +131,19 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
}
}
func createUserAndTeam(t *testing.T, sql *sqlstore.SQLStore, orgID int64) (*models.User, models.Team) {
func createUserAndTeam(t *testing.T, sql *sqlstore.SQLStore, orgID int64) (*user.User, models.Team) {
t.Helper()
user, err := sql.CreateUser(context.Background(), models.CreateUserCommand{
user, err := sql.CreateUser(context.Background(), user.CreateUserCommand{
Login: "user",
OrgId: orgID,
OrgID: orgID,
})
require.NoError(t, err)
team, err := sql.CreateTeam("team", "", orgID)
require.NoError(t, err)
err = sql.AddTeamMember(user.Id, orgID, team.Id, false, models.PERMISSION_VIEW)
err = sql.AddTeamMember(user.ID, orgID, team.Id, false, models.PERMISSION_VIEW)
require.NoError(t, err)
return user, team
@@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
const (
@@ -150,11 +151,11 @@ func generateTeamsAndUsers(b *testing.B, db *sqlstore.SQLStore, users int) ([]in
for u := 0; u < UsersPerTeam; u++ {
userName := fmt.Sprintf("%s%v", "user", globalUserId)
userEmail := fmt.Sprintf("%s@example.org", userName)
createUserCmd := models.CreateUserCommand{Email: userEmail, Name: userName, Login: userName, OrgId: 1}
createUserCmd := user.CreateUserCommand{Email: userEmail, Name: userName, Login: userName, OrgID: 1}
user, err := db.CreateUser(context.Background(), createUserCmd)
require.NoError(b, err)
userId := user.Id
userId := user.ID
globalUserId++
userIds = append(userIds, userId)
@@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
type setUserResourcePermissionTest struct {
@@ -448,13 +449,13 @@ func seedResourcePermissions(t *testing.T, store *AccessControlStore, sql *sqlst
org = &addedOrg
}
u, err := sql.CreateUser(context.Background(), models.CreateUserCommand{
u, err := sql.CreateUser(context.Background(), user.CreateUserCommand{
Login: fmt.Sprintf("user:%s%d", resourceID, i),
OrgId: org.Id,
OrgID: org.Id,
})
require.NoError(t, err)
_, err = store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: u.Id}, types.SetResourcePermissionCommand{
_, err = store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: u.ID}, types.SetResourcePermissionCommand{
Actions: actions,
Resource: resource,
ResourceID: resourceID,
@@ -19,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
)
@@ -400,7 +401,7 @@ func TestApi_setUserPermission(t *testing.T) {
server := setupTestServer(t, &models.SignedInUser{OrgId: 1, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}}, service)
// seed user
_, err := sql.CreateUser(context.Background(), models.CreateUserCommand{Login: "test", OrgId: 1})
_, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "test", OrgID: 1})
require.NoError(t, err)
recorder := setPermission(t, server, testOptions.Resource, tt.resourceID, tt.permission, "users", strconv.Itoa(int(tt.userID)))
@@ -502,9 +503,9 @@ func seedPermissions(t *testing.T, resourceID string, sql *sqlstore.SQLStore, se
_, err = service.SetTeamPermission(context.Background(), team.OrgId, team.Id, resourceID, "Edit")
require.NoError(t, err)
// seed user 1 with "View" permission on dashboard 1
u, err := sql.CreateUser(context.Background(), models.CreateUserCommand{Login: "test", OrgId: 1})
u, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "test", OrgID: 1})
require.NoError(t, err)
_, err = service.SetUserPermission(context.Background(), u.OrgId, accesscontrol.User{ID: u.Id}, resourceID, "View")
_, err = service.SetUserPermission(context.Background(), u.OrgID, accesscontrol.User{ID: u.ID}, resourceID, "View")
require.NoError(t, err)
// seed built in role Admin with "Edit" permission on dashboard 1
_, err = service.SetBuiltInRolePermission(context.Background(), 1, "Admin", resourceID, "Edit")
@@ -8,12 +8,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/database"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/licensing/licensingtest"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -43,7 +43,7 @@ func TestService_SetUserPermission(t *testing.T) {
})
// seed user
user, err := sql.CreateUser(context.Background(), models.CreateUserCommand{Login: "test", OrgId: 1})
user, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "test", OrgID: 1})
require.NoError(t, err)
var hookCalled bool
@@ -54,7 +54,7 @@ func TestService_SetUserPermission(t *testing.T) {
}
}
_, err = service.SetUserPermission(context.Background(), user.OrgId, accesscontrol.User{ID: user.Id}, "1", "")
_, err = service.SetUserPermission(context.Background(), user.OrgID, accesscontrol.User{ID: user.ID}, "1", "")
require.NoError(t, err)
assert.Equal(t, tt.callHook, hookCalled)
})
@@ -200,7 +200,7 @@ func TestService_SetPermissions(t *testing.T) {
service, sql := setupTestEnvironment(t, []accesscontrol.Permission{}, tt.options)
// seed user
_, err := sql.CreateUser(context.Background(), models.CreateUserCommand{Login: "user", OrgId: 1})
_, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "user", OrgID: 1})
require.NoError(t, err)
_, err = sql.CreateTeam("team", "", 1)
require.NoError(t, err)
+3 -2
View File
@@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
@@ -57,7 +58,7 @@ func (s *UserAuthTokenService) ActiveTokenCount(ctx context.Context) (int64, err
return count, err
}
func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *models.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
token, err := util.RandomHex(16)
if err != nil {
return nil, err
@@ -72,7 +73,7 @@ func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *models.Use
}
userAuthToken := userAuthToken{
UserId: user.Id,
UserId: user.ID,
AuthToken: hashedToken,
PrevAuthToken: hashedToken,
ClientIp: clientIPStr,
+8 -7
View File
@@ -14,13 +14,14 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
func TestUserAuthToken(t *testing.T) {
ctx := createTestContext(t)
user := &models.User{Id: int64(10)}
user := &user.User{ID: int64(10)}
// userID := user.Id
now := time.Date(2018, 12, 13, 13, 45, 0, 0, time.UTC)
@@ -49,7 +50,7 @@ func TestUserAuthToken(t *testing.T) {
userToken, err := ctx.tokenService.LookupToken(context.Background(), userToken.UnhashedToken)
require.Nil(t, err)
require.NotNil(t, userToken)
require.Equal(t, user.Id, userToken.UserId)
require.Equal(t, user.ID, userToken.UserId)
require.True(t, userToken.AuthTokenSeen)
storedAuthToken, err := ctx.getAuthTokenByID(userToken.Id)
@@ -104,21 +105,21 @@ func TestUserAuthToken(t *testing.T) {
require.NotNil(t, userToken2)
t.Run("Can get first user token", func(t *testing.T) {
token, err := ctx.tokenService.GetUserToken(context.Background(), user.Id, userToken.Id)
token, err := ctx.tokenService.GetUserToken(context.Background(), user.ID, userToken.Id)
require.Nil(t, err)
require.NotNil(t, token)
require.Equal(t, userToken.Id, token.Id)
})
t.Run("Can get second user token", func(t *testing.T) {
token, err := ctx.tokenService.GetUserToken(context.Background(), user.Id, userToken2.Id)
token, err := ctx.tokenService.GetUserToken(context.Background(), user.ID, userToken2.Id)
require.Nil(t, err)
require.NotNil(t, token)
require.Equal(t, userToken2.Id, token.Id)
})
t.Run("Can get user tokens", func(t *testing.T) {
tokens, err := ctx.tokenService.GetUserTokens(context.Background(), user.Id)
tokens, err := ctx.tokenService.GetUserTokens(context.Background(), user.ID)
require.Nil(t, err)
require.Equal(t, 2, len(tokens))
require.Equal(t, userToken.Id, tokens[0].Id)
@@ -126,7 +127,7 @@ func TestUserAuthToken(t *testing.T) {
})
t.Run("Can revoke all user tokens", func(t *testing.T) {
err := ctx.tokenService.RevokeAllUserTokens(context.Background(), user.Id)
err := ctx.tokenService.RevokeAllUserTokens(context.Background(), user.ID)
require.Nil(t, err)
model, err := ctx.getAuthTokenByID(userToken.Id)
@@ -143,7 +144,7 @@ func TestUserAuthToken(t *testing.T) {
t.Run("Can revoke all users tokens", func(t *testing.T) {
userIds := []int64{}
for i := 0; i < 3; i++ {
userId := user.Id + int64(i+1)
userId := user.ID + int64(i+1)
userIds = append(userIds, userId)
_, err := ctx.tokenService.CreateToken(context.Background(), user,
net.ParseIP("192.168.10.11"), "some user agent")
+4 -3
View File
@@ -5,10 +5,11 @@ import (
"net"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
)
type FakeUserAuthTokenService struct {
CreateTokenProvider func(ctx context.Context, user *models.User, clientIP net.IP, userAgent string) (*models.UserToken, error)
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
@@ -22,7 +23,7 @@ type FakeUserAuthTokenService struct {
func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
return &FakeUserAuthTokenService{
CreateTokenProvider: func(ctx context.Context, user *models.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
CreateTokenProvider: func(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
return &models.UserToken{
UserId: 0,
UnhashedToken: "",
@@ -64,7 +65,7 @@ func (s *FakeUserAuthTokenService) Init() error {
return nil
}
func (s *FakeUserAuthTokenService) CreateToken(ctx context.Context, user *models.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
func (s *FakeUserAuthTokenService) CreateToken(ctx context.Context, user *user.User, clientIP net.IP, userAgent string) (*models.UserToken, error) {
return s.CreateTokenProvider(context.Background(), user, clientIP, userAgent)
}
@@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/require"
@@ -81,7 +82,7 @@ func getContextHandler(t *testing.T) *ContextHandler {
authJWTSvc := models.NewFakeJWTService()
tracer := tracing.InitializeTracerForTest()
loginService := loginservice.LoginServiceMock{ExpectedUser: &models.User{Id: userID}}
loginService := loginservice.LoginServiceMock{ExpectedUser: &user.User{ID: userID}}
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, &FakeGetSignUserStore{})
authenticator := &fakeAuthenticator{}
@@ -246,7 +246,7 @@ func (auth *AuthProxy) LoginViaLDAP(reqCtx *models.ReqContext) (int64, error) {
return 0, err
}
return upsert.Result.Id, nil
return upsert.Result.ID, nil
}
// loginViaHeader logs in user from the header only
@@ -305,7 +305,7 @@ func (auth *AuthProxy) loginViaHeader(reqCtx *models.ReqContext) (int64, error)
return 0, err
}
return upsert.Result.Id, nil
return upsert.Result.ID, nil
}
// getDecodedHeader gets decoded value of a header with given headerName
@@ -7,14 +7,15 @@ import (
"net/http"
"testing"
"github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/login/loginservice"
"github.com/grafana/grafana/pkg/services/multildap"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -42,8 +43,8 @@ func prepareMiddleware(t *testing.T, remoteCache *remotecache.RemoteCache, confi
}
loginService := loginservice.LoginServiceMock{
ExpectedUser: &models.User{
Id: id,
ExpectedUser: &user.User{
ID: id,
},
}
@@ -348,11 +348,11 @@ func (h *ContextHandler) initContextWithBasicAuth(reqContext *models.ReqContext,
user := authQuery.User
query := models.GetSignedInUserQuery{UserId: user.Id, OrgId: orgID}
query := models.GetSignedInUserQuery{UserId: user.ID, OrgId: orgID}
if err := h.SQLStore.GetSignedInUserWithCacheCtx(ctx, &query); err != nil {
reqContext.Logger.Error(
"Failed at user signed in",
"id", user.Id,
"id", user.ID,
"org", orgID,
)
reqContext.JsonApiErr(401, InvalidUsernamePassword, err)
+10 -9
View File
@@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
@@ -14,7 +15,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
t.Skip("skipping integration test")
}
var sqlStore *sqlstore.SQLStore
var currentUser models.User
var currentUser user.User
var savedFolder, childDash *models.Dashboard
var dashboardStore *DashboardStore
@@ -87,7 +88,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
setup(t)
err := updateDashboardAcl(t, dashboardStore, savedFolder.Id, models.DashboardAcl{
OrgID: 1,
UserID: currentUser.Id,
UserID: currentUser.ID,
DashboardID: savedFolder.Id,
Permission: models.PERMISSION_EDIT,
})
@@ -106,7 +107,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
t.Run("Given child dashboard permission", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, childDash.Id, models.DashboardAcl{
OrgID: 1,
UserID: currentUser.Id,
UserID: currentUser.ID,
DashboardID: childDash.Id,
Permission: models.PERMISSION_EDIT,
})
@@ -131,7 +132,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
setup(t)
err := updateDashboardAcl(t, dashboardStore, childDash.Id, models.DashboardAcl{
OrgID: 1,
UserID: currentUser.Id,
UserID: currentUser.ID,
DashboardID: childDash.Id,
Permission: models.PERMISSION_EDIT,
})
@@ -158,7 +159,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
setup(t)
err := updateDashboardAcl(t, dashboardStore, savedFolder.Id, models.DashboardAcl{
OrgID: 1,
UserID: currentUser.Id,
UserID: currentUser.ID,
DashboardID: savedFolder.Id,
Permission: models.PERMISSION_EDIT,
})
@@ -171,7 +172,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
require.Equal(t, savedFolder.Id, q1.Result[0].DashboardId)
require.Equal(t, models.PERMISSION_EDIT, q1.Result[0].Permission)
require.Equal(t, "Edit", q1.Result[0].PermissionName)
require.Equal(t, currentUser.Id, q1.Result[0].UserId)
require.Equal(t, currentUser.ID, q1.Result[0].UserId)
require.Equal(t, currentUser.Login, q1.Result[0].UserLogin)
require.Equal(t, currentUser.Email, q1.Result[0].UserEmail)
@@ -248,15 +249,15 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
})
}
func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) models.User {
func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) user.User {
t.Helper()
sqlStore.Cfg.AutoAssignOrg = true
sqlStore.Cfg.AutoAssignOrgId = 1
sqlStore.Cfg.AutoAssignOrgRole = role
currentUserCmd := models.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin}
currentUserCmd := user.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin}
currentUser, err := sqlStore.CreateUser(context.Background(), currentUserCmd)
require.NoError(t, err)
q1 := models.GetUserOrgListQuery{UserId: currentUser.Id}
q1 := models.GetUserOrgListQuery{UserId: currentUser.ID}
err = sqlStore.GetUserOrgList(context.Background(), &q1)
require.NoError(t, err)
require.Equal(t, models.RoleType(role), q1.Result[0].Role)
@@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
@@ -18,7 +19,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Testing DB", func(t *testing.T) {
var sqlStore *sqlstore.SQLStore
var folder, dashInRoot, childDash *models.Dashboard
var currentUser models.User
var currentUser user.User
var dashboardStore *DashboardStore
setup := func() {
@@ -38,7 +39,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and no acls are set", func(t *testing.T) {
t.Run("should return all dashboards", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
OrgId: 1,
DashboardIds: []int64{folder.Id, dashInRoot.Id},
}
@@ -62,7 +63,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should not return folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
OrgId: 1, DashboardIds: []int64{folder.Id, dashInRoot.Id},
}
err := testSearchDashboards(dashboardStore, query)
@@ -74,13 +75,13 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("when the user is given permission", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, folder.Id, models.DashboardAcl{
DashboardID: folder.Id, OrgID: 1, UserID: currentUser.Id, Permission: models.PERMISSION_EDIT,
DashboardID: folder.Id, OrgID: 1, UserID: currentUser.ID, Permission: models.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should be able to access folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
OrgId: 1,
DashboardIds: []int64{folder.Id, dashInRoot.Id},
}
@@ -96,7 +97,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should be able to access folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{
UserId: currentUser.Id,
UserId: currentUser.ID,
OrgId: 1,
OrgRole: models.ROLE_ADMIN,
},
@@ -123,7 +124,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should not return folder or child", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id},
}
err := testSearchDashboards(dashboardStore, query)
require.NoError(t, err)
@@ -133,12 +134,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("when the user is given permission to child", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, childDash.Id, models.DashboardAcl{
DashboardID: childDash.Id, OrgID: 1, UserID: currentUser.Id, Permission: models.PERMISSION_EDIT,
DashboardID: childDash.Id, OrgID: 1, UserID: currentUser.ID, Permission: models.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should be able to search for child dashboard but not folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
query := &models.FindPersistedDashboardsQuery{SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
err := testSearchDashboards(dashboardStore, query)
require.NoError(t, err)
require.Equal(t, len(query.Result), 2)
@@ -151,7 +152,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should be able to search for child dash and folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{
UserId: currentUser.Id,
UserId: currentUser.ID,
OrgId: 1,
OrgRole: models.ROLE_ADMIN,
},
@@ -172,7 +173,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Given two dashboard folders with one dashboard each and one dashboard in the root folder", func(t *testing.T) {
var sqlStore *sqlstore.SQLStore
var folder1, folder2, dashInRoot, childDash1, childDash2 *models.Dashboard
var currentUser models.User
var currentUser user.User
var rootFolderId int64 = 0
setup2 := func() {
@@ -192,7 +193,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should return dashboards in root and expanded folder", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
FolderIds: []int64{
rootFolderId, folder1.Id}, SignedInUser: &models.SignedInUser{UserId: currentUser.Id,
rootFolderId, folder1.Id}, SignedInUser: &models.SignedInUser{UserId: currentUser.ID,
OrgId: 1, OrgRole: models.ROLE_VIEWER,
},
OrgId: 1,
@@ -219,7 +220,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should not return folder with acl or its children", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
OrgId: 1,
DashboardIds: []int64{folder1.Id, childDash1.Id, childDash2.Id, dashInRoot.Id},
}
@@ -235,7 +236,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should return folder without acl and its children", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
OrgId: 1,
DashboardIds: []int64{folder2.Id, childDash1.Id, childDash2.Id, dashInRoot.Id},
}
@@ -259,7 +260,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should return folder without acl but not the dashboard with acl", func(t *testing.T) {
query := &models.FindPersistedDashboardsQuery{
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: currentUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
OrgId: 1,
DashboardIds: []int64{folder2.Id, childDash1.Id, childDash2.Id, dashInRoot.Id},
}
@@ -278,7 +279,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Given two dashboard folders", func(t *testing.T) {
var sqlStore *sqlstore.SQLStore
var folder1, folder2 *models.Dashboard
var adminUser, editorUser, viewerUser models.User
var adminUser, editorUser, viewerUser user.User
setup3 := func() {
sqlStore = sqlstore.InitTestDB(t)
@@ -297,7 +298,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Should have write access to all dashboard folders in their org", func(t *testing.T) {
query := models.FindPersistedDashboardsQuery{
OrgId: 1,
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgRole: models.ROLE_ADMIN, OrgId: 1},
SignedInUser: &models.SignedInUser{UserId: adminUser.ID, OrgRole: models.ROLE_ADMIN, OrgId: 1},
Permission: models.PERMISSION_VIEW,
Type: "dash-folder",
}
@@ -312,7 +313,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should have edit permission in folders", func(t *testing.T) {
query := &models.HasEditPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_ADMIN},
SignedInUser: &models.SignedInUser{UserId: adminUser.ID, OrgId: 1, OrgRole: models.ROLE_ADMIN},
}
err := dashboardStore.HasEditPermissionInFolders(context.Background(), query)
require.NoError(t, err)
@@ -321,7 +322,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should have admin permission in folders", func(t *testing.T) {
query := &models.HasAdminPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_ADMIN},
SignedInUser: &models.SignedInUser{UserId: adminUser.ID, OrgId: 1, OrgRole: models.ROLE_ADMIN},
}
err := dashboardStore.HasAdminPermissionInFolders(context.Background(), query)
require.NoError(t, err)
@@ -332,7 +333,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Editor users", func(t *testing.T) {
query := models.FindPersistedDashboardsQuery{
OrgId: 1,
SignedInUser: &models.SignedInUser{UserId: editorUser.Id, OrgRole: models.ROLE_EDITOR, OrgId: 1},
SignedInUser: &models.SignedInUser{UserId: editorUser.ID, OrgRole: models.ROLE_EDITOR, OrgId: 1},
Permission: models.PERMISSION_EDIT,
}
@@ -347,7 +348,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Should have write access to one dashboard folder if default role changed to view for one folder", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, folder1.Id, models.DashboardAcl{
DashboardID: folder1.Id, OrgID: 1, UserID: editorUser.Id, Permission: models.PERMISSION_VIEW,
DashboardID: folder1.Id, OrgID: 1, UserID: editorUser.ID, Permission: models.PERMISSION_VIEW,
})
require.NoError(t, err)
@@ -360,7 +361,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should have edit permission in folders", func(t *testing.T) {
query := &models.HasEditPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: editorUser.Id, OrgId: 1, OrgRole: models.ROLE_EDITOR},
SignedInUser: &models.SignedInUser{UserId: editorUser.ID, OrgId: 1, OrgRole: models.ROLE_EDITOR},
}
err := dashboardStore.HasEditPermissionInFolders(context.Background(), query)
go require.NoError(t, err)
@@ -369,7 +370,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should not have admin permission in folders", func(t *testing.T) {
query := &models.HasAdminPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_EDITOR},
SignedInUser: &models.SignedInUser{UserId: adminUser.ID, OrgId: 1, OrgRole: models.ROLE_EDITOR},
}
err := dashboardStore.HasAdminPermissionInFolders(context.Background(), query)
require.NoError(t, err)
@@ -380,7 +381,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Viewer users", func(t *testing.T) {
query := models.FindPersistedDashboardsQuery{
OrgId: 1,
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgRole: models.ROLE_VIEWER, OrgId: 1},
SignedInUser: &models.SignedInUser{UserId: viewerUser.ID, OrgRole: models.ROLE_VIEWER, OrgId: 1},
Permission: models.PERMISSION_EDIT,
}
@@ -393,7 +394,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("Should be able to get one dashboard folder if default role changed to edit for one folder", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, folder1.Id, models.DashboardAcl{
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.Id, Permission: models.PERMISSION_EDIT,
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.ID, Permission: models.PERMISSION_EDIT,
})
require.NoError(t, err)
@@ -408,7 +409,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
setup3()
query := &models.HasEditPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: viewerUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
}
err := dashboardStore.HasEditPermissionInFolders(context.Background(), query)
go require.NoError(t, err)
@@ -417,7 +418,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("should not have admin permission in folders", func(t *testing.T) {
query := &models.HasAdminPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: adminUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
}
err := dashboardStore.HasAdminPermissionInFolders(context.Background(), query)
require.NoError(t, err)
@@ -426,13 +427,13 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and admin permission is given for user with org role viewer in one dashboard folder", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, folder1.Id, models.DashboardAcl{
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.Id, Permission: models.PERMISSION_ADMIN,
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.ID, Permission: models.PERMISSION_ADMIN,
})
require.NoError(t, err)
t.Run("should have edit permission in folders", func(t *testing.T) {
query := &models.HasEditPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: viewerUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
}
err := dashboardStore.HasEditPermissionInFolders(context.Background(), query)
go require.NoError(t, err)
@@ -442,13 +443,13 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
t.Run("and edit permission is given for user with org role viewer in one dashboard folder", func(t *testing.T) {
err := updateDashboardAcl(t, dashboardStore, folder1.Id, models.DashboardAcl{
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.Id, Permission: models.PERMISSION_EDIT,
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.ID, Permission: models.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("should have edit permission in folders", func(t *testing.T) {
query := &models.HasEditPermissionInFoldersQuery{
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
SignedInUser: &models.SignedInUser{UserId: viewerUser.ID, OrgId: 1, OrgRole: models.ROLE_VIEWER},
}
err := dashboardStore.HasEditPermissionInFolders(context.Background(), query)
go require.NoError(t, err)
@@ -18,6 +18,7 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/star/starimpl"
"github.com/grafana/grafana/pkg/services/user"
)
func TestIntegrationDashboardDataAccess(t *testing.T) {
@@ -666,15 +667,15 @@ func insertTestRule(t *testing.T, sqlStore *sqlstore.SQLStore, foderOrgID int64,
require.NoError(t, err)
}
func CreateUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) models.User {
func CreateUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) user.User {
t.Helper()
sqlStore.Cfg.AutoAssignOrg = true
sqlStore.Cfg.AutoAssignOrgId = 1
sqlStore.Cfg.AutoAssignOrgRole = role
currentUserCmd := models.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin}
currentUserCmd := user.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin}
currentUser, err := sqlStore.CreateUser(context.Background(), currentUserCmd)
require.NoError(t, err)
q1 := models.GetUserOrgListQuery{UserId: currentUser.Id}
q1 := models.GetUserOrgListQuery{UserId: currentUser.ID}
err = sqlStore.GetUserOrgList(context.Background(), &q1)
require.NoError(t, err)
require.Equal(t, models.RoleType(role), q1.Result[0].Role)
@@ -25,6 +25,7 @@ import (
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
)
@@ -345,7 +346,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
),
}
user := models.SignedInUser{
usr := models.SignedInUser{
UserId: 1,
Name: "Signed In User",
Login: "signed_in_user",
@@ -358,7 +359,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
// deliberate difference between signed in user and user in db to make it crystal clear
// what to expect in the tests
// In the real world these are identical
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: "user.in.db@test.com",
Name: "User In DB",
Login: userInDbName,
@@ -368,13 +369,13 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
require.NoError(t, err)
sc := scenarioContext{
user: user,
user: usr,
ctx: &ctx,
service: &service,
sqlStore: sqlStore,
reqContext: &models.ReqContext{
Context: &ctx,
SignedInUser: &user,
SignedInUser: &usr,
},
}
@@ -24,6 +24,7 @@ import (
"github.com/grafana/grafana/pkg/services/libraryelements"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -1507,7 +1508,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
LibraryElementService: elementService,
}
user := &models.SignedInUser{
usr := &models.SignedInUser{
UserId: 1,
Name: "Signed In User",
Login: "signed_in_user",
@@ -1520,7 +1521,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
// deliberate difference between signed in user and user in db to make it crystal clear
// what to expect in the tests
// In the real world these are identical
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: "user.in.db@test.com",
Name: "User In DB",
Login: userInDbName,
@@ -1530,7 +1531,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
require.NoError(t, err)
sc := scenarioContext{
user: user,
user: usr,
ctx: context.Background(),
service: &service,
elementService: elementService,
+2 -1
View File
@@ -4,10 +4,11 @@ import (
"context"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
)
type AuthInfoService interface {
LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*models.User, error)
LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*user.User, error)
GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error
GetExternalUserInfoByLogin(ctx context.Context, query *models.GetExternalUserInfoByLoginQuery) error
SetAuthInfo(ctx context.Context, cmd *models.SetAuthInfoCommand) error
@@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
var GetTime = time.Now
@@ -35,13 +36,13 @@ func (s *AuthInfoStore) GetExternalUserInfoByLogin(ctx context.Context, query *m
return err
}
authInfoQuery := &models.GetAuthInfoQuery{UserId: userQuery.Result.Id}
authInfoQuery := &models.GetAuthInfoQuery{UserId: userQuery.Result.ID}
if err := s.GetAuthInfo(ctx, authInfoQuery); err != nil {
return err
}
query.Result = &models.ExternalUserInfo{
UserId: userQuery.Result.Id,
UserId: userQuery.Result.ID,
Login: userQuery.Result.Login,
Email: userQuery.Result.Email,
Name: userQuery.Result.Name,
@@ -218,7 +219,7 @@ func (s *AuthInfoStore) DeleteAuthInfo(ctx context.Context, cmd *models.DeleteAu
})
}
func (s *AuthInfoStore) GetUserById(ctx context.Context, id int64) (*models.User, error) {
func (s *AuthInfoStore) GetUserById(ctx context.Context, id int64) (*user.User, error) {
query := models.GetUserByIdQuery{Id: id}
if err := s.sqlStore.GetUserById(ctx, &query); err != nil {
return nil, err
@@ -227,7 +228,7 @@ func (s *AuthInfoStore) GetUserById(ctx context.Context, id int64) (*models.User
return query.Result, nil
}
func (s *AuthInfoStore) GetUserByLogin(ctx context.Context, login string) (*models.User, error) {
func (s *AuthInfoStore) GetUserByLogin(ctx context.Context, login string) (*user.User, error) {
query := models.GetUserByLoginQuery{LoginOrEmail: login}
if err := s.sqlStore.GetUserByLogin(ctx, &query); err != nil {
return nil, err
@@ -236,7 +237,7 @@ func (s *AuthInfoStore) GetUserByLogin(ctx context.Context, login string) (*mode
return query.Result, nil
}
func (s *AuthInfoStore) GetUserByEmail(ctx context.Context, email string) (*models.User, error) {
func (s *AuthInfoStore) GetUserByEmail(ctx context.Context, email string) (*user.User, error) {
query := models.GetUserByEmailQuery{Email: email}
if err := s.sqlStore.GetUserByEmail(ctx, &query); err != nil {
return nil, err
@@ -8,6 +8,7 @@ import (
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/user"
)
const genericOAuthModule = "oauth_generic_oauth"
@@ -28,7 +29,7 @@ func ProvideAuthInfoService(userProtectionService login.UserProtectionService, a
return s
}
func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUserByAuthInfoQuery) (bool, *models.User, *models.UserAuth, error) {
func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUserByAuthInfoQuery) (bool, *user.User, *models.UserAuth, error) {
authQuery := &models.GetAuthInfoQuery{}
// Try to find the user by auth module and id first
@@ -77,8 +78,8 @@ func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUser
return false, nil, nil, models.ErrUserNotFound
}
func (s *Implementation) LookupByOneOf(ctx context.Context, userId int64, email string, login string) (*models.User, error) {
var user *models.User
func (s *Implementation) LookupByOneOf(ctx context.Context, userId int64, email string, login string) (*user.User, error) {
var user *user.User
var err error
// If not found, try to find the user by id
@@ -128,7 +129,7 @@ func (s *Implementation) GenericOAuthLookup(ctx context.Context, authModule stri
return nil, nil
}
func (s *Implementation) LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*models.User, error) {
func (s *Implementation) LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*user.User, error) {
// 1. LookupAndFix = auth info, user, error
// TODO: Not a big fan of the fact that we are deleting auth info here, might want to move that
foundUser, user, authInfo, err := s.LookupAndFix(ctx, query)
@@ -149,7 +150,7 @@ func (s *Implementation) LookupAndUpdate(ctx context.Context, query *models.GetU
}
// Special case for generic oauth duplicates
ai, err := s.GenericOAuthLookup(ctx, query.AuthModule, query.AuthId, user.Id)
ai, err := s.GenericOAuthLookup(ctx, query.AuthModule, query.AuthId, user.ID)
if !errors.Is(err, models.ErrUserNotFound) {
if err != nil {
return nil, err
@@ -162,7 +163,7 @@ func (s *Implementation) LookupAndUpdate(ctx context.Context, query *models.GetU
if query.AuthModule != "" {
if authInfo == nil {
cmd := &models.SetAuthInfoCommand{
UserId: user.Id,
UserId: user.ID,
AuthModule: query.AuthModule,
AuthId: query.AuthId,
}
@@ -12,6 +12,7 @@ import (
secretstore "github.com/grafana/grafana/pkg/services/secrets/database"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"
)
@@ -29,7 +30,7 @@ func TestUserAuth(t *testing.T) {
t.Run("Given 5 users", func(t *testing.T) {
for i := 0; i < 5; i++ {
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -49,12 +50,12 @@ func TestUserAuth(t *testing.T) {
require.Equal(t, user.Login, login)
// By ID
id := user.Id
id := user.ID
user, err = srv.LookupByOneOf(context.Background(), id, "", "")
require.Nil(t, err)
require.Equal(t, user.Id, id)
require.Equal(t, user.ID, id)
// By Email
email := "user1@test.com"
@@ -98,7 +99,7 @@ func TestUserAuth(t *testing.T) {
require.Equal(t, user.Login, login)
// get with non-matching id
id := user.Id
id := user.ID
query.UserId = id + 1
user, err = srv.LookupAndUpdate(context.Background(), query)
@@ -115,7 +116,7 @@ func TestUserAuth(t *testing.T) {
// remove user
err = sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
_, err := sess.Exec("DELETE FROM "+sqlStore.Dialect.Quote("user")+" WHERE id=?", user.Id)
_, err := sess.Exec("DELETE FROM "+sqlStore.Dialect.Quote("user")+" WHERE id=?", user.ID)
return err
})
require.NoError(t, err)
@@ -149,7 +150,7 @@ func TestUserAuth(t *testing.T) {
require.Equal(t, user.Login, login)
cmd := &models.UpdateAuthInfoCommand{
UserId: user.Id,
UserId: user.ID,
AuthId: query.AuthId,
AuthModule: query.AuthModule,
OAuthToken: token,
@@ -159,7 +160,7 @@ func TestUserAuth(t *testing.T) {
require.Nil(t, err)
getAuthQuery := &models.GetAuthInfoQuery{
UserId: user.Id,
UserId: user.ID,
}
err = srv.authInfoStore.GetAuthInfo(context.Background(), getAuthQuery)
@@ -176,7 +177,7 @@ func TestUserAuth(t *testing.T) {
sqlStore = sqlstore.InitTestDB(t)
for i := 0; i < 5; i++ {
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -210,7 +211,7 @@ func TestUserAuth(t *testing.T) {
// Get the latest entry by not supply an authmodule or authid
getAuthQuery := &models.GetAuthInfoQuery{
UserId: user.Id,
UserId: user.ID,
}
err = authInfoStore.GetAuthInfo(context.Background(), getAuthQuery)
@@ -219,14 +220,14 @@ func TestUserAuth(t *testing.T) {
require.Equal(t, getAuthQuery.Result.AuthModule, "test2")
// "log in" again with the first auth module
updateAuthCmd := &models.UpdateAuthInfoCommand{UserId: user.Id, AuthModule: "test1", AuthId: "test1"}
updateAuthCmd := &models.UpdateAuthInfoCommand{UserId: user.ID, AuthModule: "test1", AuthId: "test1"}
err = authInfoStore.UpdateAuthInfo(context.Background(), updateAuthCmd)
require.Nil(t, err)
// Get the latest entry by not supply an authmodule or authid
getAuthQuery = &models.GetAuthInfoQuery{
UserId: user.Id,
UserId: user.ID,
}
err = authInfoStore.GetAuthInfo(context.Background(), getAuthQuery)
@@ -240,7 +241,7 @@ func TestUserAuth(t *testing.T) {
sqlStore = sqlstore.InitTestDB(t)
for i := 0; i < 5; i++ {
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -273,7 +274,7 @@ func TestUserAuth(t *testing.T) {
// Get the latest entry by not supply an authmodule or authid
getAuthQuery := &models.GetAuthInfoQuery{
UserId: user.Id,
UserId: user.ID,
}
err = authInfoStore.GetAuthInfo(context.Background(), getAuthQuery)
@@ -285,7 +286,7 @@ func TestUserAuth(t *testing.T) {
database.GetTime = func() time.Time { return fixedTime }
// add oauth info to auth_info to make sure update date does not overwrite it
updateAuthCmd := &models.UpdateAuthInfoCommand{UserId: user.Id, AuthModule: "test1", AuthId: "test1", OAuthToken: &oauth2.Token{
updateAuthCmd := &models.UpdateAuthInfoCommand{UserId: user.ID, AuthModule: "test1", AuthId: "test1", OAuthToken: &oauth2.Token{
AccessToken: "access_token",
TokenType: "token_type",
RefreshToken: "refresh_token",
@@ -317,7 +318,7 @@ func TestUserAuth(t *testing.T) {
// Ensure test 1 did not have its entry modified
getAuthQueryUnchanged := &models.GetAuthInfoQuery{
UserId: user.Id,
UserId: user.ID,
AuthModule: "test1",
}
err = authInfoStore.GetAuthInfo(context.Background(), getAuthQueryUnchanged)
@@ -354,11 +355,11 @@ func TestUserAuth(t *testing.T) {
sqlStore = sqlstore.InitTestDB(t)
for i := 0; i < 5; i++ {
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
OrgId: 1,
OrgID: 1,
}
_, err := sqlStore.CreateUser(context.Background(), cmd)
require.Nil(t, err)
@@ -366,7 +367,7 @@ func TestUserAuth(t *testing.T) {
// "Skipping duplicate users test for mysql as it does make unique constraint case insensitive by default
if sqlStore.GetDialect().DriverName() != "mysql" {
dupUserEmailcmd := models.CreateUserCommand{
dupUserEmailcmd := user.CreateUserCommand{
Email: "USERDUPLICATETEST1@TEST.COM",
Name: "user name 1",
Login: "USER_DUPLICATE_TEST_1_LOGIN",
@@ -375,7 +376,7 @@ func TestUserAuth(t *testing.T) {
require.NoError(t, err)
// add additional user with duplicate login where DOMAIN is upper case
dupUserLogincmd := models.CreateUserCommand{
dupUserLogincmd := user.CreateUserCommand{
Email: "userduplicatetest1@test.com",
Name: "user name 1",
Login: "user_duplicate_test_1_login",
@@ -1,8 +1,6 @@
package authinfoservice
import (
"github.com/grafana/grafana/pkg/models"
)
import "github.com/grafana/grafana/pkg/services/user"
type OSSUserProtectionImpl struct {
}
@@ -11,6 +9,6 @@ func ProvideOSSUserProtectionService() *OSSUserProtectionImpl {
return &OSSUserProtectionImpl{}
}
func (*OSSUserProtectionImpl) AllowUserMapping(_ *models.User, _ string) error {
func (*OSSUserProtectionImpl) AllowUserMapping(_ *user.User, _ string) error {
return nil
}
+3 -2
View File
@@ -5,6 +5,7 @@ import (
"errors"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
)
var (
@@ -14,10 +15,10 @@ var (
ErrSignupNotAllowed = errors.New("system administrator has disabled signup")
)
type TeamSyncFunc func(user *models.User, externalUser *models.ExternalUserInfo) error
type TeamSyncFunc func(user *user.User, externalUser *models.ExternalUserInfo) error
type Service interface {
CreateUser(cmd models.CreateUserCommand) (*models.User, error)
CreateUser(cmd user.CreateUserCommand) (*user.User, error)
UpsertUser(ctx context.Context, cmd *models.UpsertUserCommand) error
DisableExternalUser(ctx context.Context, username string) error
SetTeamSyncFunc(TeamSyncFunc)
+53 -28
View File
@@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
var (
@@ -17,11 +18,13 @@ var (
func ProvideService(
sqlStore sqlstore.Store,
userService user.Service,
quotaService *quota.QuotaService,
authInfoService login.AuthInfoService,
) *Implementation {
s := &Implementation{
SQLStore: sqlStore,
userService: userService,
QuotaService: quotaService,
AuthInfoService: authInfoService,
}
@@ -30,13 +33,14 @@ func ProvideService(
type Implementation struct {
SQLStore sqlstore.Store
userService user.Service
AuthInfoService login.AuthInfoService
QuotaService *quota.QuotaService
TeamSync login.TeamSyncFunc
}
// CreateUser creates inserts a new one.
func (ls *Implementation) CreateUser(cmd models.CreateUserCommand) (*models.User, error) {
func (ls *Implementation) CreateUser(cmd user.CreateUserCommand) (*user.User, error) {
return ls.SQLStore.CreateUser(context.Background(), cmd)
}
@@ -44,7 +48,7 @@ func (ls *Implementation) CreateUser(cmd models.CreateUserCommand) (*models.User
func (ls *Implementation) UpsertUser(ctx context.Context, cmd *models.UpsertUserCommand) error {
extUser := cmd.ExternalUser
user, err := ls.AuthInfoService.LookupAndUpdate(ctx, &models.GetUserByAuthInfoQuery{
usr, err := ls.AuthInfoService.LookupAndUpdate(ctx, &models.GetUserByAuthInfoQuery{
AuthModule: extUser.AuthModule,
AuthId: extUser.AuthId,
UserId: extUser.UserId,
@@ -69,14 +73,36 @@ func (ls *Implementation) UpsertUser(ctx context.Context, cmd *models.UpsertUser
return login.ErrUsersQuotaReached
}
cmd.Result, err = ls.createUser(extUser)
result, err := ls.createUser(extUser)
if err != nil {
return err
}
cmd.Result = &user.User{
ID: result.ID,
Version: result.Version,
Email: result.Email,
Name: result.Name,
Login: result.Login,
Password: result.Password,
Salt: result.Salt,
Rands: result.Rands,
Company: result.Company,
EmailVerified: result.EmailVerified,
Theme: result.Theme,
HelpFlags1: result.HelpFlags1,
IsDisabled: result.IsDisabled,
IsAdmin: result.IsAdmin,
IsServiceAccount: result.IsServiceAccount,
OrgID: result.OrgID,
Created: result.Created,
Updated: result.Updated,
LastSeenAt: result.LastSeenAt,
}
if extUser.AuthModule != "" {
cmd2 := &models.SetAuthInfoCommand{
UserId: cmd.Result.Id,
UserId: cmd.Result.ID,
AuthModule: extUser.AuthModule,
AuthId: extUser.AuthId,
OAuthToken: extUser.OAuthToken,
@@ -86,7 +112,7 @@ func (ls *Implementation) UpsertUser(ctx context.Context, cmd *models.UpsertUser
}
}
} else {
cmd.Result = user
cmd.Result = usr
err = ls.updateUser(ctx, cmd.Result, extUser)
if err != nil {
@@ -101,9 +127,9 @@ func (ls *Implementation) UpsertUser(ctx context.Context, cmd *models.UpsertUser
}
}
if extUser.AuthModule == models.AuthModuleLDAP && user.IsDisabled {
if extUser.AuthModule == models.AuthModuleLDAP && usr.IsDisabled {
// Re-enable user when it found in LDAP
if err := ls.SQLStore.DisableUser(ctx, &models.DisableUserCommand{UserId: cmd.Result.Id, IsDisabled: false}); err != nil {
if err := ls.SQLStore.DisableUser(ctx, &models.DisableUserCommand{UserId: cmd.Result.ID, IsDisabled: false}); err != nil {
return err
}
}
@@ -115,7 +141,7 @@ func (ls *Implementation) UpsertUser(ctx context.Context, cmd *models.UpsertUser
// Sync isGrafanaAdmin permission
if extUser.IsGrafanaAdmin != nil && *extUser.IsGrafanaAdmin != cmd.Result.IsAdmin {
if err := ls.SQLStore.UpdateUserPermissions(cmd.Result.Id, *extUser.IsGrafanaAdmin); err != nil {
if err := ls.SQLStore.UpdateUserPermissions(cmd.Result.ID, *extUser.IsGrafanaAdmin); err != nil {
return err
}
}
@@ -175,21 +201,20 @@ func (ls *Implementation) SetTeamSyncFunc(teamSyncFunc login.TeamSyncFunc) {
ls.TeamSync = teamSyncFunc
}
func (ls *Implementation) createUser(extUser *models.ExternalUserInfo) (*models.User, error) {
cmd := models.CreateUserCommand{
func (ls *Implementation) createUser(extUser *models.ExternalUserInfo) (*user.User, error) {
cmd := user.CreateUserCommand{
Login: extUser.Login,
Email: extUser.Email,
Name: extUser.Name,
SkipOrgSetup: len(extUser.OrgRoles) > 0,
}
return ls.CreateUser(cmd)
}
func (ls *Implementation) updateUser(ctx context.Context, user *models.User, extUser *models.ExternalUserInfo) error {
func (ls *Implementation) updateUser(ctx context.Context, user *user.User, extUser *models.ExternalUserInfo) error {
// sync user info
updateCmd := &models.UpdateUserCommand{
UserId: user.Id,
UserId: user.ID,
}
needsUpdate := false
@@ -215,24 +240,24 @@ func (ls *Implementation) updateUser(ctx context.Context, user *models.User, ext
return nil
}
logger.Debug("Syncing user info", "id", user.Id, "update", updateCmd)
logger.Debug("Syncing user info", "id", user.ID, "update", updateCmd)
return ls.SQLStore.UpdateUser(ctx, updateCmd)
}
func (ls *Implementation) updateUserAuth(ctx context.Context, user *models.User, extUser *models.ExternalUserInfo) error {
func (ls *Implementation) updateUserAuth(ctx context.Context, user *user.User, extUser *models.ExternalUserInfo) error {
updateCmd := &models.UpdateAuthInfoCommand{
AuthModule: extUser.AuthModule,
AuthId: extUser.AuthId,
UserId: user.Id,
UserId: user.ID,
OAuthToken: extUser.OAuthToken,
}
logger.Debug("Updating user_auth info", "user_id", user.Id)
logger.Debug("Updating user_auth info", "user_id", user.ID)
return ls.AuthInfoService.UpdateAuthInfo(ctx, updateCmd)
}
func (ls *Implementation) syncOrgRoles(ctx context.Context, user *models.User, extUser *models.ExternalUserInfo) error {
logger.Debug("Syncing organization roles", "id", user.Id, "extOrgRoles", extUser.OrgRoles)
func (ls *Implementation) syncOrgRoles(ctx context.Context, user *user.User, extUser *models.ExternalUserInfo) error {
logger.Debug("Syncing organization roles", "id", user.ID, "extOrgRoles", extUser.OrgRoles)
// don't sync org roles if none is specified
if len(extUser.OrgRoles) == 0 {
@@ -240,7 +265,7 @@ func (ls *Implementation) syncOrgRoles(ctx context.Context, user *models.User, e
return nil
}
orgsQuery := &models.GetUserOrgListQuery{UserId: user.Id}
orgsQuery := &models.GetUserOrgListQuery{UserId: user.ID}
if err := ls.SQLStore.GetUserOrgList(ctx, orgsQuery); err != nil {
return err
}
@@ -257,7 +282,7 @@ func (ls *Implementation) syncOrgRoles(ctx context.Context, user *models.User, e
deleteOrgIds = append(deleteOrgIds, org.OrgId)
} else if extRole != org.Role {
// update role
cmd := &models.UpdateOrgUserCommand{OrgId: org.OrgId, UserId: user.Id, Role: extRole}
cmd := &models.UpdateOrgUserCommand{OrgId: org.OrgId, UserId: user.ID, Role: extRole}
if err := ls.SQLStore.UpdateOrgUser(ctx, cmd); err != nil {
return err
}
@@ -271,7 +296,7 @@ func (ls *Implementation) syncOrgRoles(ctx context.Context, user *models.User, e
}
// add role
cmd := &models.AddOrgUserCommand{UserId: user.Id, Role: orgRole, OrgId: orgId}
cmd := &models.AddOrgUserCommand{UserId: user.ID, Role: orgRole, OrgId: orgId}
err := ls.SQLStore.AddOrgUser(ctx, cmd)
if err != nil && !errors.Is(err, models.ErrOrgNotFound) {
return err
@@ -281,8 +306,8 @@ func (ls *Implementation) syncOrgRoles(ctx context.Context, user *models.User, e
// delete any removed org roles
for _, orgId := range deleteOrgIds {
logger.Debug("Removing user's organization membership as part of syncing with OAuth login",
"userId", user.Id, "orgId", orgId)
cmd := &models.RemoveOrgUserCommand{OrgId: orgId, UserId: user.Id}
"userId", user.ID, "orgId", orgId)
cmd := &models.RemoveOrgUserCommand{OrgId: orgId, UserId: user.ID}
if err := ls.SQLStore.RemoveOrgUser(ctx, cmd); err != nil {
if errors.Is(err, models.ErrLastOrgAdmin) {
logger.Error(err.Error(), "userId", cmd.UserId, "orgId", cmd.OrgId)
@@ -294,15 +319,15 @@ func (ls *Implementation) syncOrgRoles(ctx context.Context, user *models.User, e
}
// update user's default org if needed
if _, ok := extUser.OrgRoles[user.OrgId]; !ok {
if _, ok := extUser.OrgRoles[user.OrgID]; !ok {
for orgId := range extUser.OrgRoles {
user.OrgId = orgId
user.OrgID = orgId
break
}
return ls.SQLStore.SetUsingOrg(ctx, &models.SetUsingOrgCommand{
UserId: user.Id,
OrgId: user.OrgId,
UserId: user.ID,
OrgId: user.OrgID,
})
}
@@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/user"
)
type LoginServiceMock struct {
@@ -15,13 +16,13 @@ type LoginServiceMock struct {
NoExistingOrgId int64
AlreadyExitingLogin string
GeneratedUserId int64
ExpectedUser *models.User
ExpectedUserFunc func(cmd *models.UpsertUserCommand) *models.User
ExpectedUser *user.User
ExpectedUserFunc func(cmd *models.UpsertUserCommand) *user.User
ExpectedError error
}
func (s LoginServiceMock) CreateUser(cmd models.CreateUserCommand) (*models.User, error) {
if cmd.OrgId == s.NoExistingOrgId {
func (s LoginServiceMock) CreateUser(cmd user.CreateUserCommand) (*user.User, error) {
if cmd.OrgID == s.NoExistingOrgId {
return nil, models.ErrOrgNotFound
}
@@ -30,8 +31,8 @@ func (s LoginServiceMock) CreateUser(cmd models.CreateUserCommand) (*models.User
}
if s.ExpectedUserForm.Login == cmd.Login && s.ExpectedUserForm.Email == cmd.Email &&
s.ExpectedUserForm.Password == cmd.Password && s.ExpectedUserForm.Name == cmd.Name && s.ExpectedUserForm.OrgId == cmd.OrgId {
return &models.User{Id: s.GeneratedUserId}, nil
s.ExpectedUserForm.Password == cmd.Password && s.ExpectedUserForm.Name == cmd.Name && s.ExpectedUserForm.OrgId == cmd.OrgID {
return &user.User{ID: s.GeneratedUserId}, nil
}
return nil, errors.New("unexpected cmd")
@@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/login/logintest"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -69,15 +70,15 @@ func Test_teamSync(t *testing.T) {
}
upserCmd := &models.UpsertUserCommand{ExternalUser: &models.ExternalUserInfo{Email: "test_user@example.org"}}
expectedUser := &models.User{
Id: 1,
expectedUser := &user.User{
ID: 1,
Email: "test_user@example.org",
Name: "test_user",
Login: "test_user",
}
authInfoMock.ExpectedUser = expectedUser
var actualUser *models.User
var actualUser *user.User
var actualExternalUser *models.ExternalUserInfo
t.Run("login.TeamSync should not be called when nil", func(t *testing.T) {
@@ -87,7 +88,7 @@ func Test_teamSync(t *testing.T) {
assert.Nil(t, actualExternalUser)
t.Run("login.TeamSync should be called when not nil", func(t *testing.T) {
teamSyncFunc := func(user *models.User, externalUser *models.ExternalUserInfo) error {
teamSyncFunc := func(user *user.User, externalUser *models.ExternalUserInfo) error {
actualUser = user
actualExternalUser = externalUser
return nil
@@ -100,7 +101,7 @@ func Test_teamSync(t *testing.T) {
})
t.Run("login.TeamSync should propagate its errors to the caller", func(t *testing.T) {
teamSyncFunc := func(user *models.User, externalUser *models.ExternalUserInfo) error {
teamSyncFunc := func(user *user.User, externalUser *models.ExternalUserInfo) error {
return errors.New("teamsync test error")
}
login.TeamSync = teamSyncFunc
@@ -110,9 +111,9 @@ func Test_teamSync(t *testing.T) {
})
}
func createSimpleUser() models.User {
user := models.User{
Id: 1,
func createSimpleUser() user.User {
user := user.User{
ID: 1,
}
return user
+5 -4
View File
@@ -5,11 +5,12 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/user"
)
type LoginServiceFake struct{}
func (l *LoginServiceFake) CreateUser(cmd models.CreateUserCommand) (*models.User, error) {
func (l *LoginServiceFake) CreateUser(cmd user.CreateUserCommand) (*user.User, error) {
return nil, nil
}
func (l *LoginServiceFake) UpsertUser(ctx context.Context, cmd *models.UpsertUserCommand) error {
@@ -22,12 +23,12 @@ func (l *LoginServiceFake) SetTeamSyncFunc(login.TeamSyncFunc) {}
type AuthInfoServiceFake struct {
LatestUserID int64
ExpectedUser *models.User
ExpectedUser *user.User
ExpectedExternalUser *models.ExternalUserInfo
ExpectedError error
}
func (a *AuthInfoServiceFake) LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*models.User, error) {
func (a *AuthInfoServiceFake) LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*user.User, error) {
a.LatestUserID = query.UserId
return a.ExpectedUser, a.ExpectedError
}
@@ -51,7 +52,7 @@ func (a *AuthInfoServiceFake) GetExternalUserInfoByLogin(ctx context.Context, qu
}
type AuthenticatorFake struct {
ExpectedUser *models.User
ExpectedUser *user.User
ExpectedError error
}
+5 -4
View File
@@ -4,10 +4,11 @@ import (
"context"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
)
type UserProtectionService interface {
AllowUserMapping(user *models.User, authModule string) error
AllowUserMapping(user *user.User, authModule string) error
}
type Store interface {
@@ -17,8 +18,8 @@ type Store interface {
UpdateAuthInfo(ctx context.Context, cmd *models.UpdateAuthInfoCommand) error
UpdateAuthInfoDate(ctx context.Context, authInfo *models.UserAuth) error
DeleteAuthInfo(ctx context.Context, cmd *models.DeleteAuthInfoCommand) error
GetUserById(ctx context.Context, id int64) (*models.User, error)
GetUserByLogin(ctx context.Context, login string) (*models.User, error)
GetUserByEmail(ctx context.Context, email string) (*models.User, error)
GetUserById(ctx context.Context, id int64) (*user.User, error)
GetUserByLogin(ctx context.Context, login string) (*user.User, error)
GetUserByEmail(ctx context.Context, email string) (*user.User, error)
CollectLoginStats(ctx context.Context) (map[string]interface{}, error)
}
+2 -1
View File
@@ -3,6 +3,7 @@ package multildap
import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/user"
)
type MultiLDAPmock struct {
@@ -10,7 +11,7 @@ type MultiLDAPmock struct {
ID int64
UserCalled bool
LoginCalled bool
UserInfo *models.User
UserInfo *user.User
AuthModule string
ExpectedErr error
}
+5 -5
View File
@@ -8,7 +8,7 @@ import (
"github.com/unknwon/com"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -49,7 +49,7 @@ func createTimeLimitCode(data string, minutes int, startInf interface{}) (string
}
// verify time limit code
func validateUserEmailCode(cfg *setting.Cfg, user *models.User, code string) (bool, error) {
func validateUserEmailCode(cfg *setting.Cfg, user *user.User, code string) (bool, error) {
if len(code) <= 18 {
return false, nil
}
@@ -65,7 +65,7 @@ func validateUserEmailCode(cfg *setting.Cfg, user *models.User, code string) (bo
}
// right active code
data := com.ToStr(user.Id) + user.Email + user.Login + user.Password + user.Rands
data := com.ToStr(user.ID) + user.Email + user.Login + user.Password + user.Rands
retCode, err := createTimeLimitCode(data, minutes, start)
if err != nil {
return false, err
@@ -93,9 +93,9 @@ func getLoginForEmailCode(code string) string {
return string(b)
}
func createUserEmailCode(cfg *setting.Cfg, u *models.User, startInf interface{}) (string, error) {
func createUserEmailCode(cfg *setting.Cfg, u *user.User, startInf interface{}) (string, error) {
minutes := cfg.EmailCodeValidMinutes
data := com.ToStr(u.Id) + u.Email + u.Login + u.Password + u.Rands
data := com.ToStr(u.ID) + u.Email + u.Login + u.Password + u.Rands
code, err := createTimeLimitCode(data, minutes, startInf)
if err != nil {
return "", err
+2 -2
View File
@@ -3,7 +3,7 @@ package notifications
import (
"testing"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
@@ -14,7 +14,7 @@ func TestEmailCodes(t *testing.T) {
cfg := setting.NewCfg()
cfg.EmailCodeValidMinutes = 120
user := &models.User{Id: 10, Email: "t@a.com", Login: "asd", Password: "1", Rands: "2"}
user := &user.User{ID: 10, Email: "t@a.com", Login: "asd", Password: "1", Rands: "2"}
code, err := createUserEmailCode(cfg, user, nil)
require.NoError(t, err)
+2 -2
View File
@@ -1,7 +1,7 @@
package notifications
import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -24,7 +24,7 @@ type Message struct {
AttachedFiles []*AttachedFile
}
func setDefaultTemplateData(cfg *setting.Cfg, data map[string]interface{}, u *models.User) {
func setDefaultTemplateData(cfg *setting.Cfg, data map[string]interface{}, u *user.User) {
data["AppUrl"] = setting.AppUrl
data["BuildVersion"] = setting.BuildVersion
data["BuildStamp"] = setting.BuildStamp
+2 -1
View File
@@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
@@ -181,7 +182,7 @@ func (ns *NotificationService) SendResetPasswordEmail(ctx context.Context, cmd *
})
}
type GetUserByLoginFunc = func(c context.Context, login string) (*models.User, error)
type GetUserByLoginFunc = func(c context.Context, login string) (*user.User, error)
func (ns *NotificationService) ValidateResetPasswordCode(ctx context.Context, query *models.ValidateResetPasswordCodeQuery, userByLogin GetUserByLoginFunc) error {
login := getLoginForEmailCode(query.Code)
@@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -184,7 +185,7 @@ func TestSendEmailAsync(t *testing.T) {
t.Run("When sending reset email password", func(t *testing.T) {
sut, _ := createSut(t, bus)
err := sut.SendResetPasswordEmail(context.Background(), &models.SendResetPasswordEmailCommand{User: &models.User{Email: "asd@asd.com"}})
err := sut.SendResetPasswordEmail(context.Background(), &models.SendResetPasswordEmailCommand{User: &user.User{Email: "asd@asd.com"}})
require.NoError(t, err)
sentMsg := <-sut.mailQueue
+60
View File
@@ -0,0 +1,60 @@
package org
import (
"errors"
"time"
)
// Typed errors
var (
ErrOrgNotFound = errors.New("organization not found")
ErrOrgNameTaken = errors.New("organization name is taken")
)
type Org struct {
ID int64 `xorm:"pk autoincr 'id'"`
Version int
Name string
Address1 string
Address2 string
City string
ZipCode string
State string
Country string
Created time.Time
Updated time.Time
}
type OrgUser struct {
ID int64 `xorm:"pk autoincr 'id'"`
OrgID int64 `xorm:"org_id"`
UserID int64 `xorm:"user_id"`
Role RoleType
Created time.Time
Updated time.Time
}
// swagger:enum RoleType
type RoleType string
const (
ROLE_VIEWER RoleType = "Viewer"
ROLE_EDITOR RoleType = "Editor"
ROLE_ADMIN RoleType = "Admin"
)
type CreateOrgCommand struct {
Name string `json:"name" binding:"Required"`
// initial admin user for account
UserID int64 `json:"-"`
}
type GetOrgIDForNewUserCommand struct {
Email string
Login string
OrgID int64
OrgName string
SkipOrgSetup bool
}
+10
View File
@@ -0,0 +1,10 @@
package org
import (
"context"
)
type Service interface {
GetIDForNewUser(context.Context, GetOrgIDForNewUserCommand) (int64, error)
InsertUser(context.Context, *OrgUser) (int64, error)
}
+78
View File
@@ -0,0 +1,78 @@
package orgimpl
import (
"context"
"fmt"
"time"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore/db"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
type Service struct {
store store
cfg *setting.Cfg
log log.Logger
}
func ProvideService(db db.DB, cfg *setting.Cfg) org.Service {
return &Service{
store: &sqlStore{
db: db,
dialect: db.GetDialect(),
},
cfg: cfg,
log: log.New("org service"),
}
}
func (s *Service) GetIDForNewUser(ctx context.Context, cmd org.GetOrgIDForNewUserCommand) (int64, error) {
var orga org.Org
if cmd.SkipOrgSetup {
return -1, nil
}
if setting.AutoAssignOrg && cmd.OrgID != 0 {
_, err := s.store.Get(ctx, cmd.OrgID)
if err != nil {
return -1, err
}
return cmd.OrgID, nil
}
orgName := cmd.OrgName
if len(orgName) == 0 {
orgName = util.StringsFallback2(cmd.Email, cmd.Login)
}
if setting.AutoAssignOrg {
orga, err := s.store.Get(ctx, int64(s.cfg.AutoAssignOrgId))
if err != nil {
return 0, err
}
if orga.ID != 0 {
return orga.ID, nil
}
if setting.AutoAssignOrgId != 1 {
s.log.Error("Could not create user: organization ID does not exist", "orgID",
setting.AutoAssignOrgId)
return 0, fmt.Errorf("could not create user: organization ID %d does not exist",
setting.AutoAssignOrgId)
}
orga.Name = MainOrgName
orga.ID = int64(setting.AutoAssignOrgId)
} else {
orga.Name = orgName
}
orga.Created = time.Now()
orga.Updated = time.Now()
return s.store.Insert(ctx, &orga)
}
func (s *Service) InsertUser(ctx context.Context, orguser *org.OrgUser) (int64, error) {
return s.store.InsertUser(ctx, orguser)
}
+72
View File
@@ -0,0 +1,72 @@
package orgimpl
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
func TestOrgService(t *testing.T) {
orgStore := newOrgStoreFake()
orgService := Service{
store: orgStore,
cfg: setting.NewCfg(),
}
t.Run("create org", func(t *testing.T) {
_, err := orgService.GetIDForNewUser(context.Background(), org.GetOrgIDForNewUserCommand{})
require.NoError(t, err)
})
t.Run("create org", func(t *testing.T) {
_, err := orgService.GetIDForNewUser(context.Background(), org.GetOrgIDForNewUserCommand{})
require.NoError(t, err)
})
t.Run("create org with auto assign org ID", func(t *testing.T) {
setting.AutoAssignOrg = true
setting.AutoAssignOrgId = 1
orgStore.ExpectedOrgID = 1
orgStore.ExpectedOrg = &org.Org{}
_, err := orgService.GetIDForNewUser(context.Background(), org.GetOrgIDForNewUserCommand{})
require.NoError(t, err)
})
t.Run("create org with auto assign org ID and orgID", func(t *testing.T) {
setting.AutoAssignOrg = true
setting.AutoAssignOrgId = 1
orgStore.ExpectedOrgID = 1
orgStore.ExpectedOrg = &org.Org{}
_, err := orgService.GetIDForNewUser(context.Background(), org.GetOrgIDForNewUserCommand{OrgID: 1})
require.NoError(t, err)
})
setting.AutoAssignOrg = false
setting.AutoAssignOrgId = 0
}
type FakeOrgStore struct {
ExpectedOrg *org.Org
ExpectedOrgID int64
ExpectedUserID int64
ExpectedError error
}
func newOrgStoreFake() *FakeOrgStore {
return &FakeOrgStore{}
}
func (f *FakeOrgStore) Get(ctx context.Context, orgID int64) (*org.Org, error) {
return f.ExpectedOrg, f.ExpectedError
}
func (f *FakeOrgStore) Insert(ctx context.Context, org *org.Org) (int64, error) {
return f.ExpectedOrgID, f.ExpectedError
}
func (f *FakeOrgStore) InsertUser(ctx context.Context, org *org.OrgUser) (int64, error) {
return f.ExpectedUserID, f.ExpectedError
}
+83
View File
@@ -0,0 +1,83 @@
package orgimpl
import (
"context"
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/db"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
)
const MainOrgName = "Main Org."
type store interface {
Get(context.Context, int64) (*org.Org, error)
Insert(context.Context, *org.Org) (int64, error)
InsertUser(context.Context, *org.OrgUser) (int64, error)
}
type sqlStore struct {
db db.DB
dialect migrator.Dialect
}
func (ss *sqlStore) Get(ctx context.Context, orgID int64) (*org.Org, error) {
var orga org.Org
err := ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
has, err := sess.Where("id=?", orgID).Get(&orga)
if err != nil {
return err
}
if !has {
return org.ErrOrgNotFound
}
return nil
})
if err != nil {
return nil, err
}
return &orga, nil
}
func (ss *sqlStore) Insert(ctx context.Context, org *org.Org) (int64, error) {
var orgID int64
var err error
err = ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
if orgID, err = sess.InsertOne(org); err != nil {
return err
}
if org.ID != 0 {
// it sets the setval in the sequence
if err := ss.dialect.PostInsertId("org", sess.Session); err != nil {
return err
}
}
sess.PublishAfterCommit(&events.OrgCreated{
Timestamp: org.Created,
Id: org.ID,
Name: org.Name,
})
return nil
})
if err != nil {
return 0, err
}
return orgID, nil
}
func (ss *sqlStore) InsertUser(ctx context.Context, cmd *org.OrgUser) (int64, error) {
var orgID int64
var err error
err = ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
if orgID, err = sess.Insert(cmd); err != nil {
return err
}
return nil
})
if err != nil {
return 0, err
}
return orgID, nil
}
+73
View File
@@ -0,0 +1,73 @@
package orgimpl
import (
"context"
"testing"
"time"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/require"
)
func TestIntegrationOrgDataAccess(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ss := sqlstore.InitTestDB(t)
orgStore := sqlStore{
db: ss,
dialect: ss.GetDialect(),
}
t.Run("org not found", func(t *testing.T) {
_, err := orgStore.Get(context.Background(), 1)
require.Error(t, err, org.ErrOrgNotFound)
})
t.Run("org inserted", func(t *testing.T) {
_, err := orgStore.Insert(context.Background(), &org.Org{
Version: 1,
Name: "test1",
Created: time.Now(),
Updated: time.Now(),
})
require.NoError(t, err)
})
t.Run("org inserted with next available org ID", func(t *testing.T) {
orgID, err := orgStore.Insert(context.Background(), &org.Org{
ID: 55,
Version: 1,
Name: "test2",
Created: time.Now(),
Updated: time.Now(),
})
require.NoError(t, err)
_, err = orgStore.Get(context.Background(), orgID)
require.NoError(t, err)
})
}
func TestIntegrationOrgUserDataAccess(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ss := sqlstore.InitTestDB(t)
orgUserStore := sqlStore{
db: ss,
}
t.Run("org user inserted", func(t *testing.T) {
_, err := orgUserStore.InsertUser(context.Background(), &org.OrgUser{
ID: 1,
OrgID: 1,
UserID: 1,
Created: time.Now(),
Updated: time.Now(),
})
require.NoError(t, err)
})
}
+28
View File
@@ -0,0 +1,28 @@
package orgtest
import (
"context"
"github.com/grafana/grafana/pkg/services/org"
)
type FakeOrgService struct {
ExpectedOrgUserID int64
ExpectedError error
}
func NewOrgServiceFake() *FakeOrgService {
return &FakeOrgService{}
}
func (f *FakeOrgService) GetIDForNewUser(ctx context.Context, cmd org.GetOrgIDForNewUserCommand) (int64, error) {
return f.ExpectedOrgUserID, f.ExpectedError
}
func (f *FakeOrgService) Insert(ctx context.Context, cmd *org.OrgUser) (int64, error) {
return f.ExpectedOrgUserID, f.ExpectedError
}
func (f *FakeOrgService) InsertUser(ctx context.Context, cmd *org.OrgUser) (int64, error) {
return f.ExpectedOrgUserID, f.ExpectedError
}
@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/require"
@@ -51,7 +52,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
service.Cfg.QueryHistoryEnabled = true
user := models.SignedInUser{
usr := models.SignedInUser{
UserId: testUserID,
Name: "Signed In User",
Login: "signed_in_user",
@@ -61,7 +62,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
LastSeenAt: time.Now(),
}
_, err := sqlStore.CreateUser(context.Background(), models.CreateUserCommand{
_, err := sqlStore.CreateUser(context.Background(), user.CreateUserCommand{
Email: "signed.in.user@test.com",
Name: "Signed In User",
Login: "signed_in_user",
@@ -74,7 +75,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
sqlStore: sqlStore,
reqContext: &models.ReqContext{
Context: &ctx,
SignedInUser: &user,
SignedInUser: &usr,
},
}
fn(t, sc)
+4 -4
View File
@@ -185,7 +185,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) {
createduser := tests.SetupUserServiceAccount(t, store, testcase.user)
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), testcase.acmock, store, saStore)
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, fmt.Sprint(createduser.Id))).Code
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, fmt.Sprint(createduser.ID))).Code
require.Equal(t, testcase.expectedCode, actual)
})
})
@@ -209,7 +209,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) {
createduser := tests.SetupUserServiceAccount(t, store, testcase.user)
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), testcase.acmock, store, saStore)
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, createduser.Id)).Code
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, createduser.ID)).Code
require.Equal(t, testcase.expectedCode, actual)
})
})
@@ -314,7 +314,7 @@ func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
scopeID := tc.Id
if tc.user != nil {
createdUser := tests.SetupUserServiceAccount(t, store, *tc.user)
scopeID = int(createdUser.Id)
scopeID = int(createdUser.ID)
}
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), tc.acmock, store, saStore)
@@ -440,7 +440,7 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
scopeID := tc.Id
if tc.user != nil {
createdUser := tests.SetupUserServiceAccount(t, store, *tc.user)
scopeID = int(createdUser.Id)
scopeID = int(createdUser.ID)
}
var rawBody io.Reader = http.NoBody
@@ -125,7 +125,7 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
endpoint := fmt.Sprintf(serviceaccountIDTokensPath, sa.Id)
endpoint := fmt.Sprintf(serviceaccountIDTokensPath, sa.ID)
bodyString := ""
if tc.body != nil {
b, err := json.Marshal(tc.body)
@@ -146,12 +146,12 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
if actualCode == http.StatusOK {
assert.Equal(t, tc.body["name"], actualBody["name"])
query := models.GetApiKeyByNameQuery{KeyName: tc.body["name"].(string), OrgId: sa.OrgId}
query := models.GetApiKeyByNameQuery{KeyName: tc.body["name"].(string), OrgId: sa.OrgID}
err = store.GetApiKeyByName(context.Background(), &query)
require.NoError(t, err)
assert.Equal(t, sa.Id, *query.Result.ServiceAccountId)
assert.Equal(t, sa.OrgId, query.Result.OrgId)
assert.Equal(t, sa.ID, *query.Result.ServiceAccountId)
assert.Equal(t, sa.OrgID, query.Result.OrgId)
assert.True(t, strings.HasPrefix(actualBody["key"].(string), "glsa"))
keyInfo, err := apikeygenprefix.Decode(actualBody["key"].(string))
@@ -229,9 +229,9 @@ func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
token := createTokenforSA(t, saStore, tc.keyName, sa.OrgId, sa.Id, 1)
token := createTokenforSA(t, saStore, tc.keyName, sa.OrgID, sa.ID, 1)
endpoint := fmt.Sprintf(serviceaccountIDTokensDetailPath, sa.Id, token.Id)
endpoint := fmt.Sprintf(serviceaccountIDTokensDetailPath, sa.ID, token.Id)
bodyString := ""
server, _ := setupTestServer(t, svcMock, routing.NewRouteRegister(), tc.acmock, store, saStore)
actual := requestResponse(server, http.MethodDelete, endpoint, strings.NewReader(bodyString))
@@ -242,7 +242,7 @@ func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
_ = json.Unmarshal(actual.Body.Bytes(), &actualBody)
require.Equal(t, tc.expectedCode, actualCode, endpoint, actualBody)
query := models.GetApiKeyByNameQuery{KeyName: tc.keyName, OrgId: sa.OrgId}
query := models.GetApiKeyByNameQuery{KeyName: tc.keyName, OrgId: sa.OrgID}
err := store.GetApiKeyByName(context.Background(), &query)
if actualCode == http.StatusOK {
require.Error(t, err)
@@ -354,7 +354,7 @@ func TestServiceAccountsAPI_ListTokens(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
endpoint := fmt.Sprintf(serviceAccountIDPath+"/tokens", sa.Id)
endpoint := fmt.Sprintf(serviceAccountIDPath+"/tokens", sa.ID)
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), tc.acmock, store, &saStoreMockTokens{saAPIKeys: tc.tokens})
actual := requestResponse(server, http.MethodGet, endpoint, http.NoBody)
@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
)
type ServiceAccountsStoreImpl struct {
@@ -34,9 +35,9 @@ func NewServiceAccountsStore(store *sqlstore.SQLStore, kvStore kvstore.KVStore)
func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, orgId int64, name string) (saDTO *serviceaccounts.ServiceAccountDTO, err error) {
generatedLogin := "sa-" + strings.ToLower(name)
generatedLogin = strings.ReplaceAll(generatedLogin, " ", "-")
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Login: generatedLogin,
OrgId: orgId,
OrgID: orgId,
Name: name,
IsServiceAccount: true,
}
@@ -50,10 +51,10 @@ func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, org
}
return &serviceaccounts.ServiceAccountDTO{
Id: newuser.Id,
Id: newuser.ID,
Name: newuser.Name,
Login: newuser.Login,
OrgId: newuser.OrgId,
OrgId: newuser.OrgID,
Tokens: 0,
}, nil
}
@@ -89,7 +90,7 @@ func (s *ServiceAccountsStoreImpl) UpdateServiceAccount(ctx context.Context,
}
if saForm.Name != nil || saForm.IsDisabled != nil {
user := models.User{
user := user.User{
Updated: updateTime,
}
@@ -131,7 +132,7 @@ func (s *ServiceAccountsStoreImpl) DeleteServiceAccount(ctx context.Context, org
}
func (s *ServiceAccountsStoreImpl) deleteServiceAccount(sess *sqlstore.DBSession, orgId, serviceAccountId int64) error {
user := models.User{}
user := user.User{}
has, err := sess.Where(`org_id = ? and id = ? and is_service_account = ?`,
orgId, serviceAccountId, s.sqlStore.Dialect.BooleanStr(true)).Get(&user)
if err != nil {
@@ -141,7 +142,7 @@ func (s *ServiceAccountsStoreImpl) deleteServiceAccount(sess *sqlstore.DBSession
return serviceaccounts.ErrServiceAccountNotFound
}
for _, sql := range ServiceAccountDeletions() {
_, err := sess.Exec(sql, user.Id)
_, err := sess.Exec(sql, user.ID)
if err != nil {
return err
}
@@ -405,10 +406,10 @@ func (s *ServiceAccountsStoreImpl) MigrateApiKey(ctx context.Context, orgId int6
func (s *ServiceAccountsStoreImpl) CreateServiceAccountFromApikey(ctx context.Context, key *models.ApiKey) error {
prefix := "sa-autogen"
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Login: fmt.Sprintf("%v-%v-%v", prefix, key.OrgId, key.Name),
Name: fmt.Sprintf("%v-%v", prefix, key.Name),
OrgId: key.OrgId,
OrgID: key.OrgId,
DefaultOrgRole: string(key.Role),
IsServiceAccount: true,
}
@@ -419,8 +420,8 @@ func (s *ServiceAccountsStoreImpl) CreateServiceAccountFromApikey(ctx context.Co
return fmt.Errorf("failed to create service account: %w", errCreateSA)
}
if err := s.assignApiKeyToServiceAccount(sess, key.Id, newSA.Id); err != nil {
if err := s.sqlStore.DeleteUser(ctx, &models.DeleteUserCommand{UserId: newSA.Id}); err != nil {
if err := s.assignApiKeyToServiceAccount(sess, key.Id, newSA.ID); err != nil {
if err := s.sqlStore.DeleteUser(ctx, &models.DeleteUserCommand{UserId: newSA.ID}); err != nil {
s.log.Error("Error deleting service account", "error", err)
}
return fmt.Errorf("failed to migrate API key to service account token: %w", err)
@@ -451,7 +452,7 @@ func (s *ServiceAccountsStoreImpl) RevertApiKey(ctx context.Context, keyId int64
}
err = s.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
user := models.User{}
user := user.User{}
has, err := sess.Where(`org_id = ? and id = ? and is_service_account = ?`,
key.OrgId, *key.ServiceAccountId, s.sqlStore.Dialect.BooleanStr(true)).Get(&user)
if err != nil {
@@ -59,7 +59,7 @@ func TestStore_DeleteServiceAccount(t *testing.T) {
t.Run(c.desc, func(t *testing.T) {
db, store := setupTestDatabase(t)
user := tests.SetupUserServiceAccount(t, db, c.user)
err := store.DeleteServiceAccount(context.Background(), user.OrgId, user.Id)
err := store.DeleteServiceAccount(context.Background(), user.OrgID, user.ID)
if c.expectedErr != nil {
require.ErrorIs(t, err, c.expectedErr)
} else {
@@ -98,7 +98,7 @@ func TestStore_RetrieveServiceAccount(t *testing.T) {
t.Run(c.desc, func(t *testing.T) {
db, store := setupTestDatabase(t)
user := tests.SetupUserServiceAccount(t, db, c.user)
dto, err := store.RetrieveServiceAccount(context.Background(), user.OrgId, user.Id)
dto, err := store.RetrieveServiceAccount(context.Background(), user.OrgID, user.ID)
if c.expectedErr != nil {
require.ErrorIs(t, err, c.expectedErr)
} else {
@@ -18,18 +18,18 @@ func TestStore_UsageStats(t *testing.T) {
sa := tests.SetupUserServiceAccount(t, db, saToCreate)
keyName := t.Name()
key, err := apikeygen.New(sa.OrgId, keyName)
key, err := apikeygen.New(sa.OrgID, keyName)
require.NoError(t, err)
cmd := serviceaccounts.AddServiceAccountTokenCommand{
Name: keyName,
OrgId: sa.OrgId,
OrgId: sa.OrgID,
Key: key.HashedKey,
SecondsToLive: 0,
Result: &models.ApiKey{},
}
err = store.AddServiceAccountToken(context.Background(), sa.Id, &cmd)
err = store.AddServiceAccountToken(context.Background(), sa.ID, &cmd)
require.NoError(t, err)
stats, err := store.GetUsageMetrics(context.Background())
@@ -26,18 +26,18 @@ func TestStore_AddServiceAccountToken(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
keyName := t.Name()
key, err := apikeygen.New(user.OrgId, keyName)
key, err := apikeygen.New(user.OrgID, keyName)
require.NoError(t, err)
cmd := serviceaccounts.AddServiceAccountTokenCommand{
Name: keyName,
OrgId: user.OrgId,
OrgId: user.OrgID,
Key: key.HashedKey,
SecondsToLive: tc.secondsToLive,
Result: &models.ApiKey{},
}
err = store.AddServiceAccountToken(context.Background(), user.Id, &cmd)
err = store.AddServiceAccountToken(context.Background(), user.ID, &cmd)
if tc.secondsToLive < 0 {
require.Error(t, err)
return
@@ -48,7 +48,7 @@ func TestStore_AddServiceAccountToken(t *testing.T) {
require.Equal(t, t.Name(), newKey.Name)
// Verify against DB
keys, errT := store.ListTokens(context.Background(), user.OrgId, user.Id)
keys, errT := store.ListTokens(context.Background(), user.OrgID, user.ID)
require.NoError(t, errT)
@@ -76,18 +76,18 @@ func TestStore_AddServiceAccountToken_WrongServiceAccount(t *testing.T) {
sa := tests.SetupUserServiceAccount(t, db, saToCreate)
keyName := t.Name()
key, err := apikeygen.New(sa.OrgId, keyName)
key, err := apikeygen.New(sa.OrgID, keyName)
require.NoError(t, err)
cmd := serviceaccounts.AddServiceAccountTokenCommand{
Name: keyName,
OrgId: sa.OrgId,
OrgId: sa.OrgID,
Key: key.HashedKey,
SecondsToLive: 0,
Result: &models.ApiKey{},
}
err = store.AddServiceAccountToken(context.Background(), sa.Id+1, &cmd)
err = store.AddServiceAccountToken(context.Background(), sa.ID+1, &cmd)
require.Error(t, err, "It should not be possible to add token to non-existing service account")
}
@@ -97,34 +97,34 @@ func TestStore_DeleteServiceAccountToken(t *testing.T) {
sa := tests.SetupUserServiceAccount(t, db, userToCreate)
keyName := t.Name()
key, err := apikeygen.New(sa.OrgId, keyName)
key, err := apikeygen.New(sa.OrgID, keyName)
require.NoError(t, err)
cmd := serviceaccounts.AddServiceAccountTokenCommand{
Name: keyName,
OrgId: sa.OrgId,
OrgId: sa.OrgID,
Key: key.HashedKey,
SecondsToLive: 0,
Result: &models.ApiKey{},
}
err = store.AddServiceAccountToken(context.Background(), sa.Id, &cmd)
err = store.AddServiceAccountToken(context.Background(), sa.ID, &cmd)
require.NoError(t, err)
newKey := cmd.Result
// Delete key from wrong service account
err = store.DeleteServiceAccountToken(context.Background(), sa.OrgId, sa.Id+2, newKey.Id)
err = store.DeleteServiceAccountToken(context.Background(), sa.OrgID, sa.ID+2, newKey.Id)
require.Error(t, err)
// Delete key from wrong org
err = store.DeleteServiceAccountToken(context.Background(), sa.OrgId+2, sa.Id, newKey.Id)
err = store.DeleteServiceAccountToken(context.Background(), sa.OrgID+2, sa.ID, newKey.Id)
require.Error(t, err)
err = store.DeleteServiceAccountToken(context.Background(), sa.OrgId, sa.Id, newKey.Id)
err = store.DeleteServiceAccountToken(context.Background(), sa.OrgID, sa.ID, newKey.Id)
require.NoError(t, err)
// Verify against DB
keys, errT := store.ListTokens(context.Background(), sa.OrgId, sa.Id)
keys, errT := store.ListTokens(context.Background(), sa.OrgID, sa.ID)
require.NoError(t, errT)
for _, k := range keys {
+3 -2
View File
@@ -9,6 +9,7 @@ import (
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
@@ -27,13 +28,13 @@ type TestApiKey struct {
IsExpired bool
}
func SetupUserServiceAccount(t *testing.T, sqlStore *sqlstore.SQLStore, testUser TestUser) *models.User {
func SetupUserServiceAccount(t *testing.T, sqlStore *sqlstore.SQLStore, testUser TestUser) *user.User {
role := string(models.ROLE_VIEWER)
if testUser.Role != "" {
role = testUser.Role
}
u1, err := sqlStore.CreateUser(context.Background(), models.CreateUserCommand{
u1, err := sqlStore.CreateUser(context.Background(), user.CreateUserCommand{
Login: testUser.Login,
IsServiceAccount: testUser.IsServiceAccount,
DefaultOrgRole: role,
@@ -15,7 +15,9 @@ import (
acmig "github.com/grafana/grafana/pkg/services/sqlstore/migrations/accesscontrol"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -38,49 +40,49 @@ func (rp *rawPermission) toPermission(roleID int64, ts time.Time) accesscontrol.
var (
now = time.Now()
users = []models.User{
users = []user.User{
{
Id: 1,
ID: 1,
Email: "viewer1@example.org",
Name: "viewer1",
Login: "viewer1",
OrgId: 1,
OrgID: 1,
Created: now,
Updated: now,
},
{
Id: 2,
ID: 2,
Email: "viewer2@example.org",
Name: "viewer2",
Login: "viewer2",
OrgId: 1,
OrgID: 1,
Created: now,
Updated: now,
},
{
Id: 3,
ID: 3,
Email: "editor1@example.org",
Name: "editor1",
Login: "editor1",
OrgId: 1,
OrgID: 1,
Created: now,
Updated: now,
},
{
Id: 4,
ID: 4,
Email: "admin1@example.org",
Name: "admin1",
Login: "admin1",
OrgId: 1,
OrgID: 1,
Created: now,
Updated: now,
},
{
Id: 5,
ID: 5,
Email: "editor2@example.org",
Name: "editor2",
Login: "editor2",
OrgId: 2,
OrgID: 2,
Created: now,
Updated: now,
},
@@ -213,9 +215,9 @@ func TestMigrations(t *testing.T) {
for _, user := range users {
// Check managed roles exist
roleName := fmt.Sprintf("managed:users:%d:permissions", user.Id)
roleName := fmt.Sprintf("managed:users:%d:permissions", user.ID)
role := accesscontrol.Role{}
hasRole, errManagedRoleSearch := x.Table("role").Where("org_id = ? AND name = ?", user.OrgId, roleName).Get(&role)
hasRole, errManagedRoleSearch := x.Table("role").Where("org_id = ? AND name = ?", user.OrgID, roleName).Get(&role)
require.NoError(t, errManagedRoleSearch)
assert.True(t, hasRole, "expected role to be granted to user", user, roleName)
@@ -234,7 +236,7 @@ func TestMigrations(t *testing.T) {
// Check assignment of the roles
assign := accesscontrol.UserRole{}
has, errAssignmentSearch := x.Table("user_role").Where("role_id = ? AND user_id = ?", role.ID, user.Id).Get(&assign)
has, errAssignmentSearch := x.Table("user_role").Where("role_id = ? AND user_id = ?", role.ID, user.ID).Get(&assign)
require.NoError(t, errAssignmentSearch)
assert.True(t, has, "expected assignment of role to user", role, user)
}
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/user"
)
type OrgListResponse []struct {
@@ -18,7 +19,7 @@ type SQLStoreMock struct {
LastLoginAttemptCommand *models.CreateLoginAttemptCommand
LatestUserId int64
ExpectedUser *models.User
ExpectedUser *user.User
ExpectedDatasource *datasources.DataSource
ExpectedAlert *models.Alert
ExpectedPluginSetting *models.PluginSetting
@@ -132,7 +133,7 @@ func (m *SQLStoreMock) DeleteOldLoginAttempts(ctx context.Context, cmd *models.D
return m.ExpectedError
}
func (m *SQLStoreMock) CreateUser(ctx context.Context, cmd models.CreateUserCommand) (*models.User, error) {
func (m *SQLStoreMock) CreateUser(ctx context.Context, cmd user.CreateUserCommand) (*user.User, error) {
return nil, m.ExpectedError
}
+58 -57
View File
@@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
)
@@ -86,16 +87,16 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
sqlStore.Cfg.AutoAssignOrgRole = "Viewer"
t.Run("Users should be added to default organization", func(t *testing.T) {
ac1cmd := models.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac2cmd := models.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd)
require.NoError(t, err)
ac2, err := sqlStore.CreateUser(context.Background(), ac2cmd)
require.NoError(t, err)
q1 := models.GetUserOrgListQuery{UserId: ac1.Id}
q2 := models.GetUserOrgListQuery{UserId: ac2.Id}
q1 := models.GetUserOrgListQuery{UserId: ac1.ID}
q2 := models.GetUserOrgListQuery{UserId: ac2.ID}
err = sqlStore.GetUserOrgList(context.Background(), &q1)
require.NoError(t, err)
err = sqlStore.GetUserOrgList(context.Background(), &q2)
@@ -112,18 +113,18 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
sqlStore.Cfg.AutoAssignOrgId = 1
sqlStore.Cfg.AutoAssignOrgRole = "Viewer"
ac1cmd := models.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac2cmd := models.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd)
testUser.OrgId = ac1.OrgId
testUser.OrgId = ac1.OrgID
require.NoError(t, err)
_, err = sqlStore.CreateUser(context.Background(), ac2cmd)
require.NoError(t, err)
t.Run("Can get organization users paginated with query", func(t *testing.T) {
query := models.SearchOrgUsersQuery{
OrgID: ac1.OrgId,
OrgID: ac1.OrgID,
Page: 1,
User: testUser,
}
@@ -135,7 +136,7 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
t.Run("Can get organization users paginated and limited", func(t *testing.T) {
query := models.SearchOrgUsersQuery{
OrgID: ac1.OrgId,
OrgID: ac1.OrgID,
Limit: 1,
Page: 1,
User: testUser,
@@ -151,9 +152,9 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
sqlStore = InitTestDB(t)
sqlStore.Cfg.AutoAssignOrg = false
ac1cmd := models.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac2cmd := models.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true}
serviceaccountcmd := models.CreateUserCommand{Login: "serviceaccount", Email: "service@test.com", Name: "serviceaccount name", IsAdmin: true, IsServiceAccount: true}
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true}
serviceaccountcmd := user.CreateUserCommand{Login: "serviceaccount", Email: "service@test.com", Name: "serviceaccount name", IsAdmin: true, IsServiceAccount: true}
ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd)
require.NoError(t, err)
@@ -164,7 +165,7 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
require.NoError(t, err)
t.Run("Should be able to read user info projection", func(t *testing.T) {
query := models.GetUserProfileQuery{UserId: ac1.Id}
query := models.GetUserProfileQuery{UserId: ac1.ID}
err = sqlStore.GetUserProfile(context.Background(), &query)
require.NoError(t, err)
@@ -189,8 +190,8 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
t.Run("Given an added org user", func(t *testing.T) {
cmd := models.AddOrgUserCommand{
OrgId: ac1.OrgId,
UserId: ac2.Id,
OrgId: ac1.OrgID,
UserId: ac2.ID,
Role: models.ROLE_VIEWER,
}
@@ -200,15 +201,15 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
})
t.Run("Can update org user role", func(t *testing.T) {
updateCmd := models.UpdateOrgUserCommand{OrgId: ac1.OrgId, UserId: ac2.Id, Role: models.ROLE_ADMIN}
updateCmd := models.UpdateOrgUserCommand{OrgId: ac1.OrgID, UserId: ac2.ID, Role: models.ROLE_ADMIN}
err = sqlStore.UpdateOrgUser(context.Background(), &updateCmd)
require.NoError(t, err)
orgUsersQuery := models.GetOrgUsersQuery{
OrgId: ac1.OrgId,
OrgId: ac1.OrgID,
User: &models.SignedInUser{
OrgId: ac1.OrgId,
Permissions: map[int64]map[string][]string{ac1.OrgId: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
OrgId: ac1.OrgID,
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
},
}
err = sqlStore.GetOrgUsers(context.Background(), &orgUsersQuery)
@@ -218,12 +219,12 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
})
t.Run("Can get logged in user projection", func(t *testing.T) {
query := models.GetSignedInUserQuery{UserId: ac2.Id}
query := models.GetSignedInUserQuery{UserId: ac2.ID}
err := sqlStore.GetSignedInUser(context.Background(), &query)
require.NoError(t, err)
require.Equal(t, query.Result.Email, "ac2@test.com")
require.Equal(t, query.Result.OrgId, ac2.OrgId)
require.Equal(t, query.Result.OrgId, ac2.OrgID)
require.Equal(t, query.Result.Name, "ac2 name")
require.Equal(t, query.Result.Login, "ac2")
require.EqualValues(t, query.Result.OrgRole, "Admin")
@@ -232,7 +233,7 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
})
t.Run("Can get user organizations", func(t *testing.T) {
query := models.GetUserOrgListQuery{UserId: ac2.Id}
query := models.GetUserOrgListQuery{UserId: ac2.ID}
err := sqlStore.GetUserOrgList(context.Background(), &query)
require.NoError(t, err)
@@ -241,10 +242,10 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
t.Run("Can get organization users", func(t *testing.T) {
query := models.GetOrgUsersQuery{
OrgId: ac1.OrgId,
OrgId: ac1.OrgID,
User: &models.SignedInUser{
OrgId: ac1.OrgId,
Permissions: map[int64]map[string][]string{ac1.OrgId: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
OrgId: ac1.OrgID,
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
},
}
err := sqlStore.GetOrgUsers(context.Background(), &query)
@@ -256,11 +257,11 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
t.Run("Can get organization users with query", func(t *testing.T) {
query := models.GetOrgUsersQuery{
OrgId: ac1.OrgId,
OrgId: ac1.OrgID,
Query: "ac1",
User: &models.SignedInUser{
OrgId: ac1.OrgId,
Permissions: map[int64]map[string][]string{ac1.OrgId: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
OrgId: ac1.OrgID,
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
},
}
err := sqlStore.GetOrgUsers(context.Background(), &query)
@@ -272,12 +273,12 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
t.Run("Can get organization users with query and limit", func(t *testing.T) {
query := models.GetOrgUsersQuery{
OrgId: ac1.OrgId,
OrgId: ac1.OrgID,
Query: "ac",
Limit: 1,
User: &models.SignedInUser{
OrgId: ac1.OrgId,
Permissions: map[int64]map[string][]string{ac1.OrgId: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
OrgId: ac1.OrgID,
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
},
}
err := sqlStore.GetOrgUsers(context.Background(), &query)
@@ -288,16 +289,16 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
})
t.Run("Can set using org", func(t *testing.T) {
cmd := models.SetUsingOrgCommand{UserId: ac2.Id, OrgId: ac1.OrgId}
cmd := models.SetUsingOrgCommand{UserId: ac2.ID, OrgId: ac1.OrgID}
err := sqlStore.SetUsingOrg(context.Background(), &cmd)
require.NoError(t, err)
t.Run("SignedInUserQuery with a different org", func(t *testing.T) {
query := models.GetSignedInUserQuery{UserId: ac2.Id}
query := models.GetSignedInUserQuery{UserId: ac2.ID}
err := sqlStore.GetSignedInUser(context.Background(), &query)
require.NoError(t, err)
require.Equal(t, query.Result.OrgId, ac1.OrgId)
require.Equal(t, query.Result.OrgId, ac1.OrgID)
require.Equal(t, query.Result.Email, "ac2@test.com")
require.Equal(t, query.Result.Name, "ac2 name")
require.Equal(t, query.Result.Login, "ac2")
@@ -305,53 +306,53 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
})
t.Run("Should set last org as current when removing user from current", func(t *testing.T) {
remCmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac2.Id}
remCmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac2.ID}
err := sqlStore.RemoveOrgUser(context.Background(), &remCmd)
require.NoError(t, err)
query := models.GetSignedInUserQuery{UserId: ac2.Id}
query := models.GetSignedInUserQuery{UserId: ac2.ID}
err = sqlStore.GetSignedInUser(context.Background(), &query)
require.NoError(t, err)
require.Equal(t, query.Result.OrgId, ac2.OrgId)
require.Equal(t, query.Result.OrgId, ac2.OrgID)
})
})
t.Run("Removing user from org should delete user completely if in no other org", func(t *testing.T) {
// make sure ac2 has no org
err := sqlStore.DeleteOrg(context.Background(), &models.DeleteOrgCommand{Id: ac2.OrgId})
err := sqlStore.DeleteOrg(context.Background(), &models.DeleteOrgCommand{Id: ac2.OrgID})
require.NoError(t, err)
// remove ac2 user from ac1 org
remCmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac2.Id, ShouldDeleteOrphanedUser: true}
remCmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac2.ID, ShouldDeleteOrphanedUser: true}
err = sqlStore.RemoveOrgUser(context.Background(), &remCmd)
require.NoError(t, err)
require.True(t, remCmd.UserWasDeleted)
err = sqlStore.GetSignedInUser(context.Background(), &models.GetSignedInUserQuery{UserId: ac2.Id})
err = sqlStore.GetSignedInUser(context.Background(), &models.GetSignedInUserQuery{UserId: ac2.ID})
require.Equal(t, err, models.ErrUserNotFound)
})
t.Run("Cannot delete last admin org user", func(t *testing.T) {
cmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id}
cmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac1.ID}
err := sqlStore.RemoveOrgUser(context.Background(), &cmd)
require.Equal(t, err, models.ErrLastOrgAdmin)
})
t.Run("Cannot update role so no one is admin user", func(t *testing.T) {
cmd := models.UpdateOrgUserCommand{OrgId: ac1.OrgId, UserId: ac1.Id, Role: models.ROLE_VIEWER}
cmd := models.UpdateOrgUserCommand{OrgId: ac1.OrgID, UserId: ac1.ID, Role: models.ROLE_VIEWER}
err := sqlStore.UpdateOrgUser(context.Background(), &cmd)
require.Equal(t, err, models.ErrLastOrgAdmin)
})
t.Run("Given an org user with dashboard permissions", func(t *testing.T) {
ac3cmd := models.CreateUserCommand{Login: "ac3", Email: "ac3@test.com", Name: "ac3 name", IsAdmin: false}
ac3cmd := user.CreateUserCommand{Login: "ac3", Email: "ac3@test.com", Name: "ac3 name", IsAdmin: false}
ac3, err := sqlStore.CreateUser(context.Background(), ac3cmd)
require.NoError(t, err)
orgUserCmd := models.AddOrgUserCommand{
OrgId: ac1.OrgId,
UserId: ac3.Id,
OrgId: ac1.OrgID,
UserId: ac3.ID,
Role: models.ROLE_VIEWER,
}
@@ -359,36 +360,36 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
require.NoError(t, err)
query := models.GetOrgUsersQuery{
OrgId: ac1.OrgId,
OrgId: ac1.OrgID,
User: &models.SignedInUser{
OrgId: ac1.OrgId,
Permissions: map[int64]map[string][]string{ac1.OrgId: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
OrgId: ac1.OrgID,
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
},
}
err = sqlStore.GetOrgUsers(context.Background(), &query)
require.NoError(t, err)
// require.Equal(t, len(query.Result), 3)
dash1 := insertTestDashboard(t, sqlStore, "1 test dash", ac1.OrgId, 0, false, "prod", "webapp")
dash2 := insertTestDashboard(t, sqlStore, "2 test dash", ac3.OrgId, 0, false, "prod", "webapp")
dash1 := insertTestDashboard(t, sqlStore, "1 test dash", ac1.OrgID, 0, false, "prod", "webapp")
dash2 := insertTestDashboard(t, sqlStore, "2 test dash", ac3.OrgID, 0, false, "prod", "webapp")
err = updateDashboardAcl(t, sqlStore, dash1.Id, &models.DashboardAcl{
DashboardID: dash1.Id, OrgID: ac1.OrgId, UserID: ac3.Id, Permission: models.PERMISSION_EDIT,
DashboardID: dash1.Id, OrgID: ac1.OrgID, UserID: ac3.ID, Permission: models.PERMISSION_EDIT,
})
require.NoError(t, err)
err = updateDashboardAcl(t, sqlStore, dash2.Id, &models.DashboardAcl{
DashboardID: dash2.Id, OrgID: ac3.OrgId, UserID: ac3.Id, Permission: models.PERMISSION_EDIT,
DashboardID: dash2.Id, OrgID: ac3.OrgID, UserID: ac3.ID, Permission: models.PERMISSION_EDIT,
})
require.NoError(t, err)
t.Run("When org user is deleted", func(t *testing.T) {
cmdRemove := models.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac3.Id}
cmdRemove := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac3.ID}
err := sqlStore.RemoveOrgUser(context.Background(), &cmdRemove)
require.NoError(t, err)
t.Run("Should remove dependent permissions for deleted org user", func(t *testing.T) {
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash1.Id, OrgID: ac1.OrgId}
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash1.Id, OrgID: ac1.OrgID}
err = getDashboardAclInfoList(sqlStore, permQuery)
require.NoError(t, err)
@@ -397,14 +398,14 @@ func TestIntegrationAccountDataAccess(t *testing.T) {
})
t.Run("Should not remove dashboard permissions for same user in another org", func(t *testing.T) {
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash2.Id, OrgID: ac3.OrgId}
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash2.Id, OrgID: ac3.OrgID}
err = getDashboardAclInfoList(sqlStore, permQuery)
require.NoError(t, err)
require.Equal(t, len(permQuery.Result), 1)
require.Equal(t, permQuery.Result[0].OrgId, ac3.OrgId)
require.Equal(t, permQuery.Result[0].UserId, ac3.Id)
require.Equal(t, permQuery.Result[0].OrgId, ac3.OrgID)
require.Equal(t, permQuery.Result[0].UserId, ac3.ID)
})
})
})
+11 -10
View File
@@ -8,20 +8,21 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
)
func (ss *SQLStore) AddOrgUser(ctx context.Context, cmd *models.AddOrgUserCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
// check if user exists
var user models.User
var user user.User
if exists, err := sess.ID(cmd.UserId).Where(notServiceAccountFilter(ss)).Get(&user); err != nil {
return err
} else if !exists {
return models.ErrUserNotFound
}
if res, err := sess.Query("SELECT 1 from org_user WHERE org_id=? and user_id=?", cmd.OrgId, user.Id); err != nil {
if res, err := sess.Query("SELECT 1 from org_user WHERE org_id=? and user_id=?", cmd.OrgId, user.ID); err != nil {
return err
} else if len(res) == 1 {
return models.ErrOrgUserAlreadyAdded
@@ -49,7 +50,7 @@ func (ss *SQLStore) AddOrgUser(ctx context.Context, cmd *models.AddOrgUserComman
var userOrgs []*models.UserOrgDTO
sess.Table("org_user")
sess.Join("INNER", "org", "org_user.org_id=org.id")
sess.Where("org_user.user_id=? AND org_user.org_id=?", user.Id, user.OrgId)
sess.Where("org_user.user_id=? AND org_user.org_id=?", user.ID, user.OrgID)
sess.Cols("org.name", "org_user.role", "org_user.org_id")
err = sess.Find(&userOrgs)
@@ -58,7 +59,7 @@ func (ss *SQLStore) AddOrgUser(ctx context.Context, cmd *models.AddOrgUserComman
}
if len(userOrgs) == 0 {
return setUsingOrgInTransaction(sess, user.Id, cmd.OrgId)
return setUsingOrgInTransaction(sess, user.ID, cmd.OrgId)
}
return nil
@@ -243,7 +244,7 @@ func (ss *SQLStore) SearchOrgUsers(ctx context.Context, query *models.SearchOrgU
func (ss *SQLStore) RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUserCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
// check if user exists
var user models.User
var user user.User
if exists, err := sess.ID(cmd.UserId).Where(notServiceAccountFilter(ss)).Get(&user); err != nil {
return err
} else if !exists {
@@ -273,7 +274,7 @@ func (ss *SQLStore) RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUser
var userOrgs []*models.UserOrgDTO
sess.Table("org_user")
sess.Join("INNER", "org", "org_user.org_id=org.id")
sess.Where("org_user.user_id=?", user.Id)
sess.Where("org_user.user_id=?", user.ID)
sess.Cols("org.name", "org_user.role", "org_user.org_id")
err := sess.Find(&userOrgs)
@@ -284,28 +285,28 @@ func (ss *SQLStore) RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUser
if len(userOrgs) > 0 {
hasCurrentOrgSet := false
for _, userOrg := range userOrgs {
if user.OrgId == userOrg.OrgId {
if user.OrgID == userOrg.OrgId {
hasCurrentOrgSet = true
break
}
}
if !hasCurrentOrgSet {
err = setUsingOrgInTransaction(sess, user.Id, userOrgs[0].OrgId)
err = setUsingOrgInTransaction(sess, user.ID, userOrgs[0].OrgId)
if err != nil {
return err
}
}
} else if cmd.ShouldDeleteOrphanedUser {
// no other orgs, delete the full user
if err := deleteUserInTransaction(ss, sess, &models.DeleteUserCommand{UserId: user.Id}); err != nil {
if err := deleteUserInTransaction(ss, sess, &models.DeleteUserCommand{UserId: user.ID}); err != nil {
return err
}
cmd.UserWasDeleted = true
} else {
// no orgs, but keep the user -> clean up orgId
err = removeUserOrg(sess, user.Id)
err = removeUserOrg(sess, user.ID)
if err != nil {
return err
}
+10 -9
View File
@@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/user"
)
type getOrgUsersTestCase struct {
@@ -151,16 +152,16 @@ func TestSQLStore_RemoveOrgUser(t *testing.T) {
store := InitTestDB(t)
// create org and admin
_, err := store.CreateUser(context.Background(), models.CreateUserCommand{
_, err := store.CreateUser(context.Background(), user.CreateUserCommand{
Login: "admin",
OrgId: 1,
OrgID: 1,
})
require.NoError(t, err)
// create a user with no org
_, err = store.CreateUser(context.Background(), models.CreateUserCommand{
_, err = store.CreateUser(context.Background(), user.CreateUserCommand{
Login: "user",
OrgId: 1,
OrgID: 1,
SkipOrgSetup: true,
})
require.NoError(t, err)
@@ -177,7 +178,7 @@ func TestSQLStore_RemoveOrgUser(t *testing.T) {
user := &models.GetUserByIdQuery{Id: 2}
err = store.GetUserById(context.Background(), user)
require.NoError(t, err)
require.Equal(t, user.Result.OrgId, int64(1))
require.Equal(t, user.Result.OrgID, int64(1))
// remove the user org
err = store.RemoveOrgUser(context.Background(), &models.RemoveOrgUserCommand{
@@ -191,16 +192,16 @@ func TestSQLStore_RemoveOrgUser(t *testing.T) {
user = &models.GetUserByIdQuery{Id: 2}
err = store.GetUserById(context.Background(), user)
require.NoError(t, err)
require.Equal(t, user.Result.OrgId, int64(0))
require.Equal(t, user.Result.OrgID, int64(0))
}
func seedOrgUsers(t *testing.T, store *SQLStore, numUsers int) {
t.Helper()
// Seed users
for i := 1; i <= numUsers; i++ {
user, err := store.CreateUser(context.Background(), models.CreateUserCommand{
user, err := store.CreateUser(context.Background(), user.CreateUserCommand{
Login: fmt.Sprintf("user-%d", i),
OrgId: 1,
OrgID: 1,
})
require.NoError(t, err)
@@ -208,7 +209,7 @@ func seedOrgUsers(t *testing.T, store *SQLStore, numUsers int) {
err = store.AddOrgUser(context.Background(), &models.AddOrgUserCommand{
Role: "Viewer",
OrgId: 1,
UserId: user.Id,
UserId: user.ID,
})
require.NoError(t, err)
}
+4
View File
@@ -23,6 +23,10 @@ func (sess *DBSession) publishAfterCommit(msg interface{}) {
sess.events = append(sess.events, msg)
}
func (sess *DBSession) PublishAfterCommit(msg interface{}) {
sess.events = append(sess.events, msg)
}
// NewSession returns a new DBSession
func (ss *SQLStore) NewSession(ctx context.Context) *DBSession {
sess := &DBSession{Session: ss.engine.NewSession()}
+8 -7
View File
@@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -190,11 +191,11 @@ func test(t *testing.T, dashboardProps DashboardProps, dashboardPermission *Dash
})
}
func createDummyUser(t *testing.T, sqlStore *SQLStore) *models.User {
func createDummyUser(t *testing.T, sqlStore *SQLStore) *user.User {
t.Helper()
uid := strconv.Itoa(rand.Intn(9999999))
createUserCmd := models.CreateUserCommand{
createUserCmd := user.CreateUserCommand{
Email: uid + "@example.com",
Login: uid,
Name: uid,
@@ -262,12 +263,12 @@ func createDummyACL(t *testing.T, sqlStore *SQLStore, dashboardPermission *Dashb
DashboardID: dashboardID,
}
var user *models.User
var user *user.User
if dashboardPermission.User {
t.Logf("Creating user")
user = createDummyUser(t, sqlStore)
acl.UserID = user.Id
acl.UserID = user.ID
}
if dashboardPermission.Team {
@@ -275,9 +276,9 @@ func createDummyACL(t *testing.T, sqlStore *SQLStore, dashboardPermission *Dashb
team := createDummyTeam(t, sqlStore)
if search.UserFromACL {
user = createDummyUser(t, sqlStore)
err := sqlStore.AddTeamMember(user.Id, 1, team.Id, false, 0)
err := sqlStore.AddTeamMember(user.ID, 1, team.Id, false, 0)
require.NoError(t, err)
t.Logf("Created team member with ID %d", user.Id)
t.Logf("Created team member with ID %d", user.ID)
}
acl.TeamID = team.Id
@@ -290,7 +291,7 @@ func createDummyACL(t *testing.T, sqlStore *SQLStore, dashboardPermission *Dashb
err := updateDashboardAcl(t, sqlStore, dashboardID, acl)
require.NoError(t, err)
if user != nil {
return user.Id
return user.ID
}
return 0
}
+2 -1
View File
@@ -27,6 +27,7 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore/migrations"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
@@ -180,7 +181,7 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
// ensure admin user
if !ss.Cfg.DisableInitAdminCreation {
ss.log.Debug("Creating default admin user")
if _, err := ss.createUser(ctx, sess, models.CreateUserCommand{
if _, err := ss.createUser(ctx, sess, user.CreateUserCommand{
Login: ss.Cfg.AdminUser,
Email: ss.Cfg.AdminUser + "@localhost",
Password: ss.Cfg.AdminPassword,
+9 -8
View File
@@ -6,6 +6,7 @@ import (
"testing"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -64,9 +65,9 @@ func TestIntegrationStatsDataAccess(t *testing.T) {
func populateDB(t *testing.T, sqlStore *SQLStore) {
t.Helper()
users := make([]models.User, 3)
users := make([]user.User, 3)
for i := range users {
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: fmt.Sprintf("usertest%v@test.com", i),
Name: fmt.Sprintf("user name %v", i),
Login: fmt.Sprintf("user_test_%v_login", i),
@@ -78,7 +79,7 @@ func populateDB(t *testing.T, sqlStore *SQLStore) {
}
// get 1st user's organisation
getOrgByIdQuery := &models.GetOrgByIdQuery{Id: users[0].OrgId}
getOrgByIdQuery := &models.GetOrgByIdQuery{Id: users[0].OrgID}
err := sqlStore.GetOrgById(context.Background(), getOrgByIdQuery)
require.NoError(t, err)
org := getOrgByIdQuery.Result
@@ -86,7 +87,7 @@ func populateDB(t *testing.T, sqlStore *SQLStore) {
// add 2nd user as editor
cmd := &models.AddOrgUserCommand{
OrgId: org.Id,
UserId: users[1].Id,
UserId: users[1].ID,
Role: models.ROLE_EDITOR,
}
err = sqlStore.AddOrgUser(context.Background(), cmd)
@@ -95,14 +96,14 @@ func populateDB(t *testing.T, sqlStore *SQLStore) {
// add 3rd user as viewer
cmd = &models.AddOrgUserCommand{
OrgId: org.Id,
UserId: users[2].Id,
UserId: users[2].ID,
Role: models.ROLE_VIEWER,
}
err = sqlStore.AddOrgUser(context.Background(), cmd)
require.NoError(t, err)
// get 2nd user's organisation
getOrgByIdQuery = &models.GetOrgByIdQuery{Id: users[1].OrgId}
getOrgByIdQuery = &models.GetOrgByIdQuery{Id: users[1].OrgID}
err = sqlStore.GetOrgById(context.Background(), getOrgByIdQuery)
require.NoError(t, err)
org = getOrgByIdQuery.Result
@@ -110,7 +111,7 @@ func populateDB(t *testing.T, sqlStore *SQLStore) {
// add 1st user as admin
cmd = &models.AddOrgUserCommand{
OrgId: org.Id,
UserId: users[0].Id,
UserId: users[0].ID,
Role: models.ROLE_ADMIN,
}
err = sqlStore.AddOrgUser(context.Background(), cmd)
@@ -118,7 +119,7 @@ func populateDB(t *testing.T, sqlStore *SQLStore) {
// update 1st user last seen at
updateUserLastSeenAtCmd := &models.UpdateUserLastSeenAtCommand{
UserId: users[0].Id,
UserId: users[0].ID,
}
err = sqlStore.UpdateUserLastSeenAt(context.Background(), updateUserLastSeenAtCmd)
require.NoError(t, err)
+2 -1
View File
@@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/user"
)
type Store interface {
@@ -26,7 +27,7 @@ type Store interface {
CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error
GetUserLoginAttemptCount(ctx context.Context, query *models.GetUserLoginAttemptCountQuery) error
DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error
CreateUser(ctx context.Context, cmd models.CreateUserCommand) (*models.User, error)
CreateUser(ctx context.Context, cmd user.CreateUserCommand) (*user.User, error)
GetUserById(ctx context.Context, query *models.GetUserByIdQuery) error
GetUserByLogin(ctx context.Context, query *models.GetUserByLoginQuery) error
GetUserByEmail(ctx context.Context, query *models.GetUserByEmailQuery) error
+10 -9
View File
@@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/user"
)
func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
@@ -34,20 +35,20 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
var userIds []int64
const testOrgID int64 = 1
var team1, team2 models.Team
var user *models.User
var userCmd models.CreateUserCommand
var usr *user.User
var userCmd user.CreateUserCommand
var err error
setup := func() {
for i := 0; i < 5; i++ {
userCmd = models.CreateUserCommand{
userCmd = user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
}
user, err = sqlStore.CreateUser(context.Background(), userCmd)
usr, err = sqlStore.CreateUser(context.Background(), userCmd)
require.NoError(t, err)
userIds = append(userIds, user.Id)
userIds = append(userIds, usr.ID)
}
team1, err = sqlStore.CreateTeam("group1 name", "test1@test.com", testOrgID)
require.NoError(t, err)
@@ -375,7 +376,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
t.Run("Should be able to exclude service accounts from teamembers", func(t *testing.T) {
sqlStore = InitTestDB(t)
setup()
userCmd = models.CreateUserCommand{
userCmd = user.CreateUserCommand{
Email: fmt.Sprint("sa", 1, "@test.com"),
Name: fmt.Sprint("sa", 1),
Login: fmt.Sprint("login-sa", 1),
@@ -386,7 +387,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
groupId := team2.Id
// add service account to team
err = sqlStore.AddTeamMember(serviceAccount.Id, testOrgID, groupId, false, 0)
err = sqlStore.AddTeamMember(serviceAccount.ID, testOrgID, groupId, false, 0)
require.NoError(t, err)
// add user to team
@@ -498,14 +499,14 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) {
require.NoError(t, errCreateTeam)
for i := 0; i < 4; i++ {
userCmd := models.CreateUserCommand{
userCmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@example.org"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
}
user, errCreateUser := store.CreateUser(context.Background(), userCmd)
require.NoError(t, errCreateUser)
userIds[i] = user.Id
userIds[i] = user.ID
}
errAddMember := store.AddTeamMember(userIds[0], testOrgID, team1.Id, false, 0)
+69 -66
View File
@@ -11,11 +11,12 @@ import (
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
)
type ErrCaseInsensitiveLoginConflict struct {
users []models.User
users []user.User
}
func (e *ErrCaseInsensitiveLoginConflict) Unwrap() error {
@@ -27,7 +28,7 @@ func (e *ErrCaseInsensitiveLoginConflict) Error() string {
userStrings := make([]string, 0, n)
for _, v := range e.users {
userStrings = append(userStrings, fmt.Sprintf("%s (email:%s, id:%d)", v.Login, v.Email, v.Id))
userStrings = append(userStrings, fmt.Sprintf("%s (email:%s, id:%d)", v.Login, v.Email, v.ID))
}
return fmt.Sprintf(
@@ -35,12 +36,12 @@ func (e *ErrCaseInsensitiveLoginConflict) Error() string {
n, strings.Join(userStrings, ", "))
}
func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args models.CreateUserCommand) (int64, error) {
if ss.Cfg.AutoAssignOrg && args.OrgId != 0 {
if err := verifyExistingOrg(sess, args.OrgId); err != nil {
func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserCommand) (int64, error) {
if ss.Cfg.AutoAssignOrg && args.OrgID != 0 {
if err := verifyExistingOrg(sess, args.OrgID); err != nil {
return -1, err
}
return args.OrgId, nil
return args.OrgID, nil
}
orgName := args.OrgName
@@ -52,7 +53,7 @@ func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args models.CreateUserCo
}
func (ss *SQLStore) userCaseInsensitiveLoginConflict(ctx context.Context, sess *DBSession, login, email string) error {
users := make([]models.User, 0)
users := make([]user.User, 0)
if err := sess.Where("LOWER(email)=LOWER(?) OR LOWER(login)=LOWER(?)",
email, login).Find(&users); err != nil {
@@ -67,14 +68,14 @@ func (ss *SQLStore) userCaseInsensitiveLoginConflict(ctx context.Context, sess *
}
// createUser creates a user in the database
func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args models.CreateUserCommand) (models.User, error) {
var user models.User
func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.CreateUserCommand) (user.User, error) {
var usr user.User
var orgID int64 = -1
if !args.SkipOrgSetup {
var err error
orgID, err = ss.getOrgIDForNewUser(sess, args)
if err != nil {
return user, err
return usr, err
}
}
@@ -89,23 +90,23 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args models
args.Email = strings.ToLower(args.Email)
}
exists, err := sess.Where(where, args.Email, args.Login).Get(&models.User{})
exists, err := sess.Where(where, args.Email, args.Login).Get(&user.User{})
if err != nil {
return user, err
return usr, err
}
if exists {
return user, models.ErrUserAlreadyExists
return usr, models.ErrUserAlreadyExists
}
// create user
user = models.User{
usr = user.User{
Email: args.Email,
Name: args.Name,
Login: args.Login,
Company: args.Company,
IsAdmin: args.IsAdmin,
IsDisabled: args.IsDisabled,
OrgId: orgID,
OrgID: orgID,
EmailVerified: args.EmailVerified,
Created: time.Now(),
Updated: time.Now(),
@@ -115,48 +116,48 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args models
salt, err := util.GetRandomString(10)
if err != nil {
return user, err
return usr, err
}
user.Salt = salt
usr.Salt = salt
rands, err := util.GetRandomString(10)
if err != nil {
return user, err
return usr, err
}
user.Rands = rands
usr.Rands = rands
if len(args.Password) > 0 {
encodedPassword, err := util.EncodePassword(args.Password, user.Salt)
encodedPassword, err := util.EncodePassword(args.Password, usr.Salt)
if err != nil {
return user, err
return usr, err
}
user.Password = encodedPassword
usr.Password = encodedPassword
}
sess.UseBool("is_admin")
if _, err := sess.Insert(&user); err != nil {
return user, err
if _, err := sess.Insert(&usr); err != nil {
return usr, err
}
sess.publishAfterCommit(&events.UserCreated{
Timestamp: user.Created,
Id: user.Id,
Name: user.Name,
Login: user.Login,
Email: user.Email,
Timestamp: usr.Created,
Id: usr.ID,
Name: usr.Name,
Login: usr.Login,
Email: usr.Email,
})
// create org user link
if !args.SkipOrgSetup {
orgUser := models.OrgUser{
OrgId: orgID,
UserId: user.Id,
UserId: usr.ID,
Role: models.ROLE_ADMIN,
Created: time.Now(),
Updated: time.Now(),
}
if ss.Cfg.AutoAssignOrg && !user.IsAdmin {
if ss.Cfg.AutoAssignOrg && !usr.IsAdmin {
if len(args.DefaultOrgRole) > 0 {
orgUser.Role = models.RoleType(args.DefaultOrgRole)
} else {
@@ -165,15 +166,16 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args models
}
if _, err = sess.Insert(&orgUser); err != nil {
return user, err
return usr, err
}
}
return user, nil
return usr, nil
}
func (ss *SQLStore) CreateUser(ctx context.Context, cmd models.CreateUserCommand) (*models.User, error) {
var user models.User
// deprecated method, use only for tests
func (ss *SQLStore) CreateUser(ctx context.Context, cmd user.CreateUserCommand) (*user.User, error) {
var user user.User
createErr := ss.WithTransactionalDbSession(ctx, func(sess *DBSession) (err error) {
user, err = ss.createUser(ctx, sess, cmd)
return
@@ -189,7 +191,7 @@ func notServiceAccountFilter(ss *SQLStore) string {
func (ss *SQLStore) GetUserById(ctx context.Context, query *models.GetUserByIdQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
user := new(models.User)
user := new(user.User)
has, err := sess.ID(query.Id).
Where(notServiceAccountFilter(ss)).
@@ -221,13 +223,13 @@ func (ss *SQLStore) GetUserByLogin(ctx context.Context, query *models.GetUserByL
// Try and find the user by login first.
// It's not sufficient to assume that a LoginOrEmail with an "@" is an email.
user := &models.User{}
usr := &user.User{}
where := "login=?"
if ss.Cfg.CaseInsensitiveLogin {
where = "LOWER(login)=LOWER(?)"
}
has, err := sess.Where(notServiceAccountFilter(ss)).Where(where, query.LoginOrEmail).Get(user)
has, err := sess.Where(notServiceAccountFilter(ss)).Where(where, query.LoginOrEmail).Get(usr)
if err != nil {
return err
}
@@ -235,12 +237,13 @@ func (ss *SQLStore) GetUserByLogin(ctx context.Context, query *models.GetUserByL
if !has && strings.Contains(query.LoginOrEmail, "@") {
// If the user wasn't found, and it contains an "@" fallback to finding the
// user by email.
where = "email=?"
if ss.Cfg.CaseInsensitiveLogin {
where = "LOWER(email)=LOWER(?)"
}
user = &models.User{}
has, err = sess.Where(notServiceAccountFilter(ss)).Where(where, query.LoginOrEmail).Get(user)
usr = &user.User{}
has, err = sess.Where(notServiceAccountFilter(ss)).Where(where, query.LoginOrEmail).Get(usr)
}
if err != nil {
@@ -250,12 +253,12 @@ func (ss *SQLStore) GetUserByLogin(ctx context.Context, query *models.GetUserByL
}
if ss.Cfg.CaseInsensitiveLogin {
if err := ss.userCaseInsensitiveLoginConflict(ctx, sess, user.Login, user.Email); err != nil {
if err := ss.userCaseInsensitiveLoginConflict(ctx, sess, usr.Login, usr.Email); err != nil {
return err
}
}
query.Result = user
query.Result = usr
return nil
})
@@ -267,7 +270,7 @@ func (ss *SQLStore) GetUserByEmail(ctx context.Context, query *models.GetUserByE
return models.ErrUserNotFound
}
user := &models.User{}
user := &user.User{}
where := "email=?"
if ss.Cfg.CaseInsensitiveLogin {
where = "LOWER(email)=LOWER(?)"
@@ -300,7 +303,7 @@ func (ss *SQLStore) UpdateUser(ctx context.Context, cmd *models.UpdateUserComman
}
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
user := models.User{
user := user.User{
Name: cmd.Name,
Email: cmd.Email,
Login: cmd.Login,
@@ -320,7 +323,7 @@ func (ss *SQLStore) UpdateUser(ctx context.Context, cmd *models.UpdateUserComman
sess.publishAfterCommit(&events.UserUpdated{
Timestamp: user.Created,
Id: user.Id,
Id: user.ID,
Name: user.Name,
Login: user.Login,
Email: user.Email,
@@ -332,7 +335,7 @@ func (ss *SQLStore) UpdateUser(ctx context.Context, cmd *models.UpdateUserComman
func (ss *SQLStore) ChangeUserPassword(ctx context.Context, cmd *models.ChangeUserPasswordCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
user := models.User{
user := user.User{
Password: cmd.NewPassword,
Updated: time.Now(),
}
@@ -344,8 +347,8 @@ func (ss *SQLStore) ChangeUserPassword(ctx context.Context, cmd *models.ChangeUs
func (ss *SQLStore) UpdateUserLastSeenAt(ctx context.Context, cmd *models.UpdateUserLastSeenAtCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
user := models.User{
Id: cmd.UserId,
user := user.User{
ID: cmd.UserId,
LastSeenAt: time.Now(),
}
@@ -376,9 +379,9 @@ func (ss *SQLStore) SetUsingOrg(ctx context.Context, cmd *models.SetUsingOrgComm
}
func setUsingOrgInTransaction(sess *DBSession, userID int64, orgID int64) error {
user := models.User{
Id: userID,
OrgId: orgID,
user := user.User{
ID: userID,
OrgID: orgID,
}
_, err := sess.ID(userID).Update(&user)
@@ -386,9 +389,9 @@ func setUsingOrgInTransaction(sess *DBSession, userID int64, orgID int64) error
}
func removeUserOrg(sess *DBSession, userID int64) error {
user := models.User{
Id: userID,
OrgId: 0,
user := user.User{
ID: userID,
OrgID: 0,
}
_, err := sess.ID(userID).MustCols("org_id").Update(&user)
@@ -397,7 +400,7 @@ func removeUserOrg(sess *DBSession, userID int64) error {
func (ss *SQLStore) GetUserProfile(ctx context.Context, query *models.GetUserProfileQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
var user models.User
var user user.User
has, err := sess.ID(query.UserId).Where(notServiceAccountFilter(ss)).Get(&user)
if err != nil {
@@ -407,14 +410,14 @@ func (ss *SQLStore) GetUserProfile(ctx context.Context, query *models.GetUserPro
}
query.Result = models.UserProfileDTO{
Id: user.Id,
Id: user.ID,
Name: user.Name,
Email: user.Email,
Login: user.Login,
Theme: user.Theme,
IsGrafanaAdmin: user.IsAdmin,
IsDisabled: user.IsDisabled,
OrgId: user.OrgId,
OrgId: user.OrgID,
UpdatedAt: user.Updated,
CreatedAt: user.Created,
}
@@ -654,7 +657,7 @@ func (ss *SQLStore) SearchUsers(ctx context.Context, query *models.SearchUsersQu
}
// get total
user := models.User{}
user := user.User{}
countSess := dbSess.Table("user").Alias("u")
// Join with user_auth table if users filtered by auth_module
@@ -691,7 +694,7 @@ func (ss *SQLStore) SearchUsers(ctx context.Context, query *models.SearchUsersQu
func (ss *SQLStore) DisableUser(ctx context.Context, cmd *models.DisableUserCommand) error {
return ss.WithDbSession(ctx, func(dbSess *DBSession) error {
user := models.User{}
user := user.User{}
sess := dbSess.Table("user")
if has, err := sess.ID(cmd.UserId).Where(notServiceAccountFilter(ss)).Get(&user); err != nil {
@@ -737,7 +740,7 @@ func (ss *SQLStore) DeleteUser(ctx context.Context, cmd *models.DeleteUserComman
func deleteUserInTransaction(ss *SQLStore, sess *DBSession, cmd *models.DeleteUserCommand) error {
// Check if user exists
user := models.User{Id: cmd.UserId}
user := user.User{ID: cmd.UserId}
has, err := sess.Where(notServiceAccountFilter(ss)).Get(&user)
if err != nil {
return err
@@ -813,7 +816,7 @@ func UserDeletions() []string {
// UpdateUserPermissions sets the user Server Admin flag
func (ss *SQLStore) UpdateUserPermissions(userID int64, isAdmin bool) error {
return ss.WithTransactionalDbSession(context.Background(), func(sess *DBSession) error {
var user models.User
var user user.User
if _, err := sess.ID(userID).Where(notServiceAccountFilter(ss)).Get(&user); err != nil {
return err
}
@@ -821,7 +824,7 @@ func (ss *SQLStore) UpdateUserPermissions(userID int64, isAdmin bool) error {
user.IsAdmin = isAdmin
sess.UseBool("is_admin")
_, err := sess.ID(user.Id).Update(&user)
_, err := sess.ID(user.ID).Update(&user)
if err != nil {
return err
}
@@ -837,9 +840,9 @@ func (ss *SQLStore) UpdateUserPermissions(userID int64, isAdmin bool) error {
func (ss *SQLStore) SetUserHelpFlag(ctx context.Context, cmd *models.SetUserHelpFlagCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
user := models.User{
Id: cmd.UserId,
HelpFlags1: cmd.HelpFlags1,
user := user.User{
ID: cmd.UserId,
HelpFlags1: user.HelpFlags1(cmd.HelpFlags1),
Updated: time.Now(),
}
@@ -850,7 +853,7 @@ func (ss *SQLStore) SetUserHelpFlag(ctx context.Context, cmd *models.SetUserHelp
// validateOneAdminLeft validate that there is an admin user left
func validateOneAdminLeft(sess *DBSession) error {
count, err := sess.Where("is_admin=?", true).Count(&models.User{})
count, err := sess.Where("is_admin=?", true).Count(&user.User{})
if err != nil {
return err
}
+82 -81
View File
@@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -18,8 +19,8 @@ func TestIntegrationUserUpdate(t *testing.T) {
ss := InitTestDB(t)
users := createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("USER", i, "@test.com"),
Name: fmt.Sprint("USER", i),
Login: fmt.Sprint("loginUSER", i),
@@ -32,7 +33,7 @@ func TestIntegrationUserUpdate(t *testing.T) {
t.Run("Testing DB - update generates duplicate user", func(t *testing.T) {
err := ss.UpdateUser(context.Background(), &models.UpdateUserCommand{
Login: "loginuser2",
UserId: users[0].Id,
UserId: users[0].ID,
})
require.Error(t, err)
@@ -42,11 +43,11 @@ func TestIntegrationUserUpdate(t *testing.T) {
err := ss.UpdateUser(context.Background(), &models.UpdateUserCommand{
Login: "loginUSER0",
Email: "USER0@test.com",
UserId: users[0].Id,
UserId: users[0].ID,
})
require.NoError(t, err)
query := models.GetUserByIdQuery{Id: users[0].Id}
query := models.GetUserByIdQuery{Id: users[0].ID}
err = ss.GetUserById(context.Background(), &query)
require.NoError(t, err)
@@ -59,11 +60,11 @@ func TestIntegrationUserUpdate(t *testing.T) {
Login: "",
Email: "",
Name: "Change Name",
UserId: users[3].Id,
UserId: users[3].ID,
})
require.NoError(t, err)
query := models.GetUserByIdQuery{Id: users[3].Id}
query := models.GetUserByIdQuery{Id: users[3].ID}
err = ss.GetUserById(context.Background(), &query)
require.NoError(t, err)
@@ -83,13 +84,13 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Skip("skipping integration test")
}
ss := InitTestDB(t)
user := &models.SignedInUser{
usr := &models.SignedInUser{
OrgId: 1,
Permissions: map[int64]map[string][]string{1: {"users:read": {"global.users:*"}}},
}
t.Run("Testing DB - creates and loads user", func(t *testing.T) {
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: "usertest@test.com",
Name: "user name",
Login: "user_test_login",
@@ -97,7 +98,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
user, err := ss.CreateUser(context.Background(), cmd)
require.NoError(t, err)
query := models.GetUserByIdQuery{Id: user.Id}
query := models.GetUserByIdQuery{Id: user.ID}
err = ss.GetUserById(context.Background(), &query)
require.Nil(t, err)
@@ -107,7 +108,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.Len(t, query.Result.Salt, 10)
require.False(t, query.Result.IsDisabled)
query = models.GetUserByIdQuery{Id: user.Id}
query = models.GetUserByIdQuery{Id: user.ID}
err = ss.GetUserById(context.Background(), &query)
require.Nil(t, err)
@@ -166,7 +167,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - creates and loads disabled user", func(t *testing.T) {
ss = InitTestDB(t)
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: "usertest@test.com",
Name: "user name",
Login: "user_test_login",
@@ -176,7 +177,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
user, err := ss.CreateUser(context.Background(), cmd)
require.Nil(t, err)
query := models.GetUserByIdQuery{Id: user.Id}
query := models.GetUserByIdQuery{Id: user.ID}
err = ss.GetUserById(context.Background(), &query)
require.Nil(t, err)
@@ -200,17 +201,17 @@ func TestIntegrationUserDataAccess(t *testing.T) {
err := ss.CreateOrg(context.Background(), orgCmd)
require.Nil(t, err)
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: "usertest@test.com",
Name: "user name",
Login: "user_test_login",
OrgId: orgCmd.Result.Id,
OrgID: orgCmd.Result.Id,
}
user, err := ss.CreateUser(context.Background(), cmd)
usr, err := ss.CreateUser(context.Background(), cmd)
require.Nil(t, err)
query := models.GetUserByIdQuery{Id: user.Id}
query := models.GetUserByIdQuery{Id: usr.ID}
err = ss.GetUserById(context.Background(), &query)
require.Nil(t, err)
@@ -219,14 +220,14 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.Len(t, query.Result.Rands, 10)
require.Len(t, query.Result.Salt, 10)
require.False(t, query.Result.IsDisabled)
require.Equal(t, query.Result.OrgId, orgCmd.Result.Id)
require.Equal(t, query.Result.OrgID, orgCmd.Result.Id)
const nonExistingOrgID = 10000
cmd = models.CreateUserCommand{
cmd = user.CreateUserCommand{
Email: "usertest@test.com",
Name: "user name",
Login: "user_test_login",
OrgId: nonExistingOrgID,
OrgID: nonExistingOrgID,
}
_, err = ss.CreateUser(context.Background(), cmd)
@@ -236,8 +237,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - multiple users", func(t *testing.T) {
ss = InitTestDB(t)
createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -246,7 +247,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
})
// Return the first page of users and a total count
query := models.SearchUsersQuery{Query: "", Page: 1, Limit: 3, SignedInUser: user}
query := models.SearchUsersQuery{Query: "", Page: 1, Limit: 3, SignedInUser: usr}
err := ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -254,7 +255,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.EqualValues(t, query.Result.TotalCount, 5)
// Return the second page of users and a total count
query = models.SearchUsersQuery{Query: "", Page: 2, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "", Page: 2, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -262,28 +263,28 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.EqualValues(t, query.Result.TotalCount, 5)
// Return list of users matching query on user name
query = models.SearchUsersQuery{Query: "use", Page: 1, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "use", Page: 1, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
require.Len(t, query.Result.Users, 3)
require.EqualValues(t, query.Result.TotalCount, 5)
query = models.SearchUsersQuery{Query: "ser1", Page: 1, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "ser1", Page: 1, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
require.Len(t, query.Result.Users, 1)
require.EqualValues(t, query.Result.TotalCount, 1)
query = models.SearchUsersQuery{Query: "USER1", Page: 1, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "USER1", Page: 1, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
require.Len(t, query.Result.Users, 1)
require.EqualValues(t, query.Result.TotalCount, 1)
query = models.SearchUsersQuery{Query: "idontexist", Page: 1, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "idontexist", Page: 1, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -291,7 +292,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.EqualValues(t, query.Result.TotalCount, 0)
// Return list of users matching query on email
query = models.SearchUsersQuery{Query: "ser1@test.com", Page: 1, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "ser1@test.com", Page: 1, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -299,7 +300,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.EqualValues(t, query.Result.TotalCount, 1)
// Return list of users matching query on login name
query = models.SearchUsersQuery{Query: "loginuser1", Page: 1, Limit: 3, SignedInUser: user}
query = models.SearchUsersQuery{Query: "loginuser1", Page: 1, Limit: 3, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -309,8 +310,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - return list users based on their is_disabled flag", func(t *testing.T) {
ss = InitTestDB(t)
createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -319,7 +320,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
})
isDisabled := false
query := models.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: user}
query := models.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: usr}
err := ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -341,8 +342,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
// Re-init DB
ss = InitTestDB(t)
users := createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -352,27 +353,27 @@ func TestIntegrationUserDataAccess(t *testing.T) {
err = ss.AddOrgUser(context.Background(), &models.AddOrgUserCommand{
LoginOrEmail: users[1].Login, Role: models.ROLE_VIEWER,
OrgId: users[0].OrgId, UserId: users[1].Id,
OrgId: users[0].OrgID, UserId: users[1].ID,
})
require.Nil(t, err)
err = updateDashboardAcl(t, ss, 1, &models.DashboardAcl{
DashboardID: 1, OrgID: users[0].OrgId, UserID: users[1].Id,
DashboardID: 1, OrgID: users[0].OrgID, UserID: users[1].ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
// When the user is deleted
err = ss.DeleteUser(context.Background(), &models.DeleteUserCommand{UserId: users[1].Id})
err = ss.DeleteUser(context.Background(), &models.DeleteUserCommand{UserId: users[1].ID})
require.Nil(t, err)
query1 := &models.GetOrgUsersQuery{OrgId: users[0].OrgId, User: user}
query1 := &models.GetOrgUsersQuery{OrgId: users[0].OrgID, User: usr}
err = ss.GetOrgUsersForTest(context.Background(), query1)
require.Nil(t, err)
require.Len(t, query1.Result, 1)
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: users[0].OrgId}
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: users[0].OrgID}
err = getDashboardAclInfoList(ss, permQuery)
require.Nil(t, err)
@@ -381,8 +382,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
// A user is an org member and has been assigned permissions
// Re-init DB
ss = InitTestDB(t)
users = createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
users = createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -391,37 +392,37 @@ func TestIntegrationUserDataAccess(t *testing.T) {
})
err = ss.AddOrgUser(context.Background(), &models.AddOrgUserCommand{
LoginOrEmail: users[1].Login, Role: models.ROLE_VIEWER,
OrgId: users[0].OrgId, UserId: users[1].Id,
OrgId: users[0].OrgID, UserId: users[1].ID,
})
require.Nil(t, err)
err = updateDashboardAcl(t, ss, 1, &models.DashboardAcl{
DashboardID: 1, OrgID: users[0].OrgId, UserID: users[1].Id,
DashboardID: 1, OrgID: users[0].OrgID, UserID: users[1].ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
ss.CacheService.Flush()
query3 := &models.GetSignedInUserQuery{OrgId: users[1].OrgId, UserId: users[1].Id}
query3 := &models.GetSignedInUserQuery{OrgId: users[1].OrgID, UserId: users[1].ID}
err = ss.GetSignedInUserWithCacheCtx(context.Background(), query3)
require.Nil(t, err)
require.NotNil(t, query3.Result)
require.Equal(t, query3.OrgId, users[1].OrgId)
err = ss.SetUsingOrg(context.Background(), &models.SetUsingOrgCommand{UserId: users[1].Id, OrgId: users[0].OrgId})
require.Equal(t, query3.OrgId, users[1].OrgID)
err = ss.SetUsingOrg(context.Background(), &models.SetUsingOrgCommand{UserId: users[1].ID, OrgId: users[0].OrgID})
require.Nil(t, err)
query4 := &models.GetSignedInUserQuery{OrgId: 0, UserId: users[1].Id}
query4 := &models.GetSignedInUserQuery{OrgId: 0, UserId: users[1].ID}
err = ss.GetSignedInUserWithCacheCtx(context.Background(), query4)
require.Nil(t, err)
require.NotNil(t, query4.Result)
require.Equal(t, query4.Result.OrgId, users[0].OrgId)
require.Equal(t, query4.Result.OrgId, users[0].OrgID)
cacheKey := newSignedInUserCacheKey(query4.Result.OrgId, query4.UserId)
_, found := ss.CacheService.Get(cacheKey)
require.True(t, found)
disableCmd := models.BatchDisableUsersCommand{
UserIds: []int64{users[0].Id, users[1].Id, users[2].Id, users[3].Id, users[4].Id},
UserIds: []int64{users[0].ID, users[1].ID, users[2].ID, users[3].ID, users[4].ID},
IsDisabled: true,
}
@@ -429,24 +430,24 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.Nil(t, err)
isDisabled = true
query5 := &models.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: user}
query5 := &models.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), query5)
require.Nil(t, err)
require.EqualValues(t, query5.Result.TotalCount, 5)
// the user is deleted
err = ss.DeleteUser(context.Background(), &models.DeleteUserCommand{UserId: users[1].Id})
err = ss.DeleteUser(context.Background(), &models.DeleteUserCommand{UserId: users[1].ID})
require.Nil(t, err)
// delete connected org users and permissions
query2 := &models.GetOrgUsersQuery{OrgId: users[0].OrgId}
query2 := &models.GetOrgUsersQuery{OrgId: users[0].OrgID}
err = ss.GetOrgUsersForTest(context.Background(), query2)
require.Nil(t, err)
require.Len(t, query2.Result, 1)
permQuery = &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: users[0].OrgId}
permQuery = &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: users[0].OrgID}
err = getDashboardAclInfoList(ss, permQuery)
require.Nil(t, err)
@@ -455,8 +456,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - return list of users that the SignedInUser has permission to read", func(t *testing.T) {
ss := InitTestDB(t)
createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -478,7 +479,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Skip("Skipping on MySQL due to case insensitive indexes")
}
cmd := models.CreateUserCommand{
cmd := user.CreateUserCommand{
Email: "confusertest@test.com",
Name: "user name",
Login: "user_email_conflict",
@@ -486,7 +487,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
userEmailConflict, err := ss.CreateUser(context.Background(), cmd)
require.NoError(t, err)
cmd = models.CreateUserCommand{
cmd = user.CreateUserCommand{
Email: "confusertest@TEST.COM",
Name: "user name",
Login: "user_email_conflict_two",
@@ -494,7 +495,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
_, err = ss.CreateUser(context.Background(), cmd)
require.NoError(t, err)
cmd = models.CreateUserCommand{
cmd = user.CreateUserCommand{
Email: "user_test_login_conflict@test.com",
Name: "user name",
Login: "user_test_login_conflict",
@@ -502,7 +503,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
userLoginConflict, err := ss.CreateUser(context.Background(), cmd)
require.NoError(t, err)
cmd = models.CreateUserCommand{
cmd = user.CreateUserCommand{
Email: "user_test_login_conflict_two@test.com",
Name: "user name",
Login: "user_test_login_CONFLICT",
@@ -525,13 +526,13 @@ func TestIntegrationUserDataAccess(t *testing.T) {
})
t.Run("GetUserByID - email conflict", func(t *testing.T) {
query := models.GetUserByIdQuery{Id: userEmailConflict.Id}
query := models.GetUserByIdQuery{Id: userEmailConflict.ID}
err = ss.GetUserById(context.Background(), &query)
require.Error(t, err)
})
t.Run("GetUserByID - login conflict", func(t *testing.T) {
query := models.GetUserByIdQuery{Id: userLoginConflict.Id}
query := models.GetUserByIdQuery{Id: userLoginConflict.ID}
err = ss.GetUserById(context.Background(), &query)
require.Error(t, err)
})
@@ -560,8 +561,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
ss = InitTestDB(t)
t.Run("Testing DB - enable all users", func(t *testing.T) {
users := createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -570,7 +571,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
})
disableCmd := models.BatchDisableUsersCommand{
UserIds: []int64{users[0].Id, users[1].Id, users[2].Id, users[3].Id, users[4].Id},
UserIds: []int64{users[0].ID, users[1].ID, users[2].ID, users[3].ID, users[4].ID},
IsDisabled: false,
}
@@ -578,7 +579,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.Nil(t, err)
isDisabled := false
query := &models.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: user}
query := &models.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: usr}
err = ss.SearchUsers(context.Background(), query)
require.Nil(t, err)
@@ -588,8 +589,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
ss = InitTestDB(t)
t.Run("Testing DB - disable only specific users", func(t *testing.T) {
users := createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -599,7 +600,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
userIdsToDisable := []int64{}
for i := 0; i < 3; i++ {
userIdsToDisable = append(userIdsToDisable, users[i].Id)
userIdsToDisable = append(userIdsToDisable, users[i].ID)
}
disableCmd := models.BatchDisableUsersCommand{
UserIds: userIdsToDisable,
@@ -609,7 +610,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
err := ss.BatchDisableUsers(context.Background(), &disableCmd)
require.Nil(t, err)
query := models.SearchUsersQuery{SignedInUser: user}
query := models.SearchUsersQuery{SignedInUser: usr}
err = ss.SearchUsers(context.Background(), &query)
require.Nil(t, err)
@@ -636,8 +637,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - search users", func(t *testing.T) {
// Since previous tests were destructive
createFiveTestUsers(t, ss, func(i int) *models.CreateUserCommand {
return &models.CreateUserCommand{
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i),
@@ -649,21 +650,21 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - grafana admin users", func(t *testing.T) {
ss = InitTestDB(t)
createUserCmd := models.CreateUserCommand{
createUserCmd := user.CreateUserCommand{
Email: fmt.Sprint("admin", "@test.com"),
Name: "admin",
Login: "admin",
IsAdmin: true,
}
user, err := ss.CreateUser(context.Background(), createUserCmd)
usr, err := ss.CreateUser(context.Background(), createUserCmd)
require.Nil(t, err)
// Cannot make themselves a non-admin
updatePermsError := ss.UpdateUserPermissions(user.Id, false)
updatePermsError := ss.UpdateUserPermissions(usr.ID, false)
require.Equal(t, updatePermsError, models.ErrLastGrafanaAdmin)
query := models.GetUserByIdQuery{Id: user.Id}
query := models.GetUserByIdQuery{Id: usr.ID}
getUserError := ss.GetUserById(context.Background(), &query)
require.Nil(t, getUserError)
@@ -672,7 +673,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
// One user
const email = "user@test.com"
const username = "user"
createUserCmd = models.CreateUserCommand{
createUserCmd = user.CreateUserCommand{
Email: email,
Name: "user",
Login: username,
@@ -681,7 +682,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.Nil(t, err)
// When trying to create a new user with the same email, an error is returned
createUserCmd = models.CreateUserCommand{
createUserCmd = user.CreateUserCommand{
Email: email,
Name: "user2",
Login: "user2",
@@ -691,7 +692,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.Equal(t, err, models.ErrUserAlreadyExists)
// When trying to create a new user with the same login, an error is returned
createUserCmd = models.CreateUserCommand{
createUserCmd = user.CreateUserCommand{
Email: "user2@test.com",
Name: "user2",
Login: username,
@@ -715,10 +716,10 @@ func (ss *SQLStore) GetOrgUsersForTest(ctx context.Context, query *models.GetOrg
})
}
func createFiveTestUsers(t *testing.T, sqlStore *SQLStore, fn func(i int) *models.CreateUserCommand) []models.User {
func createFiveTestUsers(t *testing.T, sqlStore *SQLStore, fn func(i int) *user.CreateUserCommand) []user.User {
t.Helper()
users := []models.User{}
users := []user.User{}
for i := 0; i < 5; i++ {
cmd := fn(i)
+55
View File
@@ -0,0 +1,55 @@
package user
import "time"
type HelpFlags1 uint64
type User struct {
ID int64 `xorm:"pk autoincr 'id'"`
Version int
Email string
Name string
Login string
Password string
Salt string
Rands string
Company string
EmailVerified bool
Theme string
HelpFlags1 HelpFlags1
IsDisabled bool
IsAdmin bool
IsServiceAccount bool
OrgID int64 `xorm:"org_id"`
Created time.Time
Updated time.Time
LastSeenAt time.Time
}
type CreateUserCommand struct {
Email string
Login string
Name string
Company string
OrgID int64
OrgName string
Password string
EmailVerified bool
IsAdmin bool
IsDisabled bool
SkipOrgSetup bool
DefaultOrgRole string
IsServiceAccount bool
}
func (u *User) NameOrFallback() string {
if u.Name != "" {
return u.Name
}
if u.Login != "" {
return u.Login
}
return u.Email
}
+9
View File
@@ -0,0 +1,9 @@
package user
import (
"context"
)
type Service interface {
Create(context.Context, *CreateUserCommand) (*User, error)
}
+62
View File
@@ -0,0 +1,62 @@
package userimpl
import (
"context"
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/db"
"github.com/grafana/grafana/pkg/services/user"
)
type store interface {
Insert(context.Context, *user.User) (int64, error)
Get(context.Context, *user.User) (*user.User, error)
}
type sqlStore struct {
db db.DB
}
func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) {
var userID int64
var err error
err = ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
sess.UseBool("is_admin")
if userID, err = sess.Insert(cmd); err != nil {
return err
}
sess.PublishAfterCommit(&events.UserCreated{
Timestamp: cmd.Created,
Id: cmd.ID,
Name: cmd.Name,
Login: cmd.Login,
Email: cmd.Email,
})
return nil
})
if err != nil {
return 0, err
}
return userID, nil
}
func (ss *sqlStore) Get(ctx context.Context, cmd *user.User) (*user.User, error) {
var usr *user.User
err := ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
exists, err := sess.Where("email=? OR login=?", cmd.Email, cmd.Login).Get(&user.User{})
if !exists {
return models.ErrUserNotFound
}
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return usr, nil
}
+57
View File
@@ -0,0 +1,57 @@
package userimpl
import (
"context"
"testing"
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
func TestIntegrationUserDataAccess(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ss := sqlstore.InitTestDB(t)
userStore := sqlStore{db: ss}
t.Run("user not found", func(t *testing.T) {
_, err := userStore.Get(context.Background(),
&user.User{
Email: "test@email.com",
Name: "test1",
Login: "test1",
},
)
require.Error(t, err, models.ErrUserNotFound)
})
t.Run("insert user", func(t *testing.T) {
_, err := userStore.Insert(context.Background(),
&user.User{
Email: "test@email.com",
Name: "test1",
Login: "test1",
Created: time.Now(),
Updated: time.Now(),
},
)
require.NoError(t, err)
})
t.Run("get user", func(t *testing.T) {
_, err := userStore.Get(context.Background(),
&user.User{
Email: "test@email.com",
Name: "test1",
Login: "test1",
},
)
require.NoError(t, err)
})
}
+121
View File
@@ -0,0 +1,121 @@
package userimpl
import (
"context"
"errors"
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore/db"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
type Service struct {
store store
orgService org.Service
}
func ProvideService(db db.DB, orgService org.Service) user.Service {
return &Service{
store: &sqlStore{
db: db,
},
orgService: orgService,
}
}
func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*user.User, error) {
cmdOrg := org.GetOrgIDForNewUserCommand{
Email: cmd.Email,
Login: cmd.Login,
OrgID: cmd.OrgID,
OrgName: cmd.OrgName,
SkipOrgSetup: cmd.SkipOrgSetup,
}
orgID, err := s.orgService.GetIDForNewUser(ctx, cmdOrg)
cmd.OrgID = orgID
if err != nil {
return nil, err
}
if cmd.Email == "" {
cmd.Email = cmd.Login
}
usr := &user.User{
Login: cmd.Login,
Email: cmd.Email,
}
usr, err = s.store.Get(ctx, usr)
if err != nil && !errors.Is(err, models.ErrUserNotFound) {
return usr, err
}
// create user
usr = &user.User{
Email: cmd.Email,
Name: cmd.Name,
Login: cmd.Login,
Company: cmd.Company,
IsAdmin: cmd.IsAdmin,
IsDisabled: cmd.IsDisabled,
OrgID: cmd.OrgID,
EmailVerified: cmd.EmailVerified,
Created: time.Now(),
Updated: time.Now(),
LastSeenAt: time.Now().AddDate(-10, 0, 0),
IsServiceAccount: cmd.IsServiceAccount,
}
salt, err := util.GetRandomString(10)
if err != nil {
return nil, err
}
usr.Salt = salt
rands, err := util.GetRandomString(10)
if err != nil {
return nil, err
}
usr.Rands = rands
if len(cmd.Password) > 0 {
encodedPassword, err := util.EncodePassword(cmd.Password, usr.Salt)
if err != nil {
return nil, err
}
usr.Password = encodedPassword
}
_, err = s.store.Insert(ctx, usr)
if err != nil {
return nil, err
}
// create org user link
if !cmd.SkipOrgSetup {
orgUser := org.OrgUser{
OrgID: orgID,
UserID: usr.ID,
Role: org.ROLE_ADMIN,
Created: time.Now(),
Updated: time.Now(),
}
if setting.AutoAssignOrg && !usr.IsAdmin {
if len(cmd.DefaultOrgRole) > 0 {
orgUser.Role = org.RoleType(cmd.DefaultOrgRole)
} else {
orgUser.Role = org.RoleType(setting.AutoAssignOrgRole)
}
}
_, err = s.orgService.InsertUser(ctx, &orgUser)
if err != nil {
// HERE ADD DELETE USER
return usr, err
}
}
return usr, nil
}
+41
View File
@@ -0,0 +1,41 @@
package userimpl
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
func TestUserService(t *testing.T) {
userStore := newUserStoreFake()
orgService := orgtest.NewOrgServiceFake()
userService := Service{
store: userStore,
orgService: orgService,
}
t.Run("create user", func(t *testing.T) {
_, err := userService.Create(context.Background(), &user.CreateUserCommand{})
require.NoError(t, err)
})
}
type FakeUserStore struct {
ExpectedUser *user.User
ExpectedError error
}
func newUserStoreFake() *FakeUserStore {
return &FakeUserStore{}
}
func (f *FakeUserStore) Get(ctx context.Context, query *user.User) (*user.User, error) {
return f.ExpectedUser, f.ExpectedError
}
func (f *FakeUserStore) Insert(ctx context.Context, query *user.User) (int64, error) {
return 0, f.ExpectedError
}
+20
View File
@@ -0,0 +1,20 @@
package usertest
import (
"context"
"github.com/grafana/grafana/pkg/services/user"
)
type FakeUserService struct {
ExpectedUser *user.User
ExpectedError error
}
func NewUserServiceFake() *FakeUserService {
return &FakeUserService{}
}
func (f *FakeUserService) Create(ctx context.Context, cmd *user.CreateUserCommand) (*user.User, error) {
return f.ExpectedUser, f.ExpectedError
}