diff --git a/pkg/compute/models/dbinstance_accounts.go b/pkg/compute/models/dbinstance_accounts.go index 1cf5ec52f2..deecff79ca 100644 --- a/pkg/compute/models/dbinstance_accounts.go +++ b/pkg/compute/models/dbinstance_accounts.go @@ -33,18 +33,19 @@ import ( "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/util/rbacutils" "yunion.io/x/onecloud/pkg/util/seclib2" ) type SDBInstanceAccountManager struct { - db.SVirtualResourceBaseManager + db.SStatusStandaloneResourceBaseManager } var DBInstanceAccountManager *SDBInstanceAccountManager func init() { DBInstanceAccountManager = &SDBInstanceAccountManager{ - SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager( + SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager( SDBInstanceAccount{}, "dbinstanceaccounts_tbl", "dbinstanceaccount", @@ -55,7 +56,7 @@ func init() { } type SDBInstanceAccount struct { - db.SVirtualResourceBase + db.SStatusStandaloneResourceBase db.SExternalizedResourceBase Secret string `width:"256" charset:"ascii" nullable:"false" list:"domain" create:"optional"` @@ -68,8 +69,42 @@ func (manager *SDBInstanceAccountManager) GetContextManagers() [][]db.IModelMana } } -func (self *SDBInstanceAccountManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { - return db.IsAdminAllowList(userCred, self) +func (manager *SDBInstanceAccountManager) ResourceScope() rbacutils.TRbacScope { + return rbacutils.ScopeProject +} + +func (manager *SDBInstanceAccountManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { + if jsonutils.QueryBoolean(query, "admin", false) && !db.IsAllowList(rbacutils.ScopeProject, userCred, manager) { + return false + } + return true +} + +func (manager *SDBInstanceAccountManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { + parentId := manager.FetchParentId(ctx, data) + if len(parentId) > 0 { + instance, err := db.FetchById(DBInstanceManager, parentId) + if err != nil { + return nil, errors.Wrapf(err, "db.FetchById(DBInstanceManager, %s)", parentId) + } + return instance.(*SDBInstance).GetOwnerId(), nil + } + return nil, nil +} + +func (manager *SDBInstanceAccountManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery { + if userCred != nil { + sq := DBInstanceManager.Query("id") + switch scope { + case rbacutils.ScopeProject: + sq = sq.Equals("tenant_id", userCred.GetProjectId()) + return q.In("dbinstance_id", sq.SubQuery()) + case rbacutils.ScopeDomain: + sq = sq.Equals("domain_id", userCred.GetProjectDomainId()) + return q.In("dbinstance_id", sq.SubQuery()) + } + } + return q } func (self *SDBInstanceAccountManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { @@ -105,7 +140,7 @@ func (self *SDBInstanceAccount) getPrivilegesDetails() (*jsonutils.JSONArray, er } func (self *SDBInstanceAccount) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { - extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query) + extra := self.SStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query) extra, _ = self.getMoreDetails(ctx, userCred, extra) return extra } @@ -120,7 +155,7 @@ func (self *SDBInstanceAccount) getMoreDetails(ctx context.Context, userCred mcc } func (self *SDBInstanceAccount) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) { - extra, err := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query) + extra, err := self.SStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query) if err != nil { return nil, err } @@ -128,7 +163,7 @@ func (self *SDBInstanceAccount) GetExtraDetails(ctx context.Context, userCred mc } func (manager *SDBInstanceAccountManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) { - q, err := manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query) + q, err := manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query) if err != nil { return nil, err } @@ -205,11 +240,7 @@ func (self *SDBInstanceAccount) GetPassword() (string, error) { } func (self *SDBInstanceAccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { - self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data) - instance, _ := self.GetDBInstance() - if instance != nil { - self.SetProjectInfo(ctx, userCred, instance.ProjectId, instance.DomainId) - } + self.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data) input := &api.SDBInstanceAccountCreateInput{} data.Unmarshal(input) self.savePassword(input.Password) @@ -525,8 +556,6 @@ func (manager *SDBInstanceAccountManager) SyncDBInstanceAccounts(ctx context.Con func (self *SDBInstanceAccount) SyncWithCloudDBInstanceAccount(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, extAccount cloudprovider.ICloudDBInstanceAccount) error { _, err := db.UpdateWithLock(ctx, self, func() error { - self.ProjectId = instance.ProjectId - self.DomainId = instance.DomainId self.Status = extAccount.GetStatus() return nil }) @@ -547,8 +576,6 @@ func (manager *SDBInstanceAccountManager) newFromCloudDBInstanceAccount(ctx cont account.DBInstanceId = instance.Id account.Status = extAccount.GetStatus() account.ExternalId = extAccount.GetGlobalId() - account.ProjectId = instance.ProjectId - account.DomainId = instance.DomainId err := manager.TableSpec().Insert(&account) if err != nil { @@ -563,7 +590,7 @@ func (self *SDBInstanceAccount) Delete(ctx context.Context, userCred mcclient.To } func (self *SDBInstanceAccount) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { - return self.SVirtualResourceBase.Delete(ctx, userCred) + return self.SStatusStandaloneResourceBase.Delete(ctx, userCred) } func (self *SDBInstanceAccount) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error { diff --git a/pkg/compute/models/dbinstance_backups.go b/pkg/compute/models/dbinstance_backups.go index 852d53c9dc..788e1a8c3a 100644 --- a/pkg/compute/models/dbinstance_backups.go +++ b/pkg/compute/models/dbinstance_backups.go @@ -296,10 +296,15 @@ func (self *SDBInstanceBackup) SyncWithCloudDBInstanceBackup(ctx context.Context if dbinstanceId := extBackup.GetDBInstanceId(); len(dbinstanceId) > 0 { //有可能云上删除了实例,未删除备份 - _, err := db.FetchByExternalId(DBInstanceManager, dbinstanceId) + _instance, err := db.FetchByExternalId(DBInstanceManager, dbinstanceId) if err == sql.ErrNoRows { self.DBInstanceId = "" } + if _instance != nil { + instance := _instance.(*SDBInstance) + self.ProjectId = instance.ProjectId + self.DomainId = instance.DomainId + } } return nil @@ -308,8 +313,10 @@ func (self *SDBInstanceBackup) SyncWithCloudDBInstanceBackup(ctx context.Context return errors.Wrapf(err, "SyncWithCloudDBInstancebackup.UpdateWithLock") } - provider := self.GetCloudprovider() - SyncCloudProject(userCred, self, provider.GetOwnerId(), extBackup, self.ManagerId) + if len(self.ProjectId) == 0 { + provider := self.GetCloudprovider() + SyncCloudProject(userCred, self, provider.GetOwnerId(), extBackup, self.ManagerId) + } return nil } @@ -340,11 +347,14 @@ func (manager *SDBInstanceBackupManager) newFromCloudDBInstanceBackup(ctx contex backup.ExternalId = extBackup.GetGlobalId() if dbinstanceId := extBackup.GetDBInstanceId(); len(dbinstanceId) > 0 { - dbinstance, err := db.FetchByExternalId(DBInstanceManager, dbinstanceId) + _dbinstance, err := db.FetchByExternalId(DBInstanceManager, dbinstanceId) if err != nil { log.Warningf("failed to found dbinstance for backup %s by externalId: %s error: %v", backup.Name, dbinstanceId, err) } else { - backup.DBInstanceId = dbinstance.GetId() + instance := _dbinstance.(*SDBInstance) + backup.DBInstanceId = instance.Id + backup.ProjectId = instance.ProjectId + backup.DomainId = instance.DomainId } } @@ -353,7 +363,9 @@ func (manager *SDBInstanceBackupManager) newFromCloudDBInstanceBackup(ctx contex return errors.Wrapf(err, "newFromCloudDBInstanceBackup.Insert") } - SyncCloudProject(userCred, &backup, provider.GetOwnerId(), extBackup, backup.ManagerId) + if len(backup.ProjectId) == 0 { + SyncCloudProject(userCred, &backup, provider.GetOwnerId(), extBackup, backup.ManagerId) + } return nil } diff --git a/pkg/compute/models/dbinstance_databases.go b/pkg/compute/models/dbinstance_databases.go index e244e42c00..ddf4b37a50 100644 --- a/pkg/compute/models/dbinstance_databases.go +++ b/pkg/compute/models/dbinstance_databases.go @@ -31,17 +31,18 @@ import ( "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/util/rbacutils" ) type SDBInstanceDatabaseManager struct { - db.SVirtualResourceBaseManager + db.SStatusStandaloneResourceBaseManager } var DBInstanceDatabaseManager *SDBInstanceDatabaseManager func init() { DBInstanceDatabaseManager = &SDBInstanceDatabaseManager{ - SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager( + SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager( SDBInstanceDatabase{}, "dbinstancedatabases_tbl", "dbinstancedatabase", @@ -52,7 +53,7 @@ func init() { } type SDBInstanceDatabase struct { - db.SVirtualResourceBase + db.SStatusStandaloneResourceBase db.SExternalizedResourceBase CharacterSet string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"optional"` @@ -65,8 +66,42 @@ func (manager *SDBInstanceDatabaseManager) GetContextManagers() [][]db.IModelMan } } -func (self *SDBInstanceDatabaseManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { - return db.IsAdminAllowList(userCred, self) +func (manager *SDBInstanceDatabaseManager) ResourceScope() rbacutils.TRbacScope { + return rbacutils.ScopeProject +} + +func (manager *SDBInstanceDatabaseManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { + if jsonutils.QueryBoolean(query, "admin", false) && !db.IsAllowList(rbacutils.ScopeProject, userCred, manager) { + return false + } + return true +} + +func (manager *SDBInstanceDatabaseManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { + parentId := manager.FetchParentId(ctx, data) + if len(parentId) > 0 { + instance, err := db.FetchById(DBInstanceManager, parentId) + if err != nil { + return nil, errors.Wrapf(err, "db.FetchById(DBInstanceManager, %s)", parentId) + } + return instance.(*SDBInstance).GetOwnerId(), nil + } + return nil, nil +} + +func (manager *SDBInstanceDatabaseManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery { + if userCred != nil { + sq := DBInstanceManager.Query("id") + switch scope { + case rbacutils.ScopeProject: + sq = sq.Equals("tenant_id", userCred.GetProjectId()) + return q.In("dbinstance_id", sq.SubQuery()) + case rbacutils.ScopeDomain: + sq = sq.Equals("domain_id", userCred.GetProjectDomainId()) + return q.In("dbinstance_id", sq.SubQuery()) + } + } + return q } func (self *SDBInstanceDatabaseManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { @@ -82,12 +117,21 @@ func (self *SDBInstanceDatabase) AllowUpdateItem(ctx context.Context, userCred m return false } +func (self *SDBInstanceDatabase) GetOwnerId() mcclient.IIdentityProvider { + instance, err := self.GetDBInstance() + if err != nil { + log.Errorf("failed to get dbinstance for database %s(%s)", self.Id, self.Name) + return nil + } + return instance.GetOwnerId() +} + func (self *SDBInstanceDatabase) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { return db.IsAdminAllowDelete(userCred, self) } func (manager *SDBInstanceDatabaseManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) { - q, err := manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query) + q, err := manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query) if err != nil { return nil, err } @@ -150,11 +194,7 @@ func (manager *SDBInstanceDatabaseManager) ValidateCreateData(ctx context.Contex } func (self *SDBInstanceDatabase) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { - self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data) - instance, _ := self.GetDBInstance() - if instance != nil { - self.SetProjectInfo(ctx, userCred, instance.ProjectId, instance.DomainId) - } + self.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data) self.StartDBInstanceDatabaseCreateTask(ctx, userCred, data.(*jsonutils.JSONDict), "") } @@ -187,7 +227,7 @@ func (self *SDBInstanceDatabase) GetDBInstance() (*SDBInstance, error) { } func (self *SDBInstanceDatabase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) { - extra, err := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query) + extra, err := self.SStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query) if err != nil { return nil, err } @@ -196,7 +236,7 @@ func (self *SDBInstanceDatabase) GetExtraDetails(ctx context.Context, userCred m } func (self *SDBInstanceDatabase) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { - extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query) + extra := self.SStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query) extra, _ = self.getMoreDetails(ctx, userCred, extra) return extra } @@ -280,8 +320,6 @@ func (self *SDBInstanceDatabase) SyncWithCloudDBInstanceDatabase(ctx context.Con self.Status = extDatabase.GetStatus() self.Name = extDatabase.GetName() self.CharacterSet = extDatabase.GetCharacterSet() - self.ProjectId = instance.ProjectId - self.DomainId = instance.DomainId return nil }) @@ -303,8 +341,6 @@ func (manager *SDBInstanceDatabaseManager) newFromCloudDBInstanceDatabase(ctx co database.Status = extDatabase.GetStatus() database.CharacterSet = extDatabase.GetCharacterSet() database.ExternalId = extDatabase.GetGlobalId() - database.ProjectId = instance.ProjectId - database.DomainId = instance.DomainId err := manager.TableSpec().Insert(&database) if err != nil { @@ -319,7 +355,7 @@ func (self *SDBInstanceDatabase) Delete(ctx context.Context, userCred mcclient.T } func (self *SDBInstanceDatabase) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { - return self.SVirtualResourceBase.Delete(ctx, userCred) + return self.SStatusStandaloneResourceBase.Delete(ctx, userCred) } func (self *SDBInstanceDatabase) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error { diff --git a/pkg/compute/models/dbinstances.go b/pkg/compute/models/dbinstances.go index 6d60454489..b0b0fb8dc0 100644 --- a/pkg/compute/models/dbinstances.go +++ b/pkg/compute/models/dbinstances.go @@ -500,36 +500,16 @@ func (self *SDBInstance) GetIDBInstance() (cloudprovider.ICloudDBInstance, error func (self *SDBInstance) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { dataCopy := jsonutils.DeepCopy(data) - accounts, err := self.GetDBInstanceAccounts() - if err != nil { - return nil, httperrors.NewGeneralError(fmt.Errorf("failed get accounts: %v", err)) - } backups, err := self.GetDBInstanceBackups() if err != nil { return nil, httperrors.NewGeneralError(fmt.Errorf("failed get backups: %v", err)) } - databases, err := self.GetDBInstanceDatabases() - if err != nil { - return nil, httperrors.NewGeneralError(fmt.Errorf("failed get databases: %v", err)) - } - for i := range accounts { - _, err := accounts[i].PerformChangeOwner(ctx, userCred, query, dataCopy) - if err != nil { - return nil, err - } - } for i := range backups { _, err := backups[i].PerformChangeOwner(ctx, userCred, query, dataCopy) if err != nil { return nil, err } } - for i := range databases { - _, err := databases[i].PerformChangeOwner(ctx, userCred, query, dataCopy) - if err != nil { - return nil, err - } - } return self.SVirtualResourceBase.PerformChangeOwner(ctx, userCred, query, data) }