fix compile errors to support group array in user edge

pull/2499/head
WintBit 6 days ago
parent 0b9822ecd4
commit ca080fc758

@ -3,6 +3,7 @@ package migrator
import (
"context"
"fmt"
"github.com/cloudreve/Cloudreve/v4/application/migrator/model"
"github.com/cloudreve/Cloudreve/v4/ent/user"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
@ -71,7 +72,7 @@ func (m *Migrator) migrateUser() error {
SetNick(u.Nick).
SetStatus(userStatus).
SetStorage(int64(u.Storage)).
SetGroupID(int(u.GroupID)).
AddGroupIDs(int(u.GroupID)).
SetSettings(setting).
SetPassword(u.Password)

@ -0,0 +1,69 @@
package ent
import (
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/samber/lo"
)
func (u *User) AnyGroup(predict func(*Group) bool) bool {
return !lo.NoneBy(u.Edges.Group, predict)
}
func (u *User) EnforceGroupPermission(perm types.GroupPermission) bool {
return !lo.NoneBy(u.Edges.Group, func(item *Group) bool {
return item.Permissions.Enabled(int(perm))
})
}
func (u *User) GroupMaxStorage() int64 {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.MaxStorage > b.MaxStorage
}).MaxStorage
}
func (u *User) GroupMaxWalkedFiles() int {
return max(lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.Settings.MaxWalkedFiles > b.Settings.MaxWalkedFiles
}).Settings.MaxWalkedFiles, 1)
}
func (u *User) GroupMaxTrashRetention() int {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.Settings.TrashRetention > b.Settings.TrashRetention
}).Settings.TrashRetention
}
func (u *User) GroupMaxDecompressSize() int64 {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.Settings.DecompressSize > b.Settings.DecompressSize
}).Settings.DecompressSize
}
func (u *User) GroupMaxCompressSize() int64 {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.Settings.CompressSize > b.Settings.CompressSize
}).Settings.CompressSize
}
func (u *User) GroupMaxSpeedLimit() int {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.SpeedLimit > b.SpeedLimit
}).SpeedLimit
}
func (u *User) GroupMaxSourceBatchSize() int {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.Settings.SourceBatchSize > b.Settings.SourceBatchSize
}).Settings.SourceBatchSize
}
func (u *User) GroupMaxAria2BatchSize() int {
return lo.MaxBy(u.Edges.Group, func(a *Group, b *Group) bool {
return a.Settings.Aria2BatchSize > b.Settings.Aria2BatchSize
}).Settings.Aria2BatchSize
}
func (u *User) GetPrimaryGroup() *Group {
// TODO: design user primary group
panic("implement me")
}

@ -46,7 +46,7 @@ require (
github.com/qiniu/go-sdk/v7 v7.19.0
github.com/rafaeljusto/redigomock v0.0.0-20191117212112-00b2509252a1
github.com/robfig/cron/v3 v3.0.1
github.com/samber/lo v1.38.1
github.com/samber/lo v1.51.0
github.com/speps/go-hashids v2.0.0+incompatible
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5

@ -864,8 +864,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI=
github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=

@ -16,6 +16,7 @@ import (
"github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/ent/davaccount"
"github.com/cloudreve/Cloudreve/v4/ent/file"
"github.com/cloudreve/Cloudreve/v4/ent/group"
"github.com/cloudreve/Cloudreve/v4/ent/passkey"
"github.com/cloudreve/Cloudreve/v4/ent/schema"
"github.com/cloudreve/Cloudreve/v4/ent/task"
@ -309,7 +310,7 @@ func (c *userClient) Create(ctx context.Context, args *NewUserArgs) (*ent.User,
SetEmail(args.Email).
SetNick(nick).
SetStatus(args.Status).
SetGroupID(args.GroupID).
AddGroupIDs(args.GroupID).
SetAvatar(args.Avatar)
if args.PlainPassword != "" {
@ -334,7 +335,7 @@ func (c *userClient) Create(ctx context.Context, args *NewUserArgs) (*ent.User,
if newUser.ID == 1 {
// For the first user registered, elevate it to admin group.
if _, err := newUser.Update().SetGroupID(1).Save(ctx); err != nil {
if _, err := newUser.Update().AddGroupIDs(1).Save(ctx); err != nil {
return newUser, fmt.Errorf("failed to elevate user to admin: %w", err)
}
}
@ -434,14 +435,14 @@ func (c *userClient) AnonymousUser(ctx context.Context) (*ent.User, error) {
anonymous := &ent.User{
Settings: &types.UserSetting{},
}
anonymous.SetGroup(anonymousGroup)
anonymous.SetGroup([]*ent.Group{anonymousGroup})
return anonymous, nil
}
func (c *userClient) ListUsers(ctx context.Context, args *ListUserParameters) (*ListUserResult, error) {
query := c.client.User.Query()
if args.GroupID != 0 {
query = query.Where(user.GroupUsers(args.GroupID))
query = query.Where(user.HasGroupWith(group.ID(args.GroupID)))
}
if args.Status != "" {
query = query.Where(user.StatusEQ(args.Status))
@ -482,7 +483,7 @@ func (c *userClient) Upsert(ctx context.Context, u *ent.User, password, twoFa st
SetNick(u.Nick).
SetAvatar(u.Avatar).
SetStatus(u.Status).
SetGroupID(u.GroupUsers).
AddGroup(u.Edges.Group...).
SetPassword(u.Password).
SetSettings(&types.UserSetting{})
@ -502,7 +503,7 @@ func (c *userClient) Upsert(ctx context.Context, u *ent.User, password, twoFa st
SetNick(u.Nick).
SetAvatar(u.Avatar).
SetStatus(u.Status).
SetGroupID(u.GroupUsers)
AddGroup(u.Edges.Group...)
if password != "" {
pwdDigest, err := digestPassword(password)

@ -144,15 +144,7 @@ func WebDAVAuth() gin.HandlerFunc {
}
// 用户组已启用WebDAV
group, err := expectedUser.Edges.GroupOrErr()
if err != nil {
l.Debug("WebDAVAuth: user group not found: %s", err)
c.Status(http.StatusInternalServerError)
c.Abort()
return
}
if !group.Permissions.Enabled(int(types.GroupPermissionWebDAV)) {
if !expectedUser.EnforceGroupPermission(types.GroupPermissionWebDAV) {
c.Status(http.StatusForbidden)
l.Debug("WebDAVAuth: user %q does not have WebDAV permission.", expectedUser.Email)
c.Abort()
@ -262,7 +254,7 @@ func OSSCallbackAuth() gin.HandlerFunc {
func IsAdmin() gin.HandlerFunc {
return func(c *gin.Context) {
user := inventory.UserFromContext(c)
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if !user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
c.JSON(200, serializer.ErrWithDetails(c, serializer.CodeNoPermissionErr, "", nil))
c.Abort()
return

@ -229,13 +229,8 @@ func (f *DBFS) Capacity(ctx context.Context, u *ent.User) (*fs.Capacity, error)
res = &fs.Capacity{}
)
requesterGroup, err := u.Edges.GroupOrErr()
if err != nil {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user's group", err)
}
res.Used = f.user.Storage
res.Total = requesterGroup.MaxStorage
res.Total = f.user.GroupMaxStorage()
return res, nil
}
@ -426,7 +421,7 @@ func (f *DBFS) Get(ctx context.Context, path *fs.URI, opts ...fs.Option) (fs.Fil
}
target.FileExtendedInfo = extendedInfo
if target.OwnerID() == f.user.ID || f.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if target.OwnerID() == f.user.ID || f.user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
target.FileExtendedInfo.Shares = target.Model.Edges.Shares
if target.Model.Props != nil {
target.FileExtendedInfo.View = target.Model.Props.View
@ -463,7 +458,7 @@ func (f *DBFS) Get(ctx context.Context, path *fs.URI, opts ...fs.Option) (fs.Fil
if f.user.Edges.Group == nil {
return nil, fmt.Errorf("user group not loaded")
}
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1)
limit := f.user.GroupMaxWalkedFiles()
// disable load metadata to speed up
ctxWalk := context.WithValue(ctx, inventory.LoadFilePublicMetadata{}, false)
@ -552,7 +547,7 @@ func (f *DBFS) Walk(ctx context.Context, path *fs.URI, depth int, walk fs.WalkFu
if f.user.Edges.Group == nil {
return fmt.Errorf("user group not loaded")
}
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1)
limit := f.user.GroupMaxWalkedFiles()
if err := navigator.Walk(ctx, []*File{target}, limit, depth, func(files []*File, l int) error {
for _, file := range files {
@ -647,7 +642,7 @@ func (f *DBFS) createFile(ctx context.Context, parent *File, name string, fileTy
// getPreferredPolicy tries to get the preferred storage policy for the given file.
func (f *DBFS) getPreferredPolicy(ctx context.Context, file *File) (*ent.StoragePolicy, error) {
ownerGroup := file.Owner().Edges.Group
ownerGroup := file.Owner().GetPrimaryGroup()
if ownerGroup == nil {
return nil, fmt.Errorf("owner group not loaded")
}

@ -290,7 +290,7 @@ func (f *DBFS) SoftDelete(ctx context.Context, path ...*fs.URI) error {
if err := fc.UpsertMetadata(ctx, target.Model, map[string]string{
MetadataRestoreUri: target.Uri(true).String(),
MetadataExpectedCollectTime: strconv.FormatInt(
time.Now().Add(time.Duration(target.Owner().Edges.Group.Settings.TrashRetention)*time.Second).Unix(),
time.Now().Add(time.Duration(target.Owner().GroupMaxTrashRetention())*time.Second).Unix(),
10),
}, nil); err != nil {
_ = inventory.Rollback(tx)
@ -665,7 +665,7 @@ func (f *DBFS) TraverseFile(ctx context.Context, fileID int) (fs.File, error) {
return nil, err
}
if fileModel.OwnerID != f.user.ID && !f.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if fileModel.OwnerID != f.user.ID && !f.user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
return nil, fs.ErrOwnerOnly.WithError(fmt.Errorf("only file owner can traverse file's uri"))
}
@ -800,7 +800,7 @@ func (f *DBFS) copyFiles(ctx context.Context, targets map[Navigator][]*File, des
if f.user.Edges.Group == nil {
return nil, nil, fmt.Errorf("user group not loaded")
}
limit := max(f.user.Edges.Group.Settings.MaxWalkedFiles, 1)
limit := f.user.GroupMaxWalkedFiles()
capacity, err := f.Capacity(ctx, destination.Owner())
if err != nil {
return nil, nil, fmt.Errorf("copy files: failed to destination owner capacity: %w", err)

@ -3,6 +3,7 @@ package dbfs
import (
"context"
"fmt"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/ent"
@ -92,7 +93,7 @@ func (n *myNavigator) To(ctx context.Context, path *fs.URI) (*File, error) {
return nil, fs.ErrPathNotExist.WithError(fmt.Errorf("user not found: %w", err))
}
if targetUser.Status != user.StatusActive && !n.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if targetUser.Status != user.StatusActive && !n.user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
return nil, fs.ErrPathNotExist.WithError(fmt.Errorf("inactive user"))
}

@ -23,7 +23,7 @@ func (f *DBFS) PatchProps(ctx context.Context, uri *fs.URI, props *types.FilePro
return fmt.Errorf("failed to get target file: %w", err)
}
if target.OwnerID() != f.user.ID && !f.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if target.OwnerID() != f.user.ID && !f.user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
return fs.ErrOwnerOnly.WithError(fmt.Errorf("only file owner can modify file props"))
}

@ -156,7 +156,7 @@ func (n *shareNavigator) Root(ctx context.Context, path *fs.URI) (*File, error)
return nil, ErrShareNotFound
}
if n.user.ID != n.owner.ID && !n.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionShareDownload)) {
if n.user.ID != n.owner.ID && !n.user.EnforceGroupPermission(types.GroupPermissionShareDownload) {
if inventory.IsAnonymousUser(n.user) {
return nil, serializer.NewError(
serializer.CodeAnonymouseAccessDenied,

@ -95,8 +95,8 @@ func (m *manager) ListArchiveFiles(ctx context.Context, uri *fs.URI, entity, zip
}
// Validate file size
if m.user.Edges.Group.Settings.DecompressSize > 0 && file.Size() > m.user.Edges.Group.Settings.DecompressSize {
return nil, fs.ErrFileSizeTooBig.WithError(fmt.Errorf("file size %d exceeds the limit %d", file.Size(), m.user.Edges.Group.Settings.DecompressSize))
if m.user.GroupMaxDecompressSize() > 0 && file.Size() > m.user.GroupMaxDecompressSize() {
return nil, fs.ErrFileSizeTooBig.WithError(fmt.Errorf("file size %d exceeds the limit %d", file.Size(), m.user.GroupMaxDecompressSize()))
}
found, targetEntity := fs.FindDesiredEntity(file, entity, m.hasher, nil)

@ -61,7 +61,7 @@ type (
func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectLink, error) {
ae := serializer.NewAggregateError()
res := make([]DirectLink, 0, len(urls))
useRedirect := m.user.Edges.Group.Settings.RedirectedSource
useRedirect := m.user.GetPrimaryGroup().Settings.RedirectedSource
fileClient := m.dep.FileClient()
siteUrl := m.settings.SiteURL(ctx)
@ -76,7 +76,7 @@ func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectL
continue
}
if file.OwnerID() != m.user.ID && !m.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if file.OwnerID() != m.user.ID && !m.user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
ae.Add(url.String(), fs.ErrOwnerOnly)
continue
}
@ -98,9 +98,9 @@ func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectL
}
if useRedirect {
reuseExisting := !m.user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionUniqueRedirectDirectLink))
reuseExisting := !m.user.EnforceGroupPermission(types.GroupPermissionUniqueRedirectDirectLink)
// Use redirect source
link, err := fileClient.CreateDirectLink(ctx, file.ID(), file.Name(), m.user.Edges.Group.SpeedLimit, reuseExisting)
link, err := fileClient.CreateDirectLink(ctx, file.ID(), file.Name(), m.user.GroupMaxSpeedLimit(), reuseExisting)
if err != nil {
ae.Add(url.String(), err)
continue
@ -122,7 +122,7 @@ func (m *manager) GetDirectLink(ctx context.Context, urls ...*fs.URI) ([]DirectL
source := entitysource.NewEntitySource(target, d, policy, m.auth, m.settings, m.hasher, m.dep.RequestClient(),
m.l, m.config, m.dep.MimeDetector(ctx))
sourceUrl, err := source.Url(ctx,
entitysource.WithSpeedLimit(int64(m.user.Edges.Group.SpeedLimit)),
entitysource.WithSpeedLimit(int64(m.user.GroupMaxSpeedLimit())),
entitysource.WithDisplayName(file.Name()),
)
if err != nil {

@ -233,7 +233,7 @@ func (m *CreateArchiveTask) listEntitiesAndSendToSlave(ctx context.Context, dep
}
}
}),
fs.WithMaxArchiveSize(user.Edges.Group.Settings.CompressSize),
fs.WithMaxArchiveSize(user.GroupMaxCompressSize()),
)
if err != nil {
return task.StatusError, fmt.Errorf("failed to compress files: %w", err)
@ -390,7 +390,7 @@ func (m *CreateArchiveTask) createArchiveFile(ctx context.Context, dep dependenc
m.Unlock()
failed, err := fm.CreateArchive(ctx, uris, zipFile,
fs.WithArchiveCompression(true),
fs.WithMaxArchiveSize(user.Edges.Group.Settings.CompressSize),
fs.WithMaxArchiveSize(user.GroupMaxCompressSize()),
fs.WithProgressFunc(func(current, diff int64, total int64) {
atomic.AddInt64(&m.progress[ProgressTypeArchiveSize].Current, diff)
atomic.AddInt64(&m.progress[ProgressTypeArchiveCount].Current, 1)

@ -182,9 +182,9 @@ func (m *ExtractArchiveTask) createSlaveExtractTask(ctx context.Context, dep dep
}
// Validate file size
if user.Edges.Group.Settings.DecompressSize > 0 && archiveFile.Size() > user.Edges.Group.Settings.DecompressSize {
if user.GroupMaxDecompressSize() > 0 && archiveFile.Size() > user.GroupMaxDecompressSize() {
return task.StatusError,
fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), user.Edges.Group.Settings.DecompressSize, queue.CriticalErr)
fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), user.GroupMaxDecompressSize(), queue.CriticalErr)
}
// Create slave task
@ -269,9 +269,9 @@ func (m *ExtractArchiveTask) masterExtractArchive(ctx context.Context, dep depen
}
// Validate file size
if user.Edges.Group.Settings.DecompressSize > 0 && archiveFile.Size() > user.Edges.Group.Settings.DecompressSize {
if user.GroupMaxDecompressSize() > 0 && archiveFile.Size() > user.GroupMaxDecompressSize() {
return task.StatusError,
fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), user.Edges.Group.Settings.DecompressSize, queue.CriticalErr)
fmt.Errorf("file size %d exceeds the limit %d (%w)", archiveFile.Size(), user.GroupMaxDecompressSize(), queue.CriticalErr)
}
es, err := fm.GetEntitySource(ctx, 0, fs.WithEntity(archiveFile.PrimaryEntity()))

@ -199,7 +199,7 @@ func (m *RemoteDownloadTask) createDownloadTask(ctx context.Context, dep depende
}
// Create download task
handle, err := m.d.CreateTask(ctx, torrentUrl, user.Edges.Group.Settings.RemoteDownloadOptions)
handle, err := m.d.CreateTask(ctx, torrentUrl, user.GetPrimaryGroup().Settings.RemoteDownloadOptions)
if err != nil {
return task.StatusError, fmt.Errorf("failed to create download task: %w", err)
}

@ -347,10 +347,10 @@ func handleGetHeadPost(c *gin.Context, user *ent.User, fm manager.FileManager) (
defer es.Close()
es.Apply(entitysource.WithSpeedLimit(int64(user.Edges.Group.SpeedLimit)))
es.Apply(entitysource.WithSpeedLimit(int64(user.GroupMaxSpeedLimit())))
if es.ShouldInternalProxy() ||
(user.Edges.DavAccounts[0].Options.Enabled(int(types.DavAccountProxy)) &&
user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionWebDAVProxy))) {
user.EnforceGroupPermission(types.GroupPermissionWebDAVProxy)) {
es.Serve(c.Writer, c.Request)
} else {
settings := dependency.FromContext(c).SettingProvider()

@ -2,7 +2,9 @@ package admin
import (
"context"
"slices"
"strconv"
"unicode/utf8"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/ent"
@ -154,8 +156,10 @@ func (s *UpsertUserService) Update(c *gin.Context) (*GetUserResponse, error) {
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user", err)
}
if s.User.ID == 1 && existing.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if s.User.GroupUsers != existing.GroupUsers {
if s.User.ID == 1 && existing.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
if !slices.EqualFunc(s.User.Edges.Group, existing.Edges.Group, func(a *ent.Group, b *ent.Group) bool {
return a.ID == b.ID
}) {
return nil, serializer.NewError(serializer.CodeInvalidActionOnDefaultUser, "Cannot change default user's group", nil)
}
@ -165,7 +169,7 @@ func (s *UpsertUserService) Update(c *gin.Context) (*GetUserResponse, error) {
}
if s.Password != "" && len(s.Password) > 128 {
if s.Password != "" && utf8.RuneCountInString(s.Password) > 128 {
return nil, serializer.NewError(serializer.CodeParamErr, "Password too long", nil)
}

@ -100,11 +100,11 @@ func (s *GetDirectLinkService) Get(c *gin.Context) ([]DirectLinkResponse, error)
dep := dependency.FromContext(c)
u := inventory.UserFromContext(c)
if u.Edges.Group.Settings.SourceBatchSize == 0 {
if u.GroupMaxSourceBatchSize() == 0 {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "", nil)
}
if len(s.Uris) > u.Edges.Group.Settings.SourceBatchSize {
if len(s.Uris) > u.GroupMaxSourceBatchSize() {
return nil, serializer.NewError(serializer.CodeBatchSourceSize, "", nil)
}
@ -394,7 +394,7 @@ func (s *FileURLService) GetArchiveDownloadSession(c *gin.Context) (*FileURLResp
return nil, serializer.NewError(serializer.CodeParamErr, "unknown uri", err)
}
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveDownload)) {
if !user.EnforceGroupPermission(types.GroupPermissionArchiveDownload) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "", nil)
}
@ -454,7 +454,7 @@ func (s *FileURLService) Get(c *gin.Context) (*FileURLResponse, error) {
}
res, earliestExpire, err := m.GetEntityUrls(ctx, urlReq,
fs.WithDownloadSpeed(int64(user.Edges.Group.SpeedLimit)),
fs.WithDownloadSpeed(int64(user.GroupMaxSpeedLimit())),
fs.WithIsDownload(s.Download),
fs.WithNoCache(s.NoCache),
fs.WithUrlExpire(&expire),
@ -547,7 +547,7 @@ func (s *DeleteFileService) Delete(c *gin.Context) error {
return serializer.NewError(serializer.CodeParamErr, "unknown uri", err)
}
if s.UnlinkOnly && !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionAdvanceDelete)) {
if s.UnlinkOnly && !user.EnforceGroupPermission(types.GroupPermissionAdvanceDelete) {
return serializer.NewError(serializer.CodeNoPermissionErr, "advance delete permission is required", nil)
}
@ -731,7 +731,7 @@ func (s *ArchiveListFilesService) List(c *gin.Context) (*ArchiveListFilesRespons
user := inventory.UserFromContext(c)
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveTask)) {
if !user.EnforceGroupPermission(types.GroupPermissionArchiveTask) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to extract archive files", nil)
}

@ -2,9 +2,10 @@ package explorer
import (
"encoding/gob"
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
"time"
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/ent/task"
@ -85,7 +86,7 @@ func (service *DownloadWorkflowService) CreateDownloadTask(c *gin.Context) ([]*T
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionRemoteDownload)) {
if !user.EnforceGroupPermission(types.GroupPermissionRemoteDownload) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to download files", nil)
}
@ -111,7 +112,7 @@ func (service *DownloadWorkflowService) CreateDownloadTask(c *gin.Context) ([]*T
}
// 检查批量任务数量
limit := user.Edges.Group.Settings.Aria2BatchSize
limit := user.GroupMaxAria2BatchSize()
if limit > 0 && len(service.Src) > limit {
return nil, serializer.NewError(serializer.CodeBatchAria2Size, "", nil)
}
@ -186,7 +187,7 @@ func (service *ArchiveWorkflowService) CreateExtractTask(c *gin.Context) (*TaskR
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveTask)) {
if !user.EnforceGroupPermission(types.GroupPermissionArchiveTask) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to compress files", nil)
}
@ -225,7 +226,7 @@ func (service *ArchiveWorkflowService) CreateCompressTask(c *gin.Context) (*Task
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionArchiveTask)) {
if !user.EnforceGroupPermission(types.GroupPermissionArchiveTask) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Group not allowed to compress files", nil)
}
@ -280,7 +281,7 @@ func (service *ImportWorkflowService) CreateImportTask(c *gin.Context) (*TaskRes
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if !user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "Only admin can import files", nil)
}
@ -388,7 +389,7 @@ func TaskPhaseProgress(c *gin.Context, taskID int) (queue.Progresses, error) {
u := inventory.UserFromContext(c)
r := dep.TaskRegistry()
t, found := r.Get(taskID)
if !found || (t.Owner().ID != u.ID && !u.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin))) {
if !found || (t.Owner().ID != u.ID && !u.EnforceGroupPermission(types.GroupPermissionIsAdmin)) {
return queue.Progresses{}, nil
}

@ -154,7 +154,7 @@ func (service *CreateDavAccountService) Update(c *gin.Context) (*DavAccount, err
}
func (service *CreateDavAccountService) validateAndGetBs(user *ent.User) (*boolset.BooleanSet, error) {
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionWebDAV)) {
if !user.EnforceGroupPermission(types.GroupPermissionWebDAV) {
return nil, serializer.NewError(serializer.CodeGroupNotAllowed, "WebDAV is not enabled for this user group", nil)
}
@ -178,7 +178,7 @@ func (service *CreateDavAccountService) validateAndGetBs(user *ent.User) (*bools
boolset.Set(types.DavAccountDisableSysFiles, true, &bs)
}
if service.Proxy && user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionWebDAVProxy)) {
if service.Proxy && user.EnforceGroupPermission(types.GroupPermissionWebDAVProxy) {
boolset.Set(types.DavAccountProxy, true, &bs)
}
return &bs, nil

@ -37,7 +37,7 @@ func (service *ShareCreateService) Upsert(c *gin.Context, existed int) (string,
defer m.Recycle()
// Check group permission for creating share link
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionShare)) {
if !user.EnforceGroupPermission(types.GroupPermissionShare) {
return "", serializer.NewError(serializer.CodeGroupNotAllowed, "Group permission denied", nil)
}
@ -79,7 +79,7 @@ func DeleteShare(c *gin.Context, shareId int) error {
share *ent.Share
err error
)
if user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
if user.EnforceGroupPermission(types.GroupPermissionIsAdmin) {
share, err = shareClient.GetByID(ctx, shareId)
} else {
share, err = shareClient.GetByIDUser(ctx, shareId, user.ID)

@ -107,7 +107,7 @@ type User struct {
CreatedAt time.Time `json:"created_at"`
PreferredTheme string `json:"preferred_theme,omitempty"`
Anonymous bool `json:"anonymous,omitempty"`
Group *Group `json:"group,omitempty"`
Groups []*Group `json:"groups,omitempty"`
Pined []types.PinedFile `json:"pined,omitempty"`
Language string `json:"language,omitempty"`
DisableViewSync bool `json:"disable_view_sync,omitempty"`
@ -156,15 +156,17 @@ func BuildWebAuthnList(credentials []webauthn.Credential) []WebAuthnCredentials
// BuildUser 序列化用户
func BuildUser(user *ent.User, idEncoder hashid.Encoder) User {
return User{
ID: hashid.EncodeUserID(idEncoder, user.ID),
Email: user.Email,
Nickname: user.Nick,
Status: user.Status,
Avatar: user.Avatar,
CreatedAt: user.CreatedAt,
PreferredTheme: user.Settings.PreferredTheme,
Anonymous: user.ID == 0,
Group: BuildGroup(user.Edges.Group, idEncoder),
ID: hashid.EncodeUserID(idEncoder, user.ID),
Email: user.Email,
Nickname: user.Nick,
Status: user.Status,
Avatar: user.Avatar,
CreatedAt: user.CreatedAt,
PreferredTheme: user.Settings.PreferredTheme,
Anonymous: user.ID == 0,
Groups: lo.Map(user.Edges.Group, func(item *ent.Group, index int) *Group {
return BuildGroup(item, idEncoder)
}),
Pined: user.Settings.Pined,
Language: user.Settings.Language,
DisableViewSync: user.Settings.DisableViewSync,
@ -202,10 +204,9 @@ func BuildUserRedacted(u *ent.User, level int, idEncoder hashid.Encoder) User {
Avatar: userRaw.Avatar,
CreatedAt: userRaw.CreatedAt,
ShareLinksInProfile: userRaw.ShareLinksInProfile,
}
if userRaw.Group != nil {
user.Group = RedactedGroup(userRaw.Group)
Groups: lo.Map(userRaw.Groups, func(item *Group, level int) *Group {
return RedactedGroup(item)
}),
}
if level == RedactLevelUser {

Loading…
Cancel
Save