feat(user/role/storage): enhance user and storage operations with additional validations (#9223)

- Update `CreateUser` to adjust `BasePath` based on user roles and clean paths.
- Modify `UpdateUser` to incorporate role-based path changes.
- Add validation in `CreateStorage` and `UpdateStorage` to prevent root mount path.
- Prevent changes to admin user's role and username in user handler.
- Update `UpdateRole` to modify user base paths when role paths change, and clear user cache accordingly.
- Import `errors` package to handle error messages.
pull/9228/head v3.46.2
千石 2025-07-27 22:25:45 +08:00 committed by GitHub
parent f61d13d433
commit 91cc7529a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 66 additions and 5 deletions

View File

@ -2,6 +2,7 @@ package op
import (
"fmt"
"github.com/pkg/errors"
"time"
"github.com/Xhofe/go-cache"
@ -102,6 +103,20 @@ func UpdateRole(r *model.Role) error {
for i := range r.PermissionScopes {
r.PermissionScopes[i].Path = utils.FixAndCleanPath(r.PermissionScopes[i].Path)
}
if len(old.PermissionScopes) > 0 && len(r.PermissionScopes) > 0 &&
old.PermissionScopes[0].Path != r.PermissionScopes[0].Path {
oldPath := old.PermissionScopes[0].Path
newPath := r.PermissionScopes[0].Path
modifiedUsernames, err := db.UpdateUserBasePathPrefix(oldPath, newPath)
if err != nil {
return errors.WithMessage(err, "failed to update user base path when role updated")
}
for _, name := range modifiedUsernames {
userCache.Del(name)
}
}
roleCache.Del(fmt.Sprint(r.ID))
roleCache.Del(r.Name)
return db.UpdateRole(r)

View File

@ -46,6 +46,11 @@ func GetStorageByMountPath(mountPath string) (driver.Driver, error) {
func CreateStorage(ctx context.Context, storage model.Storage) (uint, error) {
storage.Modified = time.Now()
storage.MountPath = utils.FixAndCleanPath(storage.MountPath)
if storage.MountPath == "/" {
return 0, errors.New("Mount path cannot be '/'")
}
var err error
// check driver first
driverName := storage.Driver
@ -205,6 +210,9 @@ func UpdateStorage(ctx context.Context, storage model.Storage) error {
}
storage.Modified = time.Now()
storage.MountPath = utils.FixAndCleanPath(storage.MountPath)
if storage.MountPath == "/" {
return errors.New("Mount path cannot be '/'")
}
err = db.UpdateStorage(&storage)
if err != nil {
return errors.WithMessage(err, "failed update storage in database")

View File

@ -78,7 +78,25 @@ func GetUsers(pageIndex, pageSize int) (users []model.User, count int64, err err
func CreateUser(u *model.User) error {
u.BasePath = utils.FixAndCleanPath(u.BasePath)
return db.CreateUser(u)
err := db.CreateUser(u)
if err != nil {
return err
}
roles, err := GetRolesByUserID(u.ID)
if err == nil {
for _, role := range roles {
if len(role.PermissionScopes) > 0 {
u.BasePath = utils.FixAndCleanPath(role.PermissionScopes[0].Path)
break
}
}
_ = db.UpdateUser(u)
userCache.Del(u.Username)
}
return nil
}
func DeleteUserById(id uint) error {
@ -106,6 +124,17 @@ func UpdateUser(u *model.User) error {
}
userCache.Del(old.Username)
u.BasePath = utils.FixAndCleanPath(u.BasePath)
if len(u.Role) > 0 {
roles, err := GetRolesByUserID(u.ID)
if err == nil {
for _, role := range roles {
if len(role.PermissionScopes) > 0 {
u.BasePath = utils.FixAndCleanPath(role.PermissionScopes[0].Path)
break
}
}
}
}
return db.UpdateUser(u)
}

View File

@ -1,6 +1,7 @@
package handles
import (
"github.com/alist-org/alist/v3/pkg/utils"
"strconv"
"github.com/alist-org/alist/v3/internal/model"
@ -60,10 +61,18 @@ func UpdateUser(c *gin.Context) {
common.ErrorResp(c, err, 500)
return
}
//if !utils.SliceEqual(user.Role, req.Role) {
// common.ErrorStrResp(c, "role can not be changed", 400)
// return
//}
if user.Username == "admin" {
if !utils.SliceEqual(user.Role, req.Role) {
common.ErrorStrResp(c, "cannot change role of admin user", 403)
return
}
if user.Username != req.Username {
common.ErrorStrResp(c, "cannot change username of admin user", 403)
return
}
}
if req.Password == "" {
req.PwdHash = user.PwdHash
req.Salt = user.Salt