chore: remove CreateUser from sqlstore & replace with userService.CreateUserForTests (#59910)

This commit is contained in:
Kristin Laemmert
2022-12-07 17:03:22 +01:00
committed by GitHub
parent d036225f7b
commit 70fbf47022
44 changed files with 943 additions and 758 deletions

View File

@@ -22,6 +22,7 @@ import (
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/org/orgtest" "github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
@@ -37,11 +38,17 @@ func setUpGetOrgUsersDB(t *testing.T, sqlStore *sqlstore.SQLStore) {
sqlStore.Cfg.AutoAssignOrg = true sqlStore.Cfg.AutoAssignOrg = true
sqlStore.Cfg.AutoAssignOrgId = int(testOrgID) sqlStore.Cfg.AutoAssignOrgId = int(testOrgID)
_, err := sqlStore.CreateUser(context.Background(), user.CreateUserCommand{Email: "testUser@grafana.com", Login: testUserLogin}) quotaService := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err) require.NoError(t, err)
_, err = sqlStore.CreateUser(context.Background(), user.CreateUserCommand{Email: "user1@grafana.com", Login: "user1"}) usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, quotaService)
require.NoError(t, err) require.NoError(t, err)
_, err = sqlStore.CreateUser(context.Background(), user.CreateUserCommand{Email: "user2@grafana.com", Login: "user2"})
_, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Email: "testUser@grafana.com", Login: testUserLogin})
require.NoError(t, err)
_, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Email: "user1@grafana.com", Login: "user1"})
require.NoError(t, err)
_, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Email: "user2@grafana.com", Login: "user2"})
require.NoError(t, err) require.NoError(t, err)
} }
@@ -331,13 +338,15 @@ var (
func setupOrgUsersDBForAccessControlTests(t *testing.T, db *sqlstore.SQLStore, orgService org.Service) { func setupOrgUsersDBForAccessControlTests(t *testing.T, db *sqlstore.SQLStore, orgService org.Service) {
t.Helper() t.Helper()
var err error quotaService := quotaimpl.ProvideService(db, db.Cfg)
usrSvc, err := userimpl.ProvideService(db, orgService, db.Cfg, nil, nil, quotaService)
require.NoError(t, err)
_, err = db.CreateUser(context.Background(), user.CreateUserCommand{Email: testServerAdminViewer.Email, SkipOrgSetup: true, Login: testServerAdminViewer.Login}) _, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Email: testServerAdminViewer.Email, SkipOrgSetup: true, Login: testServerAdminViewer.Login})
require.NoError(t, err) require.NoError(t, err)
_, err = db.CreateUser(context.Background(), user.CreateUserCommand{Email: testAdminOrg2.Email, SkipOrgSetup: true, Login: testAdminOrg2.Login}) _, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Email: testAdminOrg2.Email, SkipOrgSetup: true, Login: testAdminOrg2.Login})
require.NoError(t, err) require.NoError(t, err)
_, err = db.CreateUser(context.Background(), user.CreateUserCommand{Email: testEditorOrg1.Email, SkipOrgSetup: true, Login: testEditorOrg1.Login}) _, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Email: testEditorOrg1.Email, SkipOrgSetup: true, Login: testEditorOrg1.Login})
require.NoError(t, err) require.NoError(t, err)
// Create both orgs with server admin // Create both orgs with server admin

View File

@@ -18,6 +18,7 @@ import (
"github.com/grafana/grafana/pkg/services/licensing" "github.com/grafana/grafana/pkg/services/licensing"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
@@ -25,6 +26,7 @@ import (
"github.com/grafana/grafana/pkg/services/teamguardian/database" "github.com/grafana/grafana/pkg/services/teamguardian/database"
"github.com/grafana/grafana/pkg/services/teamguardian/manager" "github.com/grafana/grafana/pkg/services/teamguardian/manager"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@@ -46,6 +48,12 @@ func setUpGetTeamMembersHandler(t *testing.T, sqlStore *sqlstore.SQLStore) {
teamSvc := teamimpl.ProvideService(sqlStore, setting.NewCfg()) teamSvc := teamimpl.ProvideService(sqlStore, setting.NewCfg())
team, err := teamSvc.CreateTeam("group1 name", "test1@test.com", testOrgID) team, err := teamSvc.CreateTeam("group1 name", "test1@test.com", testOrgID)
require.NoError(t, err) require.NoError(t, err)
quotaService := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, quotaService)
require.NoError(t, err)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
userCmd = user.CreateUserCommand{ userCmd = user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
@@ -53,7 +61,7 @@ func setUpGetTeamMembersHandler(t *testing.T, sqlStore *sqlstore.SQLStore) {
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
} }
// user // user
user, err := sqlStore.CreateUser(context.Background(), userCmd) user, err := usrSvc.CreateUserForTests(context.Background(), &userCmd)
require.NoError(t, err) require.NoError(t, err)
err = teamSvc.AddTeamMember(user.ID, testOrgID, team.Id, false, 1) err = teamSvc.AddTeamMember(user.ID, testOrgID, team.Id, false, 1)
require.NoError(t, err) require.NoError(t, err)
@@ -115,7 +123,13 @@ func TestTeamMembersAPIEndpoint_userLoggedIn(t *testing.T) {
} }
func createUser(db sqlstore.Store, orgId int64, t *testing.T) int64 { func createUser(db sqlstore.Store, orgId int64, t *testing.T) int64 {
user, err := db.CreateUser(context.Background(), user.CreateUserCommand{ quotaService := quotaimpl.ProvideService(db, setting.NewCfg())
orgService, err := orgimpl.ProvideService(db, setting.NewCfg(), quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(db, orgService, setting.NewCfg(), nil, nil, quotaService)
require.NoError(t, err)
user, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{
Login: fmt.Sprintf("TestUser%d", rand.Int()), Login: fmt.Sprintf("TestUser%d", rand.Int()),
OrgID: orgId, OrgID: orgId,
Password: "password", Password: "password",
@@ -127,7 +141,11 @@ func createUser(db sqlstore.Store, orgId int64, t *testing.T) int64 {
func setupTeamTestScenario(userCount int, db *sqlstore.SQLStore, orgService org.Service, t *testing.T) int64 { func setupTeamTestScenario(userCount int, db *sqlstore.SQLStore, orgService org.Service, t *testing.T) int64 {
teamService := teamimpl.ProvideService(db, setting.NewCfg()) // FIXME teamService := teamimpl.ProvideService(db, setting.NewCfg()) // FIXME
user, err := db.CreateUser(context.Background(), user.CreateUserCommand{SkipOrgSetup: true, Login: testUserLogin}) quotaService := quotaimpl.ProvideService(db, db.Cfg)
usrSvc, err := userimpl.ProvideService(db, orgService, db.Cfg, teamService, nil, quotaService)
require.NoError(t, err)
user, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{SkipOrgSetup: true, Login: testUserLogin})
require.NoError(t, err) require.NoError(t, err)
cmd := &org.CreateOrgCommand{Name: "TestOrg", UserID: user.ID} cmd := &org.CreateOrgCommand{Name: "TestOrg", UserID: user.ID}
testOrg, err := orgService.CreateWithMember(context.Background(), cmd) testOrg, err := orgService.CreateWithMember(context.Background(), cmd)

View File

@@ -23,6 +23,7 @@ import (
"github.com/grafana/grafana/pkg/services/login/authinfoservice" "github.com/grafana/grafana/pkg/services/login/authinfoservice"
authinfostore "github.com/grafana/grafana/pkg/services/login/authinfoservice/database" authinfostore "github.com/grafana/grafana/pkg/services/login/authinfoservice/database"
"github.com/grafana/grafana/pkg/services/login/logintest" "github.com/grafana/grafana/pkg/services/login/logintest"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/searchusers" "github.com/grafana/grafana/pkg/services/searchusers"
"github.com/grafana/grafana/pkg/services/searchusers/filters" "github.com/grafana/grafana/pkg/services/searchusers/filters"
@@ -63,6 +64,11 @@ func TestUserAPIEndpoint_userLoggedIn(t *testing.T) {
&usagestats.UsageStatsMock{}, &usagestats.UsageStatsMock{},
) )
hs.authInfoService = srv hs.authInfoService = srv
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotatest.New(false, nil))
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sc.cfg, nil, nil, quotatest.New(false, nil))
require.NoError(t, err)
hs.userService = userSvc
createUserCmd := user.CreateUserCommand{ createUserCmd := user.CreateUserCommand{
Email: fmt.Sprint("user", "@test.com"), Email: fmt.Sprint("user", "@test.com"),
@@ -70,9 +76,7 @@ func TestUserAPIEndpoint_userLoggedIn(t *testing.T) {
Login: "loginuser", Login: "loginuser",
IsAdmin: true, IsAdmin: true,
} }
user, err := sqlStore.CreateUser(context.Background(), createUserCmd) user, err := userSvc.CreateUserForTests(context.Background(), &createUserCmd)
require.Nil(t, err)
hs.userService, err = userimpl.ProvideService(sqlStore, nil, sc.cfg, nil, nil, quotatest.New(false, nil))
require.NoError(t, err) require.NoError(t, err)
sc.handlerFunc = hs.GetUserByID sc.handlerFunc = hs.GetUserByID
@@ -128,7 +132,11 @@ func TestUserAPIEndpoint_userLoggedIn(t *testing.T) {
Login: "admin", Login: "admin",
IsAdmin: true, IsAdmin: true,
} }
_, err := sqlStore.CreateUser(context.Background(), createUserCmd) orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotatest.New(false, nil))
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sc.cfg, nil, nil, quotatest.New(false, nil))
require.NoError(t, err)
_, err = userSvc.Create(context.Background(), &createUserCmd)
require.Nil(t, err) require.Nil(t, err)
sc.handlerFunc = hs.GetUserByLoginOrEmail sc.handlerFunc = hs.GetUserByLoginOrEmail

View File

@@ -12,9 +12,13 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest" "github.com/grafana/grafana/pkg/services/accesscontrol/actest"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/services/user/usertest"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@@ -102,7 +106,7 @@ func TestBuildConflictBlock(t *testing.T) {
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
usrSvc := setupTestUserService(t, sqlStore)
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
for _, u := range tc.users { for _, u := range tc.users {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -111,7 +115,7 @@ func TestBuildConflictBlock(t *testing.T) {
Login: u.Login, Login: u.Login,
OrgID: int64(testOrgID), OrgID: int64(testOrgID),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
} }
m, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore) m, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore)
@@ -207,7 +211,7 @@ conflict: test2
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
usrSvc := setupTestUserService(t, sqlStore)
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
for _, u := range tc.users { for _, u := range tc.users {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -216,7 +220,7 @@ conflict: test2
Login: u.Login, Login: u.Login,
OrgID: int64(testOrgID), OrgID: int64(testOrgID),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
} }
@@ -385,6 +389,7 @@ func TestGetConflictingUsers(t *testing.T) {
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
usrSvc := setupTestUserService(t, sqlStore)
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
for _, u := range tc.users { for _, u := range tc.users {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -394,7 +399,7 @@ func TestGetConflictingUsers(t *testing.T) {
OrgID: int64(testOrgID), OrgID: int64(testOrgID),
IsServiceAccount: u.IsServiceAccount, IsServiceAccount: u.IsServiceAccount,
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
} }
m, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore) m, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore)
@@ -493,6 +498,7 @@ func TestGenerateConflictingUsersFile(t *testing.T) {
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
usrSvc := setupTestUserService(t, sqlStore)
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
for _, u := range tc.users { for _, u := range tc.users {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -501,7 +507,7 @@ func TestGenerateConflictingUsersFile(t *testing.T) {
Login: u.Login, Login: u.Login,
OrgID: int64(testOrgID), OrgID: int64(testOrgID),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
} }
m, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore) m, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore)
@@ -543,6 +549,8 @@ func TestRunValidateConflictUserFile(t *testing.T) {
t.Run("should validate file thats gets created", func(t *testing.T) { t.Run("should validate file thats gets created", func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
usrSvc := setupTestUserService(t, sqlStore)
const testOrgID int64 = 1 const testOrgID int64 = 1
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
// add additional user with conflicting login where DOMAIN is upper case // add additional user with conflicting login where DOMAIN is upper case
@@ -551,14 +559,14 @@ func TestRunValidateConflictUserFile(t *testing.T) {
Login: "user_duplicate_test_1_login", Login: "user_duplicate_test_1_login",
OrgID: testOrgID, OrgID: testOrgID,
} }
_, err := sqlStore.CreateUser(context.Background(), dupUserLogincmd) _, err := usrSvc.Create(context.Background(), &dupUserLogincmd)
require.NoError(t, err) require.NoError(t, err)
dupUserEmailcmd := user.CreateUserCommand{ dupUserEmailcmd := user.CreateUserCommand{
Email: "USERDUPLICATETEST1@TEST.COM", Email: "USERDUPLICATETEST1@TEST.COM",
Login: "USER_DUPLICATE_TEST_1_LOGIN", Login: "USER_DUPLICATE_TEST_1_LOGIN",
OrgID: testOrgID, OrgID: testOrgID,
} }
_, err = sqlStore.CreateUser(context.Background(), dupUserEmailcmd) _, err = usrSvc.Create(context.Background(), &dupUserEmailcmd)
require.NoError(t, err) require.NoError(t, err)
// get users // get users
@@ -589,6 +597,7 @@ func TestIntegrationMergeUser(t *testing.T) {
teamSvc := teamimpl.ProvideService(sqlStore, setting.NewCfg()) teamSvc := teamimpl.ProvideService(sqlStore, setting.NewCfg())
team1, err := teamSvc.CreateTeam("team1 name", "", 1) team1, err := teamSvc.CreateTeam("team1 name", "", 1)
require.Nil(t, err) require.Nil(t, err)
usrSvc := setupTestUserService(t, sqlStore)
const testOrgID int64 = 1 const testOrgID int64 = 1
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
@@ -601,7 +610,7 @@ func TestIntegrationMergeUser(t *testing.T) {
Login: "user_duplicate_test_1_login", Login: "user_duplicate_test_1_login",
OrgID: testOrgID, OrgID: testOrgID,
} }
_, err := sqlStore.CreateUser(context.Background(), dupUserLogincmd) _, err := usrSvc.Create(context.Background(), &dupUserLogincmd)
require.NoError(t, err) require.NoError(t, err)
dupUserEmailcmd := user.CreateUserCommand{ dupUserEmailcmd := user.CreateUserCommand{
Email: "USERDUPLICATETEST1@TEST.COM", Email: "USERDUPLICATETEST1@TEST.COM",
@@ -609,7 +618,7 @@ func TestIntegrationMergeUser(t *testing.T) {
Login: "USER_DUPLICATE_TEST_1_LOGIN", Login: "USER_DUPLICATE_TEST_1_LOGIN",
OrgID: testOrgID, OrgID: testOrgID,
} }
userWithUpperCase, err := sqlStore.CreateUser(context.Background(), dupUserEmailcmd) userWithUpperCase, err := usrSvc.Create(context.Background(), &dupUserEmailcmd)
require.NoError(t, err) require.NoError(t, err)
// this is the user we want to update to another team // this is the user we want to update to another team
err = teamSvc.AddTeamMember(userWithUpperCase.ID, testOrgID, team1.Id, false, 0) err = teamSvc.AddTeamMember(userWithUpperCase.ID, testOrgID, team1.Id, false, 0)
@@ -746,6 +755,7 @@ conflict: test2
for _, tc := range testCases { for _, tc := range testCases {
// Restore after destructive operation // Restore after destructive operation
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
usrSvc := setupTestUserService(t, sqlStore)
if sqlStore.GetDialect().DriverName() != ignoredDatabase { if sqlStore.GetDialect().DriverName() != ignoredDatabase {
for _, u := range tc.users { for _, u := range tc.users {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -754,7 +764,7 @@ conflict: test2
Login: u.Login, Login: u.Login,
OrgID: int64(testOrgID), OrgID: int64(testOrgID),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
} }
// add additional user with conflicting login where DOMAIN is upper case // add additional user with conflicting login where DOMAIN is upper case
@@ -840,3 +850,13 @@ func TestMarshalConflictUser(t *testing.T) {
}) })
} }
} }
func setupTestUserService(t *testing.T, sqlStore *sqlstore.SQLStore) user.Service {
t.Helper()
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, &quotatest.FakeQuotaService{})
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, &quotatest.FakeQuotaService{})
require.NoError(t, err)
return usrSvc
}

View File

@@ -18,9 +18,12 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
@@ -399,10 +402,17 @@ func TestApi_setUserPermission(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) { t.Run(tt.desc, func(t *testing.T) {
service, sql, _ := setupTestEnvironment(t, tt.permissions, testOptions) service, sql, _ := setupTestEnvironment(t, tt.permissions, testOptions)
server := setupTestServer(t, &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}}, service) server := setupTestServer(t, &user.SignedInUser{
OrgID: 1,
Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)},
}, service)
// seed user // seed user
_, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "test", OrgID: 1}) orgSvc, err := orgimpl.ProvideService(sql, sql.Cfg, quotatest.New(false, nil))
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sql, orgSvc, sql.Cfg, nil, nil, &quotatest.FakeQuotaService{})
require.NoError(t, err)
_, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "test", OrgID: 1})
require.NoError(t, err) require.NoError(t, err)
recorder := setPermission(t, server, testOptions.Resource, tt.resourceID, tt.permission, "users", strconv.Itoa(int(tt.userID))) recorder := setPermission(t, server, testOptions.Resource, tt.resourceID, tt.permission, "users", strconv.Itoa(int(tt.userID)))
@@ -505,7 +515,11 @@ func seedPermissions(t *testing.T, resourceID string, sql *sqlstore.SQLStore, se
_, err = service.SetTeamPermission(context.Background(), team.OrgId, team.Id, resourceID, "Edit") _, err = service.SetTeamPermission(context.Background(), team.OrgId, team.Id, resourceID, "Edit")
require.NoError(t, err) require.NoError(t, err)
// seed user 1 with "View" permission on dashboard 1 // seed user 1 with "View" permission on dashboard 1
u, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "test", OrgID: 1}) orgSvc, err := orgimpl.ProvideService(sql, sql.Cfg, quotatest.New(false, nil))
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sql, orgSvc, sql.Cfg, nil, nil, &quotatest.FakeQuotaService{})
require.NoError(t, err)
u, err := usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "test", OrgID: 1})
require.NoError(t, err) 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) require.NoError(t, err)

View File

@@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/licensing/licensingtest" "github.com/grafana/grafana/pkg/services/licensing/licensingtest"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/team" "github.com/grafana/grafana/pkg/services/team"
@@ -47,7 +48,11 @@ func TestService_SetUserPermission(t *testing.T) {
}) })
// seed user // seed user
user, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "test", OrgID: 1}) orgSvc, err := orgimpl.ProvideService(sql, sql.Cfg, quotatest.New(false, nil))
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sql, orgSvc, sql.Cfg, nil, nil, &quotatest.FakeQuotaService{})
require.NoError(t, err)
user, err := usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "test", OrgID: 1})
require.NoError(t, err) require.NoError(t, err)
var hookCalled bool var hookCalled bool
@@ -204,7 +209,11 @@ func TestService_SetPermissions(t *testing.T) {
service, sql, teamSvc := setupTestEnvironment(t, []accesscontrol.Permission{}, tt.options) service, sql, teamSvc := setupTestEnvironment(t, []accesscontrol.Permission{}, tt.options)
// seed user // seed user
_, err := sql.CreateUser(context.Background(), user.CreateUserCommand{Login: "user", OrgID: 1}) orgSvc, err := orgimpl.ProvideService(sql, sql.Cfg, quotatest.New(false, nil))
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sql, orgSvc, sql.Cfg, nil, nil, &quotatest.FakeQuotaService{})
require.NoError(t, err)
_, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "user", OrgID: 1})
require.NoError(t, err) require.NoError(t, err)
_, err = teamSvc.CreateTeam("team", "", 1) _, err = teamSvc.CreateTeam("team", "", 1)
require.NoError(t, err) require.NoError(t, err)

View File

@@ -14,9 +14,12 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
datasourcesService "github.com/grafana/grafana/pkg/services/datasources/service" datasourcesService "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
) )
const ( const (
@@ -137,7 +140,11 @@ func generateTeamsAndUsers(b *testing.B, db *sqlstore.SQLStore, users int) ([]in
teamSvc := teamimpl.ProvideService(db, db.Cfg) teamSvc := teamimpl.ProvideService(db, db.Cfg)
numberOfTeams := int(math.Ceil(float64(users) / UsersPerTeam)) numberOfTeams := int(math.Ceil(float64(users) / UsersPerTeam))
globalUserId := 0 globalUserId := 0
qs := quotatest.New(false, nil)
orgSvc, err := orgimpl.ProvideService(db, db.Cfg, qs)
require.NoError(b, err)
usrSvc, err := userimpl.ProvideService(db, orgSvc, db.Cfg, nil, nil, qs)
require.NoError(b, err)
userIds := make([]int64, 0) userIds := make([]int64, 0)
teamIds := make([]int64, 0) teamIds := make([]int64, 0)
for i := 0; i < numberOfTeams; i++ { for i := 0; i < numberOfTeams; i++ {
@@ -155,7 +162,7 @@ func generateTeamsAndUsers(b *testing.B, db *sqlstore.SQLStore, users int) ([]in
userEmail := fmt.Sprintf("%s@example.org", userName) userEmail := fmt.Sprintf("%s@example.org", userName)
createUserCmd := user.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) user, err := usrSvc.Create(context.Background(), &createUserCmd)
require.NoError(b, err) require.NoError(b, err)
userId := user.ID userId := user.ID
globalUserId++ globalUserId++

View File

@@ -16,6 +16,7 @@ import (
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
) )
type setUserResourcePermissionTest struct { type setUserResourcePermissionTest struct {
@@ -488,6 +489,9 @@ func TestIntegrationStore_GetResourcePermissions(t *testing.T) {
func seedResourcePermissions(t *testing.T, store *store, sql *sqlstore.SQLStore, orgService org.Service, actions []string, resource, resourceID, resourceAttribute string, numUsers int) { func seedResourcePermissions(t *testing.T, store *store, sql *sqlstore.SQLStore, orgService org.Service, actions []string, resource, resourceID, resourceAttribute string, numUsers int) {
t.Helper() t.Helper()
var orgModel *org.Org var orgModel *org.Org
usrSvc, err := userimpl.ProvideService(sql, orgService, sql.Cfg, nil, nil, quotatest.New(false, nil))
require.NoError(t, err)
for i := 0; i < numUsers; i++ { for i := 0; i < numUsers; i++ {
if orgModel == nil { if orgModel == nil {
cmd := &org.CreateOrgCommand{Name: "test", UserID: int64(i)} cmd := &org.CreateOrgCommand{Name: "test", UserID: int64(i)}
@@ -496,7 +500,7 @@ func seedResourcePermissions(t *testing.T, store *store, sql *sqlstore.SQLStore,
orgModel = addedOrg orgModel = addedOrg
} }
u, err := sql.CreateUser(context.Background(), user.CreateUserCommand{ u, err := usrSvc.Create(context.Background(), &user.CreateUserCommand{
Login: fmt.Sprintf("user:%s%d", resourceID, i), Login: fmt.Sprintf("user:%s%d", resourceID, i),
OrgID: orgModel.ID, OrgID: orgModel.ID,
}) })

View File

@@ -16,6 +16,7 @@ import (
"github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
) )
func TestIntegrationDashboardACLDataAccess(t *testing.T) { func TestIntegrationDashboardACLDataAccess(t *testing.T) {
@@ -274,11 +275,14 @@ func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role str
sqlStore.Cfg.AutoAssignOrgId = 1 sqlStore.Cfg.AutoAssignOrgId = 1
sqlStore.Cfg.AutoAssignOrgRole = role sqlStore.Cfg.AutoAssignOrgRole = role
orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)) qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err) require.NoError(t, err)
currentUserCmd := user.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) currentUser, err := usrSvc.CreateUserForTests(context.Background(), &currentUserCmd)
require.NoError(t, err) require.NoError(t, err)
orgs, err := orgService.GetUserOrgList(context.Background(), &org.GetUserOrgListQuery{UserID: currentUser.ID}) orgs, err := orgService.GetUserOrgList(context.Background(), &org.GetUserOrgListQuery{UserID: currentUser.ID})
require.NoError(t, err) require.NoError(t, err)

View File

@@ -30,10 +30,12 @@ import (
"github.com/grafana/grafana/pkg/services/folder/folderimpl" "github.com/grafana/grafana/pkg/services/folder/folderimpl"
"github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/team/teamtest"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
@@ -456,8 +458,11 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
Name: "User In DB", Name: "User In DB",
Login: userInDbName, Login: userInDbName,
} }
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
_, err = sqlStore.CreateUser(context.Background(), cmd) require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, quotaService)
require.NoError(t, err)
_, err = usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
sc := scenarioContext{ sc := scenarioContext{

View File

@@ -28,10 +28,12 @@ import (
"github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/libraryelements" "github.com/grafana/grafana/pkg/services/libraryelements"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/team/teamtest"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@@ -856,12 +858,13 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
Name: "User In DB", Name: "User In DB",
Login: userInDbName, Login: userInDbName,
} }
ctx := appcontext.WithUser(context.Background(), usr) ctx := appcontext.WithUser(context.Background(), usr)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
_, err = sqlStore.CreateUser(ctx, cmd) require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, quotaService)
require.NoError(t, err)
_, err = usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
sc := scenarioContext{ sc := scenarioContext{
user: usr, user: usr,
ctx: ctx, ctx: ctx,

View File

@@ -15,7 +15,10 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/login" "github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/login/authinfoservice/database" "github.com/grafana/grafana/pkg/services/login/authinfoservice/database"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
) )
//nolint:goconst //nolint:goconst
@@ -29,13 +32,19 @@ func TestUserAuth(t *testing.T) {
) )
t.Run("Given 5 users", func(t *testing.T) { t.Run("Given 5 users", func(t *testing.T) {
qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.Create(context.Background(), &cmd)
require.Nil(t, err) require.Nil(t, err)
} }
@@ -204,6 +213,11 @@ func TestUserAuth(t *testing.T) {
t.Run("Always return the most recently used auth_module", func(t *testing.T) { t.Run("Always return the most recently used auth_module", func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore = db.InitTestDB(t) sqlStore = db.InitTestDB(t)
qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -211,8 +225,8 @@ func TestUserAuth(t *testing.T) {
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err = usrSvc.Create(context.Background(), &cmd)
require.Nil(t, err) require.NoError(t, err)
} }
// Find a user to set tokens on // Find a user to set tokens on
@@ -272,6 +286,11 @@ func TestUserAuth(t *testing.T) {
t.Run("Keeps track of last used auth_module when not using oauth", func(t *testing.T) { t.Run("Keeps track of last used auth_module when not using oauth", func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore = db.InitTestDB(t) sqlStore = db.InitTestDB(t)
qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -279,7 +298,7 @@ func TestUserAuth(t *testing.T) {
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.Create(context.Background(), &cmd)
require.Nil(t, err) require.Nil(t, err)
} }
@@ -406,6 +425,11 @@ func TestUserAuth(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore = db.InitTestDB(t) sqlStore = db.InitTestDB(t)
qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
@@ -413,17 +437,22 @@ func TestUserAuth(t *testing.T) {
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
OrgID: 1, OrgID: 1,
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.Create(context.Background(), &cmd)
require.Nil(t, err) require.Nil(t, err)
} }
_, err := srv.authInfoStore.GetLoginStats(context.Background()) _, err = srv.authInfoStore.GetLoginStats(context.Background())
require.Nil(t, err) require.Nil(t, err)
}) })
t.Run("calculate metrics on duplicate userstats", func(t *testing.T) { t.Run("calculate metrics on duplicate userstats", func(t *testing.T) {
// Restore after destructive operation // Restore after destructive operation
sqlStore = db.InitTestDB(t) sqlStore = db.InitTestDB(t)
qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
@@ -432,7 +461,7 @@ func TestUserAuth(t *testing.T) {
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
OrgID: 1, OrgID: 1,
} }
_, err := sqlStore.CreateUser(context.Background(), cmd) _, err := usrSvc.Create(context.Background(), &cmd)
require.Nil(t, err) require.Nil(t, err)
} }
@@ -443,7 +472,7 @@ func TestUserAuth(t *testing.T) {
Name: "user name 1", Name: "user name 1",
Login: "USER_DUPLICATE_TEST_1_LOGIN", Login: "USER_DUPLICATE_TEST_1_LOGIN",
} }
_, err := sqlStore.CreateUser(context.Background(), dupUserEmailcmd) _, err := usrSvc.Create(context.Background(), &dupUserEmailcmd)
require.NoError(t, err) require.NoError(t, err)
// add additional user with duplicate login where DOMAIN is upper case // add additional user with duplicate login where DOMAIN is upper case
@@ -452,7 +481,7 @@ func TestUserAuth(t *testing.T) {
Name: "user name 1", Name: "user name 1",
Login: "user_duplicate_test_1_login", Login: "user_duplicate_test_1_login",
} }
_, err = sqlStore.CreateUser(context.Background(), dupUserLogincmd) _, err = usrSvc.Create(context.Background(), &dupUserLogincmd)
require.NoError(t, err) require.NoError(t, err)
authInfoStore.ExpectedUser = &user.User{ authInfoStore.ExpectedUser = &user.User{
Email: "userduplicatetest1@test.com", Email: "userduplicatetest1@test.com",

View File

@@ -2,6 +2,7 @@ package orgimpl
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"time" "time"
@@ -65,10 +66,12 @@ func (s *Service) GetIDForNewUser(ctx context.Context, cmd org.GetOrgIDForNewUse
return cmd.OrgID, nil return cmd.OrgID, nil
} }
orgName := cmd.OrgName var orgName string
orgName = cmd.OrgName
if len(orgName) == 0 { if len(orgName) == 0 {
orgName = util.StringsFallback2(cmd.Email, cmd.Login) orgName = util.StringsFallback2(cmd.Email, cmd.Login)
} }
orga.Name = orgName
if setting.AutoAssignOrg { if setting.AutoAssignOrg {
orga, err := s.store.Get(ctx, int64(s.cfg.AutoAssignOrgId)) orga, err := s.store.Get(ctx, int64(s.cfg.AutoAssignOrgId))
@@ -142,12 +145,14 @@ func (s *Service) Delete(ctx context.Context, cmd *org.DeleteOrgCommand) error {
} }
func (s *Service) GetOrCreate(ctx context.Context, orgName string) (int64, error) { func (s *Service) GetOrCreate(ctx context.Context, orgName string) (int64, error) {
var orga *org.Org var orga = &org.Org{}
var err error var err error
if s.cfg.AutoAssignOrg { if s.cfg.AutoAssignOrg {
orga, err = s.store.Get(ctx, int64(s.cfg.AutoAssignOrgId)) got, err := s.store.Get(ctx, int64(s.cfg.AutoAssignOrgId))
if err != nil { if err != nil && !errors.Is(err, org.ErrOrgNotFound) {
return 0, err return 0, err
} else if err == nil {
return got.ID, nil
} }
if s.cfg.AutoAssignOrgId != 1 { if s.cfg.AutoAssignOrgId != 1 {
@@ -156,11 +161,9 @@ func (s *Service) GetOrCreate(ctx context.Context, orgName string) (int64, error
return 0, fmt.Errorf("could not create user: organization ID %d does not exist", return 0, fmt.Errorf("could not create user: organization ID %d does not exist",
s.cfg.AutoAssignOrgId) s.cfg.AutoAssignOrgId)
} }
orga.Name = MainOrgName orga.Name = MainOrgName
orga.ID = int64(s.cfg.AutoAssignOrgId) orga.ID = int64(s.cfg.AutoAssignOrgId)
} else { } else {
orga = &org.Org{}
orga.Name = orgName orga.Name = orgName
} }

View File

@@ -14,8 +14,10 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@@ -304,11 +306,12 @@ func TestIntegrationOrgUserDataAccess(t *testing.T) {
}) })
t.Run("GetOrgUsers and UpdateOrgUsers", func(t *testing.T) { t.Run("GetOrgUsers and UpdateOrgUsers", func(t *testing.T) {
ss := db.InitTestDB(t) ss := db.InitTestDB(t)
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"} _, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true} ac1cmd := &user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
ac1, err := ss.CreateUser(context.Background(), ac1cmd) ac2cmd := &user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true}
ac1, err := usrSvc.CreateUserForTests(context.Background(), ac1cmd)
require.NoError(t, err) require.NoError(t, err)
ac2, err := ss.CreateUser(context.Background(), ac2cmd) ac2, err := usrSvc.CreateUserForTests(context.Background(), ac2cmd)
require.NoError(t, err) require.NoError(t, err)
cmd := org.AddOrgUserCommand{ cmd := org.AddOrgUserCommand{
OrgID: ac1.OrgID, OrgID: ac1.OrgID,
@@ -412,6 +415,8 @@ func TestIntegrationOrgUserDataAccess(t *testing.T) {
t.Run("Given single org and 2 users inserted", func(t *testing.T) { t.Run("Given single org and 2 users inserted", func(t *testing.T) {
ss = db.InitTestDB(t) ss = db.InitTestDB(t)
_, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
testUser := &user.SignedInUser{ testUser := &user.SignedInUser{
Permissions: map[int64]map[string][]string{ Permissions: map[int64]map[string][]string{
1: {accesscontrol.ActionOrgUsersRead: []string{accesscontrol.ScopeUsersAll}}, 1: {accesscontrol.ActionOrgUsersRead: []string{accesscontrol.ScopeUsersAll}},
@@ -421,13 +426,13 @@ func TestIntegrationOrgUserDataAccess(t *testing.T) {
ss.Cfg.AutoAssignOrgId = 1 ss.Cfg.AutoAssignOrgId = 1
ss.Cfg.AutoAssignOrgRole = "Viewer" ss.Cfg.AutoAssignOrgRole = "Viewer"
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 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"} ac2cmd := &user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
ac1, err := ss.CreateUser(context.Background(), ac1cmd) ac1, err := usrSvc.CreateUserForTests(context.Background(), ac1cmd)
testUser.OrgID = ac1.OrgID testUser.OrgID = ac1.OrgID
require.NoError(t, err) require.NoError(t, err)
_, err = ss.CreateUser(context.Background(), ac2cmd) _, err = usrSvc.Create(context.Background(), ac2cmd)
require.NoError(t, err) require.NoError(t, err)
t.Run("Can get organization users paginated with query", func(t *testing.T) { t.Run("Can get organization users paginated with query", func(t *testing.T) {
@@ -470,20 +475,20 @@ func TestIntegrationSQLStore_AddOrgUser(t *testing.T) {
dialect: store.GetDialect(), dialect: store.GetDialect(),
cfg: setting.NewCfg(), cfg: setting.NewCfg(),
} }
_, usrSvc := createOrgAndUserSvc(t, store, store.Cfg)
// create org and admin // create org and admin
u, err := store.CreateUser(context.Background(), user.CreateUserCommand{ u, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{
Login: "admin", Login: "admin",
}) })
require.NoError(t, err) require.NoError(t, err)
// create a service account with no org // create a service account with no org
sa, err := store.CreateUser(context.Background(), user.CreateUserCommand{ sa, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{
Login: "sa-no-org", Login: "sa-no-org",
IsServiceAccount: true, IsServiceAccount: true,
SkipOrgSetup: true, SkipOrgSetup: true,
}) })
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int64(-1), sa.OrgID) require.Equal(t, int64(-1), sa.OrgID)
@@ -599,9 +604,11 @@ func TestIntegration_SQLStore_GetOrgUsers(t *testing.T) {
func seedOrgUsers(t *testing.T, orgUserStore store, store *sqlstore.SQLStore, numUsers int) { func seedOrgUsers(t *testing.T, orgUserStore store, store *sqlstore.SQLStore, numUsers int) {
t.Helper() t.Helper()
_, usrSvc := createOrgAndUserSvc(t, store, store.Cfg)
// Seed users // Seed users
for i := 1; i <= numUsers; i++ { for i := 1; i <= numUsers; i++ {
user, err := store.CreateUser(context.Background(), user.CreateUserCommand{ user, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{
Login: fmt.Sprintf("user-%d", i), Login: fmt.Sprintf("user-%d", i),
OrgID: 1, OrgID: 1,
}) })
@@ -633,8 +640,8 @@ func TestIntegration_SQLStore_GetOrgUsers_PopulatesCorrectly(t *testing.T) {
} }
// The millisecond part is not stored in the DB // The millisecond part is not stored in the DB
constNow := time.Date(2022, 8, 17, 20, 34, 58, 0, time.UTC) constNow := time.Date(2022, 8, 17, 20, 34, 58, 0, time.UTC)
sqlstore.MockTimeNow(constNow) userimpl.MockTimeNow(constNow)
defer sqlstore.ResetTimeNow() defer userimpl.ResetTimeNow()
store := db.InitTestDB(t, sqlstore.InitTestDBOpt{}) store := db.InitTestDB(t, sqlstore.InitTestDBOpt{})
orgUserStore := sqlStore{ orgUserStore := sqlStore{
@@ -642,6 +649,7 @@ func TestIntegration_SQLStore_GetOrgUsers_PopulatesCorrectly(t *testing.T) {
dialect: store.GetDialect(), dialect: store.GetDialect(),
cfg: setting.NewCfg(), cfg: setting.NewCfg(),
} }
_, usrSvc := createOrgAndUserSvc(t, store, store.Cfg)
id, err := orgUserStore.Insert(context.Background(), id, err := orgUserStore.Insert(context.Background(),
&org.Org{ &org.Org{
@@ -651,7 +659,7 @@ func TestIntegration_SQLStore_GetOrgUsers_PopulatesCorrectly(t *testing.T) {
}) })
require.NoError(t, err) require.NoError(t, err)
newUser, err := store.CreateUser(context.Background(), user.CreateUserCommand{ newUser, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{
Login: "Viewer", Login: "Viewer",
Email: "viewer@localhost", Email: "viewer@localhost",
OrgID: id, OrgID: id,
@@ -752,8 +760,6 @@ func TestIntegration_SQLStore_SearchOrgUsers(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) { t.Run(tt.desc, func(t *testing.T) {
result, err := orgUserStore.SearchOrgUsers(context.Background(), tt.query) result, err := orgUserStore.SearchOrgUsers(context.Background(), tt.query)
fmt.Println("users:", result)
require.NoError(t, err) require.NoError(t, err)
assert.Len(t, result.OrgUsers, tt.expectedNumUsers) assert.Len(t, result.OrgUsers, tt.expectedNumUsers)
@@ -776,15 +782,16 @@ func TestIntegration_SQLStore_RemoveOrgUser(t *testing.T) {
dialect: store.GetDialect(), dialect: store.GetDialect(),
cfg: setting.NewCfg(), cfg: setting.NewCfg(),
} }
_, usrSvc := createOrgAndUserSvc(t, store, store.Cfg)
// create org and admin // create org and admin
_, err := store.CreateUser(context.Background(), user.CreateUserCommand{ _, err := usrSvc.Create(context.Background(), &user.CreateUserCommand{
Login: "admin", Login: "admin",
OrgID: 1, OrgID: 1,
}) })
require.NoError(t, err) require.NoError(t, err)
// create a user with no org // create a user with no org
_, err = store.CreateUser(context.Background(), user.CreateUserCommand{ _, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{
Login: "user", Login: "user",
OrgID: 1, OrgID: 1,
SkipOrgSetup: true, SkipOrgSetup: true,
@@ -807,3 +814,15 @@ func TestIntegration_SQLStore_RemoveOrgUser(t *testing.T) {
}) })
require.NoError(t, err) require.NoError(t, err)
} }
func createOrgAndUserSvc(t *testing.T, store db.DB, cfg *setting.Cfg) (org.Service, user.Service) {
t.Helper()
quotaService := quotaimpl.ProvideService(store, cfg)
orgService, err := ProvideService(store, cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, cfg, nil, nil, quotaService)
require.NoError(t, err)
return orgService, usrSvc
}

View File

@@ -75,7 +75,7 @@ func (f *FakeOrgService) Delete(ctx context.Context, cmd *org.DeleteOrgCommand)
} }
func (f *FakeOrgService) GetOrCreate(ctx context.Context, orgName string) (int64, error) { func (f *FakeOrgService) GetOrCreate(ctx context.Context, orgName string) (int64, error) {
return 0, f.ExpectedError return f.ExpectedOrg.ID, f.ExpectedError
} }
func (f *FakeOrgService) AddOrgUser(ctx context.Context, cmd *org.AddOrgUserCommand) error { func (f *FakeOrgService) AddOrgUser(ctx context.Context, cmd *org.AddOrgUserCommand) error {

View File

@@ -17,7 +17,10 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
@@ -51,8 +54,12 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
Cfg: setting.NewCfg(), Cfg: setting.NewCfg(),
store: sqlStore, store: sqlStore,
} }
service.Cfg.QueryHistoryEnabled = true service.Cfg.QueryHistoryEnabled = true
quotaService := quotatest.New(false, nil)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, nil, nil, quotaService)
require.NoError(t, err)
usr := user.SignedInUser{ usr := user.SignedInUser{
UserID: testUserID, UserID: testUserID,
@@ -64,7 +71,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
LastSeenAt: time.Now(), LastSeenAt: time.Now(),
} }
_, err := sqlStore.CreateUser(context.Background(), user.CreateUserCommand{ _, err = usrSvc.Create(context.Background(), &user.CreateUserCommand{
Email: "signed.in.user@test.com", Email: "signed.in.user@test.com",
Name: "Signed In User", Name: "Signed In User",
Login: "signed_in_user", Login: "signed_in_user",

View File

@@ -23,6 +23,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol/actest" "github.com/grafana/grafana/pkg/services/accesscontrol/actest"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl" "github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey" "github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
"github.com/grafana/grafana/pkg/services/licensing" "github.com/grafana/grafana/pkg/services/licensing"
@@ -32,6 +33,7 @@ import (
"github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database" "github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests" "github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl" "github.com/grafana/grafana/pkg/services/user/userimpl"
@@ -46,14 +48,7 @@ var (
func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) { func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) {
store := db.InitTestDB(t) store := db.InitTestDB(t)
quotaService := quotatest.New(false, nil) services := setupTestServices(t, store)
apiKeyService, err := apikeyimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
kvStore := kvstore.ProvideService(store)
orgService, err := orgimpl.ProvideService(store, setting.NewCfg(), quotaService)
require.NoError(t, err)
saStore := database.ProvideServiceAccountsStore(store, apiKeyService, kvStore, orgService)
svcmock := tests.ServiceAccountMock{}
autoAssignOrg := store.Cfg.AutoAssignOrg autoAssignOrg := store.Cfg.AutoAssignOrg
store.Cfg.AutoAssignOrg = true store.Cfg.AutoAssignOrg = true
@@ -62,7 +57,7 @@ func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) {
}() }()
orgCmd := &org.CreateOrgCommand{Name: "Some Test Org"} orgCmd := &org.CreateOrgCommand{Name: "Some Test Org"}
_, err = orgService.CreateWithMember(context.Background(), orgCmd) _, err := services.OrgService.CreateWithMember(context.Background(), orgCmd)
require.Nil(t, err) require.Nil(t, err)
type testCreateSATestCase struct { type testCreateSATestCase struct {
@@ -167,7 +162,7 @@ func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
serviceAccountRequestScenario(t, http.MethodPost, serviceAccountPath, testUser, func(httpmethod string, endpoint string, usr *tests.TestUser) { serviceAccountRequestScenario(t, http.MethodPost, serviceAccountPath, testUser, func(httpmethod string, endpoint string, usr *tests.TestUser) {
server, api := setupTestServer(t, &svcmock, routing.NewRouteRegister(), tc.acmock, store, saStore) server, api := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
marshalled, err := json.Marshal(tc.body) marshalled, err := json.Marshal(tc.body)
require.NoError(t, err) require.NoError(t, err)
@@ -216,12 +211,7 @@ func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) {
// with permissions and without permissions // with permissions and without permissions
func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) { func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
store := db.InitTestDB(t) store := db.InitTestDB(t)
kvStore := kvstore.ProvideService(store) services := setupTestServices(t, store)
quotaService := quotatest.New(false, nil)
apiKeyService, err := apikeyimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
saStore := database.ProvideServiceAccountsStore(store, apiKeyService, kvStore, nil)
svcmock := tests.ServiceAccountMock{}
var requestResponse = func(server *web.Mux, httpMethod, requestpath string) *httptest.ResponseRecorder { var requestResponse = func(server *web.Mux, httpMethod, requestpath string) *httptest.ResponseRecorder {
req, err := http.NewRequest(httpMethod, requestpath, nil) req, err := http.NewRequest(httpMethod, requestpath, nil)
@@ -249,7 +239,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
} }
serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) { serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) {
createduser := tests.SetupUserServiceAccount(t, store, testcase.user) createduser := tests.SetupUserServiceAccount(t, store, testcase.user)
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), testcase.acmock, store, saStore) server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), testcase.acmock, store, services.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) require.Equal(t, testcase.expectedCode, actual)
}) })
@@ -273,7 +263,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
} }
serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) { serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) {
createduser := tests.SetupUserServiceAccount(t, store, testcase.user) createduser := tests.SetupUserServiceAccount(t, store, testcase.user)
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), testcase.acmock, store, saStore) server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), testcase.acmock, store, services.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) require.Equal(t, testcase.expectedCode, actual)
}) })
@@ -326,12 +316,7 @@ func setupTestServer(t *testing.T, svc *tests.ServiceAccountMock,
func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) { func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
store := db.InitTestDB(t) store := db.InitTestDB(t)
quotaService := quotatest.New(false, nil) services := setupTestServices(t, store)
apiKeyService, err := apikeyimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
kvStore := kvstore.ProvideService(store)
saStore := database.ProvideServiceAccountsStore(store, apiKeyService, kvStore, nil)
svcmock := tests.ServiceAccountMock{}
type testRetrieveSATestCase struct { type testRetrieveSATestCase struct {
desc string desc string
user *tests.TestUser user *tests.TestUser
@@ -395,7 +380,7 @@ func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
createdUser := tests.SetupUserServiceAccount(t, store, *tc.user) 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) server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, scopeID)) actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, scopeID))
@@ -420,12 +405,7 @@ func newString(s string) *string {
func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) { func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
store := db.InitTestDB(t) store := db.InitTestDB(t)
quotaService := quotatest.New(false, nil) services := setupTestServices(t, store)
apiKeyService, err := apikeyimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
kvStore := kvstore.ProvideService(store)
saStore := database.ProvideServiceAccountsStore(store, apiKeyService, kvStore, nil)
svcmock := tests.ServiceAccountMock{}
type testUpdateSATestCase struct { type testUpdateSATestCase struct {
desc string desc string
user *tests.TestUser user *tests.TestUser
@@ -518,7 +498,7 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
server, saAPI := setupTestServer(t, &svcmock, routing.NewRouteRegister(), tc.acmock, store, saStore) server, saAPI := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
scopeID := tc.Id scopeID := tc.Id
if tc.user != nil { if tc.user != nil {
createdUser := tests.SetupUserServiceAccount(t, store, *tc.user) createdUser := tests.SetupUserServiceAccount(t, store, *tc.user)
@@ -556,3 +536,33 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
}) })
} }
} }
type services struct {
OrgService org.Service
UserService user.Service
SAStore serviceaccounts.Store
SAService tests.ServiceAccountMock
APIKeyService apikey.Service
}
func setupTestServices(t *testing.T, db *sqlstore.SQLStore) services {
kvStore := kvstore.ProvideService(db)
quotaService := quotatest.New(false, nil)
apiKeyService, err := apikeyimpl.ProvideService(db, db.Cfg, quotaService)
require.NoError(t, err)
orgService, err := orgimpl.ProvideService(db, setting.NewCfg(), quotaService)
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(db, orgService, db.Cfg, nil, nil, quotaService)
require.NoError(t, err)
saStore := database.ProvideServiceAccountsStore(db, apiKeyService, kvStore, userSvc, orgService)
svcmock := tests.ServiceAccountMock{}
return services{
OrgService: orgService,
UserService: userSvc,
SAStore: saStore,
SAService: svcmock,
APIKeyService: apiKeyService,
}
}

View File

@@ -18,14 +18,10 @@ import (
"github.com/grafana/grafana/pkg/components/apikeygen" "github.com/grafana/grafana/pkg/components/apikeygen"
apikeygenprefix "github.com/grafana/grafana/pkg/components/apikeygenprefixed" apikeygenprefix "github.com/grafana/grafana/pkg/components/apikeygenprefixed"
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests" "github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
@@ -55,12 +51,7 @@ func createTokenforSA(t *testing.T, store serviceaccounts.Store, keyName string,
func TestServiceAccountsAPI_CreateToken(t *testing.T) { func TestServiceAccountsAPI_CreateToken(t *testing.T) {
store := db.InitTestDB(t) store := db.InitTestDB(t)
quotaService := quotatest.New(false, nil) services := setupTestServices(t, store)
apiKeyService, err := apikeyimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
kvStore := kvstore.ProvideService(store)
saStore := database.ProvideServiceAccountsStore(store, apiKeyService, kvStore, nil)
svcmock := tests.ServiceAccountMock{}
sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true}) sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true})
type testCreateSAToken struct { type testCreateSAToken struct {
@@ -140,7 +131,7 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
bodyString = string(b) bodyString = string(b)
} }
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), tc.acmock, store, saStore) server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
actual := requestResponse(server, http.MethodPost, endpoint, strings.NewReader(bodyString)) actual := requestResponse(server, http.MethodPost, endpoint, strings.NewReader(bodyString))
actualCode := actual.Code actualCode := actual.Code
@@ -154,7 +145,7 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
assert.Equal(t, tc.body["name"], actualBody["name"]) assert.Equal(t, tc.body["name"], actualBody["name"])
query := apikey.GetByNameQuery{KeyName: tc.body["name"].(string), OrgId: sa.OrgID} query := apikey.GetByNameQuery{KeyName: tc.body["name"].(string), OrgId: sa.OrgID}
err = apiKeyService.GetApiKeyByName(context.Background(), &query) err = services.APIKeyService.GetApiKeyByName(context.Background(), &query)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, sa.ID, *query.Result.ServiceAccountId) assert.Equal(t, sa.ID, *query.Result.ServiceAccountId)
@@ -174,12 +165,7 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
func TestServiceAccountsAPI_DeleteToken(t *testing.T) { func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
store := db.InitTestDB(t) store := db.InitTestDB(t)
quotaService := quotatest.New(false, nil) services := setupTestServices(t, store)
apiKeyService, err := apikeyimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
kvStore := kvstore.ProvideService(store)
svcMock := &tests.ServiceAccountMock{}
saStore := database.ProvideServiceAccountsStore(store, apiKeyService, kvStore, nil)
sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true}) sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true})
type testCreateSAToken struct { type testCreateSAToken struct {
@@ -239,11 +225,11 @@ func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) { t.Run(tc.desc, func(t *testing.T) {
token := createTokenforSA(t, saStore, tc.keyName, sa.OrgID, sa.ID, 1) token := createTokenforSA(t, services.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 := "" bodyString := ""
server, _ := setupTestServer(t, svcMock, routing.NewRouteRegister(), tc.acmock, store, saStore) server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
actual := requestResponse(server, http.MethodDelete, endpoint, strings.NewReader(bodyString)) actual := requestResponse(server, http.MethodDelete, endpoint, strings.NewReader(bodyString))
actualCode := actual.Code actualCode := actual.Code
@@ -253,7 +239,7 @@ func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
require.Equal(t, tc.expectedCode, actualCode, endpoint, actualBody) require.Equal(t, tc.expectedCode, actualCode, endpoint, actualBody)
query := apikey.GetByNameQuery{KeyName: tc.keyName, OrgId: sa.OrgID} query := apikey.GetByNameQuery{KeyName: tc.keyName, OrgId: sa.OrgID}
err := apiKeyService.GetApiKeyByName(context.Background(), &query) err := services.APIKeyService.GetApiKeyByName(context.Background(), &query)
if actualCode == http.StatusOK { if actualCode == http.StatusOK {
require.Error(t, err) require.Error(t, err)
} else { } else {

View File

@@ -30,13 +30,14 @@ type ServiceAccountsStoreImpl struct {
} }
func ProvideServiceAccountsStore(store *sqlstore.SQLStore, apiKeyService apikey.Service, func ProvideServiceAccountsStore(store *sqlstore.SQLStore, apiKeyService apikey.Service,
kvStore kvstore.KVStore, orgService org.Service) *ServiceAccountsStoreImpl { kvStore kvstore.KVStore, userService user.Service, orgService org.Service) *ServiceAccountsStoreImpl {
return &ServiceAccountsStoreImpl{ return &ServiceAccountsStoreImpl{
sqlStore: store, sqlStore: store,
apiKeyService: apiKeyService, apiKeyService: apiKeyService,
kvStore: kvStore, kvStore: kvStore,
log: log.New("serviceaccounts.store"), log: log.New("serviceaccounts.store"),
orgService: orgService, orgService: orgService,
userService: userService,
} }
} }
@@ -55,7 +56,7 @@ func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, org
var newSA *user.User var newSA *user.User
createErr := s.sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) (err error) { createErr := s.sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) (err error) {
var errUser error var errUser error
newSA, errUser = s.sqlStore.CreateUser(ctx, user.CreateUserCommand{ newSA, errUser = s.userService.CreateServiceAccount(ctx, &user.CreateUserCommand{
Login: generatedLogin, Login: generatedLogin,
OrgID: orgId, OrgID: orgId,
Name: saForm.Name, Name: saForm.Name,
@@ -461,7 +462,7 @@ func (s *ServiceAccountsStoreImpl) CreateServiceAccountFromApikey(ctx context.Co
} }
return s.sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error { return s.sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
newSA, errCreateSA := s.sqlStore.CreateUser(ctx, cmd) newSA, errCreateSA := s.userService.CreateServiceAccount(ctx, &cmd)
if errCreateSA != nil { if errCreateSA != nil {
return fmt.Errorf("failed to create service account: %w", errCreateSA) return fmt.Errorf("failed to create service account: %w", errCreateSA)
} }

View File

@@ -18,6 +18,7 @@ import (
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests" "github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@@ -118,7 +119,9 @@ func setupTestDatabase(t *testing.T) (*sqlstore.SQLStore, *ServiceAccountsStoreI
kvStore := kvstore.ProvideService(db) kvStore := kvstore.ProvideService(db)
orgService, err := orgimpl.ProvideService(db, setting.NewCfg(), quotaService) orgService, err := orgimpl.ProvideService(db, setting.NewCfg(), quotaService)
require.NoError(t, err) require.NoError(t, err)
return db, ProvideServiceAccountsStore(db, apiKeyService, kvStore, orgService) userSvc, err := userimpl.ProvideService(db, orgService, db.Cfg, nil, nil, quotaService)
require.NoError(t, err)
return db, ProvideServiceAccountsStore(db, apiKeyService, kvStore, userSvc, orgService)
} }
func TestStore_RetrieveServiceAccount(t *testing.T) { func TestStore_RetrieveServiceAccount(t *testing.T) {

View File

@@ -12,10 +12,13 @@ import (
"github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl" "github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
) )
type TestUser struct { type TestUser struct {
@@ -41,7 +44,13 @@ func SetupUserServiceAccount(t *testing.T, sqlStore *sqlstore.SQLStore, testUser
role = testUser.Role role = testUser.Role
} }
u1, err := sqlStore.CreateUser(context.Background(), user.CreateUserCommand{ quotaService := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, quotaService)
require.NoError(t, err)
u1, err := usrSvc.CreateUserForTests(context.Background(), &user.CreateUserCommand{
Login: testUser.Login, Login: testUser.Login,
IsServiceAccount: testUser.IsServiceAccount, IsServiceAccount: testUser.IsServiceAccount,
DefaultOrgRole: role, DefaultOrgRole: role,

View File

@@ -4,8 +4,9 @@ import (
"context" "context"
"testing" "testing"
"github.com/grafana/grafana/pkg/models"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
) )
func TestIntegrationGetDBHealthQuery(t *testing.T) { func TestIntegrationGetDBHealthQuery(t *testing.T) {

View File

@@ -1,70 +0,0 @@
// DO NOT ADD METHODS TO THIS FILES. SQLSTORE IS DEPRECATED AND WILL BE REMOVED.
package sqlstore
import (
"fmt"
"time"
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/models"
)
const mainOrgName = "Main Org."
func verifyExistingOrg(sess *DBSession, orgId int64) error {
var org models.Org
has, err := sess.Where("id=?", orgId).Get(&org)
if err != nil {
return err
}
if !has {
return models.ErrOrgNotFound
}
return nil
}
func (ss *SQLStore) getOrCreateOrg(sess *DBSession, orgName string) (int64, error) {
var org models.Org
if ss.Cfg.AutoAssignOrg {
has, err := sess.Where("id=?", ss.Cfg.AutoAssignOrgId).Get(&org)
if err != nil {
return 0, err
}
if has {
return org.Id, nil
}
if ss.Cfg.AutoAssignOrgId != 1 {
ss.log.Error("Could not create user: organization ID does not exist", "orgID",
ss.Cfg.AutoAssignOrgId)
return 0, fmt.Errorf("could not create user: organization ID %d does not exist",
ss.Cfg.AutoAssignOrgId)
}
org.Name = mainOrgName
org.Id = int64(ss.Cfg.AutoAssignOrgId)
} else {
org.Name = orgName
}
org.Created = time.Now()
org.Updated = time.Now()
if org.Id != 0 {
if _, err := sess.InsertId(&org); err != nil {
return 0, err
}
} else {
if _, err := sess.InsertOne(&org); err != nil {
return 0, err
}
}
sess.publishAfterCommit(&events.OrgCreated{
Timestamp: org.Created,
Id: org.Id,
Name: org.Name,
})
return org.Id, nil
}

View File

@@ -1,211 +0,0 @@
package sqlstore
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
)
func TestIntegrationAccountDataAccess(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
t.Run("Testing Account DB Access", func(t *testing.T) {
sqlStore := InitTestDB(t)
t.Run("Given single org mode", func(t *testing.T) {
sqlStore.Cfg.AutoAssignOrg = true
sqlStore.Cfg.AutoAssignOrgId = 1
sqlStore.Cfg.AutoAssignOrgRole = "Viewer"
t.Run("Users should be added to default organization", func(t *testing.T) {
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}
err = sqlStore.getUserOrgList(context.Background(), &q1)
require.NoError(t, err)
err = sqlStore.getUserOrgList(context.Background(), &q2)
require.NoError(t, err)
require.Equal(t, q1.Result[0].OrgId, q2.Result[0].OrgId)
require.Equal(t, string(q1.Result[0].Role), "Viewer")
})
})
t.Run("Given two saved users", func(t *testing.T) {
sqlStore = InitTestDB(t)
sqlStore.Cfg.AutoAssignOrg = false
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)
ac2, err := sqlStore.CreateUser(context.Background(), ac2cmd)
require.NoError(t, err)
// user only used for making sure we filter out the service accounts
_, err = sqlStore.CreateUser(context.Background(), serviceaccountcmd)
require.NoError(t, err)
t.Run("Given an added org user", func(t *testing.T) {
cmd := models.AddOrgUserCommand{
OrgId: ac1.OrgID,
UserId: ac2.ID,
Role: org.RoleViewer,
}
err := sqlStore.addOrgUser(context.Background(), &cmd)
t.Run("Should have been saved without error", func(t *testing.T) {
require.NoError(t, err)
})
t.Run("Can get user organizations", func(t *testing.T) {
query := models.GetUserOrgListQuery{UserId: ac2.ID}
err := sqlStore.getUserOrgList(context.Background(), &query)
require.NoError(t, err)
require.Equal(t, len(query.Result), 2)
})
t.Run("Given an org user with dashboard permissions", func(t *testing.T) {
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,
Role: org.RoleViewer,
}
err = sqlStore.addOrgUser(context.Background(), &orgUserCmd)
require.NoError(t, err)
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,
})
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,
})
require.NoError(t, err)
})
})
})
})
}
// TODO: Use FakeDashboardStore when org has its own service
func insertTestDashboard(t *testing.T, sqlStore *SQLStore, title string, orgId int64,
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
t.Helper()
cmd := models.SaveDashboardCommand{
OrgId: orgId,
FolderId: folderId,
IsFolder: isFolder,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": title,
"tags": tags,
}),
}
var dash *models.Dashboard
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
dash = cmd.GetDashboardModel()
dash.SetVersion(1)
dash.Created = time.Now()
dash.Updated = time.Now()
dash.Uid = util.GenerateShortUID()
_, err := sess.Insert(dash)
return err
})
require.NoError(t, err)
require.NotNil(t, dash)
dash.Data.Set("id", dash.Id)
dash.Data.Set("uid", dash.Uid)
err = sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
dashVersion := &dashver.DashboardVersion{
DashboardID: dash.Id,
ParentVersion: dash.Version,
RestoredFrom: cmd.RestoredFrom,
Version: dash.Version,
Created: time.Now(),
CreatedBy: dash.UpdatedBy,
Message: cmd.Message,
Data: dash.Data,
}
require.NoError(t, err)
if affectedRows, err := sess.Insert(dashVersion); err != nil {
return err
} else if affectedRows == 0 {
return dashboards.ErrDashboardNotFound
}
return nil
})
require.NoError(t, err)
return dash
}
// TODO: Use FakeDashboardStore when org has its own service
func updateDashboardACL(t *testing.T, sqlStore *SQLStore, dashboardID int64, items ...*models.DashboardACL) error {
t.Helper()
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
_, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID)
if err != nil {
return fmt.Errorf("deleting from dashboard_acl failed: %w", err)
}
for _, item := range items {
item.Created = time.Now()
item.Updated = time.Now()
if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) {
return models.ErrDashboardACLInfoMissing
}
if item.DashboardID == 0 {
return models.ErrDashboardPermissionDashboardEmpty
}
sess.Nullable("user_id", "team_id")
if _, err := sess.Insert(item); err != nil {
return err
}
}
// Update dashboard HasACL flag
dashboard := models.Dashboard{HasACL: true}
_, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard)
return err
})
return err
}

View File

@@ -1,68 +0,0 @@
package sqlstore
import (
"context"
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
)
func (ss *SQLStore) addOrgUser(ctx context.Context, cmd *models.AddOrgUserCommand) error {
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
// check if user exists
var usr user.User
session := sess.ID(cmd.UserId)
if !cmd.AllowAddingServiceAccount {
session = session.Where(notServiceAccountFilter(ss))
}
if exists, err := session.Get(&usr); err != nil {
return err
} else if !exists {
return user.ErrUserNotFound
}
if res, err := sess.Query("SELECT 1 from org_user WHERE org_id=? and user_id=?", cmd.OrgId, usr.ID); err != nil {
return err
} else if len(res) == 1 {
return models.ErrOrgUserAlreadyAdded
}
if res, err := sess.Query("SELECT 1 from org WHERE id=?", cmd.OrgId); err != nil {
return err
} else if len(res) != 1 {
return models.ErrOrgNotFound
}
entity := models.OrgUser{
OrgId: cmd.OrgId,
UserId: cmd.UserId,
Role: cmd.Role,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(&entity)
if err != nil {
return err
}
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=?", usr.ID, usr.OrgID)
sess.Cols("org.name", "org_user.role", "org_user.org_id")
err = sess.Find(&userOrgs)
if err != nil {
return err
}
if len(userOrgs) == 0 {
return setUsingOrgInTransaction(sess, usr.ID, cmd.OrgId)
}
return nil
})
}

View File

@@ -1,66 +0,0 @@
package sqlstore
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/user"
)
func TestSQLStore_AddOrgUser(t *testing.T) {
var orgID int64 = 1
store := InitTestDB(t)
// create org and admin
_, err := store.CreateUser(context.Background(), user.CreateUserCommand{
Login: "admin",
OrgID: orgID,
})
require.NoError(t, err)
// create a service account with no org
sa, err := store.CreateUser(context.Background(), user.CreateUserCommand{
Login: "sa-no-org",
IsServiceAccount: true,
SkipOrgSetup: true,
})
require.NoError(t, err)
require.Equal(t, int64(-1), sa.OrgID)
// assign the sa to the org but without the override. should fail
err = store.addOrgUser(context.Background(), &models.AddOrgUserCommand{
Role: "Viewer",
OrgId: orgID,
UserId: sa.ID,
})
require.Error(t, err)
// assign the sa to the org with the override. should succeed
err = store.addOrgUser(context.Background(), &models.AddOrgUserCommand{
Role: "Viewer",
OrgId: orgID,
UserId: sa.ID,
AllowAddingServiceAccount: true,
})
require.NoError(t, err)
// assert the org has been correctly set
saFound := new(user.User)
err = store.WithDbSession(context.Background(), func(sess *DBSession) error {
has, err := sess.ID(sa.ID).Get(saFound)
if err != nil {
return err
} else if !has {
return user.ErrUserNotFound
}
return nil
})
require.NoError(t, err)
require.Equal(t, saFound.OrgID, orgID)
}

View File

@@ -2,17 +2,22 @@ package sqlstore
import ( import (
"context" "context"
"fmt"
"math/rand" "math/rand"
"strconv" "strconv"
"testing" "testing"
"time" "time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
) )
func TestIntegrationSQLBuilder(t *testing.T) { func TestIntegrationSQLBuilder(t *testing.T) {
@@ -196,22 +201,28 @@ func createDummyUser(t *testing.T, sqlStore *SQLStore) *user.User {
t.Helper() t.Helper()
uid := strconv.Itoa(rand.Intn(9999999)) uid := strconv.Itoa(rand.Intn(9999999))
createUserCmd := user.CreateUserCommand{ usr := &user.User{
Email: uid + "@example.com", Email: uid + "@example.com",
Login: uid, Login: uid,
Name: uid, Name: uid,
Company: "", Company: "",
OrgName: "", Password: uid,
Password: uid, EmailVerified: true,
EmailVerified: true, IsAdmin: false,
IsAdmin: false, Created: time.Now(),
SkipOrgSetup: false, Updated: time.Now(),
DefaultOrgRole: string(org.RoleViewer),
} }
user, err := sqlStore.CreateUser(context.Background(), createUserCmd)
require.NoError(t, err)
return user var id int64
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
sess.UseBool("is_admin")
var err error
id, err = sess.Insert(usr)
return err
})
require.NoError(t, err)
usr.ID = id
return usr
} }
func createDummyDashboard(t *testing.T, sqlStore *SQLStore, dashboardProps DashboardProps) *models.Dashboard { func createDummyDashboard(t *testing.T, sqlStore *SQLStore, dashboardProps DashboardProps) *models.Dashboard {
@@ -317,3 +328,95 @@ func getDashboards(t *testing.T, sqlStore *SQLStore, search Search, aclUserID in
require.NoError(t, err) require.NoError(t, err)
return res return res
} }
// TODO: Use FakeDashboardStore when org has its own service
func insertTestDashboard(t *testing.T, sqlStore *SQLStore, title string, orgId int64,
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
t.Helper()
cmd := models.SaveDashboardCommand{
OrgId: orgId,
FolderId: folderId,
IsFolder: isFolder,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": title,
"tags": tags,
}),
}
var dash *models.Dashboard
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
dash = cmd.GetDashboardModel()
dash.SetVersion(1)
dash.Created = time.Now()
dash.Updated = time.Now()
dash.Uid = util.GenerateShortUID()
_, err := sess.Insert(dash)
return err
})
require.NoError(t, err)
require.NotNil(t, dash)
dash.Data.Set("id", dash.Id)
dash.Data.Set("uid", dash.Uid)
err = sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
dashVersion := &dashver.DashboardVersion{
DashboardID: dash.Id,
ParentVersion: dash.Version,
RestoredFrom: cmd.RestoredFrom,
Version: dash.Version,
Created: time.Now(),
CreatedBy: dash.UpdatedBy,
Message: cmd.Message,
Data: dash.Data,
}
require.NoError(t, err)
if affectedRows, err := sess.Insert(dashVersion); err != nil {
return err
} else if affectedRows == 0 {
return dashboards.ErrDashboardNotFound
}
return nil
})
require.NoError(t, err)
return dash
}
// TODO: Use FakeDashboardStore when org has its own service
func updateDashboardACL(t *testing.T, sqlStore *SQLStore, dashboardID int64, items ...*models.DashboardACL) error {
t.Helper()
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
_, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID)
if err != nil {
return fmt.Errorf("deleting from dashboard_acl failed: %w", err)
}
for _, item := range items {
item.Created = time.Now()
item.Updated = time.Now()
if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) {
return models.ErrDashboardACLInfoMissing
}
if item.DashboardID == 0 {
return models.ErrDashboardPermissionDashboardEmpty
}
sess.Nullable("user_id", "team_id")
if _, err := sess.Insert(item); err != nil {
return err
}
}
// Update dashboard HasACL flag
dashboard := models.Dashboard{HasACL: true}
_, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard)
return err
})
return err
}

View File

@@ -198,7 +198,6 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
if _, err := sess.SQL(rawSQL).Get(&stats); err != nil { if _, err := sess.SQL(rawSQL).Get(&stats); err != nil {
return fmt.Errorf("could not determine if admin user exists: %w", err) return fmt.Errorf("could not determine if admin user exists: %w", err)
} }
if stats.Count > 0 { if stats.Count > 0 {
return nil return nil
} }
@@ -206,6 +205,7 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
// ensure admin user // ensure admin user
if !ss.Cfg.DisableInitAdminCreation { if !ss.Cfg.DisableInitAdminCreation {
ss.log.Debug("Creating default admin user") ss.log.Debug("Creating default admin user")
if _, err := ss.createUser(ctx, sess, user.CreateUserCommand{ if _, err := ss.createUser(ctx, sess, user.CreateUserCommand{
Login: ss.Cfg.AdminUser, Login: ss.Cfg.AdminUser,
Email: ss.Cfg.AdminEmail, Email: ss.Cfg.AdminEmail,
@@ -216,9 +216,6 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
} }
ss.log.Info("Created default admin", "user", ss.Cfg.AdminUser) ss.log.Info("Created default admin", "user", ss.Cfg.AdminUser)
// Why should we return and not create the default org in this case?
// Returning here breaks tests using anonymous access
// return nil
} }
ss.log.Debug("Creating default org", "name", mainOrgName) ss.log.Debug("Creating default org", "name", mainOrgName)

View File

@@ -8,13 +8,11 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/sqlstore/session" "github.com/grafana/grafana/pkg/services/sqlstore/session"
"github.com/grafana/grafana/pkg/services/user"
) )
type Store interface { type Store interface {
GetDialect() migrator.Dialect GetDialect() migrator.Dialect
GetDBType() core.DbType GetDBType() core.DbType
CreateUser(ctx context.Context, cmd user.CreateUserCommand) (*user.User, error)
WithDbSession(ctx context.Context, callback DBTransactionFunc) error WithDbSession(ctx context.Context, callback DBTransactionFunc) error
WithNewDbSession(ctx context.Context, callback DBTransactionFunc) error WithNewDbSession(ctx context.Context, callback DBTransactionFunc) error
WithTransactionalDbSession(ctx context.Context, callback DBTransactionFunc) error WithTransactionalDbSession(ctx context.Context, callback DBTransactionFunc) error

View File

@@ -4,8 +4,8 @@ package sqlstore
import ( import (
"context" "context"
"fmt" "fmt"
"sort"
"strings" "strings"
"time"
"github.com/grafana/grafana/pkg/events" "github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
@@ -14,6 +14,8 @@ import (
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
) )
const mainOrgName = "Main Org."
func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserCommand) (int64, error) { func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserCommand) (int64, error) {
if ss.Cfg.AutoAssignOrg && args.OrgID != 0 { if ss.Cfg.AutoAssignOrg && args.OrgID != 0 {
if err := verifyExistingOrg(sess, args.OrgID); err != nil { if err := verifyExistingOrg(sess, args.OrgID); err != nil {
@@ -30,21 +32,19 @@ func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserComm
return ss.getOrCreateOrg(sess, orgName) return ss.getOrCreateOrg(sess, orgName)
} }
// createUser creates a user in the database // createUser creates a user in the database. It will also create a default
// if autoAssignOrg is enabled then args.OrgID will be used // organization, if none exists. This should only be used by the sqlstore
// to add to an existing Org with id=args.OrgID // Reset() function.
// if autoAssignOrg is disabled then args.OrgName will be used //
// to create a new Org with name=args.OrgName. // If AutoAssignOrg is enabled then args.OrgID will be used to add to an
// If a org already exists with that name, it will error // existing Org with id=args.OrgID. If AutoAssignOrg is disabled then
// args.OrgName will be used to create a new Org with name=args.OrgName. If an
// org already exists with that name, it will error.
func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.CreateUserCommand) (user.User, error) { func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.CreateUserCommand) (user.User, error) {
var usr user.User var usr user.User
var orgID int64 = -1 orgID, err := ss.getOrgIDForNewUser(sess, args)
if !args.SkipOrgSetup { if err != nil {
var err error return usr, err
orgID, err = ss.getOrgIDForNewUser(sess, args)
if err != nil {
return usr, err
}
} }
if args.Email == "" { if args.Email == "" {
@@ -68,18 +68,13 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.C
// create user // create user
usr = user.User{ usr = user.User{
Email: args.Email, Email: args.Email,
Name: args.Name, Login: args.Login,
Login: args.Login, IsAdmin: args.IsAdmin,
Company: args.Company, OrgID: orgID,
IsAdmin: args.IsAdmin, Created: TimeNow(),
IsDisabled: args.IsDisabled, Updated: TimeNow(),
OrgID: orgID, LastSeenAt: TimeNow().AddDate(-10, 0, 0),
EmailVerified: args.EmailVerified,
Created: TimeNow(),
Updated: TimeNow(),
LastSeenAt: TimeNow().AddDate(-10, 0, 0),
IsServiceAccount: args.IsServiceAccount,
} }
salt, err := util.GetRandomString(10) salt, err := util.GetRandomString(10)
@@ -115,95 +110,29 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.C
Email: usr.Email, Email: usr.Email,
}) })
// create org user link orgUser := models.OrgUser{
if !args.SkipOrgSetup { OrgId: orgID,
orgUser := models.OrgUser{ UserId: usr.ID,
OrgId: orgID, Role: org.RoleAdmin,
UserId: usr.ID, Created: TimeNow(),
Role: org.RoleAdmin, Updated: TimeNow(),
Created: TimeNow(), }
Updated: TimeNow(),
}
if ss.Cfg.AutoAssignOrg && !usr.IsAdmin { if ss.Cfg.AutoAssignOrg && !usr.IsAdmin {
if len(args.DefaultOrgRole) > 0 { if len(args.DefaultOrgRole) > 0 {
orgUser.Role = org.RoleType(args.DefaultOrgRole) orgUser.Role = org.RoleType(args.DefaultOrgRole)
} else { } else {
orgUser.Role = org.RoleType(ss.Cfg.AutoAssignOrgRole) orgUser.Role = org.RoleType(ss.Cfg.AutoAssignOrgRole)
}
} }
}
if _, err = sess.Insert(&orgUser); err != nil { if _, err = sess.Insert(&orgUser); err != nil {
return usr, err return usr, err
}
} }
return usr, nil return usr, nil
} }
// 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
})
return &user, createErr
}
func notServiceAccountFilter(ss *SQLStore) string {
return fmt.Sprintf("%s.is_service_account = %s",
ss.Dialect.Quote("user"),
ss.Dialect.BooleanStr(false))
}
func setUsingOrgInTransaction(sess *DBSession, userID int64, orgID int64) error {
user := user.User{
ID: userID,
OrgID: orgID,
}
_, err := sess.ID(userID).Update(&user)
return err
}
type byOrgName []*models.UserOrgDTO
// Len returns the length of an array of organisations.
func (o byOrgName) Len() int {
return len(o)
}
// Swap swaps two indices of an array of organizations.
func (o byOrgName) Swap(i, j int) {
o[i], o[j] = o[j], o[i]
}
// Less returns whether element i of an array of organizations is less than element j.
func (o byOrgName) Less(i, j int) bool {
if strings.ToLower(o[i].Name) < strings.ToLower(o[j].Name) {
return true
}
return o[i].Name < o[j].Name
}
func (ss *SQLStore) getUserOrgList(ctx context.Context, query *models.GetUserOrgListQuery) error {
return ss.WithDbSession(ctx, func(dbSess *DBSession) error {
query.Result = make([]*models.UserOrgDTO, 0)
sess := dbSess.Table("org_user")
sess.Join("INNER", "org", "org_user.org_id=org.id")
sess.Join("INNER", ss.Dialect.Quote("user"), fmt.Sprintf("org_user.user_id=%s.id", ss.Dialect.Quote("user")))
sess.Where("org_user.user_id=?", query.UserId)
sess.Where(notServiceAccountFilter(ss))
sess.Cols("org.name", "org_user.role", "org_user.org_id")
sess.OrderBy("org.name")
err := sess.Find(&query.Result)
sort.Sort(byOrgName(query.Result))
return err
})
}
func UserDeletions() []string { func UserDeletions() []string {
deletes := []string{ deletes := []string{
"DELETE FROM star WHERE user_id = ?", "DELETE FROM star WHERE user_id = ?",
@@ -218,3 +147,61 @@ func UserDeletions() []string {
} }
return deletes return deletes
} }
func verifyExistingOrg(sess *DBSession, orgId int64) error {
var org models.Org
has, err := sess.Where("id=?", orgId).Get(&org)
if err != nil {
return err
}
if !has {
return models.ErrOrgNotFound
}
return nil
}
func (ss *SQLStore) getOrCreateOrg(sess *DBSession, orgName string) (int64, error) {
var org models.Org
if ss.Cfg.AutoAssignOrg {
has, err := sess.Where("id=?", ss.Cfg.AutoAssignOrgId).Get(&org)
if err != nil {
return 0, err
}
if has {
return org.Id, nil
}
if ss.Cfg.AutoAssignOrgId != 1 {
ss.log.Error("Could not create user: organization ID does not exist", "orgID",
ss.Cfg.AutoAssignOrgId)
return 0, fmt.Errorf("could not create user: organization ID %d does not exist",
ss.Cfg.AutoAssignOrgId)
}
org.Name = mainOrgName
org.Id = int64(ss.Cfg.AutoAssignOrgId)
} else {
org.Name = orgName
}
org.Created = time.Now()
org.Updated = time.Now()
if org.Id != 0 {
if _, err := sess.InsertId(&org); err != nil {
return 0, err
}
} else {
if _, err := sess.InsertOne(&org); err != nil {
return 0, err
}
}
sess.publishAfterCommit(&events.OrgCreated{
Timestamp: org.Created,
Id: org.Id,
Name: org.Name,
})
return org.Id, nil
}

View File

@@ -5,14 +5,16 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert" "github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/stretchr/testify/require"
) )
func TestIntegrationStatsDataAccess(t *testing.T) { func TestIntegrationStatsDataAccess(t *testing.T) {
@@ -71,6 +73,7 @@ func populateDB(t *testing.T, sqlStore *sqlstore.SQLStore) {
t.Helper() t.Helper()
orgService, _ := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotatest.New(false, nil)) orgService, _ := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotatest.New(false, nil))
userSvc, _ := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, &quotatest.FakeQuotaService{})
users := make([]user.User, 3) users := make([]user.User, 3)
for i := range users { for i := range users {
@@ -80,7 +83,7 @@ func populateDB(t *testing.T, sqlStore *sqlstore.SQLStore) {
Login: fmt.Sprintf("user_test_%v_login", i), Login: fmt.Sprintf("user_test_%v_login", i),
OrgName: fmt.Sprintf("Org #%v", i), OrgName: fmt.Sprintf("Org #%v", i),
} }
user, err := sqlStore.CreateUser(context.Background(), cmd) user, err := userSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
users[i] = *user users[i] = *user
} }

View File

@@ -13,16 +13,19 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol" ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
) )
func TestIntegrationTeamCommandsAndQueries(t *testing.T) { func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
if testing.Short() { if testing.Short() {
t.Skip("skipping integration test") t.Skip("skipping integration test")
} }
t.Run("Testing Team commands & queries", func(t *testing.T) { t.Run("Testing Team commands and queries", func(t *testing.T) {
sqlStore := db.InitTestDB(t) sqlStore := db.InitTestDB(t)
teamSvc := ProvideService(sqlStore, sqlStore.Cfg) teamSvc := ProvideService(sqlStore, sqlStore.Cfg)
testUser := &user.SignedInUser{ testUser := &user.SignedInUser{
@@ -35,6 +38,11 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
}, },
}, },
} }
quotaService := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, teamSvc, nil, quotaService)
require.NoError(t, err)
t.Run("Given saved users and two teams", func(t *testing.T) { t.Run("Given saved users and two teams", func(t *testing.T) {
var userIds []int64 var userIds []int64
@@ -51,7 +59,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
} }
usr, err = sqlStore.CreateUser(context.Background(), userCmd) usr, err = userSvc.Create(context.Background(), &userCmd)
require.NoError(t, err) require.NoError(t, err)
userIds = append(userIds, usr.ID) userIds = append(userIds, usr.ID)
} }
@@ -82,7 +90,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
q1 := &models.GetTeamMembersQuery{OrgId: testOrgID, TeamId: team1.Id, SignedInUser: testUser} q1 := &models.GetTeamMembersQuery{OrgId: testOrgID, TeamId: team1.Id, SignedInUser: testUser}
err = teamSvc.GetTeamMembers(context.Background(), q1) err = teamSvc.GetTeamMembers(context.Background(), q1)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(q1.Result), 2) require.Equal(t, 2, len(q1.Result))
require.Equal(t, q1.Result[0].TeamId, team1.Id) require.Equal(t, q1.Result[0].TeamId, team1.Id)
require.Equal(t, q1.Result[0].Login, "loginuser0") require.Equal(t, q1.Result[0].Login, "loginuser0")
require.Equal(t, q1.Result[0].OrgId, testOrgID) require.Equal(t, q1.Result[0].OrgId, testOrgID)
@@ -373,6 +381,11 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
t.Run("Should be able to exclude service accounts from teamembers", func(t *testing.T) { t.Run("Should be able to exclude service accounts from teamembers", func(t *testing.T) {
sqlStore = db.InitTestDB(t) sqlStore = db.InitTestDB(t)
quotaService := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgSvc, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(sqlStore, orgSvc, sqlStore.Cfg, teamSvc, nil, quotaService)
require.NoError(t, err)
setup() setup()
userCmd = user.CreateUserCommand{ userCmd = user.CreateUserCommand{
Email: fmt.Sprint("sa", 1, "@test.com"), Email: fmt.Sprint("sa", 1, "@test.com"),
@@ -380,7 +393,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
Login: fmt.Sprint("login-sa", 1), Login: fmt.Sprint("login-sa", 1),
IsServiceAccount: true, IsServiceAccount: true,
} }
serviceAccount, err := sqlStore.CreateUser(context.Background(), userCmd) serviceAccount, err := userSvc.CreateUserForTests(context.Background(), &userCmd)
require.NoError(t, err) require.NoError(t, err)
groupId := team2.Id groupId := team2.Id
@@ -497,6 +510,11 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) {
require.NoError(t, errCreateTeam) require.NoError(t, errCreateTeam)
team2, errCreateTeam := teamSvc.CreateTeam("group2 name", "test2@example.org", testOrgID) team2, errCreateTeam := teamSvc.CreateTeam("group2 name", "test2@example.org", testOrgID)
require.NoError(t, errCreateTeam) require.NoError(t, errCreateTeam)
quotaService := quotaimpl.ProvideService(store, store.Cfg)
orgSvc, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(store, orgSvc, store.Cfg, teamSvc, nil, quotaService)
require.NoError(t, err)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
userCmd := user.CreateUserCommand{ userCmd := user.CreateUserCommand{
@@ -504,7 +522,7 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) {
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
Login: fmt.Sprint("loginuser", i), Login: fmt.Sprint("loginuser", i),
} }
user, errCreateUser := store.CreateUser(context.Background(), userCmd) user, errCreateUser := userSvc.Create(context.Background(), &userCmd)
require.NoError(t, errCreateUser) require.NoError(t, errCreateUser)
userIds[i] = user.ID userIds[i] = user.ID
} }

View File

@@ -6,6 +6,7 @@ import (
type Service interface { type Service interface {
Create(context.Context, *CreateUserCommand) (*User, error) Create(context.Context, *CreateUserCommand) (*User, error)
CreateServiceAccount(context.Context, *CreateUserCommand) (*User, error)
Delete(context.Context, *DeleteUserCommand) error Delete(context.Context, *DeleteUserCommand) error
GetByID(context.Context, *GetUserByIDQuery) (*User, error) GetByID(context.Context, *GetUserByIDQuery) (*User, error)
GetByLogin(context.Context, *GetUserByLoginQuery) (*User, error) GetByLogin(context.Context, *GetUserByLoginQuery) (*User, error)
@@ -23,4 +24,7 @@ type Service interface {
UpdatePermissions(context.Context, int64, bool) error UpdatePermissions(context.Context, int64, bool) error
SetUserHelpFlag(context.Context, *SetUserHelpFlagCommand) error SetUserHelpFlag(context.Context, *SetUserHelpFlagCommand) error
GetProfile(context.Context, *GetUserProfileQuery) (*UserProfileDTO, error) GetProfile(context.Context, *GetUserProfileQuery) (*UserProfileDTO, error)
// TEST ONLY METHOD
CreateUserForTests(context.Context, *CreateUserCommand) (*User, error)
} }

View File

@@ -11,7 +11,6 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@@ -24,6 +23,7 @@ type store interface {
GetByID(context.Context, int64) (*user.User, error) GetByID(context.Context, int64) (*user.User, error)
GetNotServiceAccount(context.Context, int64) (*user.User, error) GetNotServiceAccount(context.Context, int64) (*user.User, error)
Delete(context.Context, int64) error Delete(context.Context, int64) error
LoginConflict(ctx context.Context, login, email string, caseInsensitive bool) error
CaseInsensitiveLoginConflict(context.Context, string, string) error CaseInsensitiveLoginConflict(context.Context, string, string) error
GetByLogin(context.Context, *user.GetUserByLoginQuery) (*user.User, error) GetByLogin(context.Context, *user.GetUserByLoginQuery) (*user.User, error)
GetByEmail(context.Context, *user.GetUserByEmailQuery) (*user.User, error) GetByEmail(context.Context, *user.GetUserByEmailQuery) (*user.User, error)
@@ -59,12 +59,11 @@ func ProvideStore(db db.DB, cfg *setting.Cfg) sqlStore {
} }
func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) { func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) {
var userID int64
var err error var err error
err = ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { err = ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
sess.UseBool("is_admin") sess.UseBool("is_admin")
if userID, err = sess.Insert(cmd); err != nil { if _, err = sess.Insert(cmd); err != nil {
return err return err
} }
sess.PublishAfterCommit(&events.UserCreated{ sess.PublishAfterCommit(&events.UserCreated{
@@ -79,7 +78,7 @@ func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
return userID, nil return cmd.ID, nil
} }
func (ss *sqlStore) Get(ctx context.Context, usr *user.User) (*user.User, error) { func (ss *sqlStore) Get(ctx context.Context, usr *user.User) (*user.User, error) {
@@ -185,7 +184,6 @@ func (ss *sqlStore) GetByLogin(ctx context.Context, query *user.GetUserByLoginQu
where = "LOWER(email)=LOWER(?)" where = "LOWER(email)=LOWER(?)"
} }
has, err = sess.Where(ss.notServiceAccountFilter()).Where(where, query.LoginOrEmail).Get(usr) has, err = sess.Where(ss.notServiceAccountFilter()).Where(where, query.LoginOrEmail).Get(usr)
if err != nil { if err != nil {
return err return err
} }
@@ -264,6 +262,43 @@ func (ss *sqlStore) userCaseInsensitiveLoginConflict(ctx context.Context, sess *
return nil return nil
} }
// LoginConflict returns an error if the provided email or login are already
// associated with a user. If caseInsensitive is true the search is not case
// sensitive.
func (ss *sqlStore) LoginConflict(ctx context.Context, login, email string, caseInsensitive bool) error {
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
return ss.loginConflict(ctx, sess, login, email, caseInsensitive)
})
return err
}
func (ss *sqlStore) loginConflict(ctx context.Context, sess *db.Session, login, email string, caseInsensitive bool) error {
users := make([]user.User, 0)
where := "email=? OR login=?"
if caseInsensitive {
where = "LOWER(email)=LOWER(?) OR LOWER(login)=LOWER(?)"
login = strings.ToLower(login)
email = strings.ToLower(email)
}
exists, err := sess.Where(where, email, login).Get(&user.User{})
if err != nil {
return err
}
if exists {
return user.ErrUserAlreadyExists
}
if err := sess.Where("LOWER(email)=LOWER(?) OR LOWER(login)=LOWER(?)",
email, login).Find(&users); err != nil {
return err
}
if len(users) > 1 {
return &user.ErrCaseInsensitiveLoginConflict{Users: users}
}
return nil
}
func (ss *sqlStore) Update(ctx context.Context, cmd *user.UpdateUserCommand) error { func (ss *sqlStore) Update(ctx context.Context, cmd *user.UpdateUserCommand) error {
if ss.cfg.CaseInsensitiveLogin { if ss.cfg.CaseInsensitiveLogin {
cmd.Login = strings.ToLower(cmd.Login) cmd.Login = strings.ToLower(cmd.Login)
@@ -470,7 +505,7 @@ func (ss *sqlStore) Count(ctx context.Context) (int64, error) {
} }
r := result{} r := result{}
err := ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s WHERE is_service_account=%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().BooleanStr(false)) rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s WHERE is_service_account=%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().BooleanStr(false))
if _, err := sess.SQL(rawSQL).Get(&r); err != nil { if _, err := sess.SQL(rawSQL).Get(&r); err != nil {
return err return err

View File

@@ -15,7 +15,6 @@ import (
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl" "github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@@ -31,6 +30,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
orgService, err := orgimpl.ProvideService(ss, ss.Cfg, quotaService) orgService, err := orgimpl.ProvideService(ss, ss.Cfg, quotaService)
require.NoError(t, err) require.NoError(t, err)
userStore := ProvideStore(ss, setting.NewCfg()) userStore := ProvideStore(ss, setting.NewCfg())
usrSvc, err := ProvideService(ss, orgService, ss.Cfg, nil, nil, quotaService)
require.NoError(t, err)
usr := &user.SignedInUser{ usr := &user.SignedInUser{
OrgID: 1, OrgID: 1,
Permissions: map[int64]map[string][]string{1: {"users:read": {"global.users:*"}}}, Permissions: map[int64]map[string][]string{1: {"users:read": {"global.users:*"}}},
@@ -73,12 +74,14 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - creates and loads user", func(t *testing.T) { t.Run("Testing DB - creates and loads user", func(t *testing.T) {
ss := db.InitTestDB(t) ss := db.InitTestDB(t)
_, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
cmd := user.CreateUserCommand{ cmd := user.CreateUserCommand{
Email: "usertest@test.com", Email: "usertest@test.com",
Name: "user name", Name: "user name",
Login: "user_test_login", Login: "user_test_login",
} }
usr, err := ss.CreateUser(context.Background(), cmd) usr, err := usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
result, err := userStore.GetByID(context.Background(), usr.ID) result, err := userStore.GetByID(context.Background(), usr.ID)
@@ -147,7 +150,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Login: "user_email_conflict", Login: "user_email_conflict",
} }
// userEmailConflict // userEmailConflict
_, err := ss.CreateUser(context.Background(), cmd) _, err = usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
cmd = user.CreateUserCommand{ cmd = user.CreateUserCommand{
@@ -155,7 +158,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Name: "user name", Name: "user name",
Login: "user_email_conflict_two", Login: "user_email_conflict_two",
} }
_, err = ss.CreateUser(context.Background(), cmd) _, err := usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
cmd = user.CreateUserCommand{ cmd = user.CreateUserCommand{
@@ -164,7 +167,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Login: "user_test_login_conflict", Login: "user_test_login_conflict",
} }
// userLoginConflict // userLoginConflict
_, err = ss.CreateUser(context.Background(), cmd) _, err = usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
cmd = user.CreateUserCommand{ cmd = user.CreateUserCommand{
@@ -172,7 +175,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Name: "user name", Name: "user name",
Login: "user_test_login_CONFLICT", Login: "user_test_login_CONFLICT",
} }
_, err = ss.CreateUser(context.Background(), cmd) _, err = usrSvc.Create(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
ss.Cfg.CaseInsensitiveLogin = true ss.Cfg.CaseInsensitiveLogin = true
@@ -262,7 +265,9 @@ func TestIntegrationUserDataAccess(t *testing.T) {
}) })
t.Run("get signed in user", func(t *testing.T) { t.Run("get signed in user", func(t *testing.T) {
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { ss := db.InitTestDB(t)
orgService, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
users := createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -300,26 +305,24 @@ func TestIntegrationUserDataAccess(t *testing.T) {
}) })
t.Run("Testing DB - grafana admin users", func(t *testing.T) { t.Run("Testing DB - grafana admin users", func(t *testing.T) {
ss = db.InitTestDB(t) ss := db.InitTestDB(t)
_, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
createUserCmd := user.CreateUserCommand{ createUserCmd := user.CreateUserCommand{
Email: fmt.Sprint("admin", "@test.com"), Email: fmt.Sprint("admin", "@test.com"),
Name: "admin", Name: "admin",
Login: "admin", Login: "admin",
IsAdmin: true, IsAdmin: true,
} }
usr, err := ss.CreateUser(context.Background(), createUserCmd) usr, err := usrSvc.Create(context.Background(), &createUserCmd)
require.Nil(t, err) require.Nil(t, err)
// Cannot make themselves a non-admin // Cannot make themselves a non-admin
updatePermsError := userStore.UpdatePermissions(context.Background(), usr.ID, false) updatePermsError := userStore.UpdatePermissions(context.Background(), usr.ID, false)
require.Equal(t, user.ErrLastGrafanaAdmin, updatePermsError) require.Equal(t, user.ErrLastGrafanaAdmin, updatePermsError)
query := user.GetUserByIDQuery{ID: usr.ID} query := user.GetUserByIDQuery{ID: usr.ID}
queryResult, getUserError := userStore.GetByID(context.Background(), query.ID) queryResult, getUserError := userStore.GetByID(context.Background(), query.ID)
require.Nil(t, getUserError) require.Nil(t, getUserError)
require.True(t, queryResult.IsAdmin) require.True(t, queryResult.IsAdmin)
// One user // One user
@@ -330,7 +333,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Name: "user", Name: "user",
Login: username, Login: username,
} }
_, err = ss.CreateUser(context.Background(), createUserCmd) _, err = usrSvc.Create(context.Background(), &createUserCmd)
require.Nil(t, err) require.Nil(t, err)
// When trying to create a new user with the same email, an error is returned // When trying to create a new user with the same email, an error is returned
@@ -340,8 +343,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Login: "user2", Login: "user2",
SkipOrgSetup: true, SkipOrgSetup: true,
} }
_, err = ss.CreateUser(context.Background(), createUserCmd) _, err = usrSvc.Create(context.Background(), &createUserCmd)
require.Equal(t, err, user.ErrUserAlreadyExists) require.Equal(t, user.ErrUserAlreadyExists, err)
// When trying to create a new user with the same login, an error is returned // When trying to create a new user with the same login, an error is returned
createUserCmd = user.CreateUserCommand{ createUserCmd = user.CreateUserCommand{
@@ -350,8 +353,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
Login: username, Login: username,
SkipOrgSetup: true, SkipOrgSetup: true,
} }
_, err = ss.CreateUser(context.Background(), createUserCmd) _, err = usrSvc.Create(context.Background(), &createUserCmd)
require.Equal(t, err, user.ErrUserAlreadyExists) require.Equal(t, user.ErrUserAlreadyExists, err)
}) })
t.Run("GetProfile", func(t *testing.T) { t.Run("GetProfile", func(t *testing.T) {
@@ -366,7 +369,10 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - return list users based on their is_disabled flag", func(t *testing.T) { t.Run("Testing DB - return list users based on their is_disabled flag", func(t *testing.T) {
ss = db.InitTestDB(t) ss = db.InitTestDB(t)
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { _, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
userStore := ProvideStore(ss, ss.Cfg)
createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -379,7 +385,6 @@ func TestIntegrationUserDataAccess(t *testing.T) {
query := user.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: usr} query := user.SearchUsersQuery{IsDisabled: &isDisabled, SignedInUser: usr}
result, err := userStore.Search(context.Background(), &query) result, err := userStore.Search(context.Background(), &query)
require.Nil(t, err) require.Nil(t, err)
require.Len(t, result.Users, 2) require.Len(t, result.Users, 2)
first, third := false, false first, third := false, false
@@ -397,8 +402,10 @@ func TestIntegrationUserDataAccess(t *testing.T) {
require.True(t, third) require.True(t, third)
// Re-init DB // Re-init DB
ss = db.InitTestDB(t) ss := db.InitTestDB(t)
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { orgService, usrSvc = createOrgAndUserSvc(t, ss, ss.Cfg)
users := createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -432,7 +439,8 @@ func TestIntegrationUserDataAccess(t *testing.T) {
// A user is an org member and has been assigned permissions // A user is an org member and has been assigned permissions
// Re-init DB // Re-init DB
ss = db.InitTestDB(t) ss = db.InitTestDB(t)
users = createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { orgService, usrSvc = createOrgAndUserSvc(t, ss, ss.Cfg)
users = createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -487,7 +495,12 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - return list of users that the SignedInUser has permission to read", func(t *testing.T) { t.Run("Testing DB - return list of users that the SignedInUser has permission to read", func(t *testing.T) {
ss := db.InitTestDB(t) ss := db.InitTestDB(t)
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { orgService, err := orgimpl.ProvideService(ss, ss.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := ProvideService(ss, orgService, ss.Cfg, nil, nil, quotaService)
require.NoError(t, err)
createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -508,7 +521,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
ss = db.InitTestDB(t) ss = db.InitTestDB(t)
t.Run("Testing DB - enable all users", func(t *testing.T) { t.Run("Testing DB - enable all users", func(t *testing.T) {
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { users := createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -541,12 +554,12 @@ func TestIntegrationUserDataAccess(t *testing.T) {
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true} 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} serviceaccountcmd := user.CreateUserCommand{Login: "serviceaccount", Email: "service@test.com", Name: "serviceaccount name", IsAdmin: true, IsServiceAccount: true}
_, err := ss.CreateUser(context.Background(), ac1cmd) _, err := usrSvc.Create(context.Background(), &ac1cmd)
require.NoError(t, err) require.NoError(t, err)
_, err = ss.CreateUser(context.Background(), ac2cmd) _, err = usrSvc.Create(context.Background(), &ac2cmd)
require.NoError(t, err) require.NoError(t, err)
// user only used for making sure we filter out the service accounts // user only used for making sure we filter out the service accounts
_, err = ss.CreateUser(context.Background(), serviceaccountcmd) _, err = usrSvc.Create(context.Background(), &serviceaccountcmd)
require.NoError(t, err) require.NoError(t, err)
query := user.SearchUsersQuery{Query: "", SignedInUser: &user.SignedInUser{ query := user.SearchUsersQuery{Query: "", SignedInUser: &user.SignedInUser{
OrgID: 1, OrgID: 1,
@@ -564,7 +577,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
ss = db.InitTestDB(t) ss = db.InitTestDB(t)
t.Run("Testing DB - disable only specific users", func(t *testing.T) { t.Run("Testing DB - disable only specific users", func(t *testing.T) {
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { users := createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -594,7 +607,6 @@ func TestIntegrationUserDataAccess(t *testing.T) {
// Check if user id is in the userIdsToDisable list // Check if user id is in the userIdsToDisable list
for _, disabledUserId := range userIdsToDisable { for _, disabledUserId := range userIdsToDisable {
fmt.Println(user.ID, disabledUserId)
if user.ID == disabledUserId { if user.ID == disabledUserId {
require.True(t, user.IsDisabled) require.True(t, user.IsDisabled)
shouldBeDisabled = true shouldBeDisabled = true
@@ -612,7 +624,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - search users", func(t *testing.T) { t.Run("Testing DB - search users", func(t *testing.T) {
// Since previous tests were destructive // Since previous tests were destructive
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -636,7 +648,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
t.Run("Testing DB - multiple users", func(t *testing.T) { t.Run("Testing DB - multiple users", func(t *testing.T) {
ss = db.InitTestDB(t) ss = db.InitTestDB(t)
createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("user", i, "@test.com"), Email: fmt.Sprint("user", i, "@test.com"),
Name: fmt.Sprint("user", i), Name: fmt.Sprint("user", i),
@@ -729,8 +741,9 @@ func TestIntegrationUserUpdate(t *testing.T) {
ss := db.InitTestDB(t) ss := db.InitTestDB(t)
userStore := ProvideStore(ss, setting.NewCfg()) userStore := ProvideStore(ss, setting.NewCfg())
_, usrSvc := createOrgAndUserSvc(t, ss, ss.Cfg)
users := createFiveTestUsers(t, ss, func(i int) *user.CreateUserCommand { users := createFiveTestUsers(t, usrSvc, func(i int) *user.CreateUserCommand {
return &user.CreateUserCommand{ return &user.CreateUserCommand{
Email: fmt.Sprint("USER", i, "@test.com"), Email: fmt.Sprint("USER", i, "@test.com"),
Name: fmt.Sprint("USER", i), Name: fmt.Sprint("USER", i),
@@ -789,17 +802,15 @@ func TestIntegrationUserUpdate(t *testing.T) {
ss.Cfg.CaseInsensitiveLogin = false ss.Cfg.CaseInsensitiveLogin = false
} }
func createFiveTestUsers(t *testing.T, sqlStore *sqlstore.SQLStore, fn func(i int) *user.CreateUserCommand) []user.User { func createFiveTestUsers(t *testing.T, svc user.Service, fn func(i int) *user.CreateUserCommand) []user.User {
t.Helper() t.Helper()
users := []user.User{} users := make([]user.User, 5)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
cmd := fn(i) cmd := fn(i)
user, err := svc.CreateUserForTests(context.Background(), cmd)
user, err := sqlStore.CreateUser(context.Background(), *cmd)
users = append(users, *user)
require.Nil(t, err) require.Nil(t, err)
users[i] = *user
} }
return users return users
@@ -924,3 +935,15 @@ func (ss *sqlStore) getDashboardACLInfoList(query *models.GetDashboardACLInfoLis
return nil return nil
} }
func createOrgAndUserSvc(t *testing.T, store db.DB, cfg *setting.Cfg) (org.Service, user.Service) {
t.Helper()
quotaService := quotaimpl.ProvideService(store, cfg)
orgService, err := orgimpl.ProvideService(store, cfg, quotaService)
require.NoError(t, err)
usrSvc, err := ProvideService(store, orgService, cfg, nil, nil, quotaService)
require.NoError(t, err)
return orgService, usrSvc
}

View File

@@ -0,0 +1,16 @@
package userimpl
import "time"
// timeNow wraps time.Now so it can be mocked in tests.
var timeNow = time.Now
func MockTimeNow(constTime time.Time) {
timeNow = func() time.Time {
return constTime
}
}
func ResetTimeNow() {
timeNow = time.Now
}

View File

@@ -82,32 +82,27 @@ func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*use
SkipOrgSetup: cmd.SkipOrgSetup, SkipOrgSetup: cmd.SkipOrgSetup,
} }
orgID, err := s.orgService.GetIDForNewUser(ctx, cmdOrg) orgID, err := s.orgService.GetIDForNewUser(ctx, cmdOrg)
cmd.OrgID = orgID
if err != nil { if err != nil {
return nil, err return nil, err
} }
if cmd.Email == "" { if cmd.Email == "" {
cmd.Email = cmd.Login cmd.Email = cmd.Login
} }
usr := &user.User{
Login: cmd.Login, err = s.store.LoginConflict(ctx, cmd.Login, cmd.Email, s.cfg.CaseInsensitiveLogin)
Email: cmd.Email, if err != nil {
} return nil, user.ErrUserAlreadyExists
usr, err = s.store.Get(ctx, usr)
if err != nil && !errors.Is(err, user.ErrUserNotFound) {
return usr, err
} }
// create user // create user
usr = &user.User{ usr := &user.User{
Email: cmd.Email, Email: cmd.Email,
Name: cmd.Name, Name: cmd.Name,
Login: cmd.Login, Login: cmd.Login,
Company: cmd.Company, Company: cmd.Company,
IsAdmin: cmd.IsAdmin, IsAdmin: cmd.IsAdmin,
IsDisabled: cmd.IsDisabled, IsDisabled: cmd.IsDisabled,
OrgID: cmd.OrgID, OrgID: orgID,
EmailVerified: cmd.EmailVerified, EmailVerified: cmd.EmailVerified,
Created: time.Now(), Created: time.Now(),
Updated: time.Now(), Updated: time.Now(),
@@ -134,7 +129,7 @@ func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*use
usr.Password = encodedPassword usr.Password = encodedPassword
} }
userID, err := s.store.Insert(ctx, usr) _, err = s.store.Insert(ctx, usr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -158,11 +153,10 @@ func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*use
} }
_, err = s.orgService.InsertOrgUser(ctx, &orgUser) _, err = s.orgService.InsertOrgUser(ctx, &orgUser)
if err != nil { if err != nil {
err := s.store.Delete(ctx, userID) err := s.store.Delete(ctx, usr.ID)
return usr, err return usr, err
} }
} }
return usr, nil return usr, nil
} }
@@ -354,3 +348,198 @@ func readQuotaConfig(cfg *setting.Cfg) (*quota.Map, error) {
limits.Set(globalQuotaTag, cfg.Quota.Global.User) limits.Set(globalQuotaTag, cfg.Quota.Global.User)
return limits, nil return limits, nil
} }
// CreateUserForTests creates a test user and optionally an organization. Unlike
// Create, `cmd.SkipOrgSetup` toggles whether or not to create an org for the
// test user if there isn't already an existing org. This must only be used in tests.
func (s *Service) CreateUserForTests(ctx context.Context, cmd *user.CreateUserCommand) (*user.User, error) {
var orgID int64 = -1
var err error
if !cmd.SkipOrgSetup {
orgID, err = s.getOrgIDForNewUser(ctx, cmd)
if err != nil {
return nil, err
}
}
if cmd.Email == "" {
cmd.Email = cmd.Login
}
usr, err := s.GetByLogin(ctx, &user.GetUserByLoginQuery{LoginOrEmail: cmd.Login})
if err != nil && !errors.Is(err, user.ErrUserNotFound) {
return usr, err
} else if err == nil { // user exists
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: orgID,
EmailVerified: cmd.EmailVerified,
Created: timeNow(),
Updated: timeNow(),
LastSeenAt: timeNow().AddDate(-10, 0, 0),
IsServiceAccount: cmd.IsServiceAccount,
}
salt, err := util.GetRandomString(10)
if err != nil {
return usr, err
}
usr.Salt = salt
rands, err := util.GetRandomString(10)
if err != nil {
return usr, err
}
usr.Rands = rands
if len(cmd.Password) > 0 {
encodedPassword, err := util.EncodePassword(cmd.Password, usr.Salt)
if err != nil {
return usr, err
}
usr.Password = encodedPassword
}
_, err = s.store.Insert(ctx, usr)
if err != nil {
return usr, err
}
// create org user link
if !cmd.SkipOrgSetup {
orgCmd := &org.AddOrgUserCommand{
OrgID: orgID,
UserID: usr.ID,
Role: org.RoleAdmin,
AllowAddingServiceAccount: true,
}
if s.cfg.AutoAssignOrg && !usr.IsAdmin {
if len(cmd.DefaultOrgRole) > 0 {
orgCmd.Role = org.RoleType(cmd.DefaultOrgRole)
} else {
orgCmd.Role = org.RoleType(s.cfg.AutoAssignOrgRole)
}
}
if err = s.orgService.AddOrgUser(ctx, orgCmd); err != nil {
return nil, err
}
}
return usr, nil
}
func (s *Service) getOrgIDForNewUser(ctx context.Context, cmd *user.CreateUserCommand) (int64, error) {
if s.cfg.AutoAssignOrg && cmd.OrgID != 0 {
if _, err := s.orgService.GetByID(ctx, &org.GetOrgByIdQuery{ID: cmd.OrgID}); err != nil {
return -1, err
}
return cmd.OrgID, nil
}
orgName := cmd.OrgName
if orgName == "" {
orgName = util.StringsFallback2(cmd.Email, cmd.Login)
}
orgID, err := s.orgService.GetOrCreate(ctx, orgName)
if err != nil {
return 0, err
}
return orgID, err
}
// CreateServiceAccount is a copy of Create with a single difference; it will create the OrgUser service account.
func (s *Service) CreateServiceAccount(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)
if err != nil {
return nil, err
}
if cmd.Email == "" {
cmd.Email = cmd.Login
}
err = s.store.LoginConflict(ctx, cmd.Login, cmd.Email, s.cfg.CaseInsensitiveLogin)
if err != nil {
return nil, user.ErrUserAlreadyExists
}
// 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 {
orgCmd := &org.AddOrgUserCommand{
OrgID: orgID,
UserID: usr.ID,
Role: org.RoleAdmin,
AllowAddingServiceAccount: true,
}
if s.cfg.AutoAssignOrg && !usr.IsAdmin {
if len(cmd.DefaultOrgRole) > 0 {
orgCmd.Role = org.RoleType(cmd.DefaultOrgRole)
} else {
orgCmd.Role = org.RoleType(s.cfg.AutoAssignOrgRole)
}
}
if err = s.orgService.AddOrgUser(ctx, orgCmd); err != nil {
return nil, err
}
}
return usr, nil
}

View File

@@ -26,6 +26,7 @@ func TestUserService(t *testing.T) {
cacheService: localcache.ProvideService(), cacheService: localcache.ProvideService(),
teamService: &teamtest.FakeService{}, teamService: &teamtest.FakeService{},
} }
userService.cfg = setting.NewCfg()
t.Run("create user", func(t *testing.T) { t.Run("create user", func(t *testing.T) {
_, err := userService.Create(context.Background(), &user.CreateUserCommand{ _, err := userService.Create(context.Background(), &user.CreateUserCommand{
@@ -44,7 +45,6 @@ func TestUserService(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "login", u.Login) require.Equal(t, "login", u.Login)
require.Equal(t, "name", u.Name) require.Equal(t, "name", u.Name)
require.Equal(t, "email", u.Email) require.Equal(t, "email", u.Email)
}) })
@@ -229,6 +229,10 @@ func (f *FakeUserStore) CaseInsensitiveLoginConflict(context.Context, string, st
return f.ExpectedError return f.ExpectedError
} }
func (f *FakeUserStore) LoginConflict(context.Context, string, string, bool) error {
return f.ExpectedError
}
func (f *FakeUserStore) GetByLogin(ctx context.Context, query *user.GetUserByLoginQuery) (*user.User, error) { func (f *FakeUserStore) GetByLogin(ctx context.Context, query *user.GetUserByLoginQuery) (*user.User, error) {
return f.ExpectedUser, f.ExpectedError return f.ExpectedUser, f.ExpectedError
} }

View File

@@ -28,6 +28,14 @@ func (f *FakeUserService) Create(ctx context.Context, cmd *user.CreateUserComman
return f.ExpectedUser, f.ExpectedError return f.ExpectedUser, f.ExpectedError
} }
func (f *FakeUserService) CreateUserForTests(ctx context.Context, cmd *user.CreateUserCommand) (*user.User, error) {
return f.ExpectedUser, f.ExpectedError
}
func (f *FakeUserService) CreateServiceAccount(ctx context.Context, cmd *user.CreateUserCommand) (*user.User, error) {
return f.ExpectedUser, f.ExpectedError
}
func (f *FakeUserService) Delete(ctx context.Context, cmd *user.DeleteUserCommand) error { func (f *FakeUserService) Delete(ctx context.Context, cmd *user.DeleteUserCommand) error {
return f.ExpectedError return f.ExpectedError
} }

View File

@@ -20,8 +20,11 @@ import (
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
ngstore "github.com/grafana/grafana/pkg/services/ngalert/store" ngstore "github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tests/testinfra" "github.com/grafana/grafana/pkg/tests/testinfra"
) )
@@ -2534,7 +2537,13 @@ func createUser(t *testing.T, store *sqlstore.SQLStore, cmd user.CreateUserComma
store.Cfg.AutoAssignOrg = true store.Cfg.AutoAssignOrg = true
store.Cfg.AutoAssignOrgId = 1 store.Cfg.AutoAssignOrgId = 1
u, err := store.CreateUser(context.Background(), cmd) quotaService := quotaimpl.ProvideService(store, store.Cfg)
orgService, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, store.Cfg, nil, nil, quotaService)
require.NoError(t, err)
u, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
return u.ID return u.ID
} }

View File

@@ -7,12 +7,16 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/server" "github.com/grafana/grafana/pkg/server"
"github.com/grafana/grafana/pkg/services/correlations" "github.com/grafana/grafana/pkg/services/correlations"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/tests/testinfra" "github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/stretchr/testify/require"
) )
type errorResponseBody struct { type errorResponseBody struct {
@@ -130,11 +134,17 @@ func (c TestContext) getURL(url string, user User) string {
func (c TestContext) createUser(cmd user.CreateUserCommand) { func (c TestContext) createUser(cmd user.CreateUserCommand) {
c.t.Helper() c.t.Helper()
store := c.env.SQLStore
store.Cfg.AutoAssignOrg = true
store.Cfg.AutoAssignOrgId = 1
c.env.SQLStore.Cfg.AutoAssignOrg = true quotaService := quotaimpl.ProvideService(store, store.Cfg)
c.env.SQLStore.Cfg.AutoAssignOrgId = 1 orgService, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(c.t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, store.Cfg, nil, nil, quotaService)
require.NoError(c.t, err)
_, err := c.env.SQLStore.CreateUser(context.Background(), cmd) _, err = usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(c.t, err) require.NoError(c.t, err)
} }

View File

@@ -20,9 +20,12 @@ import (
"github.com/grafana/grafana/pkg/services/dashboardimport" "github.com/grafana/grafana/pkg/services/dashboardimport"
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/plugindashboards" "github.com/grafana/grafana/pkg/services/plugindashboards"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/tests/testinfra" "github.com/grafana/grafana/pkg/tests/testinfra"
) )
@@ -100,7 +103,13 @@ func createUser(t *testing.T, store *sqlstore.SQLStore, cmd user.CreateUserComma
store.Cfg.AutoAssignOrg = true store.Cfg.AutoAssignOrg = true
store.Cfg.AutoAssignOrgId = 1 store.Cfg.AutoAssignOrgId = 1
u, err := store.CreateUser(context.Background(), cmd) quotaService := quotaimpl.ProvideService(store, store.Cfg)
orgService, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, store.Cfg, nil, nil, quotaService)
require.NoError(t, err)
u, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
return u.ID return u.ID
} }

View File

@@ -11,8 +11,11 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/tests/testinfra" "github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -115,7 +118,13 @@ func createUser(t *testing.T, store *sqlstore.SQLStore, cmd user.CreateUserComma
store.Cfg.AutoAssignOrg = true store.Cfg.AutoAssignOrg = true
store.Cfg.AutoAssignOrgId = 1 store.Cfg.AutoAssignOrgId = 1
_, err := store.CreateUser(context.Background(), cmd) quotaService := quotaimpl.ProvideService(store, store.Cfg)
orgService, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, store.Cfg, nil, nil, quotaService)
require.NoError(t, err)
_, err = usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
} }

View File

@@ -22,8 +22,11 @@ import (
"github.com/grafana/grafana/pkg/infra/fs" "github.com/grafana/grafana/pkg/infra/fs"
"github.com/grafana/grafana/pkg/server" "github.com/grafana/grafana/pkg/server"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@@ -370,7 +373,13 @@ func CreateUser(t *testing.T, store *sqlstore.SQLStore, cmd user.CreateUserComma
store.Cfg.AutoAssignOrg = true store.Cfg.AutoAssignOrg = true
store.Cfg.AutoAssignOrgId = 1 store.Cfg.AutoAssignOrgId = 1
u, err := store.CreateUser(context.Background(), cmd) quotaService := quotaimpl.ProvideService(store, store.Cfg)
orgService, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, store.Cfg, nil, nil, quotaService)
require.NoError(t, err)
u, err := usrSvc.CreateUserForTests(context.Background(), &cmd)
require.NoError(t, err) require.NoError(t, err)
return u.ID return u.ID
} }