Skip to content

Commit

Permalink
feat: obj list api
Browse files Browse the repository at this point in the history
  • Loading branch information
xhofe committed Jun 27, 2022
1 parent c6007aa commit 7c0b86a
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 24 deletions.
5 changes: 5 additions & 0 deletions internal/bootstrap/data/data.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package data

import "github.com/alist-org/alist/v3/cmd/args"

func InitData() {
initUser()
initSettings()
if args.Dev {
initDevData()
}
}
21 changes: 21 additions & 0 deletions internal/bootstrap/data/dev.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package data

import (
"context"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/operations"
log "github.com/sirupsen/logrus"
)

func initDevData() {
err := operations.CreateAccount(context.Background(), model.Account{
VirtualPath: "/",
Index: 0,
Driver: "Local",
Status: "",
Addition: `{"root_folder":"."}`,
})
if err != nil {
log.Fatalf("failed to create account: %+v", err)
}
}
3 changes: 1 addition & 2 deletions internal/fs/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package fs

import (
"context"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/operations"
"github.com/alist-org/alist/v3/pkg/utils"
Expand All @@ -13,7 +12,7 @@ import (
// List files
// TODO: sort
func list(ctx context.Context, path string) ([]model.Obj, error) {
meta, _ := db.GetNearestMeta(path)
meta := ctx.Value("meta").(*model.Meta)
user := ctx.Value("user").(*model.User)
account, actualPath, err := operations.GetAccountAndActualPath(path)
virtualFiles := operations.GetAccountVirtualFilesByPath(path)
Expand Down
17 changes: 0 additions & 17 deletions internal/fs/util.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package fs

import (
"github.com/alist-org/alist/v3/pkg/utils"
"io"
"mime"
"net/http"
Expand Down Expand Up @@ -64,19 +63,3 @@ func getFileStreamFromLink(file model.Obj, link *model.Link) (model.FileStreamer
}
return stream, nil
}

func canAccess(user *model.User, meta *model.Meta, path string) bool {
// if is not guest, can access
if user.IsAdmin() || user.IgnorePassword {
return true
}
// if meta is nil or password is empty, can access
if meta == nil || meta.Password == "" {
return true
}
// if meta doesn't apply to sub_folder, can access
if !utils.PathEqual(meta.Path, path) && !meta.SubFolder {
return true
}
return false
}
5 changes: 4 additions & 1 deletion internal/operations/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ func GetAccountVirtualFilesByPath(prefix string) []model.Obj {
return accounts[i].GetAccount().Index < accounts[j].GetAccount().Index
})
prefix = utils.StandardizePath(prefix)
if prefix == "/" {
prefix = ""
}
set := make(map[string]interface{})
for _, v := range accounts {
// TODO should save a balanced account
Expand All @@ -197,7 +200,7 @@ func GetAccountVirtualFilesByPath(prefix string) []model.Obj {
continue
}
// not prefixed with `prefix`
if !strings.HasPrefix(virtualPath, prefix+"/") && prefix != "/" {
if !strings.HasPrefix(virtualPath, prefix+"/") {
continue
}
name := strings.Split(strings.TrimPrefix(virtualPath, prefix), "/")[1]
Expand Down
6 changes: 3 additions & 3 deletions internal/operations/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ func TestCreateAccount(t *testing.T) {
account model.Account
iserr bool
}{
{account: model.Account{Driver: "Local", VirtualPath: "/local", Addition: "{}"}, iserr: false},
{account: model.Account{Driver: "Local", VirtualPath: "/local", Addition: "{}"}, iserr: true},
{account: model.Account{Driver: "None", VirtualPath: "/none", Addition: "{}"}, iserr: true},
{account: model.Account{Driver: "Local", VirtualPath: "/local", Addition: `{"root_folder":"."}`}, iserr: false},
{account: model.Account{Driver: "Local", VirtualPath: "/local", Addition: `{"root_folder":"."}`}, iserr: true},
{account: model.Account{Driver: "None", VirtualPath: "/none", Addition: `{"root_folder":"."}`}, iserr: true},
}
for _, account := range accounts {
err := operations.CreateAccount(context.Background(), account.account)
Expand Down
15 changes: 14 additions & 1 deletion internal/operations/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var filesG singleflight.Group[[]model.Obj]

// List files in storage, not contains virtual file
func List(ctx context.Context, account driver.Driver, path string, refresh ...bool) ([]model.Obj, error) {
log.Debugf("operations.List %s", path)
dir, err := Get(ctx, account, path)
if err != nil {
return nil, errors.WithMessage(err, "failed get dir")
Expand Down Expand Up @@ -51,8 +52,20 @@ func List(ctx context.Context, account driver.Driver, path string, refresh ...bo
return files, err
}

func isRoot(path, rootFolderPath string) bool {
if utils.PathEqual(path, rootFolderPath) {
return true
}
// relative path
if utils.PathEqual(path, "/") && rootFolderPath == "." {
return true
}
return false
}

// Get object from list of files
func Get(ctx context.Context, account driver.Driver, path string) (model.Obj, error) {
log.Debugf("operations.Get %s", path)
// is root folder
if r, ok := account.GetAddition().(driver.IRootFolderId); ok && utils.PathEqual(path, "/") {
return model.Object{
Expand All @@ -63,7 +76,7 @@ func Get(ctx context.Context, account driver.Driver, path string) (model.Obj, er
IsFolder: true,
}, nil
}
if r, ok := account.GetAddition().(driver.IRootFolderPath); ok && utils.PathEqual(path, r.GetRootFolderPath()) {
if r, ok := account.GetAddition().(driver.IRootFolderPath); ok && isRoot(path, r.GetRootFolderPath()) {
return model.Object{
ID: r.GetRootFolderPath(),
Name: "root",
Expand Down
9 changes: 9 additions & 0 deletions server/common/req.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@ type PageReq struct {
PageIndex int `json:"page_index" form:"page_index"`
PageSize int `json:"page_size" form:"page_size"`
}

func (p *PageReq) Validate() {
if p.PageIndex < 1 {
p.PageIndex = 1
}
if p.PageSize < 1 {
p.PageSize = 50
}
}
99 changes: 99 additions & 0 deletions server/controllers/fslist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package controllers

import (
"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/pkg/utils"
"github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin"
"time"
)

type ListReq struct {
common.PageReq
Path string `json:"path" form:"path"`
Password string `json:"password" form:"password"`
}

type ObjResp struct {
Name string `json:"name"`
Size int64 `json:"size"`
IsDir bool `json:"is_dir"`
Modified time.Time `json:"modified"`
}

type ListResp struct {
Content []ObjResp `json:"content"`
Total int64 `json:"total"`
}

func List(c *gin.Context) {
var req ListReq
if err := c.ShouldBind(&req); err != nil {
common.ErrorResp(c, err, 400)
return
}
req.Validate()
user := c.MustGet("user").(*model.User)
meta, _ := db.GetNearestMeta(req.Path)
c.Set("meta", meta)
if !canAccess(user, meta, req.Path, req.Password) {
common.ErrorStrResp(c, "password is incorrect", 401)
return
}
objs, err := fs.List(c, req.Path)
if err != nil {
common.ErrorResp(c, err, 500, true)
return
}
total, objs := pagination(objs, &req.PageReq)
common.SuccessResp(c, ListResp{
Content: toObjResp(objs),
Total: int64(total),
})
}

func canAccess(user *model.User, meta *model.Meta, path string, password string) bool {
// if is not guest, can access
if user.IsAdmin() || user.IgnorePassword {
return true
}
// if meta is nil or password is empty, can access
if meta == nil || meta.Password == "" {
return true
}
// if meta doesn't apply to sub_folder, can access
if !utils.PathEqual(meta.Path, path) && !meta.SubFolder {
return true
}
// validate password
return meta.Password == password
}

func pagination(objs []model.Obj, req *common.PageReq) (int, []model.Obj) {
pageIndex, pageSize := req.PageIndex, req.PageSize
total := len(objs)
start := (pageIndex - 1) * pageSize
if start > total {
return total, []model.Obj{}
}
end := start + pageSize
if end > total {
end = total
}
return total, objs[start:end]
}

func toObjResp(objs []model.Obj) []ObjResp {
var resp []ObjResp
for _, obj := range objs {
resp = append(resp, ObjResp{
Name: obj.GetName(),
Size: obj.GetSize(),
IsDir: obj.IsDir(),
Modified: obj.ModTime(),
})
}
return resp
}
1 change: 1 addition & 0 deletions server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func Init(r *gin.Engine) {

public := api.Group("/public")
public.GET("/settings", controllers.PublicSettings)
public.GET("/list", controllers.List)
}

func Cors(r *gin.Engine) {
Expand Down

0 comments on commit 7c0b86a

Please sign in to comment.