Feat: sign file source url
This commit is contained in:
parent
1963a495fb
commit
36d5f51495
15 changed files with 174 additions and 47 deletions
|
@ -1,12 +1,26 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SignRequired 验证请求签名
|
||||
func SignRequired() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 获取待验证的签名正文
|
||||
queries := c.Request.URL.Query()
|
||||
queries.Del("sign")
|
||||
c.Request.URL.RawQuery = queries.Encode()
|
||||
requestURI := c.Request.URL.RequestURI()
|
||||
fmt.Println(requestURI)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// CurrentUser 获取登录用户
|
||||
func CurrentUser() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package model
|
|||
import (
|
||||
"github.com/HFO4/cloudreve/pkg/cache"
|
||||
"github.com/jinzhu/gorm"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Setting 系统设置模型
|
||||
|
@ -62,3 +63,12 @@ func GetSettingByType(types []string) map[string]string {
|
|||
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSiteURL 获取站点地址
|
||||
func GetSiteURL() *url.URL {
|
||||
base, err := url.Parse(GetSettingByName("siteURL"))
|
||||
if err != nil {
|
||||
base, _ = url.Parse("https://cloudreve.org")
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package auth
|
|||
import (
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -21,7 +22,26 @@ type Auth interface {
|
|||
Check(body string, sign string) error
|
||||
}
|
||||
|
||||
// SignURI 对URI进行签名
|
||||
// TODO 测试
|
||||
func SignURI(uri string, expires int64) (*url.URL, error) {
|
||||
// 生成签名
|
||||
sign := General.Sign(uri, expires)
|
||||
|
||||
// 将签名加到URI中
|
||||
base, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queries := base.Query()
|
||||
queries.Set("sign", sign)
|
||||
base.RawQuery = queries.Encode()
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// Init 初始化通用鉴权器
|
||||
// TODO slave模式下从配置文件获取
|
||||
func Init() {
|
||||
General = HMACAuth{
|
||||
SecretKey: []byte(model.GetSettingByName("secret_key")),
|
||||
|
|
|
@ -3,6 +3,7 @@ package filesystem
|
|||
import (
|
||||
"context"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/juju/ratelimit"
|
||||
|
@ -33,8 +34,8 @@ func withSpeedLimit(rs io.ReadSeeker, speed int) io.ReadSeeker {
|
|||
|
||||
// AddFile 新增文件记录
|
||||
func (fs *FileSystem) AddFile(ctx context.Context, parent *model.Folder) (*model.File, error) {
|
||||
file := ctx.Value(FileHeaderCtx).(FileHeader)
|
||||
filePath := ctx.Value(SavePathCtx).(string)
|
||||
file := ctx.Value(fsctx.FileHeaderCtx).(FileHeader)
|
||||
filePath := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
|
||||
newFile := model.File{
|
||||
Name: file.GetFileName(),
|
||||
|
@ -86,7 +87,7 @@ func (fs *FileSystem) GetContent(ctx context.Context, path string) (io.ReadSeeke
|
|||
return nil, ErrObjectNotExist
|
||||
}
|
||||
fs.FileTarget = []model.File{*file}
|
||||
|
||||
ctx = context.WithValue(ctx, fsctx.FileModelCtx, file)
|
||||
// 将当前存储策略重设为文件使用的
|
||||
fs.Policy = file.GetPolicy()
|
||||
err = fs.dispatchHandler()
|
||||
|
@ -161,6 +162,8 @@ func (fs *FileSystem) GetSource(ctx context.Context, fileID uint) (string, error
|
|||
}
|
||||
|
||||
fs.FileTarget = []model.File{fileObject[0]}
|
||||
ctx = context.WithValue(ctx, fsctx.FileModelCtx, fileObject[0])
|
||||
|
||||
// 将当前存储策略重设为文件使用的
|
||||
fs.Policy = fileObject[0].GetPolicy()
|
||||
err = fs.dispatchHandler()
|
||||
|
@ -172,5 +175,13 @@ func (fs *FileSystem) GetSource(ctx context.Context, fileID uint) (string, error
|
|||
if !fs.Policy.IsOriginLinkEnable {
|
||||
return "", serializer.NewError(serializer.CodePolicyNotAllowed, "当前存储策略无法获得外链", nil)
|
||||
}
|
||||
return "", nil
|
||||
|
||||
// 生成外链地址
|
||||
siteURL := model.GetSiteURL()
|
||||
source, err := fs.Handler.Source(ctx, fileObject[0].SourceName, *siteURL, 0)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeNotSet, "无法获取外链", err)
|
||||
}
|
||||
|
||||
return source, nil
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/local"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/jinzhu/gorm"
|
||||
|
@ -35,8 +36,8 @@ func TestFileSystem_AddFile(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), FileHeaderCtx, file)
|
||||
ctx = context.WithValue(ctx, SavePathCtx, "/Uploads/1_sad.txt")
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileHeaderCtx, file)
|
||||
ctx = context.WithValue(ctx, fsctx.SavePathCtx, "/Uploads/1_sad.txt")
|
||||
|
||||
_, err := fs.AddFile(ctx, &folder)
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/HFO4/cloudreve/pkg/filesystem/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// FileHeader 上传来的文件数据处理器
|
||||
|
@ -30,6 +31,8 @@ type Handler interface {
|
|||
Get(ctx context.Context, path string) (io.ReadSeeker, error)
|
||||
// 获取缩略图
|
||||
Thumb(ctx context.Context, path string) (*response.ContentResponse, error)
|
||||
// 获取外链地址,url
|
||||
Source(ctx context.Context, path string, url url.URL, expires int64) (string, error)
|
||||
}
|
||||
|
||||
// FileSystem 管理文件的文件系统
|
||||
|
@ -79,17 +82,23 @@ func NewFileSystem(user *model.User) (*FileSystem, error) {
|
|||
// dispatchHandler 根据存储策略分配文件适配器
|
||||
func (fs *FileSystem) dispatchHandler() error {
|
||||
var policyType string
|
||||
var currentPolicy *model.Policy
|
||||
|
||||
if fs.Policy == nil {
|
||||
// 如果没有具体指定,就是用用户当前存储策略
|
||||
policyType = fs.User.Policy.Type
|
||||
currentPolicy = &fs.User.Policy
|
||||
} else {
|
||||
policyType = fs.Policy.Type
|
||||
currentPolicy = fs.Policy
|
||||
}
|
||||
|
||||
// 根据存储策略类型分配适配器
|
||||
switch policyType {
|
||||
case "local":
|
||||
fs.Handler = local.Handler{}
|
||||
fs.Handler = local.Handler{
|
||||
Policy: currentPolicy,
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return ErrUnknownPolicyType
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package filesystem
|
||||
package fsctx
|
||||
|
||||
type key int
|
||||
|
||||
|
@ -11,4 +11,6 @@ const (
|
|||
FileHeaderCtx
|
||||
// PathCtx 文件或目录的虚拟路径
|
||||
PathCtx
|
||||
// FileModelCtx 文件数据库模型
|
||||
FileModelCtx
|
||||
)
|
|
@ -3,6 +3,7 @@ package filesystem
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -40,7 +41,7 @@ func (fs *FileSystem) Trigger(ctx context.Context, hooks []Hook) error {
|
|||
|
||||
// HookIsFileExist 检查虚拟路径文件是否存在
|
||||
func HookIsFileExist(ctx context.Context, fs *FileSystem) error {
|
||||
filePath := ctx.Value(PathCtx).(string)
|
||||
filePath := ctx.Value(fsctx.PathCtx).(string)
|
||||
if ok, _ := fs.IsFileExist(filePath); ok {
|
||||
return nil
|
||||
}
|
||||
|
@ -49,7 +50,7 @@ func HookIsFileExist(ctx context.Context, fs *FileSystem) error {
|
|||
|
||||
// HookValidateFile 一系列对文件检验的集合
|
||||
func HookValidateFile(ctx context.Context, fs *FileSystem) error {
|
||||
file := ctx.Value(FileHeaderCtx).(FileHeader)
|
||||
file := ctx.Value(fsctx.FileHeaderCtx).(FileHeader)
|
||||
|
||||
// 验证单文件尺寸
|
||||
if !fs.ValidateFileSize(ctx, file.GetSize()) {
|
||||
|
@ -72,7 +73,7 @@ func HookValidateFile(ctx context.Context, fs *FileSystem) error {
|
|||
|
||||
// HookValidateCapacity 验证并扣除用户容量,包含数据库操作
|
||||
func HookValidateCapacity(ctx context.Context, fs *FileSystem) error {
|
||||
file := ctx.Value(FileHeaderCtx).(FileHeader)
|
||||
file := ctx.Value(fsctx.FileHeaderCtx).(FileHeader)
|
||||
// 验证并扣除容量
|
||||
if !fs.ValidateCapacity(ctx, file.GetSize()) {
|
||||
return ErrInsufficientCapacity
|
||||
|
@ -82,7 +83,7 @@ func HookValidateCapacity(ctx context.Context, fs *FileSystem) error {
|
|||
|
||||
// HookDeleteTempFile 删除已保存的临时文件
|
||||
func HookDeleteTempFile(ctx context.Context, fs *FileSystem) error {
|
||||
filePath := ctx.Value(SavePathCtx).(string)
|
||||
filePath := ctx.Value(fsctx.SavePathCtx).(string)
|
||||
// 删除临时文件
|
||||
if util.Exists(filePath) {
|
||||
_, err := fs.Handler.Delete(ctx, []string{filePath})
|
||||
|
@ -96,7 +97,7 @@ func HookDeleteTempFile(ctx context.Context, fs *FileSystem) error {
|
|||
|
||||
// HookGiveBackCapacity 归还用户容量
|
||||
func HookGiveBackCapacity(ctx context.Context, fs *FileSystem) error {
|
||||
file := ctx.Value(FileHeaderCtx).(FileHeader)
|
||||
file := ctx.Value(fsctx.FileHeaderCtx).(FileHeader)
|
||||
|
||||
// 归还用户容量
|
||||
if !fs.User.DeductionStorage(file.GetSize()) {
|
||||
|
@ -108,7 +109,7 @@ func HookGiveBackCapacity(ctx context.Context, fs *FileSystem) error {
|
|||
// GenericAfterUpload 文件上传完成后,包含数据库操作
|
||||
func GenericAfterUpload(ctx context.Context, fs *FileSystem) error {
|
||||
// 文件存放的虚拟路径
|
||||
virtualPath := ctx.Value(FileHeaderCtx).(FileHeader).GetVirtualPath()
|
||||
virtualPath := ctx.Value(fsctx.FileHeaderCtx).(FileHeader).GetVirtualPath()
|
||||
|
||||
// 检查路径是否存在
|
||||
isExist, folder := fs.IsPathExist(virtualPath)
|
||||
|
@ -119,7 +120,7 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem) error {
|
|||
// 检查文件是否存在
|
||||
if ok, _ := fs.IsChildFileExist(
|
||||
folder,
|
||||
ctx.Value(FileHeaderCtx).(FileHeader).GetFileName(),
|
||||
ctx.Value(fsctx.FileHeaderCtx).(FileHeader).GetFileName(),
|
||||
); ok {
|
||||
return ErrFileExisted
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/local"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -18,7 +19,7 @@ func TestGenericBeforeUpload(t *testing.T) {
|
|||
Size: 5,
|
||||
Name: "1.txt",
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), FileHeaderCtx, file)
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileHeaderCtx, file)
|
||||
fs := FileSystem{
|
||||
User: &model.User{
|
||||
Storage: 0,
|
||||
|
@ -38,15 +39,15 @@ func TestGenericBeforeUpload(t *testing.T) {
|
|||
|
||||
file.Size = 1
|
||||
file.Name = "1"
|
||||
ctx = context.WithValue(context.Background(), FileHeaderCtx, file)
|
||||
ctx = context.WithValue(context.Background(), fsctx.FileHeaderCtx, file)
|
||||
asserts.Error(HookValidateFile(ctx, &fs))
|
||||
|
||||
file.Name = "1.txt"
|
||||
ctx = context.WithValue(context.Background(), FileHeaderCtx, file)
|
||||
ctx = context.WithValue(context.Background(), fsctx.FileHeaderCtx, file)
|
||||
asserts.NoError(HookValidateFile(ctx, &fs))
|
||||
|
||||
file.Name = "1.t/xt"
|
||||
ctx = context.WithValue(context.Background(), FileHeaderCtx, file)
|
||||
ctx = context.WithValue(context.Background(), fsctx.FileHeaderCtx, file)
|
||||
asserts.Error(HookValidateFile(ctx, &fs))
|
||||
}
|
||||
|
||||
|
@ -59,8 +60,8 @@ func TestGenericAfterUploadCanceled(t *testing.T) {
|
|||
Size: 5,
|
||||
Name: "TestGenericAfterUploadCanceled",
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), SavePathCtx, "TestGenericAfterUploadCanceled")
|
||||
ctx = context.WithValue(ctx, FileHeaderCtx, file)
|
||||
ctx := context.WithValue(context.Background(), fsctx.SavePathCtx, "TestGenericAfterUploadCanceled")
|
||||
ctx = context.WithValue(ctx, fsctx.FileHeaderCtx, file)
|
||||
fs := FileSystem{
|
||||
User: &model.User{Storage: 5},
|
||||
Handler: local.Handler{},
|
||||
|
@ -97,11 +98,11 @@ func TestGenericAfterUpload(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), FileHeaderCtx, local.FileStream{
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileHeaderCtx, local.FileStream{
|
||||
VirtualPath: "/我的文件",
|
||||
Name: "test.txt",
|
||||
})
|
||||
ctx = context.WithValue(ctx, SavePathCtx, "")
|
||||
ctx = context.WithValue(ctx, fsctx.SavePathCtx, "")
|
||||
|
||||
// 正常
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
|
@ -228,7 +229,7 @@ func TestHookIsFileExist(t *testing.T) {
|
|||
ID: 1,
|
||||
},
|
||||
}}
|
||||
ctx := context.WithValue(context.Background(), PathCtx, "/test.txt")
|
||||
ctx := context.WithValue(context.Background(), fsctx.PathCtx, "/test.txt")
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WithArgs(1).
|
||||
|
@ -263,7 +264,7 @@ func TestHookValidateCapacity(t *testing.T) {
|
|||
MaxStorage: 11,
|
||||
},
|
||||
}}
|
||||
ctx := context.WithValue(context.Background(), FileHeaderCtx, local.FileStream{Size: 10})
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileHeaderCtx, local.FileStream{Size: 10})
|
||||
{
|
||||
err := HookValidateCapacity(ctx, fs)
|
||||
asserts.NoError(err)
|
||||
|
|
|
@ -2,16 +2,25 @@ package local
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/auth"
|
||||
"github.com/HFO4/cloudreve/pkg/conf"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/response"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Handler 本地策略适配器
|
||||
type Handler struct{}
|
||||
type Handler struct {
|
||||
Policy *model.Policy
|
||||
}
|
||||
|
||||
// Get 获取文件内容
|
||||
func (handler Handler) Get(ctx context.Context, path string) (io.ReadSeeker, error) {
|
||||
|
@ -97,3 +106,23 @@ func (handler Handler) Thumb(ctx context.Context, path string) (*response.Conten
|
|||
Content: file,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Source 获取外链URL
|
||||
func (handler Handler) Source(ctx context.Context, path string, url url.URL, expires int64) (string, error) {
|
||||
file, ok := ctx.Value(fsctx.FileModelCtx).(model.File)
|
||||
if !ok {
|
||||
return "", errors.New("无法获取文件记录上下文")
|
||||
}
|
||||
|
||||
// 签名生成文件记录
|
||||
signedURI, err := auth.SignURI(
|
||||
fmt.Sprintf("/api/v3/file/get/%d/%s", file.ID, file.Name),
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeEncryptError, "无法对URL进行签名", err)
|
||||
}
|
||||
|
||||
finalURL := url.ResolveReference(signedURI).String()
|
||||
return finalURL, nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package filesystem
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/gin-gonic/gin"
|
||||
"path/filepath"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
|
||||
// Upload 上传文件
|
||||
func (fs *FileSystem) Upload(ctx context.Context, file FileHeader) (err error) {
|
||||
ctx = context.WithValue(ctx, FileHeaderCtx, file)
|
||||
ctx = context.WithValue(ctx, fsctx.FileHeaderCtx, file)
|
||||
|
||||
// 上传前的钩子
|
||||
err = fs.Trigger(ctx, fs.BeforeUpload)
|
||||
|
@ -35,7 +36,7 @@ func (fs *FileSystem) Upload(ctx context.Context, file FileHeader) (err error) {
|
|||
}
|
||||
|
||||
// 上传完成后的钩子
|
||||
ctx = context.WithValue(ctx, SavePathCtx, savePath)
|
||||
ctx = context.WithValue(ctx, fsctx.SavePathCtx, savePath)
|
||||
err = fs.Trigger(ctx, fs.AfterUpload)
|
||||
|
||||
if err != nil {
|
||||
|
@ -70,7 +71,7 @@ func (fs *FileSystem) GenerateSavePath(ctx context.Context, file FileHeader) str
|
|||
|
||||
// CancelUpload 监测客户端取消上传
|
||||
func (fs *FileSystem) CancelUpload(ctx context.Context, path string, file FileHeader) {
|
||||
ginCtx := ctx.Value(GinCtx).(*gin.Context)
|
||||
ginCtx := ctx.Value(fsctx.GinCtx).(*gin.Context)
|
||||
select {
|
||||
case <-ginCtx.Request.Context().Done():
|
||||
select {
|
||||
|
@ -82,7 +83,7 @@ func (fs *FileSystem) CancelUpload(ctx context.Context, path string, file FileHe
|
|||
if fs.AfterUploadCanceled == nil {
|
||||
return
|
||||
}
|
||||
ctx = context.WithValue(ctx, SavePathCtx, path)
|
||||
ctx = context.WithValue(ctx, fsctx.SavePathCtx, path)
|
||||
err := fs.Trigger(ctx, fs.AfterUploadCanceled)
|
||||
if err != nil {
|
||||
util.Log().Debug("执行 AfterUploadCanceled 钩子出错,%s", err)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/local"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -13,6 +14,7 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -40,6 +42,11 @@ func (m FileHeaderMock) Thumb(ctx context.Context, files string) (*response.Cont
|
|||
return args.Get(0).(*response.ContentResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m FileHeaderMock) Source(ctx context.Context, path string, url url.URL, expires int64) (string, error) {
|
||||
args := m.Called(ctx, path, url, expires)
|
||||
return args.Get(0).(string), args.Error(1)
|
||||
}
|
||||
|
||||
func TestFileSystem_Upload(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
|
||||
|
@ -61,7 +68,7 @@ func TestFileSystem_Upload(t *testing.T) {
|
|||
ctx, cancel := context.WithCancel(context.Background())
|
||||
c, _ := gin.CreateTestContext(httptest.NewRecorder())
|
||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||
ctx = context.WithValue(ctx, GinCtx, c)
|
||||
ctx = context.WithValue(ctx, fsctx.GinCtx, c)
|
||||
cancel()
|
||||
file := local.FileStream{
|
||||
Size: 5,
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/local"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
|
@ -15,6 +16,11 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// AnonymousGetContent 匿名获取文件资源
|
||||
func AnonymousGetContent(c *gin.Context) {
|
||||
c.JSON(200, serializer.Response{})
|
||||
}
|
||||
|
||||
// GetSource 获取文件的外链地址
|
||||
func GetSource(c *gin.Context) {
|
||||
// 创建上下文
|
||||
|
@ -152,7 +158,7 @@ func FileUploadStream(c *gin.Context) {
|
|||
fs.Use("AfterValidateFailed", filesystem.HookGiveBackCapacity)
|
||||
|
||||
// 执行上传
|
||||
uploadCtx := context.WithValue(ctx, filesystem.GinCtx, c)
|
||||
uploadCtx := context.WithValue(ctx, fsctx.GinCtx, c)
|
||||
err = fs.Upload(uploadCtx, fileData)
|
||||
if err != nil {
|
||||
c.JSON(200, serializer.Err(serializer.CodeUploadFailed, err.Error(), err))
|
||||
|
|
|
@ -39,23 +39,37 @@ func InitRouter() *gin.Engine {
|
|||
*/
|
||||
v3 := r.Group("/api/v3")
|
||||
{
|
||||
// 测试用路由
|
||||
v3.GET("site/ping", controllers.Ping)
|
||||
|
||||
// 不需要登录的用户相关路由
|
||||
// 全局设置相关
|
||||
site := v3.Group("site")
|
||||
{
|
||||
// 用户登录
|
||||
v3.POST("user/session", controllers.UserLogin)
|
||||
// WebAuthn登陆初始化
|
||||
v3.GET("user/authn/:username", controllers.StartLoginAuthn)
|
||||
// WebAuthn登陆
|
||||
v3.POST("user/authn/finish/:username", controllers.FinishLoginAuthn)
|
||||
// 测试用路由
|
||||
site.GET("ping", controllers.Ping)
|
||||
// 验证码
|
||||
site.GET("captcha", controllers.Captcha)
|
||||
// 站点全局配置
|
||||
site.GET("config", controllers.SiteConfig)
|
||||
}
|
||||
|
||||
// 验证码
|
||||
v3.GET("captcha", controllers.Captcha)
|
||||
// 站点全局配置
|
||||
v3.GET("site/config", controllers.SiteConfig)
|
||||
// 用户相关路由
|
||||
user := v3.Group("user")
|
||||
{
|
||||
// 用户登录
|
||||
user.POST("session", controllers.UserLogin)
|
||||
// WebAuthn登陆初始化
|
||||
user.GET("authn/:username", controllers.StartLoginAuthn)
|
||||
// WebAuthn登陆
|
||||
user.POST("authn/finish/:username", controllers.FinishLoginAuthn)
|
||||
}
|
||||
|
||||
// 需要携带签名验证的
|
||||
sign := v3.Group("")
|
||||
sign.Use(middleware.SignRequired())
|
||||
{
|
||||
file := sign.Group("file")
|
||||
{
|
||||
file.GET("get/:id/:name", controllers.AnonymousGetContent)
|
||||
}
|
||||
}
|
||||
|
||||
// 需要登录保护的
|
||||
auth := v3.Group("")
|
||||
|
|
|
@ -3,6 +3,7 @@ package explorer
|
|||
import (
|
||||
"context"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
|
@ -22,7 +23,7 @@ func (service *FileDownloadService) Download(ctx context.Context, c *gin.Context
|
|||
}
|
||||
|
||||
// 开始处理下载
|
||||
ctx = context.WithValue(ctx, filesystem.GinCtx, c)
|
||||
ctx = context.WithValue(ctx, fsctx.GinCtx, c)
|
||||
rs, err := fs.GetDownloadContent(ctx, service.Path)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeNotSet, err.Error(), err)
|
||||
|
|
Loading…
Add table
Reference in a new issue