chore: remove CreateUser from sqlstore & replace with userService.CreateUserForTests (#59910)
This commit is contained in:
@@ -4,8 +4,9 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestIntegrationGetDBHealthQuery(t *testing.T) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -2,17 +2,22 @@ package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"testing"
|
||||
"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/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) {
|
||||
@@ -196,22 +201,28 @@ func createDummyUser(t *testing.T, sqlStore *SQLStore) *user.User {
|
||||
t.Helper()
|
||||
|
||||
uid := strconv.Itoa(rand.Intn(9999999))
|
||||
createUserCmd := user.CreateUserCommand{
|
||||
Email: uid + "@example.com",
|
||||
Login: uid,
|
||||
Name: uid,
|
||||
Company: "",
|
||||
OrgName: "",
|
||||
Password: uid,
|
||||
EmailVerified: true,
|
||||
IsAdmin: false,
|
||||
SkipOrgSetup: false,
|
||||
DefaultOrgRole: string(org.RoleViewer),
|
||||
usr := &user.User{
|
||||
Email: uid + "@example.com",
|
||||
Login: uid,
|
||||
Name: uid,
|
||||
Company: "",
|
||||
Password: uid,
|
||||
EmailVerified: true,
|
||||
IsAdmin: false,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
}
|
||||
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 {
|
||||
@@ -317,3 +328,95 @@ func getDashboards(t *testing.T, sqlStore *SQLStore, search Search, aclUserID in
|
||||
require.NoError(t, err)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -198,7 +198,6 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
|
||||
if _, err := sess.SQL(rawSQL).Get(&stats); err != nil {
|
||||
return fmt.Errorf("could not determine if admin user exists: %w", err)
|
||||
}
|
||||
|
||||
if stats.Count > 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -206,6 +205,7 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
|
||||
// ensure admin user
|
||||
if !ss.Cfg.DisableInitAdminCreation {
|
||||
ss.log.Debug("Creating default admin user")
|
||||
|
||||
if _, err := ss.createUser(ctx, sess, user.CreateUserCommand{
|
||||
Login: ss.Cfg.AdminUser,
|
||||
Email: ss.Cfg.AdminEmail,
|
||||
@@ -216,9 +216,6 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -8,13 +8,11 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
GetDialect() migrator.Dialect
|
||||
GetDBType() core.DbType
|
||||
CreateUser(ctx context.Context, cmd user.CreateUserCommand) (*user.User, error)
|
||||
WithDbSession(ctx context.Context, callback DBTransactionFunc) error
|
||||
WithNewDbSession(ctx context.Context, callback DBTransactionFunc) error
|
||||
WithTransactionalDbSession(ctx context.Context, callback DBTransactionFunc) error
|
||||
|
||||
+94
-107
@@ -4,8 +4,8 @@ package sqlstore
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
const mainOrgName = "Main Org."
|
||||
|
||||
func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserCommand) (int64, error) {
|
||||
if ss.Cfg.AutoAssignOrg && args.OrgID != 0 {
|
||||
if err := verifyExistingOrg(sess, args.OrgID); err != nil {
|
||||
@@ -30,21 +32,19 @@ func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserComm
|
||||
return ss.getOrCreateOrg(sess, orgName)
|
||||
}
|
||||
|
||||
// createUser creates a user in the database
|
||||
// if autoAssignOrg is enabled then args.OrgID will be used
|
||||
// to add to an 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 a org already exists with that name, it will error
|
||||
// createUser creates a user in the database. It will also create a default
|
||||
// organization, if none exists. This should only be used by the sqlstore
|
||||
// Reset() function.
|
||||
//
|
||||
// If AutoAssignOrg is enabled then args.OrgID will be used to add to an
|
||||
// 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) {
|
||||
var usr user.User
|
||||
var orgID int64 = -1
|
||||
if !args.SkipOrgSetup {
|
||||
var err error
|
||||
orgID, err = ss.getOrgIDForNewUser(sess, args)
|
||||
if err != nil {
|
||||
return usr, err
|
||||
}
|
||||
orgID, err := ss.getOrgIDForNewUser(sess, args)
|
||||
if err != nil {
|
||||
return usr, err
|
||||
}
|
||||
|
||||
if args.Email == "" {
|
||||
@@ -68,18 +68,13 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.C
|
||||
|
||||
// create user
|
||||
usr = user.User{
|
||||
Email: args.Email,
|
||||
Name: args.Name,
|
||||
Login: args.Login,
|
||||
Company: args.Company,
|
||||
IsAdmin: args.IsAdmin,
|
||||
IsDisabled: args.IsDisabled,
|
||||
OrgID: orgID,
|
||||
EmailVerified: args.EmailVerified,
|
||||
Created: TimeNow(),
|
||||
Updated: TimeNow(),
|
||||
LastSeenAt: TimeNow().AddDate(-10, 0, 0),
|
||||
IsServiceAccount: args.IsServiceAccount,
|
||||
Email: args.Email,
|
||||
Login: args.Login,
|
||||
IsAdmin: args.IsAdmin,
|
||||
OrgID: orgID,
|
||||
Created: TimeNow(),
|
||||
Updated: TimeNow(),
|
||||
LastSeenAt: TimeNow().AddDate(-10, 0, 0),
|
||||
}
|
||||
|
||||
salt, err := util.GetRandomString(10)
|
||||
@@ -115,95 +110,29 @@ func (ss *SQLStore) createUser(ctx context.Context, sess *DBSession, args user.C
|
||||
Email: usr.Email,
|
||||
})
|
||||
|
||||
// create org user link
|
||||
if !args.SkipOrgSetup {
|
||||
orgUser := models.OrgUser{
|
||||
OrgId: orgID,
|
||||
UserId: usr.ID,
|
||||
Role: org.RoleAdmin,
|
||||
Created: TimeNow(),
|
||||
Updated: TimeNow(),
|
||||
}
|
||||
orgUser := models.OrgUser{
|
||||
OrgId: orgID,
|
||||
UserId: usr.ID,
|
||||
Role: org.RoleAdmin,
|
||||
Created: TimeNow(),
|
||||
Updated: TimeNow(),
|
||||
}
|
||||
|
||||
if ss.Cfg.AutoAssignOrg && !usr.IsAdmin {
|
||||
if len(args.DefaultOrgRole) > 0 {
|
||||
orgUser.Role = org.RoleType(args.DefaultOrgRole)
|
||||
} else {
|
||||
orgUser.Role = org.RoleType(ss.Cfg.AutoAssignOrgRole)
|
||||
}
|
||||
if ss.Cfg.AutoAssignOrg && !usr.IsAdmin {
|
||||
if len(args.DefaultOrgRole) > 0 {
|
||||
orgUser.Role = org.RoleType(args.DefaultOrgRole)
|
||||
} else {
|
||||
orgUser.Role = org.RoleType(ss.Cfg.AutoAssignOrgRole)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(&orgUser); err != nil {
|
||||
return usr, err
|
||||
}
|
||||
if _, err = sess.Insert(&orgUser); err != nil {
|
||||
return usr, err
|
||||
}
|
||||
|
||||
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 {
|
||||
deletes := []string{
|
||||
"DELETE FROM star WHERE user_id = ?",
|
||||
@@ -218,3 +147,61 @@ func UserDeletions() []string {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user