Feat: WebDAV mount folders

pull/247/head
HFO4 5 years ago
parent 86889e2fac
commit b4219927d6

@ -30,6 +30,13 @@ func (folder *Folder) Create() (uint, error) {
return folder.ID, nil 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的子目录不存在则返回错误 // GetChild 返回folder下名为name的子目录不存在则返回错误
func (folder *Folder) GetChild(name string) (*Folder, error) { func (folder *Folder) GetChild(name string) (*Folder, error) {
var resFolder Folder var resFolder Folder
@ -265,6 +272,11 @@ func (folder *Folder) Rename(new string) error {
return nil return nil
} }
// Mount 目录挂载
func (folder *Folder) Mount(new uint) error {
return DB.Model(&folder).Update("policy_id", new).Error
}
/* /*
FileInfo.FileInfo FileInfo.FileInfo
TODO TODO

@ -13,9 +13,11 @@ const (
FileID // 文件ID FileID // 文件ID
FolderID // 目录ID FolderID // 目录ID
TagID // 标签ID TagID // 标签ID
PolicyID // 存储策略ID
) )
var ( var (
// ErrTypeNotMatch ID类型不匹配
ErrTypeNotMatch = errors.New("ID类型不匹配") ErrTypeNotMatch = errors.New("ID类型不匹配")
) )

@ -2,6 +2,8 @@ package serializer
import ( import (
model "github.com/HFO4/cloudreve/models" model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/hashid"
"github.com/HFO4/cloudreve/pkg/util"
) )
type quota struct { type quota struct {
@ -20,6 +22,58 @@ type storagePacks struct {
ExpirationDate string `json:"expiration_date"` 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 序列化用户存储配额概况响应 // BuildUserQuotaResponse 序列化用户存储配额概况响应
func BuildUserQuotaResponse(user *model.User, packs []model.StoragePack) Response { func BuildUserQuotaResponse(user *model.User, packs []model.StoragePack) Response {
packSize := user.GetAvailablePackSize() packSize := user.GetAvailablePackSize()

@ -135,3 +135,15 @@ func UserStorage(c *gin.Context) {
res := serializer.BuildUserStorageResponse(*currUser) res := serializer.BuildUserStorageResponse(*currUser)
c.JSON(200, res) 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账户 // CreateWebDAVAccounts 创建WebDAV账户
func CreateWebDAVAccounts(c *gin.Context) { func CreateWebDAVAccounts(c *gin.Context) {
var service setting.WebDAVAccountCreateService var service setting.WebDAVAccountCreateService
@ -74,3 +85,14 @@ func CreateWebDAVAccounts(c *gin.Context) {
c.JSON(200, ErrorResponse(err)) 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("", controllers.StartRegAuthn)
authn.PUT("finish", controllers.FinishRegAuthn) 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.POST("accounts", controllers.CreateWebDAVAccounts)
// 删除账号 // 删除账号
webdav.DELETE("accounts/:id", controllers.DeleteWebDAVAccounts) 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 ( import (
model "github.com/HFO4/cloudreve/models" 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/serializer"
"github.com/HFO4/cloudreve/pkg/util" "github.com/HFO4/cloudreve/pkg/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -22,6 +24,65 @@ type WebDAVAccountCreateService struct {
Name string `json:"name" binding:"required,min=1,max=255"` 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账户 // Create 创建WebDAV账户
func (service *WebDAVAccountCreateService) Create(c *gin.Context, user *model.User) serializer.Response { func (service *WebDAVAccountCreateService) Create(c *gin.Context, user *model.User) serializer.Response {
account := model.Webdav{ account := model.Webdav{
@ -53,7 +114,12 @@ func (service *WebDAVAccountService) Delete(c *gin.Context, user *model.User) se
// Accounts 列出WebDAV账号 // Accounts 列出WebDAV账号
func (service *WebDAVListService) Accounts(c *gin.Context, user *model.User) serializer.Response { func (service *WebDAVListService) Accounts(c *gin.Context, user *model.User) serializer.Response {
accounts := model.ListWebDAVAccounts(user.ID) accounts := model.ListWebDAVAccounts(user.ID)
// 查找挂载了存储策略的目录
folders := model.GetMountedFolders(user.ID)
return serializer.Response{Data: map[string]interface{}{ return serializer.Response{Data: map[string]interface{}{
"accounts": accounts, "accounts": accounts,
"folders": serializer.BuildMountedFolderRes(folders, user.Group.PolicyList),
}} }}
} }

@ -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, &current)
}
Loading…
Cancel
Save