mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Team/User: UID migrations (#82298)
* Add user uid migration to run on every startup to protect against empty values in a upgrade downgrade scenario * Add team uid migration to run on every startup to protect against empty values in a upgrade downgrade scenario * Run team uid migration
This commit is contained in:
@@ -207,7 +207,8 @@ func setupDB(b testing.TB) benchScenario {
|
||||
quotaService := quotatest.New(false, nil)
|
||||
cfg := setting.NewCfg()
|
||||
|
||||
teamSvc := teamimpl.ProvideService(db, cfg)
|
||||
teamSvc, err := teamimpl.ProvideService(db, cfg)
|
||||
require.NoError(b, err)
|
||||
orgService, err := orgimpl.ProvideService(db, cfg, quotaService)
|
||||
require.NoError(b, err)
|
||||
|
||||
|
||||
@@ -613,9 +613,10 @@ func TestIntegrationMergeUser(t *testing.T) {
|
||||
t.Run("should be able to merge user", func(t *testing.T) {
|
||||
// Restore after destructive operation
|
||||
sqlStore := db.InitTestDB(t)
|
||||
teamSvc := teamimpl.ProvideService(sqlStore, setting.NewCfg())
|
||||
teamSvc, err := teamimpl.ProvideService(sqlStore, setting.NewCfg())
|
||||
require.NoError(t, err)
|
||||
team1, err := teamSvc.CreateTeam("team1 name", "", 1)
|
||||
require.Nil(t, err)
|
||||
require.NoError(t, err)
|
||||
usrSvc := setupTestUserService(t, sqlStore)
|
||||
const testOrgID int64 = 1
|
||||
|
||||
|
||||
@@ -322,7 +322,8 @@ func setupTestEnv(t testing.TB) (*AccessControlStore, rs.Store, user.Service, te
|
||||
cfg.AutoAssignOrgId = 1
|
||||
acstore := ProvideService(sql)
|
||||
permissionStore := rs.NewStore(sql, featuremgmt.WithFeatures())
|
||||
teamService := teamimpl.ProvideService(sql, cfg)
|
||||
teamService, err := teamimpl.ProvideService(sql, cfg)
|
||||
require.NoError(t, err)
|
||||
orgService, err := orgimpl.ProvideService(sql, cfg, quotatest.New(false, nil))
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -508,7 +508,8 @@ func checkSeededPermissions(t *testing.T, permissions []resourcePermissionDTO) {
|
||||
func seedPermissions(t *testing.T, resourceID string, sql *sqlstore.SQLStore, service *Service) {
|
||||
t.Helper()
|
||||
// seed team 1 with "Edit" permission on dashboard 1
|
||||
teamSvc := teamimpl.ProvideService(sql, sql.Cfg)
|
||||
teamSvc, err := teamimpl.ProvideService(sql, sql.Cfg)
|
||||
require.NoError(t, err)
|
||||
team, err := teamSvc.CreateTeam("test", "test@test.com", 1)
|
||||
require.NoError(t, err)
|
||||
_, err = service.SetTeamPermission(context.Background(), team.OrgID, team.ID, resourceID, "Edit")
|
||||
|
||||
@@ -237,8 +237,9 @@ func setupTestEnvironment(t *testing.T, ops Options) (*Service, *sqlstore.SQLSto
|
||||
|
||||
sql := db.InitTestDB(t)
|
||||
cfg := setting.NewCfg()
|
||||
teamSvc := teamimpl.ProvideService(sql, cfg)
|
||||
userSvc, err := userimpl.ProvideService(sql, nil, cfg, teamimpl.ProvideService(sql, cfg), nil, quotatest.New(false, nil), supportbundlestest.NewFakeBundleService())
|
||||
teamSvc, err := teamimpl.ProvideService(sql, cfg)
|
||||
require.NoError(t, err)
|
||||
userSvc, err := userimpl.ProvideService(sql, nil, cfg, teamSvc, nil, quotatest.New(false, nil), supportbundlestest.NewFakeBundleService())
|
||||
require.NoError(t, err)
|
||||
license := licensingtest.NewFakeLicensing()
|
||||
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
|
||||
|
||||
@@ -138,7 +138,8 @@ func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *stor
|
||||
}
|
||||
|
||||
func generateTeamsAndUsers(b *testing.B, db *sqlstore.SQLStore, users int) ([]int64, []int64) {
|
||||
teamSvc := teamimpl.ProvideService(db, db.Cfg)
|
||||
teamSvc, err := teamimpl.ProvideService(db, db.Cfg)
|
||||
require.NoError(b, err)
|
||||
numberOfTeams := int(math.Ceil(float64(users) / UsersPerTeam))
|
||||
globalUserId := 0
|
||||
qs := quotatest.New(false, nil)
|
||||
|
||||
@@ -57,7 +57,8 @@ func NewTestMigrationStore(t testing.TB, sqlStore *sqlstore.SQLStore, cfg *setti
|
||||
|
||||
license := licensingtest.NewFakeLicensing()
|
||||
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
|
||||
teamSvc := teamimpl.ProvideService(sqlStore, cfg)
|
||||
teamSvc, err := teamimpl.ProvideService(sqlStore, cfg)
|
||||
require.NoError(t, err)
|
||||
orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService)
|
||||
require.NoError(t, err)
|
||||
userSvc, err := userimpl.ProvideService(sqlStore, orgService, cfg, teamSvc, cache, quotaService, bundleregistry.ProvideService())
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@@ -600,3 +601,25 @@ func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMemb
|
||||
func (ss *xormStore) RegisterDelete(query string) {
|
||||
ss.deletes = append(ss.deletes, query)
|
||||
}
|
||||
|
||||
// This is just to ensure that all teams have a valid uid.
|
||||
// To protect against upgrade / downgrade we need to run this for a couple of releases.
|
||||
// FIXME: Remove this migration and make uid field required https://github.com/grafana/identity-access-team/issues/552
|
||||
func (ss *xormStore) uidMigration() error {
|
||||
return ss.db.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
switch ss.db.GetDBType() {
|
||||
case migrator.SQLite:
|
||||
_, err := sess.Exec("UPDATE team SET uid=printf('t%09d',id) WHERE uid IS NULL;")
|
||||
return err
|
||||
case migrator.Postgres:
|
||||
_, err := sess.Exec("UPDATE team SET uid='t' || lpad('' || id::text,9,'0') WHERE uid IS NULL;")
|
||||
return err
|
||||
case migrator.MySQL:
|
||||
_, err := sess.Exec("UPDATE team SET uid=concat('t',lpad(id,9,'0')) WHERE uid IS NULL;")
|
||||
return err
|
||||
default:
|
||||
// this branch should be unreachable
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
}
|
||||
t.Run("Testing Team commands and queries", func(t *testing.T) {
|
||||
sqlStore := db.InitTestDB(t)
|
||||
teamSvc := ProvideService(sqlStore, sqlStore.Cfg)
|
||||
teamSvc, err := ProvideService(sqlStore, sqlStore.Cfg)
|
||||
require.NoError(t, err)
|
||||
testUser := &user.SignedInUser{
|
||||
OrgID: 1,
|
||||
Permissions: map[int64]map[string][]string{
|
||||
@@ -489,7 +490,8 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
|
||||
}
|
||||
|
||||
store := db.InitTestDB(t, db.InitTestDBOpt{})
|
||||
teamSvc := ProvideService(store, store.Cfg)
|
||||
teamSvc, err := ProvideService(store, store.Cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Seed 10 teams
|
||||
for i := 1; i <= 10; i++ {
|
||||
@@ -525,7 +527,8 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) {
|
||||
|
||||
// Seed 2 teams with 2 members
|
||||
setup := func(store *sqlstore.SQLStore) {
|
||||
teamSvc := ProvideService(store, store.Cfg)
|
||||
teamSvc, err := ProvideService(store, store.Cfg)
|
||||
require.NoError(t, err)
|
||||
team1, errCreateTeam := teamSvc.CreateTeam("group1 name", "test1@example.org", testOrgID)
|
||||
require.NoError(t, errCreateTeam)
|
||||
team2, errCreateTeam := teamSvc.CreateTeam("group2 name", "test2@example.org", testOrgID)
|
||||
@@ -559,7 +562,8 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) {
|
||||
|
||||
store := db.InitTestDB(t, db.InitTestDBOpt{})
|
||||
setup(store)
|
||||
teamSvc := ProvideService(store, store.Cfg)
|
||||
teamSvc, err := ProvideService(store, store.Cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
type getTeamMembersTestCase struct {
|
||||
desc string
|
||||
|
||||
@@ -13,8 +13,13 @@ type Service struct {
|
||||
store store
|
||||
}
|
||||
|
||||
func ProvideService(db db.DB, cfg *setting.Cfg) team.Service {
|
||||
return &Service{store: &xormStore{db: db, cfg: cfg, deletes: []string{}}}
|
||||
func ProvideService(db db.DB, cfg *setting.Cfg) (team.Service, error) {
|
||||
store := &xormStore{db: db, cfg: cfg, deletes: []string{}}
|
||||
|
||||
if err := store.uidMigration(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Service{store: &xormStore{db: db, cfg: cfg, deletes: []string{}}}, nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateTeam(name, email string, orgID int64) (team.Team, error) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@@ -60,6 +61,10 @@ func ProvideService(
|
||||
return s, err
|
||||
}
|
||||
|
||||
if err := s.uidMigration(db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bundleRegistry.RegisterSupportItemCollector(s.supportBundleCollector())
|
||||
return s, nil
|
||||
}
|
||||
@@ -485,3 +490,25 @@ func (s *Service) supportBundleCollector() supportbundles.Collector {
|
||||
Fn: collectorFn,
|
||||
}
|
||||
}
|
||||
|
||||
// This is just to ensure that all users have a valid uid.
|
||||
// To protect against upgrade / downgrade we need to run this for a couple of releases.
|
||||
// FIXME: Remove this migration and make uid field required https://github.com/grafana/identity-access-team/issues/552
|
||||
func (s *Service) uidMigration(store db.DB) error {
|
||||
return store.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
switch store.GetDBType() {
|
||||
case migrator.SQLite:
|
||||
_, err := sess.Exec("UPDATE user SET uid=printf('u%09d',id) WHERE uid IS NULL;")
|
||||
return err
|
||||
case migrator.Postgres:
|
||||
_, err := sess.Exec("UPDATE `user` SET uid='u' || lpad('' || id::text,9,'0') WHERE uid IS NULL;")
|
||||
return err
|
||||
case migrator.MySQL:
|
||||
_, err := sess.Exec("UPDATE user SET uid=concat('u',lpad(id,9,'0')) WHERE uid IS NULL;")
|
||||
return err
|
||||
default:
|
||||
// this branch should be unreachable
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -377,7 +377,9 @@ func (c K8sTestHelper) createTestUsers(orgName string) OrgUsers {
|
||||
store.Cfg.AutoAssignOrg = true
|
||||
store.Cfg.AutoAssignOrgId = int(orgId)
|
||||
|
||||
teamSvc := teamimpl.ProvideService(store, store.Cfg)
|
||||
teamSvc, err := teamimpl.ProvideService(store, store.Cfg)
|
||||
require.NoError(c.t, err)
|
||||
|
||||
cache := localcache.ProvideService()
|
||||
userSvc, err := userimpl.ProvideService(store,
|
||||
orgService, store.Cfg, teamSvc, cache, quotaService,
|
||||
|
||||
Reference in New Issue
Block a user