fix(keystone): displays the reason why user cannot be deleted (#17663)

This commit is contained in:
屈轩
2023-08-13 22:42:31 +08:00
committed by GitHub
parent 62e17595ae
commit 43f6e8236d
2 changed files with 62 additions and 20 deletions
+1 -1
View File
@@ -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)
+61 -19
View File
@@ -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
}