Pack 3.0.0.Beta2
This commit is contained in:
@ -12,7 +12,7 @@ const (
|
||||
//db table's prefix. tank30_ means current version is tank:3.0.x
|
||||
TABLE_PREFIX = "tank30_"
|
||||
|
||||
VERSION = "3.0.0.beta1"
|
||||
VERSION = "3.0.0.beta2"
|
||||
)
|
||||
|
||||
type Config interface {
|
||||
|
@ -3,6 +3,7 @@ package rest
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/eyebluecn/tank/code/core"
|
||||
"github.com/eyebluecn/tank/code/tool/i18n"
|
||||
"github.com/eyebluecn/tank/code/tool/result"
|
||||
"github.com/eyebluecn/tank/code/tool/util"
|
||||
"github.com/json-iterator/go"
|
||||
@ -55,7 +56,7 @@ func (this *BaseController) Wrap(f func(writer http.ResponseWriter, request *htt
|
||||
|
||||
if user.Status == USER_STATUS_DISABLED {
|
||||
//check user's status
|
||||
webResult = result.ConstWebResult(result.USER_DISABLED)
|
||||
webResult = result.CustomWebResultI18n(request, result.USER_DISABLED, i18n.UserDisabled)
|
||||
} else {
|
||||
if qualifiedRole == USER_ROLE_ADMINISTRATOR && user.Role != USER_ROLE_ADMINISTRATOR {
|
||||
webResult = result.ConstWebResult(result.UNAUTHORIZED)
|
||||
|
@ -103,10 +103,14 @@ var LivePropMap = map[xml.Name]LiveProp{
|
||||
{Space: "DAV:", Local: "quota-available-bytes"}: {
|
||||
findFn: func(user *User, matter *Matter) string {
|
||||
var size int64 = 0
|
||||
if user.SizeLimit >= 0 {
|
||||
size = user.SizeLimit
|
||||
if user.TotalSizeLimit >= 0 {
|
||||
if user.TotalSizeLimit-user.TotalSize > 0 {
|
||||
size = user.TotalSizeLimit - user.TotalSize
|
||||
} else {
|
||||
size = 0
|
||||
}
|
||||
} else {
|
||||
//TODO: no limit, default 100G.
|
||||
// no limit, default 100G.
|
||||
size = 100 * 1024 * 1024 * 1024
|
||||
}
|
||||
return fmt.Sprintf(`%d`, size)
|
||||
@ -115,8 +119,7 @@ var LivePropMap = map[xml.Name]LiveProp{
|
||||
},
|
||||
{Space: "DAV:", Local: "quota-used-bytes"}: {
|
||||
findFn: func(user *User, matter *Matter) string {
|
||||
//TODO: default 0
|
||||
return fmt.Sprintf(`%d`, 0)
|
||||
return fmt.Sprintf(`%d`, user.TotalSize)
|
||||
},
|
||||
dir: true,
|
||||
},
|
||||
|
@ -225,7 +225,7 @@ func (this *DavService) HandlePut(writer http.ResponseWriter, request *http.Requ
|
||||
//if exist delete it.
|
||||
srcMatter := this.matterDao.findByUserUuidAndPath(user.Uuid, subPath)
|
||||
if srcMatter != nil {
|
||||
this.matterService.AtomicDelete(request, srcMatter)
|
||||
this.matterService.AtomicDelete(request, srcMatter, user)
|
||||
}
|
||||
|
||||
this.matterService.Upload(request, request.Body, user, dirMatter, filename, true)
|
||||
@ -239,7 +239,7 @@ func (this *DavService) HandleDelete(writer http.ResponseWriter, request *http.R
|
||||
|
||||
matter := this.matterDao.CheckWithRootByPath(subPath, user)
|
||||
|
||||
this.matterService.AtomicDelete(request, matter)
|
||||
this.matterService.AtomicDelete(request, matter, user)
|
||||
}
|
||||
|
||||
//crate a directory
|
||||
@ -369,7 +369,7 @@ func (this *DavService) HandleMove(writer http.ResponseWriter, request *http.Req
|
||||
//if destination path not change. it means rename.
|
||||
this.matterService.AtomicRename(request, srcMatter, destinationName, user)
|
||||
} else {
|
||||
this.matterService.AtomicMove(request, srcMatter, destDirMatter, overwrite)
|
||||
this.matterService.AtomicMove(request, srcMatter, destDirMatter, overwrite, user)
|
||||
}
|
||||
|
||||
this.logger.Info("finish moving %s => %s", subPath, destDirMatter.Path)
|
||||
@ -383,7 +383,7 @@ func (this *DavService) HandleCopy(writer http.ResponseWriter, request *http.Req
|
||||
srcMatter, destDirMatter, _, _, destinationName, overwrite := this.prepareMoveCopy(writer, request, user, subPath)
|
||||
|
||||
//copy to the new directory
|
||||
this.matterService.AtomicCopy(request, srcMatter, destDirMatter, destinationName, overwrite)
|
||||
this.matterService.AtomicCopy(request, srcMatter, destDirMatter, destinationName, overwrite, user)
|
||||
|
||||
this.logger.Info("finish copying %s => %s", subPath, destDirMatter.Path)
|
||||
|
||||
|
@ -294,7 +294,7 @@ func (this *MatterController) Delete(writer http.ResponseWriter, request *http.R
|
||||
panic(result.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
this.matterService.AtomicDelete(request, matter)
|
||||
this.matterService.AtomicDelete(request, matter, user)
|
||||
|
||||
return this.Success("OK")
|
||||
}
|
||||
@ -322,7 +322,7 @@ func (this *MatterController) DeleteBatch(writer http.ResponseWriter, request *h
|
||||
panic(result.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
this.matterService.AtomicDelete(request, matter)
|
||||
this.matterService.AtomicDelete(request, matter, user)
|
||||
|
||||
}
|
||||
|
||||
@ -417,7 +417,7 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req
|
||||
srcMatters = append(srcMatters, srcMatter)
|
||||
}
|
||||
|
||||
this.matterService.AtomicMoveBatch(request, srcMatters, destMatter)
|
||||
this.matterService.AtomicMoveBatch(request, srcMatters, destMatter, user)
|
||||
|
||||
return this.Success(nil)
|
||||
}
|
||||
|
@ -332,39 +332,6 @@ func (this *MatterDao) SizeByPuuidAndUserUuid(matterUuid string, userUuid string
|
||||
return sumSize
|
||||
}
|
||||
|
||||
// compute route size. It will compute upward until root directory
|
||||
func (this *MatterDao) ComputeRouteSize(matterUuid string, userUuid string) {
|
||||
|
||||
//if to root directory, then update to user's info.
|
||||
if matterUuid == MATTER_ROOT {
|
||||
|
||||
size := this.SizeByPuuidAndUserUuid(MATTER_ROOT, userUuid)
|
||||
|
||||
db := core.CONTEXT.GetDB().Model(&User{}).Where("uuid = ?", userUuid).Update("total_size", size)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
matter := this.CheckByUuid(matterUuid)
|
||||
|
||||
//only compute dir
|
||||
if matter.Dir {
|
||||
//compute the total size.
|
||||
size := this.SizeByPuuidAndUserUuid(matterUuid, userUuid)
|
||||
|
||||
//when changed, we update
|
||||
if matter.Size != size {
|
||||
db := core.CONTEXT.GetDB().Model(&Matter{}).Where("uuid = ?", matterUuid).Update("size", size)
|
||||
this.PanicError(db.Error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//update parent recursively.
|
||||
this.ComputeRouteSize(matter.Puuid, userUuid)
|
||||
}
|
||||
|
||||
//delete a file from db and disk.
|
||||
func (this *MatterDao) Delete(matter *Matter) {
|
||||
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
/**
|
||||
* file
|
||||
* file is too common. so we use matter as file.
|
||||
*/
|
||||
type Matter struct {
|
||||
Base
|
||||
|
@ -242,7 +242,7 @@ func (this *MatterService) zipMatters(request *http.Request, matters []*Matter,
|
||||
}
|
||||
|
||||
//delete files.
|
||||
func (this *MatterService) Delete(request *http.Request, matter *Matter) {
|
||||
func (this *MatterService) Delete(request *http.Request, matter *Matter, user *User) {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.BadRequest("matter cannot be nil"))
|
||||
@ -251,11 +251,11 @@ func (this *MatterService) Delete(request *http.Request, matter *Matter) {
|
||||
this.matterDao.Delete(matter)
|
||||
|
||||
//re compute the size of Route.
|
||||
this.matterDao.ComputeRouteSize(matter.Puuid, matter.UserUuid)
|
||||
this.ComputeRouteSize(matter.Puuid, user)
|
||||
}
|
||||
|
||||
//atomic delete files
|
||||
func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter) {
|
||||
func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter, user *User) {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.BadRequest("matter cannot be nil"))
|
||||
@ -265,7 +265,7 @@ func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter) {
|
||||
this.userService.MatterLock(matter.UserUuid)
|
||||
defer this.userService.MatterUnlock(matter.UserUuid)
|
||||
|
||||
this.Delete(request, matter)
|
||||
this.Delete(request, matter, user)
|
||||
}
|
||||
|
||||
//upload files.
|
||||
@ -283,12 +283,19 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(filename), MATTER_NAME_MAX_LENGTH))
|
||||
}
|
||||
|
||||
//check the total size limit.
|
||||
if user.TotalSizeLimit >= 0 {
|
||||
if user.TotalSize > user.TotalSizeLimit {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterSizeExceedTotalLimit, util.HumanFileSize(user.TotalSize), util.HumanFileSize(user.TotalSizeLimit)))
|
||||
}
|
||||
}
|
||||
|
||||
dirAbsolutePath := dirMatter.AbsolutePath()
|
||||
dirRelativePath := dirMatter.Path
|
||||
|
||||
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, false, filename)
|
||||
if count > 0 {
|
||||
panic(result.BadRequest("%s already exists", filename))
|
||||
panic(result.BadRequestI18n(request, i18n.MatterExist, filename))
|
||||
}
|
||||
|
||||
fileAbsolutePath := dirAbsolutePath + "/" + filename
|
||||
@ -344,12 +351,48 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
|
||||
|
||||
//compute the size of directory
|
||||
go core.RunWithRecovery(func() {
|
||||
this.matterDao.ComputeRouteSize(dirMatter.Uuid, user.Uuid)
|
||||
this.ComputeRouteSize(dirMatter.Uuid, user)
|
||||
})
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
// compute route size. It will compute upward until root directory
|
||||
func (this *MatterService) ComputeRouteSize(matterUuid string, user *User) {
|
||||
|
||||
//if to root directory, then update to user's info.
|
||||
if matterUuid == MATTER_ROOT {
|
||||
|
||||
size := this.matterDao.SizeByPuuidAndUserUuid(MATTER_ROOT, user.Uuid)
|
||||
|
||||
db := core.CONTEXT.GetDB().Model(&User{}).Where("uuid = ?", user.Uuid).Update("total_size", size)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
//update user total size info in cache.
|
||||
user.TotalSize = size
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
matter := this.matterDao.CheckByUuid(matterUuid)
|
||||
|
||||
//only compute dir
|
||||
if matter.Dir {
|
||||
//compute the total size.
|
||||
size := this.matterDao.SizeByPuuidAndUserUuid(matterUuid, user.Uuid)
|
||||
|
||||
//when changed, we update
|
||||
if matter.Size != size {
|
||||
db := core.CONTEXT.GetDB().Model(&Matter{}).Where("uuid = ?", matterUuid).Update("size", size)
|
||||
this.PanicError(db.Error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//update parent recursively.
|
||||
this.ComputeRouteSize(matter.Puuid, user)
|
||||
}
|
||||
|
||||
//inner create directory.
|
||||
func (this *MatterService) createDirectory(request *http.Request, dirMatter *Matter, name string, user *User) *Matter {
|
||||
|
||||
@ -427,14 +470,14 @@ func (this *MatterService) AtomicCreateDirectory(request *http.Request, dirMatte
|
||||
}
|
||||
|
||||
//copy or move may overwrite.
|
||||
func (this *MatterService) handleOverwrite(request *http.Request, userUuid string, destinationPath string, overwrite bool) {
|
||||
func (this *MatterService) handleOverwrite(request *http.Request, user *User, destinationPath string, overwrite bool) {
|
||||
|
||||
destMatter := this.matterDao.findByUserUuidAndPath(userUuid, destinationPath)
|
||||
destMatter := this.matterDao.findByUserUuidAndPath(user.Uuid, destinationPath)
|
||||
if destMatter != nil {
|
||||
//if exist
|
||||
if overwrite {
|
||||
//delete.
|
||||
this.Delete(request, destMatter)
|
||||
this.Delete(request, destMatter, user)
|
||||
} else {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterExist, destMatter.Path))
|
||||
}
|
||||
@ -443,7 +486,7 @@ func (this *MatterService) handleOverwrite(request *http.Request, userUuid strin
|
||||
}
|
||||
|
||||
//move srcMatter to destMatter. invoker must handled the overwrite and lock.
|
||||
func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDirMatter *Matter) {
|
||||
func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDirMatter *Matter, user *User) {
|
||||
|
||||
if srcMatter == nil {
|
||||
panic(result.BadRequest("srcMatter cannot be nil."))
|
||||
@ -453,7 +496,6 @@ func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDi
|
||||
panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory))
|
||||
}
|
||||
|
||||
userUuid := srcMatter.UserUuid
|
||||
srcPuuid := srcMatter.Puuid
|
||||
destDirUuid := destDirMatter.Uuid
|
||||
|
||||
@ -499,13 +541,13 @@ func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDi
|
||||
}
|
||||
|
||||
//reCompute the size of src and dest.
|
||||
this.matterDao.ComputeRouteSize(srcPuuid, userUuid)
|
||||
this.matterDao.ComputeRouteSize(destDirUuid, userUuid)
|
||||
this.ComputeRouteSize(srcPuuid, user)
|
||||
this.ComputeRouteSize(destDirUuid, user)
|
||||
|
||||
}
|
||||
|
||||
//move srcMatter to destMatter(must be dir)
|
||||
func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter, destDirMatter *Matter, overwrite bool) {
|
||||
func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter, destDirMatter *Matter, overwrite bool, user *User) {
|
||||
|
||||
if srcMatter == nil {
|
||||
panic(result.BadRequest("srcMatter cannot be nil."))
|
||||
@ -533,14 +575,14 @@ func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter,
|
||||
|
||||
//handle the overwrite
|
||||
destinationPath := destDirMatter.Path + "/" + srcMatter.Name
|
||||
this.handleOverwrite(request, srcMatter.UserUuid, destinationPath, overwrite)
|
||||
this.handleOverwrite(request, user, destinationPath, overwrite)
|
||||
|
||||
//do the move operation.
|
||||
this.move(request, srcMatter, destDirMatter)
|
||||
this.move(request, srcMatter, destDirMatter, user)
|
||||
}
|
||||
|
||||
//move srcMatters to destMatter(must be dir)
|
||||
func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*Matter, destDirMatter *Matter) {
|
||||
func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*Matter, destDirMatter *Matter, user *User) {
|
||||
|
||||
if destDirMatter == nil {
|
||||
panic(result.BadRequest("destDirMatter cannot be nil."))
|
||||
@ -571,7 +613,7 @@ func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*
|
||||
}
|
||||
|
||||
for _, srcMatter := range srcMatters {
|
||||
this.move(request, srcMatter, destDirMatter)
|
||||
this.move(request, srcMatter, destDirMatter, user)
|
||||
}
|
||||
|
||||
}
|
||||
@ -626,7 +668,7 @@ func (this *MatterService) copy(request *http.Request, srcMatter *Matter, destDi
|
||||
}
|
||||
|
||||
//copy srcMatter to destMatter.
|
||||
func (this *MatterService) AtomicCopy(request *http.Request, srcMatter *Matter, destDirMatter *Matter, name string, overwrite bool) {
|
||||
func (this *MatterService) AtomicCopy(request *http.Request, srcMatter *Matter, destDirMatter *Matter, name string, overwrite bool, user *User) {
|
||||
|
||||
if srcMatter == nil {
|
||||
panic(result.BadRequest("srcMatter cannot be nil."))
|
||||
@ -640,7 +682,7 @@ func (this *MatterService) AtomicCopy(request *http.Request, srcMatter *Matter,
|
||||
}
|
||||
|
||||
destinationPath := destDirMatter.Path + "/" + name
|
||||
this.handleOverwrite(request, srcMatter.UserUuid, destinationPath, overwrite)
|
||||
this.handleOverwrite(request, user, destinationPath, overwrite)
|
||||
|
||||
this.copy(request, srcMatter, destDirMatter, name)
|
||||
}
|
||||
@ -785,7 +827,7 @@ func (this *MatterService) mirror(request *http.Request, srcPath string, destDir
|
||||
if matter != nil {
|
||||
//如果是覆盖,那么删除之前的文件
|
||||
if overwrite {
|
||||
this.Delete(request, matter)
|
||||
this.Delete(request, matter, user)
|
||||
} else {
|
||||
//直接完成。
|
||||
return
|
||||
|
@ -47,6 +47,10 @@ func (this *UserController) RegisterRoutes() map[string]func(writer http.Respons
|
||||
|
||||
func (this *UserController) innerLogin(writer http.ResponseWriter, request *http.Request, user *User) {
|
||||
|
||||
if user.Status == USER_STATUS_DISABLED {
|
||||
panic(result.BadRequestI18n(request, i18n.UserDisabled))
|
||||
}
|
||||
|
||||
//set cookie. expire after 30 days.
|
||||
expiration := time.Now()
|
||||
expiration = expiration.AddDate(0, 0, 30)
|
||||
@ -160,13 +164,16 @@ func (this *UserController) Register(writer http.ResponseWriter, request *http.R
|
||||
|
||||
func (this *UserController) Edit(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
avatarUrl := request.FormValue("avatarUrl")
|
||||
uuid := request.FormValue("uuid")
|
||||
avatarUrl := request.FormValue("avatarUrl")
|
||||
sizeLimitStr := request.FormValue("sizeLimit")
|
||||
totalSizeLimitStr := request.FormValue("totalSizeLimit")
|
||||
|
||||
user := this.checkUser(request)
|
||||
currentUser := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
currentUser.AvatarUrl = avatarUrl
|
||||
|
||||
if user.Role == USER_ROLE_ADMINISTRATOR {
|
||||
//only admin can edit user's sizeLimit
|
||||
var sizeLimit int64 = 0
|
||||
@ -180,12 +187,23 @@ func (this *UserController) Edit(writer http.ResponseWriter, request *http.Reque
|
||||
sizeLimit = int64(intSizeLimit)
|
||||
}
|
||||
currentUser.SizeLimit = sizeLimit
|
||||
|
||||
var totalSizeLimit int64 = 0
|
||||
if totalSizeLimitStr == "" {
|
||||
panic("user's total limit size is required")
|
||||
} else {
|
||||
intTotalSizeLimit, err := strconv.Atoi(totalSizeLimitStr)
|
||||
if err != nil {
|
||||
this.PanicError(err)
|
||||
}
|
||||
totalSizeLimit = int64(intTotalSizeLimit)
|
||||
}
|
||||
currentUser.TotalSizeLimit = totalSizeLimit
|
||||
|
||||
} else if user.Uuid != uuid {
|
||||
panic(result.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
currentUser.AvatarUrl = avatarUrl
|
||||
|
||||
currentUser = this.userDao.Save(currentUser)
|
||||
|
||||
return this.Success(currentUser)
|
||||
|
@ -30,6 +30,7 @@ var (
|
||||
UserRegisterNotAllowd = &Item{English: `admin has banned register`, Chinese: `管理员已禁用自主注册`}
|
||||
UserPasswordLengthError = &Item{English: `password at least 6 chars`, Chinese: `密码长度至少为6位`}
|
||||
UserOldPasswordError = &Item{English: `old password error`, Chinese: `旧密码不正确`}
|
||||
UserDisabled = &Item{English: `user has been disabled`, Chinese: `用户已经被禁用了`}
|
||||
MatterDestinationMustDirectory = &Item{English: `destination must be directory'`, Chinese: `目标对象只能是文件夹。`}
|
||||
MatterExist = &Item{English: `"%s" already exists, invalid operation`, Chinese: `"%s" 已经存在了,操作无效`}
|
||||
MatterDepthExceedLimit = &Item{English: `directory's depth exceed the limit %d > %d`, Chinese: `文件加层数超过限制 %d > %d `}
|
||||
@ -37,6 +38,7 @@ var (
|
||||
MatterSelectNumExceedLimit = &Item{English: `selected files' num exceed the limit %d > %d`, Chinese: `选择的文件数量超出限制了 %d > %d `}
|
||||
MatterSelectSizeExceedLimit = &Item{English: `selected files' size exceed the limit %s > %s`, Chinese: `选择的文件大小超出限制了 %s > %s `}
|
||||
MatterSizeExceedLimit = &Item{English: `uploaded file's size exceed the size limit %s > %s `, Chinese: `上传的文件超过了限制 %s > %s `}
|
||||
MatterSizeExceedTotalLimit = &Item{English: `file's size exceed the total size limit %s > %s `, Chinese: `上传的文件超过了总大小限制 %s > %s `}
|
||||
MatterNameContainSpecialChars = &Item{English: `file name cannot contain special chars \ / : * ? " < > |"`, Chinese: `名称中不能包含以下特殊符号:\ / : * ? " < > |`}
|
||||
MatterMoveRecursive = &Item{English: `directory cannot be moved to itself or its children`, Chinese: `文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。`}
|
||||
MatterNameNoChange = &Item{English: `filename not change, invalid operation`, Chinese: `文件名没有改变,操作无效!`}
|
||||
|
Reference in New Issue
Block a user