chore: change permission check

refactor/fs
Noah Hsu 2022-06-29 17:08:31 +08:00
parent bf950ee6e1
commit a09a1b814b
6 changed files with 52 additions and 16 deletions

View File

@ -4,7 +4,7 @@ type Meta struct {
ID uint `json:"id" gorm:"primaryKey"` ID uint `json:"id" gorm:"primaryKey"`
Path string `json:"path" gorm:"unique" binding:"required"` Path string `json:"path" gorm:"unique" binding:"required"`
Password string `json:"password"` Password string `json:"password"`
Upload bool `json:"upload"` Write bool `json:"upload"`
Hide string `json:"hide"` Hide string `json:"hide"`
SubFolder bool `json:"sub_folder"` SubFolder bool `json:"sub_folder"`
Readme string `json:"readme"` Readme string `json:"readme"`

View File

@ -21,6 +21,7 @@ type User struct {
Role int `json:"role"` // user's role Role int `json:"role"` // user's role
IgnoreHide bool `json:"can_hide"` // can see hide files IgnoreHide bool `json:"can_hide"` // can see hide files
IgnorePassword bool `json:"ignore_password"` // can access without password IgnorePassword bool `json:"ignore_password"` // can access without password
Aira2 bool `json:"aira_2"` // can add aria2 tasks
} }
func (u User) IsGuest() bool { func (u User) IsGuest() bool {
@ -40,3 +41,7 @@ func (u User) ValidatePassword(password string) error {
} }
return nil return nil
} }
func (u User) CanWrite() bool {
return u.IsAdmin() || !u.ReadOnly
}

View File

@ -2,6 +2,7 @@ package controllers
import ( import (
"fmt" "fmt"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/internal/sign"
@ -24,6 +25,17 @@ func FsMkdir(c *gin.Context) {
} }
user := c.MustGet("user").(*model.User) user := c.MustGet("user").(*model.User)
req.Path = stdpath.Join(user.BasePath, req.Path) 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 { if err := fs.MakeDir(c, req.Path); err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
@ -31,6 +43,13 @@ func FsMkdir(c *gin.Context) {
common.SuccessResp(c) 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 { type MoveCopyReq struct {
SrcDir string `json:"src_dir"` SrcDir string `json:"src_dir"`
DstDir string `json:"dst_dir"` DstDir string `json:"dst_dir"`
@ -142,6 +161,18 @@ func FsPut(c *gin.Context) {
path := c.GetHeader("File-Path") path := c.GetHeader("File-Path")
user := c.MustGet("user").(*model.User) user := c.MustGet("user").(*model.User)
path = stdpath.Join(user.BasePath, path) 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) dir, name := stdpath.Split(path)
sizeStr := c.GetHeader("Content-Length") sizeStr := c.GetHeader("Content-Length")
size, err := strconv.ParseInt(sizeStr, 10, 64) size, err := strconv.ParseInt(sizeStr, 10, 64)
@ -164,9 +195,9 @@ func FsPut(c *gin.Context) {
common.SuccessResp(c) 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) { func Link(c *gin.Context) {
var req MkdirOrLinkReq var req FsGetOrLinkReq
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400) common.ErrorResp(c, err, 400)
return return

View File

@ -114,7 +114,7 @@ func toObjResp(objs []model.Obj) []ObjResp {
return resp return resp
} }
type FsGetReq struct { type FsGetOrLinkReq struct {
Path string `json:"path" form:"path"` Path string `json:"path" form:"path"`
Password string `json:"password" form:"password"` Password string `json:"password" form:"password"`
} }
@ -125,7 +125,7 @@ type FsGetResp struct {
} }
func FsGet(c *gin.Context) { func FsGet(c *gin.Context) {
var req FsGetReq var req FsGetOrLinkReq
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400) common.ErrorResp(c, err, 400)
return return

View File

@ -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) user := c.MustGet("user").(*model.User)
if !user.IsAdmin() && user.ReadOnly { if user.CanWrite() {
c.Next()
return
}
common.ErrorStrResp(c, "You have no write access", 403) common.ErrorStrResp(c, "You have no write access", 403)
c.Abort() c.Abort()
} else {
c.Next()
}
} }

View File

@ -57,14 +57,14 @@ func Init(r *gin.Engine) {
public.Any("/list", controllers.FsList) public.Any("/list", controllers.FsList)
public.Any("/get", controllers.FsGet) public.Any("/get", controllers.FsGet)
fs := api.Group("/fs", middlewares.AuthWrite) fs := api.Group("/fs")
fs.POST("/mkdir", controllers.FsMkdir) fs.POST("/mkdir", controllers.FsMkdir)
fs.POST("/rename", controllers.FsRename) fs.POST("/rename", middlewares.AuthManage, controllers.FsRename)
fs.POST("/move", controllers.FsMove) fs.POST("/move", middlewares.AuthManage, controllers.FsMove)
fs.POST("/copy", controllers.FsCopy) fs.POST("/copy", middlewares.AuthManage, controllers.FsCopy)
fs.POST("/remove", controllers.FsRemove) fs.POST("/remove", middlewares.AuthManage, controllers.FsRemove)
fs.POST("/put", controllers.FsPut) fs.POST("/put", controllers.FsPut)
fs.POST("/link", controllers.Link) fs.POST("/link", middlewares.AuthAdmin, controllers.Link)
} }
func Cors(r *gin.Engine) { func Cors(r *gin.Engine) {