mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix(keystone): displays the reason why user cannot be deleted (#17663)
This commit is contained in:
@@ -860,7 +860,7 @@ func (self *SIdentityProvider) Purge(ctx context.Context, userCred mcclient.Toke
|
||||
if self.isSsoIdp() && self.AutoCreateUser.IsFalse() {
|
||||
continue
|
||||
}
|
||||
err = users[i].ValidatePurgeCondition(ctx)
|
||||
err = users[i].ValidatePurgeCondition(ctx, nil)
|
||||
if err != nil {
|
||||
db.OpsLog.LogEvent(&users[i], db.ACT_DELETE_FAIL, err, userCred)
|
||||
log.Errorf("users %s ValidatePurgeCondition fail %s", users[i].Name, err)
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
"yunion.io/x/sqlchemy"
|
||||
@@ -631,6 +632,40 @@ func (user *SUser) GetCredentialCount() (int, error) {
|
||||
return q.CountWithError()
|
||||
}
|
||||
|
||||
func (manager *SUserManager) FetchScopeResources(userIds []string) (map[string]api.ExternalResourceInfo, error) {
|
||||
resources := ScopeResourceManager.Query().In("owner_id", userIds).SubQuery()
|
||||
q := resources.Query(
|
||||
resources.Field("resource"),
|
||||
resources.Field("owner_id"),
|
||||
sqlchemy.SUM("res_count", resources.Field("count")),
|
||||
sqlchemy.MAX("last_update", resources.Field("updated_at")),
|
||||
)
|
||||
q = q.GroupBy(resources.Field("resource"))
|
||||
ret := []struct {
|
||||
Resource string
|
||||
OwnerId string
|
||||
ResCount int
|
||||
LastUpdate time.Time
|
||||
}{}
|
||||
err := q.All(&ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := map[string]api.ExternalResourceInfo{}
|
||||
for _, res := range ret {
|
||||
_, ok := result[res.OwnerId]
|
||||
if !ok && res.ResCount > 0 {
|
||||
result[res.OwnerId] = api.ExternalResourceInfo{
|
||||
ExtResource: map[string]int{},
|
||||
ExtResourcesLastUpdate: res.LastUpdate,
|
||||
ExtResourcesNextUpdate: res.LastUpdate.Add(time.Duration(options.Options.FetchScopeResourceCountIntervalSeconds) * time.Second),
|
||||
}
|
||||
}
|
||||
result[res.OwnerId].ExtResource[res.Resource] = res.ResCount
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (manager *SUserManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
@@ -658,7 +693,14 @@ func (manager *SUserManager) FetchCustomizeColumns(
|
||||
return rows
|
||||
}
|
||||
|
||||
scopeResources, err := manager.FetchScopeResources(userIds)
|
||||
if err != nil {
|
||||
log.Errorf("FetchScopeResources error: %v", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
for i := range rows {
|
||||
rows[i].ExternalResourceInfo, _ = scopeResources[userIds[i]]
|
||||
if idps, ok := idpsMaps[userIds[i]]; ok {
|
||||
if len(idps) > 0 {
|
||||
// rows[i].IdpResourceInfo = idps[0].IdpResourceInfo
|
||||
@@ -697,17 +739,6 @@ func userExtra(ctx context.Context, userCred mcclient.TokenCredential, user *SUs
|
||||
out.IsLocal = false
|
||||
}
|
||||
|
||||
external, update, _ := user.getExternalResources()
|
||||
if len(external) > 0 {
|
||||
out.ExtResource = external
|
||||
out.ExtResourcesLastUpdate = update
|
||||
if update.IsZero() {
|
||||
update = time.Now()
|
||||
}
|
||||
nextUpdate := update.Add(time.Duration(options.Options.FetchScopeResourceCountIntervalSeconds) * time.Second)
|
||||
out.ExtResourcesNextUpdate = nextUpdate
|
||||
}
|
||||
|
||||
projects, _ := ProjectManager.FetchUserProjects(user.Id)
|
||||
out.Projects = make([]api.SFetchDomainObjectWithMetadata, len(projects))
|
||||
for i, proj := range projects {
|
||||
@@ -815,7 +846,7 @@ func (user *SUser) PostUpdate(ctx context.Context, userCred mcclient.TokenCreden
|
||||
}
|
||||
}
|
||||
|
||||
func (user *SUser) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
func (user *SUser) ValidateDeleteCondition(ctx context.Context, info *api.UserDetails) error {
|
||||
idMappings, err := user.getIdmappings()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getIdmappings")
|
||||
@@ -831,21 +862,32 @@ func (user *SUser) ValidateDeleteCondition(ctx context.Context, info jsonutils.J
|
||||
}
|
||||
}
|
||||
}
|
||||
err = user.ValidatePurgeCondition(ctx)
|
||||
err = user.ValidatePurgeCondition(ctx, info)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ValidatePurgeCondition")
|
||||
return err
|
||||
}
|
||||
return user.SIdentityBaseResource.ValidateDeleteCondition(ctx, nil)
|
||||
}
|
||||
|
||||
func (user *SUser) ValidatePurgeCondition(ctx context.Context) error {
|
||||
external, _, _ := user.getExternalResources()
|
||||
if len(external) > 0 {
|
||||
return httperrors.NewNotEmptyError("user contains external resources")
|
||||
}
|
||||
func (user *SUser) ValidatePurgeCondition(ctx context.Context, info *api.UserDetails) error {
|
||||
if user.IsAdminUser() {
|
||||
return httperrors.NewForbiddenError("cannot delete system user")
|
||||
}
|
||||
if gotypes.IsNil(info) {
|
||||
info = &api.UserDetails{}
|
||||
scopResource, err := UserManager.FetchScopeResources([]string{user.Id})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchScopeResources")
|
||||
}
|
||||
info.ExternalResourceInfo, _ = scopResource[user.Id]
|
||||
}
|
||||
if len(info.ExtResource) > 0 {
|
||||
for k, cnt := range info.ExtResource {
|
||||
if cnt > 0 {
|
||||
return httperrors.NewNotEmptyError("user contains %d external resources %s", cnt, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user