From 252456a1cd0f427d869bccd7986b918795b64a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Sun, 19 May 2024 04:18:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/http/controllers/file_controller.go | 40 +++++++++++++++++++++++-- app/http/requests/file/exist.go | 2 +- app/models/cert.go | 2 -- docs/docs.go | 10 +++++++ docs/swagger.json | 10 +++++++ docs/swagger.yaml | 6 ++++ pkg/tools/system.go | 25 ++++++++++++++++ 7 files changed, 90 insertions(+), 5 deletions(-) diff --git a/app/http/controllers/file_controller.go b/app/http/controllers/file_controller.go index a0f5e3ab..242f71eb 100644 --- a/app/http/controllers/file_controller.go +++ b/app/http/controllers/file_controller.go @@ -6,9 +6,11 @@ import ( "os" "path/filepath" "strings" + "syscall" "github.com/goravel/framework/contracts/http" "github.com/goravel/framework/support/carbon" + commonrequests "panel/app/http/requests/common" requests "panel/app/http/requests/file" "panel/pkg/tools" @@ -454,7 +456,8 @@ func (r *FileController) Search(ctx http.Context) http.Response { // @Tags 文件管理 // @Accept json // @Produce json -// @Param data query requests.Exist true "request" +// @Param data query requests.Exist true "request" +// @Param data query commonrequests.Paginate true "request" // @Success 200 {object} SuccessResponse // @Router /panel/file/list [get] func (r *FileController) List(ctx http.Context) http.Response { @@ -464,6 +467,12 @@ func (r *FileController) List(ctx http.Context) http.Response { return sanitize } + var paginate commonrequests.Paginate + paginateSanitize := Sanitize(ctx, &paginate) + if paginateSanitize != nil { + return paginateSanitize + } + fileInfoList, err := os.ReadDir(request.Path) if err != nil { return Error(ctx, http.StatusInternalServerError, err.Error()) @@ -472,17 +481,44 @@ func (r *FileController) List(ctx http.Context) http.Response { var paths []any for _, fileInfo := range fileInfoList { info, _ := fileInfo.Info() + var owner, group string + stat, ok := info.Sys().(*syscall.Stat_t) + if ok { + owner = tools.GetUser(stat.Uid) + group = tools.GetGroup(stat.Gid) + } + paths = append(paths, map[string]any{ "name": info.Name(), + "full": filepath.Join(request.Path, info.Name()), "size": tools.FormatBytes(float64(info.Size())), "mode_str": info.Mode().String(), "mode": fmt.Sprintf("%04o", info.Mode().Perm()), + "owner": owner, + "group": group, "dir": info.IsDir(), "modify": carbon.FromStdTime(info.ModTime()).ToDateTimeString(), }) } - return Success(ctx, paths) + start := paginate.Limit * (paginate.Page - 1) + end := paginate.Limit * paginate.Page + if start > len(paths) { + start = len(paths) + } + if end > len(paths) { + end = len(paths) + } + + paged := paths[start:end] + if paged == nil { + paged = []any{} + } + + return Success(ctx, http.Json{ + "total": len(paths), + "items": paged, + }) } // setPermission diff --git a/app/http/requests/file/exist.go b/app/http/requests/file/exist.go index 153db043..25d312aa 100644 --- a/app/http/requests/file/exist.go +++ b/app/http/requests/file/exist.go @@ -15,7 +15,7 @@ func (r *Exist) Authorize(ctx http.Context) error { func (r *Exist) Rules(ctx http.Context) map[string]string { return map[string]string{ - "path": "regex:^/[a-zA-Z0-9_.@#$%-]+(\\/[a-zA-Z0-9_.@#$%-]+)*$|path_exists", + "path": "regex:^/([a-zA-Z0-9_.@#$%-]+(\\/[a-zA-Z0-9_.@#$%-]+)*)?$|path_exists", } } diff --git a/app/models/cert.go b/app/models/cert.go index 097de666..d013fd50 100644 --- a/app/models/cert.go +++ b/app/models/cert.go @@ -1,12 +1,10 @@ package models import ( - "github.com/goravel/framework/database/orm" "github.com/goravel/framework/support/carbon" ) type Cert struct { - orm.Model ID uint `gorm:"primaryKey" json:"id"` UserID uint `gorm:"default:null" json:"user_id"` // 关联的 ACME 用户 ID WebsiteID *uint `gorm:"default:null" json:"website_id"` // 关联的网站 ID diff --git a/docs/docs.go b/docs/docs.go index 751276df..72e33f83 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -2339,6 +2339,16 @@ const docTemplate = `{ "type": "string", "name": "path", "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" } ], "responses": { diff --git a/docs/swagger.json b/docs/swagger.json index 3d0ed8df..b178ab0a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -2332,6 +2332,16 @@ "type": "string", "name": "path", "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" } ], "responses": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 7849a358..234f0d85 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2051,6 +2051,12 @@ paths: - in: query name: path type: string + - in: query + name: limit + type: integer + - in: query + name: page + type: integer produces: - application/json responses: diff --git a/pkg/tools/system.go b/pkg/tools/system.go index cb104d52..35d4eaad 100644 --- a/pkg/tools/system.go +++ b/pkg/tools/system.go @@ -7,7 +7,9 @@ import ( "io" "os" "os/exec" + "os/user" "path/filepath" + "strconv" "strings" "github.com/goravel/framework/support" @@ -258,3 +260,26 @@ func TempDir(prefix string) (string, error) { func TempFile(prefix string) (*os.File, error) { return os.CreateTemp("", prefix) } + +// IsSymlink 判读是否为软链接 +func IsSymlink(mode os.FileMode) bool { + return mode&os.ModeSymlink != 0 +} + +// GetUser 通过 uid 获取用户名 +func GetUser(uid uint32) string { + usr, err := user.LookupId(strconv.Itoa(int(uid))) + if err != nil { + return "" + } + return usr.Username +} + +// GetGroup 通过 gid 获取组名 +func GetGroup(gid uint32) string { + usr, err := user.LookupGroupId(strconv.Itoa(int(gid))) + if err != nil { + return "" + } + return usr.Name +}