diff --git a/internal/model/meta.go b/internal/model/meta.go index a0841ddd..45ad8fed 100644 --- a/internal/model/meta.go +++ b/internal/model/meta.go @@ -4,7 +4,7 @@ type Meta struct { ID uint `json:"id" gorm:"primaryKey"` Path string `json:"path" gorm:"unique" binding:"required"` Password string `json:"password"` - Upload bool `json:"upload"` + Write bool `json:"upload"` Hide string `json:"hide"` SubFolder bool `json:"sub_folder"` Readme string `json:"readme"` diff --git a/internal/model/user.go b/internal/model/user.go index 5b4cab2c..ba18d831 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -21,6 +21,7 @@ type User struct { Role int `json:"role"` // user's role IgnoreHide bool `json:"can_hide"` // can see hide files IgnorePassword bool `json:"ignore_password"` // can access without password + Aira2 bool `json:"aira_2"` // can add aria2 tasks } func (u User) IsGuest() bool { @@ -40,3 +41,7 @@ func (u User) ValidatePassword(password string) error { } return nil } + +func (u User) CanWrite() bool { + return u.IsAdmin() || !u.ReadOnly +} diff --git a/server/controllers/fsmanage.go b/server/controllers/fsmanage.go index f50344fd..98d82f21 100644 --- a/server/controllers/fsmanage.go +++ b/server/controllers/fsmanage.go @@ -2,6 +2,7 @@ package controllers import ( "fmt" + "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/sign" @@ -24,6 +25,17 @@ func FsMkdir(c *gin.Context) { } user := c.MustGet("user").(*model.User) req.Path = stdpath.Join(user.BasePath, req.Path) + if !user.CanWrite() { + meta, err := db.GetNearestMeta(req.Path) + if err != nil { + common.ErrorResp(c, err, 500) + return + } + if !canMkdirOrPut(meta, req.Path) { + common.ErrorStrResp(c, "Permission denied", 403) + return + } + } if err := fs.MakeDir(c, req.Path); err != nil { common.ErrorResp(c, err, 500) return @@ -31,6 +43,13 @@ func FsMkdir(c *gin.Context) { common.SuccessResp(c) } +func canMkdirOrPut(meta *model.Meta, path string) bool { + if meta == nil || !meta.Write { + return false + } + return meta.SubFolder || meta.Path == path +} + type MoveCopyReq struct { SrcDir string `json:"src_dir"` DstDir string `json:"dst_dir"` @@ -142,6 +161,18 @@ func FsPut(c *gin.Context) { path := c.GetHeader("File-Path") user := c.MustGet("user").(*model.User) path = stdpath.Join(user.BasePath, path) + if !user.CanWrite() { + meta, err := db.GetNearestMeta(path) + if err != nil { + common.ErrorResp(c, err, 500) + return + } + if !canMkdirOrPut(meta, path) { + common.ErrorStrResp(c, "Permission denied", 403) + return + } + } + dir, name := stdpath.Split(path) sizeStr := c.GetHeader("Content-Length") size, err := strconv.ParseInt(sizeStr, 10, 64) @@ -164,9 +195,9 @@ func FsPut(c *gin.Context) { common.SuccessResp(c) } -// Link return real link, just for proxy program +// Link return real link, just for proxy program, it may contain cookie func Link(c *gin.Context) { - var req MkdirOrLinkReq + var req FsGetOrLinkReq if err := c.ShouldBind(&req); err != nil { common.ErrorResp(c, err, 400) return diff --git a/server/controllers/fsread.go b/server/controllers/fsread.go index 680e02ae..548b5ad1 100644 --- a/server/controllers/fsread.go +++ b/server/controllers/fsread.go @@ -114,7 +114,7 @@ func toObjResp(objs []model.Obj) []ObjResp { return resp } -type FsGetReq struct { +type FsGetOrLinkReq struct { Path string `json:"path" form:"path"` Password string `json:"password" form:"password"` } @@ -125,7 +125,7 @@ type FsGetResp struct { } func FsGet(c *gin.Context) { - var req FsGetReq + var req FsGetOrLinkReq if err := c.ShouldBind(&req); err != nil { common.ErrorResp(c, err, 400) return diff --git a/server/middlewares/auth.go b/server/middlewares/auth.go index 093c5273..38abe0ac 100644 --- a/server/middlewares/auth.go +++ b/server/middlewares/auth.go @@ -61,12 +61,12 @@ func AuthAdmin(c *gin.Context) { } } -func AuthWrite(c *gin.Context) { +func AuthManage(c *gin.Context) { user := c.MustGet("user").(*model.User) - if !user.IsAdmin() && user.ReadOnly { - common.ErrorStrResp(c, "You have no write access", 403) - c.Abort() - } else { + if user.CanWrite() { c.Next() + return } + common.ErrorStrResp(c, "You have no write access", 403) + c.Abort() } diff --git a/server/router.go b/server/router.go index c0fcfc80..f0fd6345 100644 --- a/server/router.go +++ b/server/router.go @@ -57,14 +57,14 @@ func Init(r *gin.Engine) { public.Any("/list", controllers.FsList) public.Any("/get", controllers.FsGet) - fs := api.Group("/fs", middlewares.AuthWrite) + fs := api.Group("/fs") fs.POST("/mkdir", controllers.FsMkdir) - fs.POST("/rename", controllers.FsRename) - fs.POST("/move", controllers.FsMove) - fs.POST("/copy", controllers.FsCopy) - fs.POST("/remove", controllers.FsRemove) + fs.POST("/rename", middlewares.AuthManage, controllers.FsRename) + fs.POST("/move", middlewares.AuthManage, controllers.FsMove) + fs.POST("/copy", middlewares.AuthManage, controllers.FsCopy) + fs.POST("/remove", middlewares.AuthManage, controllers.FsRemove) fs.POST("/put", controllers.FsPut) - fs.POST("/link", controllers.Link) + fs.POST("/link", middlewares.AuthAdmin, controllers.Link) } func Cors(r *gin.Engine) {