alist/internal/op/user.go
千石 91cc7529a0
Some checks failed
beta release / Beta Release Changelog (1.21, ubuntu-latest) (push) Has been cancelled
build / Build (ubuntu-latest, android-arm64) (push) Has been cancelled
build / Build (ubuntu-latest, darwin-amd64) (push) Has been cancelled
build / Build (ubuntu-latest, darwin-arm64) (push) Has been cancelled
build / Build (ubuntu-latest, linux-amd64-musl) (push) Has been cancelled
build / Build (ubuntu-latest, linux-arm64-musl) (push) Has been cancelled
build / Build (ubuntu-latest, windows-amd64) (push) Has been cancelled
build / Build (ubuntu-latest, windows-arm64) (push) Has been cancelled
release_docker / Build Binaries for Docker Release (push) Has been cancelled
beta release / Beta Release (md5, !(*musl*|*windows-arm64*|*android*|*freebsd*)) (push) Has been cancelled
beta release / Beta Release (md5-android, android-*) (push) Has been cancelled
beta release / Beta Release (md5-freebsd, freebsd-*) (push) Has been cancelled
beta release / Beta Release (md5-linux-musl, linux-!(arm*)-musl*) (push) Has been cancelled
beta release / Beta Release (md5-linux-musl-arm, linux-arm*-musl*) (push) Has been cancelled
beta release / Beta Release (md5-windows-arm64, windows-arm64) (push) Has been cancelled
beta release / Beta Release Desktop (push) Has been cancelled
release_docker / Release Docker image (, latest, ) (push) Has been cancelled
release_docker / Release Docker image (INSTALL_ARIA2=true, aria2, suffix=-aria2,onlatest=true) (push) Has been cancelled
release_docker / Release Docker image (INSTALL_FFMPEG=true INSTALL_ARIA2=true , aio, suffix=-aio,onlatest=true) (push) Has been cancelled
release_docker / Release Docker image (INSTALL_FFMPEG=true, ffmpeg, suffix=-ffmpeg,onlatest=true) (push) Has been cancelled
Close inactive / close-inactive (push) Has been cancelled
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.
2025-07-27 22:25:45 +08:00

168 lines
3.3 KiB
Go

package op
import (
"time"
"github.com/Xhofe/go-cache"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/pkg/singleflight"
"github.com/alist-org/alist/v3/pkg/utils"
)
var userCache = cache.NewMemCache(cache.WithShards[*model.User](2))
var userG singleflight.Group[*model.User]
var guestUser *model.User
var adminUser *model.User
func GetAdmin() (*model.User, error) {
if adminUser == nil {
role, err := GetRoleByName("admin")
if err != nil {
return nil, err
}
user, err := db.GetUserByRole(int(role.ID))
if err != nil {
return nil, err
}
adminUser = user
}
return adminUser, nil
}
func GetGuest() (*model.User, error) {
if guestUser == nil {
role, err := GetRoleByName("guest")
if err != nil {
return nil, err
}
user, err := db.GetUserByRole(int(role.ID))
if err != nil {
return nil, err
}
guestUser = user
}
return guestUser, nil
}
func GetUserByRole(role int) (*model.User, error) {
return db.GetUserByRole(role)
}
func GetUserByName(username string) (*model.User, error) {
if username == "" {
return nil, errs.EmptyUsername
}
if user, ok := userCache.Get(username); ok {
return user, nil
}
user, err, _ := userG.Do(username, func() (*model.User, error) {
_user, err := db.GetUserByName(username)
if err != nil {
return nil, err
}
userCache.Set(username, _user, cache.WithEx[*model.User](time.Hour))
return _user, nil
})
return user, err
}
func GetUserById(id uint) (*model.User, error) {
return db.GetUserById(id)
}
func GetUsers(pageIndex, pageSize int) (users []model.User, count int64, err error) {
return db.GetUsers(pageIndex, pageSize)
}
func CreateUser(u *model.User) error {
u.BasePath = utils.FixAndCleanPath(u.BasePath)
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 {
old, err := db.GetUserById(id)
if err != nil {
return err
}
if old.IsAdmin() || old.IsGuest() {
return errs.DeleteAdminOrGuest
}
userCache.Del(old.Username)
return db.DeleteUserById(id)
}
func UpdateUser(u *model.User) error {
old, err := db.GetUserById(u.ID)
if err != nil {
return err
}
if u.IsAdmin() {
adminUser = nil
}
if u.IsGuest() {
guestUser = nil
}
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)
}
func Cancel2FAByUser(u *model.User) error {
u.OtpSecret = ""
return UpdateUser(u)
}
func Cancel2FAById(id uint) error {
user, err := db.GetUserById(id)
if err != nil {
return err
}
return Cancel2FAByUser(user)
}
func DelUserCache(username string) error {
user, err := GetUserByName(username)
if err != nil {
return err
}
if user.IsAdmin() {
adminUser = nil
}
if user.IsGuest() {
guestUser = nil
}
userCache.Del(username)
return nil
}