diff --git a/code/rest/alien_controller.go b/code/rest/alien_controller.go index 5971a15..d1c1c2a 100644 --- a/code/rest/alien_controller.go +++ b/code/rest/alien_controller.go @@ -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" "net/http" @@ -120,8 +121,8 @@ func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, reques filename := request.FormValue("filename") if filename == "" { panic("文件名必填") - } else if m, _ := regexp.MatchString(`[<>|*?/\\]`, filename); m { - panic(fmt.Sprintf(`【%s】不符合要求,文件名中不能包含以下特殊符号:< > | * ? / \`, filename)) + } else if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, filename); m { + panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars)) } //什么时间后过期,默认24h @@ -175,7 +176,7 @@ func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, reques dir := request.FormValue("dir") user := this.checkUser(request) - dirMatter := this.matterService.CreateDirectories(user, dir) + dirMatter := this.matterService.CreateDirectories(request, user, dir) mm, _ := time.ParseDuration(fmt.Sprintf("%ds", expire)) uploadToken := &UploadToken{ @@ -257,7 +258,7 @@ func (this *AlienController) Upload(writer http.ResponseWriter, request *http.Re dirMatter := this.matterDao.CheckWithRootByUuid(uploadToken.FolderUuid, user) - matter := this.matterService.AtomicUpload(file, user, dirMatter, uploadToken.Filename, uploadToken.Privacy) + matter := this.matterService.AtomicUpload(request, file, user, dirMatter, uploadToken.Filename, uploadToken.Privacy) //更新这个uploadToken的信息. uploadToken.ExpireTime = time.Now() @@ -294,7 +295,7 @@ func (this *AlienController) CrawlToken(writer http.ResponseWriter, request *htt dirMatter := this.matterDao.CheckWithRootByUuid(uploadToken.FolderUuid, user) - matter := this.matterService.AtomicCrawl(url, uploadToken.Filename, user, dirMatter, uploadToken.Privacy) + matter := this.matterService.AtomicCrawl(request, url, uploadToken.Filename, user, dirMatter, uploadToken.Privacy) //更新这个uploadToken的信息. uploadToken.ExpireTime = time.Now() @@ -316,8 +317,8 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht if filename == "" { panic("文件名必填") - } else if m, _ := regexp.MatchString(`[<>|*?/\\]`, filename); m { - panic(fmt.Sprintf(`【%s】不符合要求,文件名中不能包含以下特殊符号:< > | * ? / \`, filename)) + } else if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, filename); m { + panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars)) } var privacy bool @@ -334,9 +335,9 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht } user := this.checkUser(request) - dirMatter := this.matterService.CreateDirectories(user, dir) + dirMatter := this.matterService.CreateDirectories(request, user, dir) - matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, privacy) + matter := this.matterService.AtomicCrawl(request, url, filename, user, dirMatter, privacy) return this.Success(matter) } diff --git a/code/rest/dav_controller.go b/code/rest/dav_controller.go index f5aa62a..82ec0a0 100644 --- a/code/rest/dav_controller.go +++ b/code/rest/dav_controller.go @@ -4,6 +4,7 @@ import ( "bytes" "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" "io/ioutil" @@ -84,10 +85,10 @@ func (this *DavController) CheckCurrentUser(writer http.ResponseWriter, request user := this.userDao.FindByUsername(username) if user == nil { - panic(result.BadRequest("用户名或密码错误")) + panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError)) } else { if !util.MatchBcrypt(password, user.Password) { - panic(result.BadRequest("用户名或密码错误")) + panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError)) } } @@ -108,7 +109,7 @@ func (this *DavController) HandleRoutes(writer http.ResponseWriter, request *htt path := request.URL.Path //匹配 /api/dav{subPath} - pattern := fmt.Sprintf(`^%s(.*)$`, WEBDAV_PREFFIX) + pattern := fmt.Sprintf(`^%s(.*)$`, WEBDAV_PREFIX) reg := regexp.MustCompile(pattern) strs := reg.FindStringSubmatch(path) if len(strs) == 2 { diff --git a/code/rest/dav_model.go b/code/rest/dav_model.go index becea89..e20a6fe 100644 --- a/code/rest/dav_model.go +++ b/code/rest/dav_model.go @@ -10,7 +10,7 @@ import ( ) //访问前缀,这个是特殊入口 -var WEBDAV_PREFFIX = "/api/dav" +var WEBDAV_PREFIX = "/api/dav" //动态的文件属性 type LiveProp struct { diff --git a/code/rest/dav_service.go b/code/rest/dav_service.go index 8601c26..14633cc 100644 --- a/code/rest/dav_service.go +++ b/code/rest/dav_service.go @@ -59,7 +59,7 @@ func (this *DavService) ParseDepth(request *http.Request) int { return 1 } } else { - panic(result.BadRequest("必须指定Header Depth")) + panic(result.BadRequest("Header Depth cannot be null")) } return depth } @@ -108,7 +108,7 @@ func (this *DavService) PropstatsFromXmlNames(user *User, matter *Matter, xmlNam } if len(properties) == 0 { - panic(result.BadRequest("请求的属性项无法解析!")) + panic(result.BadRequest("cannot parse request properties")) } okPropstat := dav.Propstat{Status: http.StatusOK, Props: properties} @@ -137,7 +137,7 @@ func (this *DavService) Propstats(user *User, matter *Matter, propfind *dav.Prop propstats := make([]dav.Propstat, 0) if propfind.Propname != nil { - panic(result.BadRequest("propfind.Propname != nil 尚未处理")) + panic(result.BadRequest("TODO: propfind.Propname != nil ")) } else if propfind.Allprop != nil { //TODO: 如果include中还有内容,那么包含进去。 @@ -187,7 +187,7 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http fmt.Printf("处理Matter %s\n", matter.Path) propstats := this.Propstats(user, matter, propfind) - path := fmt.Sprintf("%s%s", WEBDAV_PREFFIX, matter.Path) + path := fmt.Sprintf("%s%s", WEBDAV_PREFIX, matter.Path) response := this.makePropstatResponse(path, propstats) err := multiStatusWriter.Write(response) @@ -234,10 +234,10 @@ func (this *DavService) HandlePut(writer http.ResponseWriter, request *http.Requ //如果存在,那么先删除再说。 srcMatter := this.matterDao.findByUserUuidAndPath(user.Uuid, subPath) if srcMatter != nil { - this.matterService.AtomicDelete(srcMatter) + this.matterService.AtomicDelete(request, srcMatter) } - this.matterService.Upload(request.Body, user, dirMatter, filename, true) + this.matterService.Upload(request, request.Body, user, dirMatter, filename, true) } @@ -249,7 +249,7 @@ func (this *DavService) HandleDelete(writer http.ResponseWriter, request *http.R //寻找符合条件的matter. matter := this.matterDao.CheckWithRootByPath(subPath, user) - this.matterService.AtomicDelete(matter) + this.matterService.AtomicDelete(request, matter) } //创建文件夹 @@ -263,7 +263,7 @@ func (this *DavService) HandleMkcol(writer http.ResponseWriter, request *http.Re //寻找符合条件的matter. dirMatter := this.matterDao.CheckWithRootByPath(dirPath, user) - this.matterService.AtomicCreateDirectory(dirMatter, thisDirName, user) + this.matterService.AtomicCreateDirectory(request, dirMatter, thisDirName, user) } @@ -314,17 +314,17 @@ func (this *DavService) prepareMoveCopy( var destinationPath string if destinationStr == "" { - panic(result.BadRequest("Header Destination必填")) + panic(result.BadRequest("Header Destination cannot be null")) } //如果是重命名,那么就不是http开头了。 - if strings.HasPrefix(destinationStr, WEBDAV_PREFFIX) { + if strings.HasPrefix(destinationStr, WEBDAV_PREFIX) { fullDestinationPath = destinationStr } else { destinationUrl, err := url.Parse(destinationStr) this.PanicError(err) if destinationUrl.Host != request.Host { - panic(result.BadRequest("Destination Host不一致. %s %s != %s", destinationStr, destinationUrl.Host, request.Host)) + panic(result.BadRequest("Destination Host not the same. %s %s != %s", destinationStr, destinationUrl.Host, request.Host)) } fullDestinationPath = destinationUrl.Path } @@ -333,13 +333,13 @@ func (this *DavService) prepareMoveCopy( fullDestinationPath = path.Clean(fullDestinationPath) //去除前缀 - pattern := fmt.Sprintf(`^%s(.*)$`, WEBDAV_PREFFIX) + pattern := fmt.Sprintf(`^%s(.*)$`, WEBDAV_PREFIX) reg := regexp.MustCompile(pattern) strs := reg.FindStringSubmatch(fullDestinationPath) if len(strs) == 2 { destinationPath = strs[1] } else { - panic(result.BadRequest("目标前缀必须为:%s", WEBDAV_PREFFIX)) + panic(result.BadRequest("destination prefix must be %s", WEBDAV_PREFIX)) } destinationName = util.GetFilenameOfPath(destinationPath) @@ -362,7 +362,7 @@ func (this *DavService) prepareMoveCopy( //如果是空或者/就是请求根目录 if srcMatter.Uuid == MATTER_ROOT { - panic(result.BadRequest("你不能移动根目录!")) + panic(result.BadRequest("you cannot move the root directory")) } //寻找目标文件夹matter @@ -381,9 +381,9 @@ func (this *DavService) HandleMove(writer http.ResponseWriter, request *http.Req //移动到新目录中去。 if destinationDirPath == srcDirPath { //文件夹没变化,相当于重命名。 - this.matterService.AtomicRename(srcMatter, destinationName, user) + this.matterService.AtomicRename(request, srcMatter, destinationName, user) } else { - this.matterService.AtomicMove(srcMatter, destDirMatter, overwrite) + this.matterService.AtomicMove(request, srcMatter, destDirMatter, overwrite) } this.logger.Info("完成移动 %s => %s", subPath, destDirMatter.Path) @@ -397,7 +397,7 @@ func (this *DavService) HandleCopy(writer http.ResponseWriter, request *http.Req srcMatter, destDirMatter, _, _, destinationName, overwrite := this.prepareMoveCopy(writer, request, user, subPath) //复制到新目录中去。 - this.matterService.AtomicCopy(srcMatter, destDirMatter, destinationName, overwrite) + this.matterService.AtomicCopy(request, srcMatter, destDirMatter, destinationName, overwrite) this.logger.Info("完成复制 %s => %s", subPath, destDirMatter.Path) @@ -406,19 +406,19 @@ func (this *DavService) HandleCopy(writer http.ResponseWriter, request *http.Req //加锁 func (this *DavService) HandleLock(writer http.ResponseWriter, request *http.Request, user *User, subPath string) { - panic(result.BadRequest("不支持LOCK方法")) + panic(result.BadRequest("not support LOCK yet.")) } //解锁 func (this *DavService) HandleUnlock(writer http.ResponseWriter, request *http.Request, user *User, subPath string) { - panic(result.BadRequest("不支持UNLOCK方法")) + panic(result.BadRequest("not support UNLOCK yet.")) } //修改文件属性 func (this *DavService) HandleProppatch(writer http.ResponseWriter, request *http.Request, user *User, subPath string) { - panic(result.BadRequest("不支持PROPPATCH方法")) + panic(result.BadRequest("not support PROPPATCH yet.")) } //处理所有的请求 @@ -482,7 +482,7 @@ func (this *DavService) HandleDav(writer http.ResponseWriter, request *http.Requ } else { - panic(result.BadRequest("该方法还不支持。%s", method)) + panic(result.BadRequest("not support %s yet.", method)) } diff --git a/code/rest/image_cache_controller.go b/code/rest/image_cache_controller.go index b9ad5f6..f346c6f 100644 --- a/code/rest/image_cache_controller.go +++ b/code/rest/image_cache_controller.go @@ -51,7 +51,7 @@ func (this *ImageCacheController) Detail(writer http.ResponseWriter, request *ht uuid := request.FormValue("uuid") if uuid == "" { - panic(result.BadRequest("图片缓存的uuid必填")) + panic(result.BadRequest("uuid cannot be null")) } imageCache := this.imageCacheService.Detail(uuid) @@ -125,7 +125,7 @@ func (this *ImageCacheController) Delete(writer http.ResponseWriter, request *ht uuid := request.FormValue("uuid") if uuid == "" { - panic(result.BadRequest("图片缓存的uuid必填")) + panic(result.BadRequest("uuid cannot be null")) } imageCache := this.imageCacheDao.FindByUuid(uuid) @@ -147,7 +147,7 @@ func (this *ImageCacheController) DeleteBatch(writer http.ResponseWriter, reques uuids := request.FormValue("uuids") if uuids == "" { - panic(result.BadRequest("图片缓存的uuids必填")) + panic(result.BadRequest("uuids cannot be null")) } uuidArray := strings.Split(uuids, ",") diff --git a/code/rest/install_controller.go b/code/rest/install_controller.go index 25405c8..45f64c1 100644 --- a/code/rest/install_controller.go +++ b/code/rest/install_controller.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" + "github.com/eyebluecn/tank/code/tool/i18n" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" "github.com/jinzhu/gorm" @@ -226,10 +227,10 @@ func (this *InstallController) validateTableMetaList(tableInfoList []*InstallTab strs = append(strs, v.DBName) } - panic(result.BadRequest(fmt.Sprintf("%s 表的以下字段缺失:%v", tableInfo.Name, strs))) + panic(result.BadRequest(fmt.Sprintf("table %s miss the following fields %v", tableInfo.Name, strs))) } } else { - panic(result.BadRequest(tableInfo.Name + "表不存在")) + panic(result.BadRequest(tableInfo.Name + " table not exist")) } } @@ -314,11 +315,11 @@ func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request * //验证超级管理员的信息 if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, adminUsername); !m { - panic(result.BadRequest(`超级管理员用户名必填,且只能包含字母,数字和'_''`)) + panic(result.BadRequest(`admin's username cannot oly be alphabet, number or '_'`)) } if len(adminPassword) < 6 { - panic(result.BadRequest(`超级管理员密码长度至少为6位`)) + panic(result.BadRequest(`admin's password at least 6 chars'`)) } //检查是否有重复。 @@ -326,7 +327,7 @@ func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request * db2 := db.Model(&User{}).Where("username = ?", adminUsername).Count(&count2) this.PanicError(db2.Error) if count2 > 0 { - panic(result.BadRequest(`%s该用户名已存在`, adminUsername)) + panic(result.BadRequestI18n(request, i18n.UsernameExist, adminUsername)) } user := &User{} @@ -360,24 +361,24 @@ func (this *InstallController) ValidateAdmin(writer http.ResponseWriter, request //验证超级管理员的信息 if adminUsername == "" { - panic(result.BadRequest(`超级管理员用户名必填`)) + panic(result.BadRequest(`admin's username cannot be null'`)) } if len(adminPassword) < 6 { - panic(result.BadRequest(`超级管理员密码长度至少为6位`)) + panic(result.BadRequest(`admin's password at least 6 chars'`)) } var existUsernameUser = &User{} db = db.Where(&User{Username: adminUsername}).First(existUsernameUser) if db.Error != nil { - panic(result.BadRequest(fmt.Sprintf("%s对应的用户不存在", adminUsername))) + panic(result.BadRequestI18n(request, i18n.UsernameNotExist, adminUsername)) } if !util.MatchBcrypt(adminPassword, existUsernameUser.Password) { - panic(result.BadRequest("用户名或密码错误")) + panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError, adminUsername)) } if existUsernameUser.Role != USER_ROLE_ADMINISTRATOR { - panic(result.BadRequest("该账号不是管理员")) + panic(result.BadRequestI18n(request, i18n.UsernameIsNotAdmin, adminUsername)) } return this.Success("OK") @@ -413,7 +414,7 @@ func (this *InstallController) Finish(writer http.ResponseWriter, request *http. db1 := db.Model(&User{}).Where("role = ?", USER_ROLE_ADMINISTRATOR).Count(&count1) this.PanicError(db1.Error) if count1 == 0 { - panic(result.BadRequest(`请至少配置一名管理员`)) + panic(result.BadRequest(`please config at least one admin user`)) } //通知配置文件安装完毕。 diff --git a/code/rest/matter_controller.go b/code/rest/matter_controller.go index 4a47cdf..94a90c9 100644 --- a/code/rest/matter_controller.go +++ b/code/rest/matter_controller.go @@ -3,6 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" + "github.com/eyebluecn/tank/code/tool/i18n" "github.com/eyebluecn/tank/code/tool/result" "net/http" "strconv" @@ -96,10 +97,10 @@ func (this *MatterController) Detail(writer http.ResponseWriter, request *http.R uuid := request.FormValue("uuid") if uuid == "" { - panic(result.BadRequest("文件的uuid必填")) + panic(result.BadRequest("uuid cannot be null")) } - matter := this.matterService.Detail(uuid) + matter := this.matterService.Detail(request, uuid) //验证当前之人是否有权限查看这么详细。 user := this.checkUser(request) @@ -139,12 +140,12 @@ func (this *MatterController) Page(writer http.ResponseWriter, request *http.Req if shareUuid != "" { if puuid == "" { - panic(result.BadRequest("puuid必填!")) + panic(result.BadRequest("puuid cannot be null")) } dirMatter := this.matterDao.CheckByUuid(puuid) if !dirMatter.Dir { - panic(result.BadRequest("puuid 对应的不是文件夹")) + panic(result.BadRequest("puuid is not a directory")) } user := this.findUser(request) @@ -231,7 +232,7 @@ func (this *MatterController) CreateDirectory(writer http.ResponseWriter, reques dirMatter = this.matterDao.CheckByUuid(puuid) } - matter := this.matterService.AtomicCreateDirectory(dirMatter, name, user) + matter := this.matterService.AtomicCreateDirectory(request, dirMatter, name, user) return this.Success(matter) } @@ -268,7 +269,7 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R dirMatter := this.matterDao.CheckWithRootByUuid(puuid, user) //为了支持多文件同时上传 - matter := this.matterService.Upload(file, user, dirMatter, fileName, privacy) + matter := this.matterService.Upload(request, file, user, dirMatter, fileName, privacy) return this.Success(matter) } @@ -282,7 +283,7 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re user := this.checkUser(request) - dirMatter := this.matterService.CreateDirectories(user, destPath) + dirMatter := this.matterService.CreateDirectories(request, user, destPath) if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) { panic("资源url必填,并且应该以http://或者https://开头") @@ -292,7 +293,7 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re panic("filename 必填") } - matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, true) + matter := this.matterService.AtomicCrawl(request, url, filename, user, dirMatter, true) return this.Success(matter) } @@ -302,7 +303,7 @@ func (this *MatterController) Delete(writer http.ResponseWriter, request *http.R uuid := request.FormValue("uuid") if uuid == "" { - panic(result.BadRequest("文件的uuid必填")) + panic(result.BadRequest("uuid cannot be null")) } matter := this.matterDao.CheckByUuid(uuid) @@ -313,7 +314,7 @@ func (this *MatterController) Delete(writer http.ResponseWriter, request *http.R panic(result.UNAUTHORIZED) } - this.matterService.AtomicDelete(matter) + this.matterService.AtomicDelete(request, matter) return this.Success("删除成功!") } @@ -323,7 +324,7 @@ func (this *MatterController) DeleteBatch(writer http.ResponseWriter, request *h uuids := request.FormValue("uuids") if uuids == "" { - panic(result.BadRequest("文件的uuids必填")) + panic(result.BadRequest("uuids cannot be null")) } uuidArray := strings.Split(uuids, ",") @@ -334,7 +335,7 @@ func (this *MatterController) DeleteBatch(writer http.ResponseWriter, request *h //如果matter已经是nil了,直接跳过 if matter == nil { - this.logger.Warn("%s 对应的文件记录已经不存在了", uuid) + this.logger.Warn("%s not exist anymore", uuid) continue } @@ -344,7 +345,7 @@ func (this *MatterController) DeleteBatch(writer http.ResponseWriter, request *h panic(result.UNAUTHORIZED) } - this.matterService.AtomicDelete(matter) + this.matterService.AtomicDelete(request, matter) } @@ -366,7 +367,7 @@ func (this *MatterController) Rename(writer http.ResponseWriter, request *http.R panic(result.UNAUTHORIZED) } - this.matterService.AtomicRename(matter, name, user) + this.matterService.AtomicRename(request, matter, name, user) return this.Success(matter) } @@ -407,7 +408,7 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req var srcUuids []string //验证参数。 if srcUuidsStr == "" { - panic(result.BadRequest("srcUuids参数必填")) + panic(result.BadRequest("srcUuids cannot be null")) } else { srcUuids = strings.Split(srcUuidsStr, ",") } @@ -417,7 +418,7 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req //验证dest是否有问题 var destMatter = this.matterDao.CheckWithRootByUuid(destUuid, user) if !destMatter.Dir { - panic(result.BadRequest("目标不是文件夹")) + panic(result.BadRequest("destination is not a directory")) } if destMatter.UserUuid != user.Uuid { @@ -431,25 +432,25 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req srcMatter := this.matterDao.CheckByUuid(uuid) if srcMatter.Puuid == destMatter.Uuid { - panic(result.BadRequest("没有进行移动,操作无效!")) + panic(result.BadRequest("no move, invalid operation")) } //判断同级文件夹中是否有同名的文件 count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, destMatter.Uuid, srcMatter.Dir, srcMatter.Name) if count > 0 { - panic(result.BadRequest("【" + srcMatter.Name + "】在目标文件夹已经存在了,操作失败。")) + panic(result.BadRequestI18n(request, i18n.MatterExist, srcMatter.Name)) } //判断和目标文件夹是否是同一个主人。 if srcMatter.UserUuid != destMatter.UserUuid { - panic("文件和目标文件夹的拥有者不是同一人") + panic("owner not the same") } srcMatters = append(srcMatters, srcMatter) } - this.matterService.AtomicMoveBatch(srcMatters, destMatter) + this.matterService.AtomicMoveBatch(request, srcMatters, destMatter) return this.Success(nil) } @@ -462,7 +463,7 @@ func (this *MatterController) Mirror(writer http.ResponseWriter, request *http.R overwriteStr := request.FormValue("overwrite") if srcPath == "" { - panic(result.BadRequest("srcPath必填")) + panic(result.BadRequest("srcPath cannot be null")) } overwrite := false @@ -472,7 +473,7 @@ func (this *MatterController) Mirror(writer http.ResponseWriter, request *http.R user := this.userDao.checkUser(request) - this.matterService.AtomicMirror(srcPath, destPath, overwrite, user) + this.matterService.AtomicMirror(request, srcPath, destPath, overwrite, user) return this.Success(nil) @@ -483,7 +484,7 @@ func (this *MatterController) Zip(writer http.ResponseWriter, request *http.Requ uuids := request.FormValue("uuids") if uuids == "" { - panic(result.BadRequest("文件的uuids必填")) + panic(result.BadRequest("uuids cannot be null")) } uuidArray := strings.Split(uuids, ",") diff --git a/code/rest/matter_dao.go b/code/rest/matter_dao.go index 6d0bea7..bfccb3f 100644 --- a/code/rest/matter_dao.go +++ b/code/rest/matter_dao.go @@ -63,13 +63,13 @@ func (this *MatterDao) CheckByUuid(uuid string) *Matter { func (this *MatterDao) CheckWithRootByUuid(uuid string, user *User) *Matter { if uuid == "" { - panic(result.BadRequest("uuid cannot be nil.")) + panic(result.BadRequest("uuid cannot be null.")) } var matter *Matter if uuid == MATTER_ROOT { if user == nil { - panic(result.BadRequest("user cannot be nil.")) + panic(result.BadRequest("user cannot be null.")) } matter = NewRootMatter(user) } else { @@ -85,7 +85,7 @@ func (this *MatterDao) CheckWithRootByPath(path string, user *User) *Matter { var matter *Matter if user == nil { - panic(result.BadRequest("user cannot be nil.")) + panic(result.BadRequest("user cannot be null.")) } //目标文件夹matter @@ -471,11 +471,11 @@ func (this *MatterDao) findByUserUuidAndPath(userUuid string, path string) *Matt func (this *MatterDao) checkByUserUuidAndPath(userUuid string, path string) *Matter { if path == "" { - panic(result.BadRequest("path 不能为空")) + panic(result.BadRequest("path cannot be null")) } matter := this.findByUserUuidAndPath(userUuid, path) if matter == nil { - panic(result.NotFound("path = %s 不存在", path)) + panic(result.NotFound("path = %s not exists", path)) } return matter diff --git a/code/rest/matter_model.go b/code/rest/matter_model.go index 7296627..806e8f3 100644 --- a/code/rest/matter_model.go +++ b/code/rest/matter_model.go @@ -17,6 +17,8 @@ const ( MATTER_NAME_MAX_LENGTH = 200 //matter文件夹最大深度 MATTER_NAME_MAX_DEPTH = 32 + //matter name pattern + MATTER_NAME_PATTERN = `[\\/:*?"<>|]` ) /** diff --git a/code/rest/matter_service.go b/code/rest/matter_service.go index 5f337cd..867a0ba 100644 --- a/code/rest/matter_service.go +++ b/code/rest/matter_service.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/download" + "github.com/eyebluecn/tank/code/tool/i18n" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" "io" @@ -107,12 +108,10 @@ func (this *MatterService) DownloadZip( count = count + this.matterDao.CountByUserUuidAndPath(matter.UserUuid, matter.Path) } - this.logger.Info("此次下载包含文件数量 %d", count) - //文件数量判断。 if preference.DownloadDirMaxNum >= 0 { if count > preference.DownloadDirMaxNum { - panic(result.BadRequest("下载包中文件数量 %d 超出限制了 %d ", count, preference.DownloadDirMaxNum)) + panic(result.BadRequestI18n(request, i18n.MatterSelectNumExceedLimit, count, preference.DownloadDirMaxNum)) } } @@ -122,14 +121,11 @@ func (this *MatterService) DownloadZip( sumSize = sumSize + this.matterDao.SumSizeByUserUuidAndPath(matter.UserUuid, matter.Path) } - //验证文件夹中文件总大小。 - this.logger.Info("此次下载大小为 %s", util.HumanFileSize(sumSize)) - //判断用户自身上传大小的限制 //大小判断 if preference.DownloadDirMaxSize >= 0 { if sumSize > preference.DownloadDirMaxSize { - panic(result.BadRequest("文件夹大小%s超出下载限制%s ", util.HumanFileSize(sumSize), util.HumanFileSize(preference.DownloadDirMaxSize))) + panic(result.BadRequestI18n(request, i18n.MatterSelectSizeExceedLimit, util.HumanFileSize(sumSize), util.HumanFileSize(preference.DownloadDirMaxSize))) } } @@ -145,7 +141,7 @@ func (this *MatterService) DownloadZip( destZipPath := fmt.Sprintf("%s/%s", destZipDirPath, destZipName) //_ = util.Zip(matter.AbsolutePath(), destZipPath) - this.zipMatters(matters, destZipPath) + this.zipMatters(request, matters, destZipPath) //下载 download.DownloadFile(writer, request, destZipPath, destZipName, true) @@ -153,17 +149,17 @@ func (this *MatterService) DownloadZip( //删除临时压缩文件 err := os.Remove(destZipPath) if err != nil { - this.logger.Error("删除磁盘上的文件出错 %s", err.Error()) + this.logger.Error("error while deleting zip file %s", err.Error()) } util.DeleteEmptyDir(destZipDirPath) } //打包一系列的matter -func (this *MatterService) zipMatters(matters []*Matter, destPath string) { +func (this *MatterService) zipMatters(request *http.Request, matters []*Matter, destPath string) { if util.PathExists(destPath) { - panic(result.BadRequest("%s 已经存在了", destPath)) + panic(result.BadRequest("%s exists", destPath)) } //要求必须是同一个父matter下的。 @@ -184,7 +180,7 @@ func (this *MatterService) zipMatters(matters []*Matter, destPath string) { //将每个matter的children装填好 for _, m := range matters { - this.WrapChildrenDetail(m) + this.WrapChildrenDetail(request, m) } // 创建准备写入的文件 @@ -259,10 +255,10 @@ func (this *MatterService) zipMatters(matters []*Matter, destPath string) { } //删除文件 -func (this *MatterService) Delete(matter *Matter) { +func (this *MatterService) Delete(request *http.Request, matter *Matter) { if matter == nil { - panic(result.BadRequest("matter不能为nil")) + panic(result.BadRequest("matter cannot be nil")) } this.matterDao.Delete(matter) @@ -272,21 +268,21 @@ func (this *MatterService) Delete(matter *Matter) { } //删除文件 -func (this *MatterService) AtomicDelete(matter *Matter) { +func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter) { if matter == nil { - panic(result.BadRequest("matter不能为nil")) + panic(result.BadRequest("matter cannot be nil")) } //操作锁 this.userService.MatterLock(matter.UserUuid) defer this.userService.MatterUnlock(matter.UserUuid) - this.Delete(matter) + this.Delete(request, matter) } //上传文件 -func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { +func (this *MatterService) Upload(request *http.Request, file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { if user == nil { panic(result.BadRequest("user cannot be nil.")) @@ -299,7 +295,7 @@ func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, //文件名不能太长。 if len(filename) > MATTER_NAME_MAX_LENGTH { - panic(result.BadRequest("文件名不能超过%s", MATTER_NAME_MAX_LENGTH)) + panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(filename), MATTER_NAME_MAX_LENGTH)) } //文件夹路径 @@ -308,7 +304,7 @@ func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, false, filename) if count > 0 { - panic(result.BadRequest("该目录下%s已经存在了", filename)) + panic(result.BadRequest("%s already exists", filename)) } //获取文件应该存放在的物理路径的绝对路径和相对路径。 @@ -346,7 +342,7 @@ func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, err = os.Remove(fileAbsolutePath) this.PanicError(err) - panic(result.BadRequest("文件大小超出限制 %s > %s ", util.HumanFileSize(user.SizeLimit), util.HumanFileSize(fileSize))) + panic(result.BadRequest("file's size exceed the limit %s > %s ", util.HumanFileSize(user.SizeLimit), util.HumanFileSize(fileSize))) } } @@ -373,7 +369,7 @@ func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter, } //上传文件 -func (this *MatterService) AtomicUpload(file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { +func (this *MatterService) AtomicUpload(request *http.Request, file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { if user == nil { panic(result.BadRequest("user cannot be nil.")) @@ -383,41 +379,41 @@ func (this *MatterService) AtomicUpload(file io.Reader, user *User, dirMatter *M this.userService.MatterLock(user.Uuid) defer this.userService.MatterUnlock(user.Uuid) - return this.Upload(file, user, dirMatter, filename, privacy) + return this.Upload(request, file, user, dirMatter, filename, privacy) } //内部创建文件,不带操作锁。 -func (this *MatterService) createDirectory(dirMatter *Matter, name string, user *User) *Matter { +func (this *MatterService) createDirectory(request *http.Request, dirMatter *Matter, name string, user *User) *Matter { //父级matter必须存在 if dirMatter == nil { - panic(result.BadRequest("dirMatter必须指定")) + panic(result.BadRequest("dirMatter cannot be nil")) } //必须是文件夹 if !dirMatter.Dir { - panic(result.BadRequest("dirMatter必须是文件夹")) + panic(result.BadRequest("dirMatter must be directory")) } if dirMatter.UserUuid != user.Uuid { - panic(result.BadRequest("dirMatter的userUuid和user不一致")) + panic(result.BadRequest("file's user not the same")) } name = strings.TrimSpace(name) //验证参数。 if name == "" { - panic(result.BadRequest("name参数必填,并且不能全是空格")) + panic(result.BadRequest("name cannot be blank")) } if len(name) > MATTER_NAME_MAX_LENGTH { - panic(result.BadRequest("name长度不能超过%d", MATTER_NAME_MAX_LENGTH)) + panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(name), MATTER_NAME_MAX_LENGTH)) } - if m, _ := regexp.MatchString(`[<>|*?/\\]`, name); m { - panic(result.BadRequest(`名称中不能包含以下特殊符号:< > | * ? / \`)) + if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, name); m { + panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars)) } //判断同级文件夹中是否有同名的文件夹。存在了直接返回即可。 @@ -427,10 +423,9 @@ func (this *MatterService) createDirectory(dirMatter *Matter, name string, user } parts := strings.Split(dirMatter.Path, "/") - this.logger.Info("%s的层数:%d", dirMatter.Name, len(parts)) - if len(parts) > 32 { - panic(result.BadRequest("文件夹最多%d层", MATTER_NAME_MAX_DEPTH)) + if len(parts) > MATTER_NAME_MAX_DEPTH { + panic(result.BadRequestI18n(request, i18n.MatterDepthExceedLimit, len(parts), MATTER_NAME_MAX_DEPTH)) } //绝对路径 @@ -459,19 +454,19 @@ func (this *MatterService) createDirectory(dirMatter *Matter, name string, user } //在dirMatter中创建文件夹 返回刚刚创建的这个文件夹 -func (this *MatterService) AtomicCreateDirectory(dirMatter *Matter, name string, user *User) *Matter { +func (this *MatterService) AtomicCreateDirectory(request *http.Request, dirMatter *Matter, name string, user *User) *Matter { //操作锁 this.userService.MatterLock(user.Uuid) defer this.userService.MatterUnlock(user.Uuid) - matter := this.createDirectory(dirMatter, name, user) + matter := this.createDirectory(request, dirMatter, name, user) return matter } //处理 移动和复制时可能存在的覆盖问题。 -func (this *MatterService) handleOverwrite(userUuid string, destinationPath string, overwrite bool) { +func (this *MatterService) handleOverwrite(request *http.Request, userUuid string, destinationPath string, overwrite bool) { //目标matter。因为有可能已经存在了 destMatter := this.matterDao.findByUserUuidAndPath(userUuid, destinationPath) @@ -480,23 +475,23 @@ func (this *MatterService) handleOverwrite(userUuid string, destinationPath stri //如果目标matter还存在了。 if overwrite { //要求覆盖。那么删除。 - this.Delete(destMatter) + this.Delete(request, destMatter) } else { - panic(result.BadRequest("%s已经存在,操作失败!", destMatter.Path)) + panic(result.BadRequestI18n(request, i18n.MatterExist, destMatter.Path)) } } } //将一个srcMatter放置到另一个destMatter(必须为文件夹)下 不关注 overwrite 和 lock. -func (this *MatterService) move(srcMatter *Matter, destDirMatter *Matter) { +func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDirMatter *Matter) { if srcMatter == nil { panic(result.BadRequest("srcMatter cannot be nil.")) } if !destDirMatter.Dir { - panic(result.BadRequest("目标必须为文件夹")) + panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory)) } userUuid := srcMatter.UserUuid @@ -550,7 +545,7 @@ func (this *MatterService) move(srcMatter *Matter, destDirMatter *Matter) { } //将一个srcMatter放置到另一个destMatter(必须为文件夹)下 -func (this *MatterService) AtomicMove(srcMatter *Matter, destDirMatter *Matter, overwrite bool) { +func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter, destDirMatter *Matter, overwrite bool) { if srcMatter == nil { panic(result.BadRequest("srcMatter cannot be nil.")) @@ -564,29 +559,29 @@ func (this *MatterService) AtomicMove(srcMatter *Matter, destDirMatter *Matter, panic(result.BadRequest("destDirMatter cannot be nil.")) } if !destDirMatter.Dir { - panic(result.BadRequest("目标必须为文件夹")) + panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory)) } //文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。 - destDirMatter = this.WrapParentDetail(destDirMatter) + destDirMatter = this.WrapParentDetail(request, destDirMatter) tmpMatter := destDirMatter for tmpMatter != nil { if srcMatter.Uuid == tmpMatter.Uuid { - panic("文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。") + panic(result.BadRequestI18n(request, i18n.MatterMoveRecursive)) } tmpMatter = tmpMatter.Parent } //处理覆盖的问题 destinationPath := destDirMatter.Path + "/" + srcMatter.Name - this.handleOverwrite(srcMatter.UserUuid, destinationPath, overwrite) + this.handleOverwrite(request, srcMatter.UserUuid, destinationPath, overwrite) //做move操作。 - this.move(srcMatter, destDirMatter) + this.move(request, srcMatter, destDirMatter) } //将一个srcMatter放置到另一个destMatter(必须为文件夹)下 -func (this *MatterService) AtomicMoveBatch(srcMatters []*Matter, destDirMatter *Matter) { +func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*Matter, destDirMatter *Matter) { if destDirMatter == nil { panic(result.BadRequest("destDirMatter cannot be nil.")) @@ -601,11 +596,11 @@ func (this *MatterService) AtomicMoveBatch(srcMatters []*Matter, destDirMatter * } if !destDirMatter.Dir { - panic(result.BadRequest("目标必须为文件夹")) + panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory)) } //文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。 - destDirMatter = this.WrapParentDetail(destDirMatter) + destDirMatter = this.WrapParentDetail(request, destDirMatter) for _, srcMatter := range srcMatters { tmpMatter := destDirMatter @@ -618,13 +613,13 @@ func (this *MatterService) AtomicMoveBatch(srcMatters []*Matter, destDirMatter * } for _, srcMatter := range srcMatters { - this.move(srcMatter, destDirMatter) + this.move(request, srcMatter, destDirMatter) } } //内部移动一个文件(提供给Copy调用),无需关心overwrite问题。 -func (this *MatterService) copy(srcMatter *Matter, destDirMatter *Matter, name string) { +func (this *MatterService) copy(request *http.Request, srcMatter *Matter, destDirMatter *Matter, name string) { if srcMatter.Dir { @@ -648,7 +643,7 @@ func (this *MatterService) copy(srcMatter *Matter, destDirMatter *Matter, name s //复制子文件或文件夹 matters := this.matterDao.ListByPuuidAndUserUuid(srcMatter.Uuid, srcMatter.UserUuid, nil) for _, m := range matters { - this.copy(m, newMatter, m.Name) + this.copy(request, m, newMatter, m.Name) } } else { @@ -678,7 +673,7 @@ func (this *MatterService) copy(srcMatter *Matter, destDirMatter *Matter, name s } //将一个srcMatter复制到另一个destMatter(必须为文件夹)下,名字叫做name -func (this *MatterService) AtomicCopy(srcMatter *Matter, destDirMatter *Matter, name string, overwrite bool) { +func (this *MatterService) AtomicCopy(request *http.Request, srcMatter *Matter, destDirMatter *Matter, name string, overwrite bool) { if srcMatter == nil { panic(result.BadRequest("srcMatter cannot be nil.")) @@ -689,17 +684,17 @@ func (this *MatterService) AtomicCopy(srcMatter *Matter, destDirMatter *Matter, defer this.userService.MatterUnlock(srcMatter.UserUuid) if !destDirMatter.Dir { - panic(result.BadRequest("目标必须为文件夹")) + panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory)) } destinationPath := destDirMatter.Path + "/" + name - this.handleOverwrite(srcMatter.UserUuid, destinationPath, overwrite) + this.handleOverwrite(request, srcMatter.UserUuid, destinationPath, overwrite) - this.copy(srcMatter, destDirMatter, name) + this.copy(request, srcMatter, destDirMatter, name) } //将一个matter 重命名为 name -func (this *MatterService) AtomicRename(matter *Matter, name string, user *User) { +func (this *MatterService) AtomicRename(request *http.Request, matter *Matter, name string, user *User) { if user == nil { panic(result.BadRequest("user cannot be nil")) @@ -711,25 +706,27 @@ func (this *MatterService) AtomicRename(matter *Matter, name string, user *User) //验证参数。 if name == "" { - panic(result.BadRequest("name参数必填")) + panic(result.BadRequest("name cannot be null")) } - if m, _ := regexp.MatchString(`[<>|*?/\\]`, name); m { - panic(result.BadRequest(`名称中不能包含以下特殊符号:< > | * ? / \`)) + if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, name); m { + panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars)) } - if len(name) > 200 { - panic("name长度不能超过200") + //文件名不能太长。 + if len(name) > MATTER_NAME_MAX_LENGTH { + panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(name), MATTER_NAME_MAX_LENGTH)) } if name == matter.Name { - panic(result.BadRequest("新名称和旧名称一样,操作失败!")) + panic(result.BadRequestI18n(request, i18n.MatterNameNoChange)) } //判断同级文件夹中是否有同名的文件 count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, matter.Puuid, matter.Dir, name) if count > 0 { - panic(result.BadRequest("【" + name + "】已经存在了,请使用其他名称。")) + + panic(result.BadRequestI18n(request, i18n.MatterExist, name)) } if matter.Dir { @@ -781,7 +778,7 @@ func (this *MatterService) AtomicRename(matter *Matter, name string, user *User) } //将本地文件映射到蓝眼云盘中去。 -func (this *MatterService) AtomicMirror(srcPath string, destPath string, overwrite bool, user *User) { +func (this *MatterService) AtomicMirror(request *http.Request, srcPath string, destPath string, overwrite bool, user *User) { if user == nil { panic(result.BadRequest("user cannot be nil")) @@ -793,16 +790,16 @@ func (this *MatterService) AtomicMirror(srcPath string, destPath string, overwri //验证参数。 if destPath == "" { - panic(result.BadRequest("dest 参数必填")) + panic(result.BadRequest("dest cannot be null")) } - destDirMatter := this.CreateDirectories(user, destPath) + destDirMatter := this.CreateDirectories(request, user, destPath) - this.mirror(srcPath, destDirMatter, overwrite, user) + this.mirror(request, srcPath, destDirMatter, overwrite, user) } //将本地文件/文件夹映射到蓝眼云盘中去。 -func (this *MatterService) mirror(srcPath string, destDirMatter *Matter, overwrite bool, user *User) { +func (this *MatterService) mirror(request *http.Request, srcPath string, destDirMatter *Matter, overwrite bool, user *User) { if user == nil { panic(result.BadRequest("user cannot be nil")) @@ -828,7 +825,7 @@ func (this *MatterService) mirror(srcPath string, destDirMatter *Matter, overwri srcDirMatter := this.matterDao.FindByUserUuidAndPuuidAndDirAndName(user.Uuid, destDirMatter.Uuid, true, fileStat.Name()) if srcDirMatter == nil { - srcDirMatter = this.createDirectory(destDirMatter, fileStat.Name(), user) + srcDirMatter = this.createDirectory(request, destDirMatter, fileStat.Name(), user) } fileInfos, err := ioutil.ReadDir(srcPath) @@ -838,7 +835,7 @@ func (this *MatterService) mirror(srcPath string, destDirMatter *Matter, overwri for _, fileInfo := range fileInfos { path := fmt.Sprintf("%s/%s", srcPath, fileInfo.Name()) - this.mirror(path, srcDirMatter, overwrite, user) + this.mirror(request, path, srcDirMatter, overwrite, user) } } else { @@ -848,7 +845,7 @@ func (this *MatterService) mirror(srcPath string, destDirMatter *Matter, overwri if matter != nil { //如果是覆盖,那么删除之前的文件 if overwrite { - this.Delete(matter) + this.Delete(request, matter) } else { //直接完成。 return @@ -863,14 +860,14 @@ func (this *MatterService) mirror(srcPath string, destDirMatter *Matter, overwri this.PanicError(err) }() - this.Upload(file, user, destDirMatter, fileStat.Name(), true) + this.Upload(request, file, user, destDirMatter, fileStat.Name(), true) } } //根据一个文件夹路径,依次创建,找到最后一个文件夹的matter,如果中途出错,返回err. 如果存在了那就直接返回即可。 -func (this *MatterService) CreateDirectories(user *User, dirPath string) *Matter { +func (this *MatterService) CreateDirectories(request *http.Request, user *User, dirPath string) *Matter { if dirPath == "" { panic(`文件夹不能为空`) @@ -878,8 +875,8 @@ func (this *MatterService) CreateDirectories(user *User, dirPath string) *Matter panic(`文件夹必须以/开头`) } else if strings.Index(dirPath, "//") != -1 { panic(`文件夹不能出现连续的//`) - } else if m, _ := regexp.MatchString(`[<>|*?\\]`, dirPath); m { - panic(`文件夹中不能包含以下特殊符号:< > | * ? \`) + } else if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, dirPath); m { + panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars)) } if dirPath == "/" { @@ -895,7 +892,7 @@ func (this *MatterService) CreateDirectories(user *User, dirPath string) *Matter folders := strings.Split(dirPath, "/") if len(folders) > MATTER_NAME_MAX_DEPTH { - panic(result.BadRequest("文件夹最多%d层。", MATTER_NAME_MAX_DEPTH)) + panic(result.BadRequestI18n(request, i18n.MatterDepthExceedLimit, len(folders), MATTER_NAME_MAX_DEPTH)) } var dirMatter *Matter @@ -907,14 +904,14 @@ func (this *MatterService) CreateDirectories(user *User, dirPath string) *Matter continue } - dirMatter = this.createDirectory(dirMatter, name, user) + dirMatter = this.createDirectory(request, dirMatter, name, user) } return dirMatter } //包装某个matter的详情。会把父级依次倒着装进去。如果中途出错,直接抛出异常。 -func (this *MatterService) WrapParentDetail(matter *Matter) *Matter { +func (this *MatterService) WrapParentDetail(request *http.Request, matter *Matter) *Matter { if matter == nil { panic(result.BadRequest("matter cannot be nil.")) @@ -934,7 +931,7 @@ func (this *MatterService) WrapParentDetail(matter *Matter) *Matter { } //包装某个matter的详情。会把子级依次装进去。如果中途出错,直接抛出异常。 -func (this *MatterService) WrapChildrenDetail(matter *Matter) { +func (this *MatterService) WrapChildrenDetail(request *http.Request, matter *Matter) { if matter == nil { panic(result.BadRequest("matter cannot be nil.")) @@ -946,20 +943,20 @@ func (this *MatterService) WrapChildrenDetail(matter *Matter) { matter.Children = children for _, child := range matter.Children { - this.WrapChildrenDetail(child) + this.WrapChildrenDetail(request, child) } } } //获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。 -func (this *MatterService) Detail(uuid string) *Matter { +func (this *MatterService) Detail(request *http.Request, uuid string) *Matter { matter := this.matterDao.CheckByUuid(uuid) - return this.WrapParentDetail(matter) + return this.WrapParentDetail(request, matter) } //去指定的url中爬文件 -func (this *MatterService) AtomicCrawl(url string, filename string, user *User, dirMatter *Matter, privacy bool) *Matter { +func (this *MatterService) AtomicCrawl(request *http.Request, url string, filename string, user *User, dirMatter *Matter, privacy bool) *Matter { if user == nil { panic(result.BadRequest("user cannot be nil.")) @@ -970,7 +967,7 @@ func (this *MatterService) AtomicCrawl(url string, filename string, user *User, defer this.userService.MatterUnlock(user.Uuid) if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) { - panic("资源url必填,并且应该以http://或者https://开头") + panic(`url must start with http:// or https://`) } if filename == "" { @@ -981,7 +978,7 @@ func (this *MatterService) AtomicCrawl(url string, filename string, user *User, resp, err := http.Get(url) this.PanicError(err) - return this.Upload(resp.Body, user, dirMatter, filename, privacy) + return this.Upload(request, resp.Body, user, dirMatter, filename, privacy) } //调整一个Matter的path值 diff --git a/code/rest/preference_controller.go b/code/rest/preference_controller.go index 3e1d1e5..5634abe 100644 --- a/code/rest/preference_controller.go +++ b/code/rest/preference_controller.go @@ -136,7 +136,7 @@ func (this *PreferenceController) SystemCleanup(writer http.ResponseWriter, requ password := request.FormValue("password") if !util.MatchBcrypt(password, user.Password) { - panic(result.BadRequest("密码错误,不能执行!")) + panic(result.BadRequest("password error")) } //清空系统 diff --git a/code/rest/share_controller.go b/code/rest/share_controller.go index 4c3f965..b803077 100644 --- a/code/rest/share_controller.go +++ b/code/rest/share_controller.go @@ -3,6 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" + "github.com/eyebluecn/tank/code/tool/i18n" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" "net/http" @@ -77,7 +78,7 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re expireTimeStr := request.FormValue("expireTime") if matterUuids == "" { - panic(result.BadRequest("matterUuids必填")) + panic(result.BadRequest("matterUuids cannot be null")) } var expireTime time.Time @@ -88,13 +89,13 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re } else { if expireTimeStr == "" { - panic(result.BadRequest("时间格式错误!")) + panic(result.BadRequest("time format error")) } else { expireTime = util.ConvertDateTimeStringToTime(expireTimeStr) } if expireTime.Before(time.Now()) { - panic(result.BadRequest("过期时间错误!")) + panic(result.BadRequest("expire time cannot before now")) } } @@ -102,9 +103,9 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re uuidArray := strings.Split(matterUuids, ",") if len(uuidArray) == 0 { - panic(result.BadRequest("请至少分享一个文件")) + panic(result.BadRequest("share at least one file")) } else if len(uuidArray) > SHARE_MAX_NUM { - panic(result.BadRequest("一次分享文件数不能超过 %d", SHARE_MAX_NUM)) + panic(result.BadRequestI18n(request, i18n.ShareNumExceedLimit, len(uuidArray), SHARE_MAX_NUM)) } var name string @@ -174,7 +175,7 @@ func (this *ShareController) Delete(writer http.ResponseWriter, request *http.Re uuid := request.FormValue("uuid") if uuid == "" { - panic(result.BadRequest("uuid必填")) + panic(result.BadRequest("uuid cannot be null")) } share := this.shareDao.FindByUuid(uuid) @@ -195,7 +196,7 @@ func (this *ShareController) DeleteBatch(writer http.ResponseWriter, request *ht uuids := request.FormValue("uuids") if uuids == "" { - panic(result.BadRequest("uuids必填")) + panic(result.BadRequest("uuids cannot be null")) } uuidArray := strings.Split(uuids, ",") @@ -221,7 +222,7 @@ func (this *ShareController) Detail(writer http.ResponseWriter, request *http.Re uuid := request.FormValue("uuid") if uuid == "" { - panic(result.BadRequest("分享的uuid必填")) + panic(result.BadRequest("uuid cannot be null")) } share := this.shareDao.CheckByUuid(uuid) @@ -327,12 +328,12 @@ func (this *ShareController) Browse(writer http.ResponseWriter, request *http.Re dirMatter := this.matterDao.CheckByUuid(puuid) share.DirMatter = dirMatter } else { - dirMatter := this.matterService.Detail(puuid) + dirMatter := this.matterService.Detail(request, puuid) //验证 shareRootMatter是否在被分享。 shareRootMatter := this.matterDao.CheckByUuid(rootUuid) if !shareRootMatter.Dir { - panic(result.BadRequest("只有文件夹可以浏览!")) + panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory)) } this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, shareRootMatter.Uuid) @@ -349,7 +350,7 @@ func (this *ShareController) Browse(writer http.ResponseWriter, request *http.Re } if !find { - panic(result.BadRequest("rootUuid不是分享的根目录")) + panic(result.BadRequest("rootUuid is not the root of share.")) } share.DirMatter = dirMatter diff --git a/code/rest/share_service.go b/code/rest/share_service.go index 4c98bb0..e0e42fe 100644 --- a/code/rest/share_service.go +++ b/code/rest/share_service.go @@ -65,12 +65,11 @@ func (this *ShareService) CheckShare(shareUuid string, code string, user *User) } else { if !share.ExpireInfinity { if share.ExpireTime.Before(time.Now()) { - panic(result.BadRequest("分享已过期")) + panic(result.BadRequest("share expired")) } } } } - return share } @@ -106,7 +105,7 @@ func (this *ShareService) ValidateMatter(shareUuid string, code string, user *Us //保证 puuid对应的matter是shareRootMatter的子文件夹。 child := strings.HasPrefix(matter.Path, shareRootMatter.Path) if !child { - panic(result.Unauthorized("%s 不是 %s 的子文件夹!", matter.Uuid, shareRootUuid)) + panic(result.BadRequest("%s is not %s's children", matter.Uuid, shareRootUuid)) } } diff --git a/code/rest/user_controller.go b/code/rest/user_controller.go index bc21ff9..041c041 100644 --- a/code/rest/user_controller.go +++ b/code/rest/user_controller.go @@ -3,6 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" + "github.com/eyebluecn/tank/code/tool/i18n" "github.com/eyebluecn/tank/code/tool/result" "github.com/eyebluecn/tank/code/tool/util" "net/http" @@ -87,20 +88,17 @@ func (this *UserController) Login(writer http.ResponseWriter, request *http.Requ password := request.FormValue("password") if "" == username || "" == password { - - panic(result.BadRequest("请输入用户名和密码")) + panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordCannotNull)) } user := this.userDao.FindByUsername(username) if user == nil { - panic(result.BadRequest("用户名或密码错误")) + panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError)) } if !util.MatchBcrypt(password, user.Password) { - - panic(result.BadRequest("用户名或密码错误")) + panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError)) } - this.innerLogin(writer, request, user) return this.Success(user) @@ -111,15 +109,15 @@ func (this *UserController) AuthenticationLogin(writer http.ResponseWriter, requ authentication := request.FormValue("authentication") if authentication == "" { - panic(result.BadRequest("authentication 必填")) + panic(result.BadRequest("authentication cannot be null")) } session := this.sessionDao.FindByUuid(authentication) if session == nil { - panic(result.BadRequest("authentication 错误")) + panic(result.BadRequest("authentication error")) } duration := session.ExpireTime.Sub(time.Now()) if duration <= 0 { - panic(result.BadRequest("登录信息已过期")) + panic(result.BadRequest("login info has expired")) } user := this.userDao.CheckByUuid(session.UserUuid) @@ -135,20 +133,20 @@ func (this *UserController) Register(writer http.ResponseWriter, request *http.R preference := this.preferenceService.Fetch() if !preference.AllowRegister { - panic(result.Unauthorized("管理员已禁用自主注册!")) + panic(result.BadRequestI18n(request, i18n.UserRegisterNotAllowd)) } if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, username); !m { - panic(`用户名必填,且只能包含字母,数字和'_''`) + panic(result.BadRequestI18n(request, i18n.UsernameError)) } if len(password) < 6 { - panic(`密码长度至少为6位`) + panic(result.BadRequestI18n(request, i18n.UserPasswordLengthError)) } //判断重名。 if this.userDao.CountByUsername(username) > 0 { - panic(result.BadRequest("%s已经被使用,请更换。", username)) + panic(result.BadRequestI18n(request, i18n.UsernameExist, username)) } user := &User{ @@ -193,7 +191,7 @@ func (this *UserController) Edit(writer http.ResponseWriter, request *http.Reque user.SizeLimit = sizeLimit } else { if currentUser.Uuid != uuid { - panic(result.Unauthorized("没有权限")) + panic(result.UNAUTHORIZED) } } @@ -354,7 +352,7 @@ func (this *UserController) ChangePassword(writer http.ResponseWriter, request * oldPassword := request.FormValue("oldPassword") newPassword := request.FormValue("newPassword") if oldPassword == "" || newPassword == "" { - panic(result.BadRequest("旧密码和新密码都不能为空")) + panic(result.BadRequest("oldPassword and newPassword cannot be null")) } user := this.checkUser(request) @@ -365,7 +363,7 @@ func (this *UserController) ChangePassword(writer http.ResponseWriter, request * } if !util.MatchBcrypt(oldPassword, user.Password) { - panic(result.BadRequest("旧密码不正确!")) + panic(result.BadRequestI18n(request, i18n.UserOldPasswordError)) } user.Password = util.GetBcrypt(newPassword) @@ -381,16 +379,16 @@ func (this *UserController) ResetPassword(writer http.ResponseWriter, request *h userUuid := request.FormValue("userUuid") password := request.FormValue("password") if userUuid == "" { - panic(result.BadRequest("用户不能为空")) + panic(result.BadRequest("userUuid cannot be null")) } if password == "" { - panic(result.BadRequest("密码不能为空")) + panic(result.BadRequest("password cannot be null")) } currentUser := this.checkUser(request) if currentUser.Role != USER_ROLE_ADMINISTRATOR { - panic(result.Unauthorized("没有权限")) + panic(result.UNAUTHORIZED) } user := this.userDao.CheckByUuid(userUuid) diff --git a/code/rest/user_service.go b/code/rest/user_service.go index 4edc576..cb24bbe 100644 --- a/code/rest/user_service.go +++ b/code/rest/user_service.go @@ -46,12 +46,12 @@ func (this *UserService) MatterLock(userUuid string) { //去缓存中捞取 cacheItem, err := this.locker.Value(userUuid) if err != nil { - this.logger.Error("获取缓存时出错了" + err.Error()) + this.logger.Error("error while get cache" + err.Error()) } //当前被锁住了。 if cacheItem != nil && cacheItem.Data() != nil { - panic(result.BadRequest("当前正在进行文件操作,请稍后再试!")) + panic(result.BadRequest("file is being operating, retry later")) } //添加一把新锁,有效期为12小时 diff --git a/code/tool/i18n/i18n.go b/code/tool/i18n/i18n.go index f7712c9..2bb3eeb 100644 --- a/code/tool/i18n/i18n.go +++ b/code/tool/i18n/i18n.go @@ -1,16 +1,69 @@ package i18n -const ( - //英文 - ENGLISH = "ENGLISH" - //中文 - CHINESE = "CHINESE" +import ( + "golang.org/x/text/language" + "net/http" ) -func Message(lang string, key string) { - if lang == ENGLISH { +const ( + LANG_KEY = "_lang" +) - } else if lang == CHINESE { +var matcher = language.NewMatcher([]language.Tag{ + // The first language is used as fallback. + language.English, + language.Chinese, +}) + +type Item struct { + English string + Chinese string +} + +var ( + UsernameOrPasswordCannotNull = &Item{English: `username or password cannot be null`, Chinese: `用户名或密码不能为空`} + UsernameOrPasswordError = &Item{English: `username or password error`, Chinese: `用户名或密码错误`} + UsernameExist = &Item{English: `username "%s" exists`, Chinese: `用户名"%s"已存在`} + UsernameNotExist = &Item{English: `username "%s" not exists`, Chinese: `用户名"%s"不存在`} + UsernameIsNotAdmin = &Item{English: `username "%s" is not admin user`, Chinese: `用户名"%s"不是管理员账号`} + UsernameError = &Item{English: `username can only be letters, numbers or _`, Chinese: `用户名必填,且只能包含字母,数字和'_'`} + 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: `旧密码不正确`} + 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 `} + MatterNameLengthExceedLimit = &Item{English: `filename's length exceed the limit %d > %d`, Chinese: `文件名称长度超过限制 %d > %d `} + 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 `} + 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: `文件名没有改变,操作无效!`} + ShareNumExceedLimit = &Item{English: `sharing files' num exceed the limit %d > %d`, Chinese: `一次分享的文件数量超出限制了 %d > %d `} +) + +func (this *Item) Message(request *http.Request) string { + + if request == nil { + return this.English + } + + lang, _ := request.Cookie(LANG_KEY) + formLangStr := request.FormValue(LANG_KEY) + acceptLangStr := request.Header.Get("Accept-Language") + var cookieLangStr string + if lang != nil { + cookieLangStr = lang.Value + } + tag, _ := language.MatchStrings(matcher, cookieLangStr, formLangStr, acceptLangStr) + + tagBase, _ := tag.Base() + chineseBase, _ := language.Chinese.Base() + + if tagBase == chineseBase { + return this.Chinese + } else { + return this.English + } - } } diff --git a/code/tool/result/web_result.go b/code/tool/result/web_result.go index b5c2a7b..d9538e2 100644 --- a/code/tool/result/web_result.go +++ b/code/tool/result/web_result.go @@ -2,6 +2,7 @@ package result import ( "fmt" + "github.com/eyebluecn/tank/code/tool/i18n" "net/http" ) @@ -101,7 +102,11 @@ func CustomWebResult(codeWrapper *CodeWrapper, description string) *WebResult { return wr } -//请求参数有问题 +func BadRequestI18n(request *http.Request, item *i18n.Item, v ...interface{}) *WebResult { + return CustomWebResult(BAD_REQUEST, fmt.Sprintf(item.Message(request), v...)) +} + +//没有权限 func BadRequest(format string, v ...interface{}) *WebResult { return CustomWebResult(BAD_REQUEST, fmt.Sprintf(format, v...)) } diff --git a/go.mod b/go.mod index cbdc142..8463310 100644 --- a/go.mod +++ b/go.mod @@ -14,4 +14,5 @@ require ( github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c + golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 ) diff --git a/go.sum b/go.sum index 6c657f1..3ed7708 100644 --- a/go.sum +++ b/go.sum @@ -162,6 +162,7 @@ golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=