feat: Check usage before deleting storage (#9322)

* feat(storage): Added role and user path checking functionality

- Added `GetAllRoles` function to retrieve all roles
- Added `GetAllUsers` function to retrieve all users
- Added `firstPathSegment` function to extract the first segment of a path
- Checks whether a storage object is used by a role or user, and returns relevant information for unusing it

* fix(storage): Fixed a potential null value issue with not checking firstMount.

- Added a check to see if `firstMount` is null to prevent logic errors.
- Adjusted the loading logic of `GetAllRoles` and `GetAllUsers` to only execute when `firstMount` is non-null.
- Fixed the `usedBy` check logic to ensure that an error message is returned under the correct conditions.
- Optimized code structure to reduce unnecessary execution paths.
pull/9292/merge v3.53.0
千石 2025-09-12 17:56:23 +08:00 committed by GitHub
parent 16cce37947
commit e1800f18e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 0 deletions

View File

@ -34,6 +34,14 @@ func GetRoles(pageIndex, pageSize int) (roles []model.Role, count int64, err err
return roles, count, nil
}
func GetAllRoles() ([]model.Role, error) {
var roles []model.Role
if err := db.Find(&roles).Error; err != nil {
return nil, errors.WithStack(err)
}
return roles, nil
}
func CreateRole(r *model.Role) error {
if err := db.Create(r).Error; err != nil {
return errors.WithStack(err)

View File

@ -83,6 +83,14 @@ func GetUsers(pageIndex, pageSize int) (users []model.User, count int64, err err
return users, count, nil
}
func GetAllUsers() ([]model.User, error) {
var users []model.User
if err := db.Find(&users).Error; err != nil {
return nil, errors.WithStack(err)
}
return users, nil
}
func DeleteUserById(id uint) error {
return errors.WithStack(db.Delete(&model.User{}, id).Error)
}

View File

@ -41,6 +41,18 @@ func GetStorageByMountPath(mountPath string) (driver.Driver, error) {
return storageDriver, nil
}
func firstPathSegment(p string) string {
p = utils.FixAndCleanPath(p)
p = strings.TrimPrefix(p, "/")
if p == "" {
return ""
}
if i := strings.Index(p, "/"); i >= 0 {
return p[:i]
}
return p
}
// CreateStorage Save the storage to database so storage can get an id
// then instantiate corresponding driver and save it in memory
func CreateStorage(ctx context.Context, storage model.Storage) (uint, error) {
@ -267,6 +279,34 @@ func DeleteStorageById(ctx context.Context, id uint) error {
if err != nil {
return errors.WithMessage(err, "failed get storage")
}
firstMount := firstPathSegment(storage.MountPath)
if firstMount != "" {
roles, err := db.GetAllRoles()
if err != nil {
return errors.WithMessage(err, "failed to load roles")
}
users, err := db.GetAllUsers()
if err != nil {
return errors.WithMessage(err, "failed to load users")
}
var usedBy []string
for _, r := range roles {
for _, entry := range r.PermissionScopes {
if firstPathSegment(entry.Path) == firstMount {
usedBy = append(usedBy, "role:"+r.Name)
break
}
}
}
for _, u := range users {
if firstPathSegment(u.BasePath) == firstMount {
usedBy = append(usedBy, "user:"+u.Username)
}
}
if len(usedBy) > 0 {
return errors.Errorf("storage is used by %s, please cancel usage first", strings.Join(usedBy, ", "))
}
}
if !storage.Disabled {
storageDriver, err := GetStorageByMountPath(storage.MountPath)
if err != nil {