Pack 3.0.0.Beta2

This commit is contained in:
zicla
2019-05-07 02:21:39 +08:00
parent 5b95c1a2f4
commit 4780ff8698
26 changed files with 220 additions and 187 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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,
},

View File

@ -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)

View File

@ -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)
}

View File

@ -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) {

View File

@ -25,7 +25,7 @@ const (
)
/**
* file
* file is too common. so we use matter as file.
*/
type Matter struct {
Base

View File

@ -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

View File

@ -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)

View File

@ -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: `文件名没有改变,操作无效!`}