Feat: WebDAV mount folders
This commit is contained in:
parent
86889e2fac
commit
b4219927d6
8 changed files with 209 additions and 0 deletions
|
@ -30,6 +30,13 @@ func (folder *Folder) Create() (uint, error) {
|
|||
return folder.ID, nil
|
||||
}
|
||||
|
||||
// GetMountedFolders 列出已挂载存储策略的目录
|
||||
func GetMountedFolders(uid uint) []Folder {
|
||||
var folders []Folder
|
||||
DB.Where("owner_id = ? and policy_id <> ?", uid, 0).Find(&folders)
|
||||
return folders
|
||||
}
|
||||
|
||||
// GetChild 返回folder下名为name的子目录,不存在则返回错误
|
||||
func (folder *Folder) GetChild(name string) (*Folder, error) {
|
||||
var resFolder Folder
|
||||
|
@ -265,6 +272,11 @@ func (folder *Folder) Rename(new string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Mount 目录挂载
|
||||
func (folder *Folder) Mount(new uint) error {
|
||||
return DB.Model(&folder).Update("policy_id", new).Error
|
||||
}
|
||||
|
||||
/*
|
||||
实现 FileInfo.FileInfo 接口
|
||||
TODO 测试
|
||||
|
|
|
@ -13,9 +13,11 @@ const (
|
|||
FileID // 文件ID
|
||||
FolderID // 目录ID
|
||||
TagID // 标签ID
|
||||
PolicyID // 存储策略ID
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrTypeNotMatch ID类型不匹配
|
||||
ErrTypeNotMatch = errors.New("ID类型不匹配")
|
||||
)
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package serializer
|
|||
|
||||
import (
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
)
|
||||
|
||||
type quota struct {
|
||||
|
@ -20,6 +22,58 @@ type storagePacks struct {
|
|||
ExpirationDate string `json:"expiration_date"`
|
||||
}
|
||||
|
||||
// MountedFolders 已挂载的目录
|
||||
type MountedFolders struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PolicyName string `json:"policy_name"`
|
||||
}
|
||||
|
||||
type policyOptions struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
// BuildPolicySettingRes 构建存储策略选项选择
|
||||
func BuildPolicySettingRes(policies []model.Policy, current *model.Policy) Response {
|
||||
options := make([]policyOptions, 0, len(policies))
|
||||
for _, policy := range policies {
|
||||
options = append(options, policyOptions{
|
||||
Name: policy.Name,
|
||||
ID: hashid.HashID(policy.ID, hashid.PolicyID),
|
||||
})
|
||||
}
|
||||
|
||||
return Response{
|
||||
Data: map[string]interface{}{
|
||||
"options": options,
|
||||
"current": policyOptions{
|
||||
Name: current.Name,
|
||||
ID: hashid.HashID(current.ID, hashid.PolicyID),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// BuildMountedFolderRes 构建已挂载目录响应,list为当前用户可用存储策略ID
|
||||
func BuildMountedFolderRes(folders []model.Folder, list []uint) []MountedFolders {
|
||||
res := make([]MountedFolders, 0, len(folders))
|
||||
for _, folder := range folders {
|
||||
single := MountedFolders{
|
||||
ID: hashid.HashID(folder.ID, hashid.FolderID),
|
||||
Name: folder.Name,
|
||||
PolicyName: "[已失效存储策略]",
|
||||
}
|
||||
if policy, err := model.GetPolicyByID(folder.PolicyID); err == nil && util.ContainsUint(list, policy.ID) {
|
||||
single.PolicyName = policy.Name
|
||||
}
|
||||
|
||||
res = append(res, single)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// BuildUserQuotaResponse 序列化用户存储配额概况响应
|
||||
func BuildUserQuotaResponse(user *model.User, packs []model.StoragePack) Response {
|
||||
packSize := user.GetAvailablePackSize()
|
||||
|
|
|
@ -135,3 +135,15 @@ func UserStorage(c *gin.Context) {
|
|||
res := serializer.BuildUserStorageResponse(*currUser)
|
||||
c.JSON(200, res)
|
||||
}
|
||||
|
||||
// UserAvailablePolicies 用户存储策略设置
|
||||
func UserAvailablePolicies(c *gin.Context) {
|
||||
var service user.SettingService
|
||||
if err := c.ShouldBindUri(&service); err == nil {
|
||||
res := service.Policy(c, CurrentUser(c))
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,17 @@ func DeleteWebDAVAccounts(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
// DeleteWebDAVMounts 删除WebDAV挂载
|
||||
func DeleteWebDAVMounts(c *gin.Context) {
|
||||
var service setting.WebDAVListService
|
||||
if err := c.ShouldBindUri(&service); err == nil {
|
||||
res := service.Unmount(c, CurrentUser(c))
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
||||
// CreateWebDAVAccounts 创建WebDAV账户
|
||||
func CreateWebDAVAccounts(c *gin.Context) {
|
||||
var service setting.WebDAVAccountCreateService
|
||||
|
@ -74,3 +85,14 @@ func CreateWebDAVAccounts(c *gin.Context) {
|
|||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
||||
// CreateWebDAVMounts 创建WebDAV目录挂载
|
||||
func CreateWebDAVMounts(c *gin.Context) {
|
||||
var service setting.WebDAVMountCreateService
|
||||
if err := c.ShouldBindJSON(&service); err == nil {
|
||||
res := service.Create(c, CurrentUser(c))
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,6 +253,13 @@ func InitMasterRouter() *gin.Engine {
|
|||
authn.PUT("", controllers.StartRegAuthn)
|
||||
authn.PUT("finish", controllers.FinishRegAuthn)
|
||||
}
|
||||
|
||||
// 用户设置
|
||||
setting := user.Group("setting")
|
||||
{
|
||||
// 获取用户可选存储策略
|
||||
setting.GET("policies", controllers.UserAvailablePolicies)
|
||||
}
|
||||
}
|
||||
|
||||
// 文件
|
||||
|
@ -390,6 +397,13 @@ func InitMasterRouter() *gin.Engine {
|
|||
webdav.POST("accounts", controllers.CreateWebDAVAccounts)
|
||||
// 删除账号
|
||||
webdav.DELETE("accounts/:id", controllers.DeleteWebDAVAccounts)
|
||||
// 删除目录挂载
|
||||
webdav.DELETE("mount/:id",
|
||||
middleware.HashID(hashid.FolderID),
|
||||
controllers.DeleteWebDAVMounts,
|
||||
)
|
||||
// 创建目录挂载
|
||||
webdav.POST("mount", controllers.CreateWebDAVMounts)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package setting
|
|||
|
||||
import (
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -22,6 +24,65 @@ type WebDAVAccountCreateService struct {
|
|||
Name string `json:"name" binding:"required,min=1,max=255"`
|
||||
}
|
||||
|
||||
// WebDAVMountCreateService WebDAV 挂载创建服务
|
||||
type WebDAVMountCreateService struct {
|
||||
Path string `json:"path" binding:"required,min=1,max=65535"`
|
||||
Policy string `json:"policy" binding:"required,min=1"`
|
||||
}
|
||||
|
||||
// Create 创建目录挂载
|
||||
func (service *WebDAVMountCreateService) Create(c *gin.Context, user *model.User) serializer.Response {
|
||||
// 创建文件系统
|
||||
fs, err := filesystem.NewFileSystem(user)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||
}
|
||||
defer fs.Recycle()
|
||||
|
||||
// 检索要挂载的目录
|
||||
exist, folder := fs.IsPathExist(service.Path)
|
||||
if !exist {
|
||||
return serializer.Err(serializer.CodeNotFound, "路径不存在", err)
|
||||
}
|
||||
|
||||
// 检索要挂载的存储策略
|
||||
policyID, err := hashid.DecodeHashID(service.Policy, hashid.PolicyID)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeNotFound, "存储策略不存在", err)
|
||||
}
|
||||
|
||||
// 检查存储策略是否可用
|
||||
if policy, err := model.GetPolicyByID(policyID); err != nil || !util.ContainsUint(user.Group.PolicyList, policy.ID) {
|
||||
return serializer.Err(serializer.CodeNotFound, "存储策略不可用", err)
|
||||
}
|
||||
|
||||
// 挂载
|
||||
if err := folder.Mount(policyID); err != nil {
|
||||
return serializer.Err(serializer.CodeDBError, "挂载失败", err)
|
||||
}
|
||||
|
||||
return serializer.Response{
|
||||
Data: map[string]interface{}{
|
||||
"id": hashid.HashID(folder.ID, hashid.FolderID),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Unmount 取消目录挂载
|
||||
func (service *WebDAVListService) Unmount(c *gin.Context, user *model.User) serializer.Response {
|
||||
folderID, _ := c.Get("object_id")
|
||||
folder, err := model.GetFoldersByIDs([]uint{folderID.(uint)}, user.ID)
|
||||
if err != nil || len(folder) == 0 {
|
||||
return serializer.Err(serializer.CodeNotFound, "目录不存在", err)
|
||||
}
|
||||
|
||||
if err := folder[0].Mount(0); err != nil {
|
||||
return serializer.Err(serializer.CodeDBError, "取消挂载失败", err)
|
||||
}
|
||||
|
||||
return serializer.Response{}
|
||||
}
|
||||
|
||||
// Create 创建WebDAV账户
|
||||
func (service *WebDAVAccountCreateService) Create(c *gin.Context, user *model.User) serializer.Response {
|
||||
account := model.Webdav{
|
||||
|
@ -53,7 +114,12 @@ func (service *WebDAVAccountService) Delete(c *gin.Context, user *model.User) se
|
|||
// Accounts 列出WebDAV账号
|
||||
func (service *WebDAVListService) Accounts(c *gin.Context, user *model.User) serializer.Response {
|
||||
accounts := model.ListWebDAVAccounts(user.ID)
|
||||
|
||||
// 查找挂载了存储策略的目录
|
||||
folders := model.GetMountedFolders(user.ID)
|
||||
|
||||
return serializer.Response{Data: map[string]interface{}{
|
||||
"accounts": accounts,
|
||||
"folders": serializer.BuildMountedFolderRes(folders, user.Group.PolicyList),
|
||||
}}
|
||||
}
|
||||
|
|
27
service/user/setting.go
Normal file
27
service/user/setting.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SettingService 通用设置服务
|
||||
type SettingService struct {
|
||||
}
|
||||
|
||||
// Policy 获取用户存储策略设置
|
||||
func (service *SettingService) Policy(c *gin.Context, user *model.User) serializer.Response {
|
||||
// 取得用户可用存储策略
|
||||
available := make([]model.Policy, 0, len(user.Group.PolicyList))
|
||||
for _, id := range user.Group.PolicyList {
|
||||
if policy, err := model.GetPolicyByID(id); err == nil {
|
||||
available = append(available, policy)
|
||||
}
|
||||
}
|
||||
|
||||
// 取得用户当前策略
|
||||
current := user.Policy
|
||||
|
||||
return serializer.BuildPolicySettingRes(available, ¤t)
|
||||
}
|
Loading…
Add table
Reference in a new issue