Finish all the i18n things of code.
This commit is contained in:
@ -2,7 +2,6 @@ package rest
|
||||
|
||||
import (
|
||||
"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"
|
||||
@ -119,11 +118,7 @@ func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, reques
|
||||
//store dir path
|
||||
dirPath := request.FormValue("dirPath")
|
||||
|
||||
if filename == "" {
|
||||
panic(result.BadRequest("filename cannot be null"))
|
||||
} else if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, filename); m {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars))
|
||||
}
|
||||
filename = CheckMatterName(request, filename)
|
||||
|
||||
var expireTime time.Time
|
||||
if expireTimeStr == "" {
|
||||
@ -288,11 +283,7 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht
|
||||
dirPath := request.FormValue("dirPath")
|
||||
url := request.FormValue("url")
|
||||
|
||||
if filename == "" {
|
||||
panic(result.BadRequest("filename cannot be null."))
|
||||
} else if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, filename); m {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars))
|
||||
}
|
||||
filename = CheckMatterName(request, filename)
|
||||
|
||||
var privacy bool
|
||||
if privacyStr == TRUE {
|
||||
|
@ -111,7 +111,7 @@ func (this *AlienService) PreviewOrDownload(
|
||||
shareCode := request.FormValue("shareCode")
|
||||
shareRootUuid := request.FormValue("shareRootUuid")
|
||||
|
||||
this.shareService.ValidateMatter(shareUuid, shareCode, operator, shareRootUuid, matter)
|
||||
this.shareService.ValidateMatter(request, shareUuid, shareCode, operator, shareRootUuid, matter)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func (this *DashboardService) etl() {
|
||||
longTimeAgo := time.Now()
|
||||
longTimeAgo = longTimeAgo.AddDate(-20, 0, 0)
|
||||
|
||||
this.logger.Info("Time %s -> %s", util.ConvertTimeToDateTimeString(startTime), util.ConvertTimeToDateTimeString(endTime))
|
||||
this.logger.Info("ETL dashboard data from %s to %s", util.ConvertTimeToDateTimeString(startTime), util.ConvertTimeToDateTimeString(endTime))
|
||||
|
||||
//check whether the record has created.
|
||||
dbDashboard := this.dashboardDao.FindByDt(dt)
|
||||
|
@ -272,8 +272,8 @@ func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request *
|
||||
adminPassword := request.FormValue("adminPassword")
|
||||
|
||||
//validate admin's username
|
||||
if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, adminUsername); !m {
|
||||
panic(result.BadRequest(`admin's username cannot oly be alphabet, number or '_'`))
|
||||
if m, _ := regexp.MatchString(USERNAME_PATTERN, adminUsername); !m {
|
||||
panic(result.BadRequestI18n(request, i18n.UsernameError))
|
||||
}
|
||||
|
||||
if len(adminPassword) < 6 {
|
||||
|
@ -142,7 +142,7 @@ func (this *MatterController) Page(writer http.ResponseWriter, request *http.Req
|
||||
|
||||
user := this.findUser(request)
|
||||
|
||||
this.shareService.ValidateMatter(shareUuid, shareCode, user, shareRootUuid, dirMatter)
|
||||
this.shareService.ValidateMatter(request, shareUuid, shareCode, user, shareRootUuid, dirMatter)
|
||||
userUuid = dirMatter.Uuid
|
||||
|
||||
} else {
|
||||
|
@ -3,7 +3,12 @@ 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"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -89,3 +94,22 @@ func GetUserZipRootDir(username string) (rootDirPath string) {
|
||||
|
||||
return rootDirPath
|
||||
}
|
||||
|
||||
//check matter's name. If error, panic.
|
||||
func CheckMatterName(request *http.Request, name string) string {
|
||||
|
||||
if name == "" {
|
||||
panic(result.BadRequest("name cannot be null"))
|
||||
}
|
||||
if strings.HasPrefix(name, " ") || strings.HasSuffix(name, " ") {
|
||||
panic(result.BadRequest("name cannot start with or end with space"))
|
||||
}
|
||||
if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, name); m {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars))
|
||||
}
|
||||
|
||||
if len(name) > MATTER_NAME_MAX_LENGTH {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(name), MATTER_NAME_MAX_LENGTH))
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
@ -12,14 +12,14 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
/**
|
||||
* 操作文件的Service
|
||||
* 以 Atomic 开头的方法带有操作锁,这种方法不能被其他的Atomic方法调用,只能提供给外部调用。
|
||||
* Methods start with Atomic has Lock. These method cannot be invoked by other Atomic Methods.
|
||||
*/
|
||||
//@Service
|
||||
type MatterService struct {
|
||||
@ -67,7 +67,7 @@ func (this *MatterService) Init() {
|
||||
|
||||
}
|
||||
|
||||
//文件下载。支持分片下载
|
||||
//Download. Support chunk download.
|
||||
func (this *MatterService) DownloadFile(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
@ -78,7 +78,7 @@ func (this *MatterService) DownloadFile(
|
||||
download.DownloadFile(writer, request, filePath, filename, withContentDisposition)
|
||||
}
|
||||
|
||||
//下载文件 要求必须是同一个父matter下的。
|
||||
//Download specified matters. matters must have the same puuid.
|
||||
func (this *MatterService) DownloadZip(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
@ -100,34 +100,31 @@ func (this *MatterService) DownloadZip(
|
||||
|
||||
preference := this.preferenceService.Fetch()
|
||||
|
||||
//count the num of files will be downloaded.
|
||||
var count int64 = 0
|
||||
for _, matter := range matters {
|
||||
//验证文件夹中文件数量
|
||||
count = count + this.matterDao.CountByUserUuidAndPath(matter.UserUuid, matter.Path)
|
||||
}
|
||||
|
||||
//文件数量判断。
|
||||
if preference.DownloadDirMaxNum >= 0 {
|
||||
if count > preference.DownloadDirMaxNum {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterSelectNumExceedLimit, count, preference.DownloadDirMaxNum))
|
||||
}
|
||||
}
|
||||
|
||||
//count the size of files will be downloaded.
|
||||
var sumSize int64 = 0
|
||||
for _, matter := range matters {
|
||||
//验证文件夹中文件数量
|
||||
sumSize = sumSize + this.matterDao.SumSizeByUserUuidAndPath(matter.UserUuid, matter.Path)
|
||||
}
|
||||
|
||||
//判断用户自身上传大小的限制
|
||||
//大小判断
|
||||
if preference.DownloadDirMaxSize >= 0 {
|
||||
if sumSize > preference.DownloadDirMaxSize {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterSelectSizeExceedLimit, util.HumanFileSize(sumSize), util.HumanFileSize(preference.DownloadDirMaxSize)))
|
||||
}
|
||||
}
|
||||
|
||||
//准备zip放置的目录。
|
||||
//prepare the temp zip dir
|
||||
destZipDirPath := fmt.Sprintf("%s/%d", GetUserZipRootDir(matters[0].Username), time.Now().UnixNano()/1e6)
|
||||
util.MakeDirAll(destZipDirPath)
|
||||
|
||||
@ -138,13 +135,11 @@ func (this *MatterService) DownloadZip(
|
||||
|
||||
destZipPath := fmt.Sprintf("%s/%s", destZipDirPath, destZipName)
|
||||
|
||||
//_ = util.Zip(matter.AbsolutePath(), destZipPath)
|
||||
this.zipMatters(request, matters, destZipPath)
|
||||
|
||||
//下载
|
||||
download.DownloadFile(writer, request, destZipPath, destZipName, true)
|
||||
|
||||
//删除临时压缩文件
|
||||
//delete the temp zip file.
|
||||
err := os.Remove(destZipPath)
|
||||
if err != nil {
|
||||
this.logger.Error("error while deleting zip file %s", err.Error())
|
||||
@ -153,14 +148,14 @@ func (this *MatterService) DownloadZip(
|
||||
|
||||
}
|
||||
|
||||
//打包一系列的matter
|
||||
//zip matters.
|
||||
func (this *MatterService) zipMatters(request *http.Request, matters []*Matter, destPath string) {
|
||||
|
||||
if util.PathExists(destPath) {
|
||||
panic(result.BadRequest("%s exists", destPath))
|
||||
}
|
||||
|
||||
//要求必须是同一个父matter下的。
|
||||
//matters must have the same puuid.
|
||||
if matters == nil || len(matters) == 0 {
|
||||
panic(result.BadRequest("matters cannot be nil."))
|
||||
}
|
||||
@ -176,12 +171,12 @@ func (this *MatterService) zipMatters(request *http.Request, matters []*Matter,
|
||||
}
|
||||
}
|
||||
|
||||
//将每个matter的children装填好
|
||||
//wrap children for every matter.
|
||||
for _, m := range matters {
|
||||
this.WrapChildrenDetail(request, m)
|
||||
}
|
||||
|
||||
// 创建准备写入的文件
|
||||
// create temp zip file.
|
||||
fileWriter, err := os.Create(destPath)
|
||||
this.PanicError(err)
|
||||
|
||||
@ -190,15 +185,13 @@ func (this *MatterService) zipMatters(request *http.Request, matters []*Matter,
|
||||
this.PanicError(err)
|
||||
}()
|
||||
|
||||
// 通过 fileWriter 来创建 zip.Write
|
||||
zipWriter := zip.NewWriter(fileWriter)
|
||||
defer func() {
|
||||
// 检测一下是否成功关闭
|
||||
err := zipWriter.Close()
|
||||
this.PanicError(err)
|
||||
}()
|
||||
|
||||
//采用深度优先搜索算法。
|
||||
//DFS algorithm
|
||||
var walkFunc func(matter *Matter)
|
||||
walkFunc = func(matter *Matter) {
|
||||
|
||||
@ -207,27 +200,24 @@ func (this *MatterService) zipMatters(request *http.Request, matters []*Matter,
|
||||
fileInfo, err := os.Stat(path)
|
||||
this.PanicError(err)
|
||||
|
||||
// 通过文件信息,创建 zip 的文件信息
|
||||
// Create file info.
|
||||
fileHeader, err := zip.FileInfoHeader(fileInfo)
|
||||
this.PanicError(err)
|
||||
|
||||
// 替换文件信息中的文件名
|
||||
// Trim the baseDirPath
|
||||
fileHeader.Name = strings.TrimPrefix(path, baseDirPath)
|
||||
|
||||
// 目录前要加上/
|
||||
// directory has prefix /
|
||||
if matter.Dir {
|
||||
fileHeader.Name += "/"
|
||||
}
|
||||
|
||||
// 写入文件信息,并返回一个 Write 结构
|
||||
writer, err := zipWriter.CreateHeader(fileHeader)
|
||||
this.PanicError(err)
|
||||
|
||||
// 检测,如果不是标准文件就只写入头信息,不写入文件数据到 writer
|
||||
// 如目录,也没有数据需要写
|
||||
// only regular file has things to write.
|
||||
if fileHeader.Mode().IsRegular() {
|
||||
|
||||
// 打开要压缩的文件
|
||||
fileToBeZip, err := os.Open(path)
|
||||
defer func() {
|
||||
err = fileToBeZip.Close()
|
||||
@ -235,13 +225,12 @@ func (this *MatterService) zipMatters(request *http.Request, matters []*Matter,
|
||||
}()
|
||||
this.PanicError(err)
|
||||
|
||||
// 将打开的文件 Copy 到 writer
|
||||
_, err = io.Copy(writer, fileToBeZip)
|
||||
this.PanicError(err)
|
||||
|
||||
}
|
||||
|
||||
//如果有子文件,继续往下钻
|
||||
//dfs.
|
||||
for _, m := range matter.Children {
|
||||
walkFunc(m)
|
||||
}
|
||||
@ -252,7 +241,7 @@ func (this *MatterService) zipMatters(request *http.Request, matters []*Matter,
|
||||
}
|
||||
}
|
||||
|
||||
//删除文件
|
||||
//delete files.
|
||||
func (this *MatterService) Delete(request *http.Request, matter *Matter) {
|
||||
|
||||
if matter == nil {
|
||||
@ -261,42 +250,39 @@ 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)
|
||||
}
|
||||
|
||||
//删除文件
|
||||
//atomic delete files
|
||||
func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter) {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.BadRequest("matter cannot be nil"))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
//lock
|
||||
this.userService.MatterLock(matter.UserUuid)
|
||||
defer this.userService.MatterUnlock(matter.UserUuid)
|
||||
|
||||
this.Delete(request, matter)
|
||||
}
|
||||
|
||||
//上传文件
|
||||
//upload files.
|
||||
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."))
|
||||
}
|
||||
|
||||
//验证dirMatter
|
||||
if dirMatter == nil {
|
||||
panic(result.BadRequest("dirMatter cannot be nil."))
|
||||
}
|
||||
|
||||
//文件名不能太长。
|
||||
if len(filename) > MATTER_NAME_MAX_LENGTH {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(filename), MATTER_NAME_MAX_LENGTH))
|
||||
}
|
||||
|
||||
//文件夹路径
|
||||
dirAbsolutePath := dirMatter.AbsolutePath()
|
||||
dirRelativePath := dirMatter.Path
|
||||
|
||||
@ -305,17 +291,15 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
|
||||
panic(result.BadRequest("%s already exists", filename))
|
||||
}
|
||||
|
||||
//获取文件应该存放在的物理路径的绝对路径和相对路径。
|
||||
fileAbsolutePath := dirAbsolutePath + "/" + filename
|
||||
fileRelativePath := dirRelativePath + "/" + filename
|
||||
|
||||
//创建父文件夹
|
||||
util.MakeDirAll(dirAbsolutePath)
|
||||
|
||||
//如果文件已经存在了,那么直接覆盖。
|
||||
//if exist, overwrite it.
|
||||
exist := util.PathExists(fileAbsolutePath)
|
||||
if exist {
|
||||
this.logger.Error("%s已经存在,将其删除", fileAbsolutePath)
|
||||
this.logger.Error("%s exits, overwrite it.", fileAbsolutePath)
|
||||
removeError := os.Remove(fileAbsolutePath)
|
||||
this.PanicError(removeError)
|
||||
}
|
||||
@ -331,20 +315,20 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
|
||||
fileSize, err := io.Copy(destFile, file)
|
||||
this.PanicError(err)
|
||||
|
||||
this.logger.Info("上传文件 %s 大小为 %v ", filename, util.HumanFileSize(fileSize))
|
||||
this.logger.Info("upload %s %v ", filename, util.HumanFileSize(fileSize))
|
||||
|
||||
//判断用户自身上传大小的限制。
|
||||
//check the size limit.
|
||||
if user.SizeLimit >= 0 {
|
||||
if fileSize > user.SizeLimit {
|
||||
//删除上传过来的内容
|
||||
//delete the file on disk.
|
||||
err = os.Remove(fileAbsolutePath)
|
||||
this.PanicError(err)
|
||||
|
||||
panic(result.BadRequest("file's size exceed the limit %s > %s ", util.HumanFileSize(user.SizeLimit), util.HumanFileSize(fileSize)))
|
||||
panic(result.BadRequestI18n(request, i18n.MatterSizeExceedLimit, util.HumanFileSize(fileSize), util.HumanFileSize(user.SizeLimit)))
|
||||
}
|
||||
}
|
||||
|
||||
//将文件信息存入数据库中。
|
||||
//write to db.
|
||||
matter := &Matter{
|
||||
Puuid: dirMatter.Uuid,
|
||||
UserUuid: user.Uuid,
|
||||
@ -358,7 +342,7 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
|
||||
}
|
||||
matter = this.matterDao.Create(matter)
|
||||
|
||||
//统计文件夹的大小。
|
||||
//compute the size of directory
|
||||
go core.RunWithRecovery(func() {
|
||||
this.matterDao.ComputeRouteSize(dirMatter.Uuid, user.Uuid)
|
||||
})
|
||||
@ -366,15 +350,13 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
|
||||
return matter
|
||||
}
|
||||
|
||||
//内部创建文件,不带操作锁。
|
||||
//inner create directory.
|
||||
func (this *MatterService) createDirectory(request *http.Request, dirMatter *Matter, name string, user *User) *Matter {
|
||||
|
||||
//父级matter必须存在
|
||||
if dirMatter == nil {
|
||||
panic(result.BadRequest("dirMatter cannot be nil"))
|
||||
}
|
||||
|
||||
//必须是文件夹
|
||||
if !dirMatter.Dir {
|
||||
panic(result.BadRequest("dirMatter must be directory"))
|
||||
}
|
||||
@ -385,7 +367,6 @@ func (this *MatterService) createDirectory(request *http.Request, dirMatter *Mat
|
||||
}
|
||||
|
||||
name = strings.TrimSpace(name)
|
||||
//验证参数。
|
||||
if name == "" {
|
||||
panic(result.BadRequest("name cannot be blank"))
|
||||
}
|
||||
@ -400,7 +381,7 @@ func (this *MatterService) createDirectory(request *http.Request, dirMatter *Mat
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars))
|
||||
}
|
||||
|
||||
//判断同级文件夹中是否有同名的文件夹。存在了直接返回即可。
|
||||
//if exist. return.
|
||||
matter := this.matterDao.FindByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, true, name)
|
||||
if matter != nil {
|
||||
return matter
|
||||
@ -412,17 +393,15 @@ func (this *MatterService) createDirectory(request *http.Request, dirMatter *Mat
|
||||
panic(result.BadRequestI18n(request, i18n.MatterDepthExceedLimit, len(parts), MATTER_NAME_MAX_DEPTH))
|
||||
}
|
||||
|
||||
//绝对路径
|
||||
absolutePath := GetUserMatterRootDir(user.Username) + dirMatter.Path + "/" + name
|
||||
|
||||
//相对路径
|
||||
relativePath := dirMatter.Path + "/" + name
|
||||
|
||||
//磁盘中创建文件夹。
|
||||
//crate directory on disk.
|
||||
dirPath := util.MakeDirAll(absolutePath)
|
||||
this.logger.Info("Create Directory: %s", dirPath)
|
||||
|
||||
//数据库中创建文件夹。
|
||||
//create in db
|
||||
matter = &Matter{
|
||||
Puuid: dirMatter.Uuid,
|
||||
UserUuid: user.Uuid,
|
||||
@ -437,10 +416,8 @@ func (this *MatterService) createDirectory(request *http.Request, dirMatter *Mat
|
||||
return matter
|
||||
}
|
||||
|
||||
//在dirMatter中创建文件夹 返回刚刚创建的这个文件夹
|
||||
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)
|
||||
|
||||
@ -449,16 +426,14 @@ func (this *MatterService) AtomicCreateDirectory(request *http.Request, dirMatte
|
||||
return matter
|
||||
}
|
||||
|
||||
//处理 移动和复制时可能存在的覆盖问题。
|
||||
//copy or move may overwrite.
|
||||
func (this *MatterService) handleOverwrite(request *http.Request, userUuid string, destinationPath string, overwrite bool) {
|
||||
|
||||
//目标matter。因为有可能已经存在了
|
||||
destMatter := this.matterDao.findByUserUuidAndPath(userUuid, destinationPath)
|
||||
//如果目标matter存在了。
|
||||
if destMatter != nil {
|
||||
//如果目标matter还存在了。
|
||||
//if exist
|
||||
if overwrite {
|
||||
//要求覆盖。那么删除。
|
||||
//delete.
|
||||
this.Delete(request, destMatter)
|
||||
} else {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterExist, destMatter.Path))
|
||||
@ -467,7 +442,7 @@ func (this *MatterService) handleOverwrite(request *http.Request, userUuid strin
|
||||
|
||||
}
|
||||
|
||||
//将一个srcMatter放置到另一个destMatter(必须为文件夹)下 不关注 overwrite 和 lock.
|
||||
//move srcMatter to destMatter. invoker must handled the overwrite and lock.
|
||||
func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDirMatter *Matter) {
|
||||
|
||||
if srcMatter == nil {
|
||||
@ -483,59 +458,59 @@ func (this *MatterService) move(request *http.Request, srcMatter *Matter, destDi
|
||||
destDirUuid := destDirMatter.Uuid
|
||||
|
||||
if srcMatter.Dir {
|
||||
//如果源是文件夹
|
||||
|
||||
//if src is dir.
|
||||
destAbsolutePath := destDirMatter.AbsolutePath() + "/" + srcMatter.Name
|
||||
srcAbsolutePath := srcMatter.AbsolutePath()
|
||||
|
||||
//物理文件一口气移动
|
||||
//move src to dest on disk.
|
||||
err := os.Rename(srcAbsolutePath, destAbsolutePath)
|
||||
this.PanicError(err)
|
||||
|
||||
//修改数据库中信息
|
||||
//change info on db.
|
||||
srcMatter.Puuid = destDirMatter.Uuid
|
||||
srcMatter.Path = destDirMatter.Path + "/" + srcMatter.Name
|
||||
srcMatter = this.matterDao.Save(srcMatter)
|
||||
|
||||
//调整该文件夹下文件的Path.
|
||||
//reCompute the path.
|
||||
matters := this.matterDao.ListByPuuidAndUserUuid(srcMatter.Uuid, srcMatter.UserUuid, nil)
|
||||
for _, m := range matters {
|
||||
this.adjustPath(m, srcMatter)
|
||||
}
|
||||
|
||||
} else {
|
||||
//如果源是普通文件
|
||||
|
||||
//if src is NOT dir.
|
||||
destAbsolutePath := destDirMatter.AbsolutePath() + "/" + srcMatter.Name
|
||||
srcAbsolutePath := srcMatter.AbsolutePath()
|
||||
|
||||
//物理文件进行移动
|
||||
//move src to dest on disk.
|
||||
err := os.Rename(srcAbsolutePath, destAbsolutePath)
|
||||
this.PanicError(err)
|
||||
|
||||
//删除对应的缓存。
|
||||
//delete caches.
|
||||
this.imageCacheDao.DeleteByMatterUuid(srcMatter.Uuid)
|
||||
|
||||
//修改数据库中信息
|
||||
//change info in db.
|
||||
srcMatter.Puuid = destDirMatter.Uuid
|
||||
srcMatter.Path = destDirMatter.Path + "/" + srcMatter.Name
|
||||
srcMatter = this.matterDao.Save(srcMatter)
|
||||
|
||||
}
|
||||
|
||||
//调整两个文件夹的大小
|
||||
//reCompute the size of src and dest.
|
||||
this.matterDao.ComputeRouteSize(srcPuuid, userUuid)
|
||||
this.matterDao.ComputeRouteSize(destDirUuid, userUuid)
|
||||
|
||||
}
|
||||
|
||||
//将一个srcMatter放置到另一个destMatter(必须为文件夹)下
|
||||
//move srcMatter to destMatter(must be dir)
|
||||
func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter, destDirMatter *Matter, overwrite bool) {
|
||||
|
||||
if srcMatter == nil {
|
||||
panic(result.BadRequest("srcMatter cannot be nil."))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(srcMatter.UserUuid)
|
||||
defer this.userService.MatterUnlock(srcMatter.UserUuid)
|
||||
|
||||
@ -546,7 +521,7 @@ func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter,
|
||||
panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory))
|
||||
}
|
||||
|
||||
//文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。
|
||||
//neither move to itself, nor move to its children.
|
||||
destDirMatter = this.WrapParentDetail(request, destDirMatter)
|
||||
tmpMatter := destDirMatter
|
||||
for tmpMatter != nil {
|
||||
@ -556,22 +531,21 @@ func (this *MatterService) AtomicMove(request *http.Request, srcMatter *Matter,
|
||||
tmpMatter = tmpMatter.Parent
|
||||
}
|
||||
|
||||
//处理覆盖的问题
|
||||
//handle the overwrite
|
||||
destinationPath := destDirMatter.Path + "/" + srcMatter.Name
|
||||
this.handleOverwrite(request, srcMatter.UserUuid, destinationPath, overwrite)
|
||||
|
||||
//做move操作。
|
||||
//do the move operation.
|
||||
this.move(request, srcMatter, destDirMatter)
|
||||
}
|
||||
|
||||
//将一个srcMatter放置到另一个destMatter(必须为文件夹)下
|
||||
//move srcMatters to destMatter(must be dir)
|
||||
func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*Matter, destDirMatter *Matter) {
|
||||
|
||||
if destDirMatter == nil {
|
||||
panic(result.BadRequest("destDirMatter cannot be nil."))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(destDirMatter.UserUuid)
|
||||
defer this.userService.MatterUnlock(destDirMatter.UserUuid)
|
||||
|
||||
@ -583,14 +557,14 @@ func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*
|
||||
panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory))
|
||||
}
|
||||
|
||||
//文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。
|
||||
//neither move to itself, nor move to its children.
|
||||
destDirMatter = this.WrapParentDetail(request, destDirMatter)
|
||||
for _, srcMatter := range srcMatters {
|
||||
|
||||
tmpMatter := destDirMatter
|
||||
for tmpMatter != nil {
|
||||
if srcMatter.Uuid == tmpMatter.Uuid {
|
||||
panic("文件夹不能把自己移入到自己中,也不可以移入到自己的子文件夹下。")
|
||||
panic(result.BadRequestI18n(request, i18n.MatterMoveRecursive))
|
||||
}
|
||||
tmpMatter = tmpMatter.Parent
|
||||
}
|
||||
@ -602,14 +576,11 @@ func (this *MatterService) AtomicMoveBatch(request *http.Request, srcMatters []*
|
||||
|
||||
}
|
||||
|
||||
//内部移动一个文件(提供给Copy调用),无需关心overwrite问题。
|
||||
//copy srcMatter to destMatter. invoker must handled the overwrite and lock.
|
||||
func (this *MatterService) copy(request *http.Request, srcMatter *Matter, destDirMatter *Matter, name string) {
|
||||
|
||||
if srcMatter.Dir {
|
||||
|
||||
//如果源是文件夹
|
||||
|
||||
//在目标地址创建新文件夹。
|
||||
newMatter := &Matter{
|
||||
Puuid: destDirMatter.Uuid,
|
||||
UserUuid: srcMatter.UserUuid,
|
||||
@ -624,7 +595,7 @@ func (this *MatterService) copy(request *http.Request, srcMatter *Matter, destDi
|
||||
|
||||
newMatter = this.matterDao.Create(newMatter)
|
||||
|
||||
//复制子文件或文件夹
|
||||
//copy children
|
||||
matters := this.matterDao.ListByPuuidAndUserUuid(srcMatter.Uuid, srcMatter.UserUuid, nil)
|
||||
for _, m := range matters {
|
||||
this.copy(request, m, newMatter, m.Name)
|
||||
@ -632,14 +603,12 @@ func (this *MatterService) copy(request *http.Request, srcMatter *Matter, destDi
|
||||
|
||||
} else {
|
||||
|
||||
//如果源是普通文件
|
||||
destAbsolutePath := destDirMatter.AbsolutePath() + "/" + name
|
||||
srcAbsolutePath := srcMatter.AbsolutePath()
|
||||
|
||||
//物理文件进行复制
|
||||
//copy file on disk.
|
||||
util.CopyFile(srcAbsolutePath, destAbsolutePath)
|
||||
|
||||
//创建新文件的数据库信息。
|
||||
newMatter := &Matter{
|
||||
Puuid: destDirMatter.Uuid,
|
||||
UserUuid: srcMatter.UserUuid,
|
||||
@ -656,14 +625,13 @@ func (this *MatterService) copy(request *http.Request, srcMatter *Matter, destDi
|
||||
}
|
||||
}
|
||||
|
||||
//将一个srcMatter复制到另一个destMatter(必须为文件夹)下,名字叫做name
|
||||
//copy srcMatter to destMatter.
|
||||
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."))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(srcMatter.UserUuid)
|
||||
defer this.userService.MatterUnlock(srcMatter.UserUuid)
|
||||
|
||||
@ -677,29 +645,17 @@ func (this *MatterService) AtomicCopy(request *http.Request, srcMatter *Matter,
|
||||
this.copy(request, srcMatter, destDirMatter, name)
|
||||
}
|
||||
|
||||
//将一个matter 重命名为 name
|
||||
//rename matter to name
|
||||
func (this *MatterService) AtomicRename(request *http.Request, matter *Matter, name string, user *User) {
|
||||
|
||||
if user == nil {
|
||||
panic(result.BadRequest("user cannot be nil"))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(user.Uuid)
|
||||
defer this.userService.MatterUnlock(user.Uuid)
|
||||
|
||||
//验证参数。
|
||||
if name == "" {
|
||||
panic(result.BadRequest("name cannot be null"))
|
||||
}
|
||||
if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, name); m {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars))
|
||||
}
|
||||
|
||||
//文件名不能太长。
|
||||
if len(name) > MATTER_NAME_MAX_LENGTH {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(name), MATTER_NAME_MAX_LENGTH))
|
||||
}
|
||||
name = CheckMatterName(request, name)
|
||||
|
||||
if name == matter.Name {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameNoChange))
|
||||
@ -853,36 +809,33 @@ func (this *MatterService) mirror(request *http.Request, srcPath string, destDir
|
||||
//根据一个文件夹路径,依次创建,找到最后一个文件夹的matter,如果中途出错,返回err. 如果存在了那就直接返回即可。
|
||||
func (this *MatterService) CreateDirectories(request *http.Request, user *User, dirPath string) *Matter {
|
||||
|
||||
if dirPath == "" {
|
||||
panic(`文件夹不能为空`)
|
||||
} else if dirPath[0:1] != "/" {
|
||||
panic(`文件夹必须以/开头`)
|
||||
} else if strings.Index(dirPath, "//") != -1 {
|
||||
panic(`文件夹不能出现连续的//`)
|
||||
} else if m, _ := regexp.MatchString(MATTER_NAME_PATTERN, dirPath); m {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterNameContainSpecialChars))
|
||||
}
|
||||
dirPath = path.Clean(dirPath)
|
||||
|
||||
if dirPath == "/" {
|
||||
return NewRootMatter(user)
|
||||
}
|
||||
|
||||
//如果最后一个符号为/自动忽略
|
||||
if dirPath[len(dirPath)-1] == '/' {
|
||||
dirPath = dirPath[:len(dirPath)-1]
|
||||
}
|
||||
//ignore the last slash.
|
||||
dirPath = strings.TrimSuffix(dirPath, "/")
|
||||
|
||||
//递归找寻文件的上级目录uuid.
|
||||
folders := strings.Split(dirPath, "/")
|
||||
|
||||
if len(folders) > MATTER_NAME_MAX_DEPTH {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterDepthExceedLimit, len(folders), MATTER_NAME_MAX_DEPTH))
|
||||
}
|
||||
|
||||
//validate every matter name.
|
||||
for k, name := range folders {
|
||||
//first element is ""
|
||||
if k != 0 {
|
||||
CheckMatterName(request, name)
|
||||
}
|
||||
}
|
||||
|
||||
var dirMatter *Matter
|
||||
for k, name := range folders {
|
||||
|
||||
//split的第一个元素为空字符串,忽略。
|
||||
//ignore the first element.
|
||||
if k == 0 {
|
||||
dirMatter = NewRootMatter(user)
|
||||
continue
|
||||
@ -894,14 +847,13 @@ func (this *MatterService) CreateDirectories(request *http.Request, user *User,
|
||||
return dirMatter
|
||||
}
|
||||
|
||||
//包装某个matter的详情。会把父级依次倒着装进去。如果中途出错,直接抛出异常。
|
||||
//wrap a matter. put its parent.
|
||||
func (this *MatterService) WrapParentDetail(request *http.Request, matter *Matter) *Matter {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.BadRequest("matter cannot be nil."))
|
||||
}
|
||||
|
||||
//组装file的内容,展示其父组件。
|
||||
puuid := matter.Puuid
|
||||
tmpMatter := matter
|
||||
for puuid != MATTER_ROOT {
|
||||
@ -914,7 +866,7 @@ func (this *MatterService) WrapParentDetail(request *http.Request, matter *Matte
|
||||
return matter
|
||||
}
|
||||
|
||||
//包装某个matter的详情。会把子级依次装进去。如果中途出错,直接抛出异常。
|
||||
//wrap a matter ,put its children
|
||||
func (this *MatterService) WrapChildrenDetail(request *http.Request, matter *Matter) {
|
||||
|
||||
if matter == nil {
|
||||
@ -933,20 +885,19 @@ func (this *MatterService) WrapChildrenDetail(request *http.Request, matter *Mat
|
||||
|
||||
}
|
||||
|
||||
//获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。
|
||||
//fetch a matter's detail with parent info.
|
||||
func (this *MatterService) Detail(request *http.Request, uuid string) *Matter {
|
||||
matter := this.matterDao.CheckByUuid(uuid)
|
||||
return this.WrapParentDetail(request, matter)
|
||||
}
|
||||
|
||||
//去指定的url中爬文件
|
||||
//crawl a url to dirMatter
|
||||
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."))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(user.Uuid)
|
||||
defer this.userService.MatterUnlock(user.Uuid)
|
||||
|
||||
@ -958,36 +909,31 @@ func (this *MatterService) AtomicCrawl(request *http.Request, url string, filena
|
||||
panic(result.BadRequest("filename cannot be null."))
|
||||
}
|
||||
|
||||
//从指定的url下载一个文件。参考:https://golangcode.com/download-a-file-from-a-url/
|
||||
//download from url.
|
||||
resp, err := http.Get(url)
|
||||
this.PanicError(err)
|
||||
|
||||
return this.Upload(request, resp.Body, user, dirMatter, filename, privacy)
|
||||
}
|
||||
|
||||
//调整一个Matter的path值
|
||||
//adjust a matter's path.
|
||||
func (this *MatterService) adjustPath(matter *Matter, parentMatter *Matter) {
|
||||
|
||||
if matter.Dir {
|
||||
//如果源是文件夹
|
||||
|
||||
//首先调整好自己
|
||||
matter.Path = parentMatter.Path + "/" + matter.Name
|
||||
matter = this.matterDao.Save(matter)
|
||||
|
||||
//调整该文件夹下文件的Path.
|
||||
//adjust children.
|
||||
matters := this.matterDao.ListByPuuidAndUserUuid(matter.Uuid, matter.UserUuid, nil)
|
||||
for _, m := range matters {
|
||||
this.adjustPath(m, matter)
|
||||
}
|
||||
|
||||
} else {
|
||||
//如果源是普通文件
|
||||
|
||||
//删除该文件的所有缓存
|
||||
//delete caches.
|
||||
this.imageCacheDao.DeleteByMatterUuid(matter.Uuid)
|
||||
|
||||
//调整path
|
||||
matter.Path = parentMatter.Path + "/" + matter.Name
|
||||
matter = this.matterDao.Save(matter)
|
||||
}
|
||||
|
@ -41,14 +41,13 @@ func (this *PreferenceController) RegisterRoutes() map[string]func(writer http.R
|
||||
return routeMap
|
||||
}
|
||||
|
||||
//简单验证蓝眼云盘服务是否已经启动了。
|
||||
//ping the application. Return current version.
|
||||
func (this *PreferenceController) Ping(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
return this.Success(nil)
|
||||
return this.Success(core.VERSION)
|
||||
|
||||
}
|
||||
|
||||
//查看某个偏好设置的详情。
|
||||
func (this *PreferenceController) Fetch(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
preference := this.preferenceService.Fetch()
|
||||
@ -56,14 +55,9 @@ func (this *PreferenceController) Fetch(writer http.ResponseWriter, request *htt
|
||||
return this.Success(preference)
|
||||
}
|
||||
|
||||
//修改
|
||||
func (this *PreferenceController) Edit(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
//验证参数。
|
||||
name := request.FormValue("name")
|
||||
if name == "" {
|
||||
panic("name参数必填")
|
||||
}
|
||||
|
||||
logoUrl := request.FormValue("logoUrl")
|
||||
faviconUrl := request.FormValue("faviconUrl")
|
||||
@ -74,9 +68,13 @@ func (this *PreferenceController) Edit(writer http.ResponseWriter, request *http
|
||||
defaultTotalSizeLimitStr := request.FormValue("defaultTotalSizeLimit")
|
||||
allowRegisterStr := request.FormValue("allowRegister")
|
||||
|
||||
if name == "" {
|
||||
panic(result.BadRequest("name cannot be null"))
|
||||
}
|
||||
|
||||
var downloadDirMaxSize int64 = 0
|
||||
if downloadDirMaxSizeStr == "" {
|
||||
panic("文件下载大小限制必填!")
|
||||
panic(result.BadRequest("downloadDirMaxSize cannot be null"))
|
||||
} else {
|
||||
intDownloadDirMaxSize, err := strconv.Atoi(downloadDirMaxSizeStr)
|
||||
this.PanicError(err)
|
||||
@ -85,7 +83,7 @@ func (this *PreferenceController) Edit(writer http.ResponseWriter, request *http
|
||||
|
||||
var downloadDirMaxNum int64 = 0
|
||||
if downloadDirMaxNumStr == "" {
|
||||
panic("文件下载数量限制必填!")
|
||||
panic(result.BadRequest("downloadDirMaxNum cannot be null"))
|
||||
} else {
|
||||
intDownloadDirMaxNum, err := strconv.Atoi(downloadDirMaxNumStr)
|
||||
this.PanicError(err)
|
||||
@ -94,7 +92,7 @@ func (this *PreferenceController) Edit(writer http.ResponseWriter, request *http
|
||||
|
||||
var defaultTotalSizeLimit int64 = 0
|
||||
if defaultTotalSizeLimitStr == "" {
|
||||
panic("用户默认总限制!")
|
||||
panic(result.BadRequest("defaultTotalSizeLimit cannot be null"))
|
||||
} else {
|
||||
intDefaultTotalSizeLimit, err := strconv.Atoi(defaultTotalSizeLimitStr)
|
||||
this.PanicError(err)
|
||||
@ -119,13 +117,13 @@ func (this *PreferenceController) Edit(writer http.ResponseWriter, request *http
|
||||
|
||||
preference = this.preferenceDao.Save(preference)
|
||||
|
||||
//重置缓存中的偏好
|
||||
//reset the preference cache
|
||||
this.preferenceService.Reset()
|
||||
|
||||
return this.Success(preference)
|
||||
}
|
||||
|
||||
//清扫系统,所有数据全部丢失。一定要非常慎点,非常慎点!只在系统初始化的时候点击!
|
||||
//cleanup system data.
|
||||
func (this *PreferenceController) SystemCleanup(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
user := this.checkUser(request)
|
||||
@ -135,7 +133,7 @@ func (this *PreferenceController) SystemCleanup(writer http.ResponseWriter, requ
|
||||
panic(result.BadRequest("password error"))
|
||||
}
|
||||
|
||||
//清空系统
|
||||
//this will trigger every bean to cleanup.
|
||||
core.CONTEXT.Cleanup()
|
||||
|
||||
return this.Success("OK")
|
||||
|
@ -33,7 +33,6 @@ func (this *PreferenceDao) Fetch() *Preference {
|
||||
return preference
|
||||
}
|
||||
|
||||
//创建
|
||||
func (this *PreferenceDao) Create(preference *Preference) *Preference {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
@ -47,7 +46,6 @@ func (this *PreferenceDao) Create(preference *Preference) *Preference {
|
||||
return preference
|
||||
}
|
||||
|
||||
//修改一个偏好设置
|
||||
func (this *PreferenceDao) Save(preference *Preference) *Preference {
|
||||
|
||||
preference.UpdateTime = time.Now()
|
||||
|
@ -19,7 +19,6 @@ func (this *PreferenceService) Init() {
|
||||
|
||||
}
|
||||
|
||||
//获取单例的配置。
|
||||
func (this *PreferenceService) Fetch() *Preference {
|
||||
|
||||
if this.preference == nil {
|
||||
|
@ -34,7 +34,6 @@ func (this *SessionDao) CheckByUuid(uuid string) *Session {
|
||||
return entity
|
||||
}
|
||||
|
||||
//创建一个session并且持久化到数据库中。
|
||||
func (this *SessionDao) Create(session *Session) *Session {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
@ -48,7 +47,6 @@ func (this *SessionDao) Create(session *Session) *Session {
|
||||
return session
|
||||
}
|
||||
|
||||
//修改一个session
|
||||
func (this *SessionDao) Save(session *Session) *Session {
|
||||
|
||||
session.UpdateTime = time.Now()
|
||||
|
@ -66,7 +66,6 @@ func (this *ShareController) RegisterRoutes() map[string]func(writer http.Respon
|
||||
return routeMap
|
||||
}
|
||||
|
||||
//创建一个分享
|
||||
func (this *ShareController) Create(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
matterUuids := request.FormValue("matterUuids")
|
||||
@ -113,9 +112,8 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
matter := this.matterDao.CheckByUuid(uuid)
|
||||
|
||||
//判断文件的所属人是否正确
|
||||
if matter.UserUuid != user.Uuid {
|
||||
panic(result.Unauthorized("不是你的文件,没有权限"))
|
||||
panic(result.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
matters = append(matters, matter)
|
||||
@ -130,7 +128,7 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re
|
||||
}
|
||||
} else {
|
||||
if matter.Puuid != puuid {
|
||||
panic(result.Unauthorized("一次只能分享同一个文件夹中的内容"))
|
||||
panic(result.Unauthorized("you can only share files in the same directory"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,10 +136,9 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
if len(matters) > 1 {
|
||||
shareType = SHARE_TYPE_MIX
|
||||
name = matters[0].Name + "," + matters[1].Name + " 等"
|
||||
name = matters[0].Name + "," + matters[1].Name + " ..."
|
||||
}
|
||||
|
||||
//创建share记录
|
||||
share := &Share{
|
||||
Name: name,
|
||||
ShareType: shareType,
|
||||
@ -154,7 +151,6 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re
|
||||
}
|
||||
this.shareDao.Create(share)
|
||||
|
||||
//创建关联的matter
|
||||
for _, matter := range matters {
|
||||
bridge := &Bridge{
|
||||
ShareUuid: share.Uuid,
|
||||
@ -177,7 +173,6 @@ func (this *ShareController) Delete(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
if share != nil {
|
||||
|
||||
//删除对应的bridge.
|
||||
this.bridgeDao.DeleteByShareUuid(share.Uuid)
|
||||
|
||||
this.shareDao.Delete(share)
|
||||
@ -186,7 +181,6 @@ func (this *ShareController) Delete(writer http.ResponseWriter, request *http.Re
|
||||
return this.Success(nil)
|
||||
}
|
||||
|
||||
//删除一系列分享
|
||||
func (this *ShareController) DeleteBatch(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
uuids := request.FormValue("uuids")
|
||||
@ -200,7 +194,6 @@ func (this *ShareController) DeleteBatch(writer http.ResponseWriter, request *ht
|
||||
|
||||
imageCache := this.shareDao.FindByUuid(uuid)
|
||||
|
||||
//判断图片缓存的所属人是否正确
|
||||
user := this.checkUser(request)
|
||||
if imageCache.UserUuid != user.Uuid {
|
||||
panic(result.UNAUTHORIZED)
|
||||
@ -209,10 +202,9 @@ func (this *ShareController) DeleteBatch(writer http.ResponseWriter, request *ht
|
||||
this.shareDao.Delete(imageCache)
|
||||
}
|
||||
|
||||
return this.Success("删除成功!")
|
||||
return this.Success("OK")
|
||||
}
|
||||
|
||||
//查看详情。
|
||||
func (this *ShareController) Detail(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
@ -222,7 +214,6 @@ func (this *ShareController) Detail(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
share := this.shareDao.CheckByUuid(uuid)
|
||||
|
||||
//验证当前之人是否有权限查看这么详细。
|
||||
user := this.checkUser(request)
|
||||
|
||||
if share.UserUuid != user.Uuid {
|
||||
@ -233,10 +224,8 @@ func (this *ShareController) Detail(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
}
|
||||
|
||||
//按照分页的方式查询
|
||||
func (this *ShareController) Page(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
//如果是根目录,那么就传入root.
|
||||
pageStr := request.FormValue("page")
|
||||
pageSizeStr := request.FormValue("pageSize")
|
||||
orderCreateTime := request.FormValue("orderCreateTime")
|
||||
@ -268,37 +257,30 @@ func (this *ShareController) Page(writer http.ResponseWriter, request *http.Requ
|
||||
return this.Success(pager)
|
||||
}
|
||||
|
||||
//验证提取码对应的某个shareUuid是否有效
|
||||
func (this *ShareController) CheckShare(writer http.ResponseWriter, request *http.Request) *Share {
|
||||
|
||||
//如果是根目录,那么就传入root.
|
||||
shareUuid := request.FormValue("shareUuid")
|
||||
code := request.FormValue("code")
|
||||
user := this.findUser(request)
|
||||
|
||||
return this.shareService.CheckShare(shareUuid, code, user)
|
||||
return this.shareService.CheckShare(request, shareUuid, code, user)
|
||||
}
|
||||
|
||||
//浏览某个分享中的文件
|
||||
func (this *ShareController) Browse(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
//如果是根目录,那么就传入root.
|
||||
shareUuid := request.FormValue("shareUuid")
|
||||
code := request.FormValue("code")
|
||||
|
||||
//当前查看的puuid。 puuid=root表示查看分享的根目录,其余表示查看某个文件夹下的文件。
|
||||
//puuid can be "root"
|
||||
puuid := request.FormValue("puuid")
|
||||
rootUuid := request.FormValue("rootUuid")
|
||||
|
||||
user := this.findUser(request)
|
||||
share := this.shareService.CheckShare(shareUuid, code, user)
|
||||
share := this.shareService.CheckShare(request, shareUuid, code, user)
|
||||
bridges := this.bridgeDao.FindByShareUuid(share.Uuid)
|
||||
|
||||
if puuid == MATTER_ROOT {
|
||||
|
||||
//分享的根目录
|
||||
|
||||
//获取对应的 matter.
|
||||
var matters []*Matter
|
||||
if len(bridges) != 0 {
|
||||
uuids := make([]string, 0)
|
||||
@ -318,21 +300,21 @@ func (this *ShareController) Browse(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
} else {
|
||||
|
||||
//如果当前查看的目录就是根目录,那么无需再验证
|
||||
//if root. No need to validate.
|
||||
if puuid == rootUuid {
|
||||
dirMatter := this.matterDao.CheckByUuid(puuid)
|
||||
share.DirMatter = dirMatter
|
||||
} else {
|
||||
dirMatter := this.matterService.Detail(request, puuid)
|
||||
|
||||
//验证 shareRootMatter是否在被分享。
|
||||
//check whether shareRootMatter is being sharing
|
||||
shareRootMatter := this.matterDao.CheckByUuid(rootUuid)
|
||||
if !shareRootMatter.Dir {
|
||||
panic(result.BadRequestI18n(request, i18n.MatterDestinationMustDirectory))
|
||||
}
|
||||
this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, shareRootMatter.Uuid)
|
||||
|
||||
//到rootUuid的地方掐断。
|
||||
//stop at rootUuid
|
||||
find := false
|
||||
parentMatter := dirMatter.Parent
|
||||
for parentMatter != nil {
|
||||
@ -357,14 +339,11 @@ func (this *ShareController) Browse(writer http.ResponseWriter, request *http.Re
|
||||
|
||||
}
|
||||
|
||||
//下载压缩包
|
||||
func (this *ShareController) Zip(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
//如果是根目录,那么就传入root.
|
||||
shareUuid := request.FormValue("shareUuid")
|
||||
code := request.FormValue("code")
|
||||
|
||||
//当前查看的puuid。 puuid=root表示查看分享的根目录,其余表示查看某个文件夹下的文件。
|
||||
puuid := request.FormValue("puuid")
|
||||
rootUuid := request.FormValue("rootUuid")
|
||||
|
||||
@ -372,8 +351,8 @@ func (this *ShareController) Zip(writer http.ResponseWriter, request *http.Reque
|
||||
|
||||
if puuid == MATTER_ROOT {
|
||||
|
||||
//下载分享全部内容。
|
||||
share := this.shareService.CheckShare(shareUuid, code, user)
|
||||
//download all things.
|
||||
share := this.shareService.CheckShare(request, shareUuid, code, user)
|
||||
bridges := this.bridgeDao.FindByShareUuid(share.Uuid)
|
||||
var matterUuids []string
|
||||
for _, bridge := range bridges {
|
||||
@ -384,9 +363,9 @@ func (this *ShareController) Zip(writer http.ResponseWriter, request *http.Reque
|
||||
|
||||
} else {
|
||||
|
||||
//下载某个目录。
|
||||
//download a folder.
|
||||
matter := this.matterDao.CheckByUuid(puuid)
|
||||
this.shareService.ValidateMatter(shareUuid, code, user, rootUuid, matter)
|
||||
this.shareService.ValidateMatter(request, shareUuid, code, user, rootUuid, matter)
|
||||
this.matterService.DownloadZip(writer, request, []*Matter{matter})
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ func (this *ShareDao) CheckByUuid(uuid string) *Share {
|
||||
return entity
|
||||
}
|
||||
|
||||
//按分页条件获取分页
|
||||
func (this *ShareDao) Page(page int, pageSize int, userUuid string, sortArray []builder.OrderPair) *Pager {
|
||||
|
||||
var wp = &builder.WherePair{}
|
||||
@ -61,7 +60,6 @@ func (this *ShareDao) Page(page int, pageSize int, userUuid string, sortArray []
|
||||
return pager
|
||||
}
|
||||
|
||||
//创建
|
||||
func (this *ShareDao) Create(share *Share) *Share {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
@ -75,7 +73,6 @@ func (this *ShareDao) Create(share *Share) *Share {
|
||||
return share
|
||||
}
|
||||
|
||||
//修改一条记录
|
||||
func (this *ShareDao) Save(share *Share) *Share {
|
||||
|
||||
share.UpdateTime = time.Now()
|
||||
|
@ -6,11 +6,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
//单文件
|
||||
//single file.
|
||||
SHARE_TYPE_FILE = "FILE"
|
||||
//文件夹
|
||||
//directory
|
||||
SHARE_TYPE_DIRECTORY = "DIRECTORY"
|
||||
//混合体
|
||||
//mix things
|
||||
SHARE_TYPE_MIX = "MIX"
|
||||
)
|
||||
|
||||
@ -19,7 +19,7 @@ const (
|
||||
)
|
||||
|
||||
/**
|
||||
* 分享记录
|
||||
* share record
|
||||
*/
|
||||
type Share struct {
|
||||
Base
|
||||
|
@ -2,7 +2,9 @@ package rest
|
||||
|
||||
import (
|
||||
"github.com/eyebluecn/tank/code/core"
|
||||
"github.com/eyebluecn/tank/code/tool/i18n"
|
||||
"github.com/eyebluecn/tank/code/tool/result"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -41,7 +43,6 @@ func (this *ShareService) Init() {
|
||||
|
||||
}
|
||||
|
||||
//获取某个分享的详情。
|
||||
func (this *ShareService) Detail(uuid string) *Share {
|
||||
|
||||
share := this.shareDao.CheckByUuid(uuid)
|
||||
@ -49,17 +50,17 @@ func (this *ShareService) Detail(uuid string) *Share {
|
||||
return share
|
||||
}
|
||||
|
||||
//验证一个shareUuid和shareCode是否匹配和有权限。
|
||||
func (this *ShareService) CheckShare(shareUuid string, code string, user *User) *Share {
|
||||
// check whether shareUuid and shareCode matches. check whether user can access.
|
||||
func (this *ShareService) CheckShare(request *http.Request, shareUuid string, code string, user *User) *Share {
|
||||
|
||||
share := this.shareDao.CheckByUuid(shareUuid)
|
||||
//如果是自己的分享,可以不要提取码
|
||||
//if self, not need shareCode
|
||||
if user == nil || user.Uuid != share.UserUuid {
|
||||
//没有登录,或者查看的不是自己的分享,要求有验证码
|
||||
//if not login or not self's share, shareCode is required.
|
||||
if code == "" {
|
||||
panic(result.CustomWebResult(result.NEED_SHARE_CODE, "提取码必填"))
|
||||
panic(result.CustomWebResultI18n(request, result.NEED_SHARE_CODE, i18n.ShareCodeRequired))
|
||||
} else if share.Code != code {
|
||||
panic(result.CustomWebResult(result.SHARE_CODE_ERROR, "提取码错误"))
|
||||
panic(result.CustomWebResultI18n(request, result.SHARE_CODE_ERROR, i18n.ShareCodeError))
|
||||
} else {
|
||||
if !share.ExpireInfinity {
|
||||
if share.ExpireTime.Before(time.Now()) {
|
||||
@ -71,15 +72,14 @@ func (this *ShareService) CheckShare(shareUuid string, code string, user *User)
|
||||
return share
|
||||
}
|
||||
|
||||
//根据某个shareUuid和code,某个用户是否有权限获取 shareRootUuid 下面的 matterUuid
|
||||
//如果是根目录下的文件,那么shareRootUuid传root.
|
||||
func (this *ShareService) ValidateMatter(shareUuid string, code string, user *User, shareRootUuid string, matter *Matter) {
|
||||
//check whether a user can access a matter. shareRootUuid is matter's parent(or parent's parent and so on)
|
||||
func (this *ShareService) ValidateMatter(request *http.Request, shareUuid string, code string, user *User, shareRootUuid string, matter *Matter) {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.Unauthorized("matter cannot be nil"))
|
||||
}
|
||||
|
||||
//如果文件是自己的,那么放行
|
||||
//if self's matter, ok.
|
||||
if user != nil && matter.UserUuid == user.Uuid {
|
||||
return
|
||||
}
|
||||
@ -88,19 +88,19 @@ func (this *ShareService) ValidateMatter(shareUuid string, code string, user *Us
|
||||
panic(result.Unauthorized("shareUuid,code,shareRootUuid cannot be null"))
|
||||
}
|
||||
|
||||
share := this.CheckShare(shareUuid, code, user)
|
||||
share := this.CheckShare(request, shareUuid, code, user)
|
||||
|
||||
//如果shareRootUuid是根,那么matterUuid在bridge中应该有记录
|
||||
//if shareRootUuid is root. Bridge must has record.
|
||||
if shareRootUuid == MATTER_ROOT {
|
||||
|
||||
this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, matter.Uuid)
|
||||
|
||||
} else {
|
||||
//验证 shareRootMatter是否在被分享。
|
||||
//check whether shareRootMatter is being sharing
|
||||
shareRootMatter := this.matterDao.CheckByUuid(shareRootUuid)
|
||||
this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, shareRootMatter.Uuid)
|
||||
|
||||
//保证 puuid对应的matter是shareRootMatter的子文件夹。
|
||||
// shareRootMatter is ancestor of matter.
|
||||
child := strings.HasPrefix(matter.Path, shareRootMatter.Path)
|
||||
if !child {
|
||||
panic(result.BadRequest("%s is not %s's children", matter.Uuid, shareRootUuid))
|
||||
|
@ -34,7 +34,6 @@ func (this *UploadTokenDao) CheckByUuid(uuid string) *UploadToken {
|
||||
return entity
|
||||
}
|
||||
|
||||
//创建一个session并且持久化到数据库中。
|
||||
func (this *UploadTokenDao) Create(uploadToken *UploadToken) *UploadToken {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
@ -49,7 +48,6 @@ func (this *UploadTokenDao) Create(uploadToken *UploadToken) *UploadToken {
|
||||
return uploadToken
|
||||
}
|
||||
|
||||
//修改一个uploadToken
|
||||
func (this *UploadTokenDao) Save(uploadToken *UploadToken) *UploadToken {
|
||||
|
||||
uploadToken.UpdateTime = time.Now()
|
||||
|
@ -47,11 +47,11 @@ func (this *UserController) RegisterRoutes() map[string]func(writer http.Respons
|
||||
|
||||
func (this *UserController) innerLogin(writer http.ResponseWriter, request *http.Request, user *User) {
|
||||
|
||||
//登录成功,设置Cookie。有效期30天。
|
||||
//set cookie. expire after 30 days.
|
||||
expiration := time.Now()
|
||||
expiration = expiration.AddDate(0, 0, 30)
|
||||
|
||||
//持久化用户的session.
|
||||
//save session to db.
|
||||
session := &Session{
|
||||
UserUuid: user.Uuid,
|
||||
Ip: util.GetIpAddress(request),
|
||||
@ -61,7 +61,7 @@ func (this *UserController) innerLogin(writer http.ResponseWriter, request *http
|
||||
session.CreateTime = time.Now()
|
||||
session = this.sessionDao.Create(session)
|
||||
|
||||
//设置用户的cookie.
|
||||
//set cookie
|
||||
cookie := http.Cookie{
|
||||
Name: core.COOKIE_AUTH_KEY,
|
||||
Path: "/",
|
||||
@ -69,16 +69,13 @@ func (this *UserController) innerLogin(writer http.ResponseWriter, request *http
|
||||
Expires: expiration}
|
||||
http.SetCookie(writer, &cookie)
|
||||
|
||||
//更新用户上次登录时间和ip
|
||||
//update lastTime and lastIp
|
||||
user.LastTime = time.Now()
|
||||
user.LastIp = util.GetIpAddress(request)
|
||||
this.userDao.Save(user)
|
||||
}
|
||||
|
||||
//使用用户名和密码进行登录。
|
||||
//参数:
|
||||
// @username:用户名
|
||||
// @password:密码
|
||||
//login by username and password
|
||||
func (this *UserController) Login(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
username := request.FormValue("username")
|
||||
@ -101,7 +98,7 @@ func (this *UserController) Login(writer http.ResponseWriter, request *http.Requ
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//使用Authentication进行登录。
|
||||
//login by authentication.
|
||||
func (this *UserController) AuthenticationLogin(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
authentication := request.FormValue("authentication")
|
||||
@ -122,7 +119,7 @@ func (this *UserController) AuthenticationLogin(writer http.ResponseWriter, requ
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//用户自主注册。
|
||||
//register by username and password. After registering, will auto login.
|
||||
func (this *UserController) Register(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
username := request.FormValue("username")
|
||||
@ -133,7 +130,7 @@ func (this *UserController) Register(writer http.ResponseWriter, request *http.R
|
||||
panic(result.BadRequestI18n(request, i18n.UserRegisterNotAllowd))
|
||||
}
|
||||
|
||||
if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, username); !m {
|
||||
if m, _ := regexp.MatchString(USERNAME_PATTERN, username); !m {
|
||||
panic(result.BadRequestI18n(request, i18n.UsernameError))
|
||||
}
|
||||
|
||||
@ -141,7 +138,6 @@ func (this *UserController) Register(writer http.ResponseWriter, request *http.R
|
||||
panic(result.BadRequestI18n(request, i18n.UserPasswordLengthError))
|
||||
}
|
||||
|
||||
//判断重名。
|
||||
if this.userDao.CountByUsername(username) > 0 {
|
||||
panic(result.BadRequestI18n(request, i18n.UsernameExist, username))
|
||||
}
|
||||
@ -156,50 +152,45 @@ func (this *UserController) Register(writer http.ResponseWriter, request *http.R
|
||||
|
||||
user = this.userDao.Create(user)
|
||||
|
||||
//做一次登录操作
|
||||
//auto login
|
||||
this.innerLogin(writer, request, user)
|
||||
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//编辑一个用户的资料。
|
||||
func (this *UserController) Edit(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
avatarUrl := request.FormValue("avatarUrl")
|
||||
uuid := request.FormValue("uuid")
|
||||
sizeLimitStr := request.FormValue("sizeLimit")
|
||||
|
||||
currentUser := this.checkUser(request)
|
||||
user := this.userDao.CheckByUuid(uuid)
|
||||
user := this.checkUser(request)
|
||||
currentUser := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
if currentUser.Role == USER_ROLE_ADMINISTRATOR {
|
||||
//只有管理员可以改变用户上传的大小
|
||||
//判断用户上传大小限制。
|
||||
sizeLimitStr := request.FormValue("sizeLimit")
|
||||
if user.Role == USER_ROLE_ADMINISTRATOR {
|
||||
//only admin can edit user's sizeLimit
|
||||
var sizeLimit int64 = 0
|
||||
if sizeLimitStr == "" {
|
||||
panic("用户上传限制必填!")
|
||||
panic("user's limit size is required")
|
||||
} else {
|
||||
intsizeLimit, err := strconv.Atoi(sizeLimitStr)
|
||||
intSizeLimit, err := strconv.Atoi(sizeLimitStr)
|
||||
if err != nil {
|
||||
this.PanicError(err)
|
||||
}
|
||||
sizeLimit = int64(intsizeLimit)
|
||||
}
|
||||
user.SizeLimit = sizeLimit
|
||||
} else {
|
||||
if currentUser.Uuid != uuid {
|
||||
panic(result.UNAUTHORIZED)
|
||||
sizeLimit = int64(intSizeLimit)
|
||||
}
|
||||
currentUser.SizeLimit = sizeLimit
|
||||
} else if user.Uuid != uuid {
|
||||
panic(result.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
user.AvatarUrl = avatarUrl
|
||||
currentUser.AvatarUrl = avatarUrl
|
||||
|
||||
user = this.userDao.Save(user)
|
||||
currentUser = this.userDao.Save(currentUser)
|
||||
|
||||
return this.Success(user)
|
||||
return this.Success(currentUser)
|
||||
}
|
||||
|
||||
//获取用户详情
|
||||
func (this *UserController) Detail(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
@ -210,13 +201,12 @@ func (this *UserController) Detail(writer http.ResponseWriter, request *http.Req
|
||||
|
||||
}
|
||||
|
||||
//退出登录
|
||||
func (this *UserController) Logout(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
//session置为过期
|
||||
//expire session.
|
||||
sessionCookie, err := request.Cookie(core.COOKIE_AUTH_KEY)
|
||||
if err != nil {
|
||||
return this.Success("已经退出登录了!")
|
||||
return this.Success("OK")
|
||||
}
|
||||
sessionId := sessionCookie.Value
|
||||
|
||||
@ -227,13 +217,13 @@ func (this *UserController) Logout(writer http.ResponseWriter, request *http.Req
|
||||
this.sessionDao.Save(session)
|
||||
}
|
||||
|
||||
//删掉session缓存
|
||||
//delete session.
|
||||
_, err = core.CONTEXT.GetSessionCache().Delete(sessionId)
|
||||
if err != nil {
|
||||
this.logger.Error("删除用户session缓存时出错")
|
||||
this.logger.Error("error while deleting session.")
|
||||
}
|
||||
|
||||
//清空客户端的cookie.
|
||||
//clear cookie.
|
||||
expiration := time.Now()
|
||||
expiration = expiration.AddDate(-1, 0, 0)
|
||||
cookie := http.Cookie{
|
||||
@ -243,10 +233,9 @@ func (this *UserController) Logout(writer http.ResponseWriter, request *http.Req
|
||||
Expires: expiration}
|
||||
http.SetCookie(writer, &cookie)
|
||||
|
||||
return this.Success("退出成功!")
|
||||
return this.Success("OK")
|
||||
}
|
||||
|
||||
//获取用户列表 管理员的权限。
|
||||
func (this *UserController) Page(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
pageStr := request.FormValue("page")
|
||||
@ -298,14 +287,13 @@ func (this *UserController) Page(writer http.ResponseWriter, request *http.Reque
|
||||
return this.Success(pager)
|
||||
}
|
||||
|
||||
//修改用户状态
|
||||
func (this *UserController) ToggleStatus(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
currentUser := this.userDao.CheckByUuid(uuid)
|
||||
user := this.checkUser(request)
|
||||
if uuid == user.Uuid {
|
||||
panic(result.Unauthorized("你不能操作自己的状态。"))
|
||||
panic(result.UNAUTHORIZED)
|
||||
}
|
||||
|
||||
if currentUser.Status == USER_STATUS_OK {
|
||||
@ -320,17 +308,15 @@ func (this *UserController) ToggleStatus(writer http.ResponseWriter, request *ht
|
||||
|
||||
}
|
||||
|
||||
//变身为指定用户。
|
||||
func (this *UserController) Transfiguration(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
currentUser := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
//有效期10分钟
|
||||
//expire after 10 minutes.
|
||||
expiration := time.Now()
|
||||
expiration = expiration.Add(10 * time.Minute)
|
||||
|
||||
//持久化用户的session.
|
||||
session := &Session{
|
||||
UserUuid: currentUser.Uuid,
|
||||
Ip: util.GetIpAddress(request),
|
||||
@ -343,7 +329,6 @@ func (this *UserController) Transfiguration(writer http.ResponseWriter, request
|
||||
return this.Success(session.Uuid)
|
||||
}
|
||||
|
||||
//用户修改密码
|
||||
func (this *UserController) ChangePassword(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
oldPassword := request.FormValue("oldPassword")
|
||||
@ -354,8 +339,8 @@ func (this *UserController) ChangePassword(writer http.ResponseWriter, request *
|
||||
|
||||
user := this.checkUser(request)
|
||||
|
||||
//如果是demo账号,不提供修改密码的功能。
|
||||
if user.Username == "demo" {
|
||||
//if username is demo, cannot change password.
|
||||
if user.Username == USERNAME_DEMO {
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
@ -370,7 +355,7 @@ func (this *UserController) ChangePassword(writer http.ResponseWriter, request *
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//管理员重置用户密码
|
||||
//admin reset password.
|
||||
func (this *UserController) ResetPassword(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
userUuid := request.FormValue("userUuid")
|
||||
|
@ -16,11 +16,10 @@ func (this *UserDao) Init() {
|
||||
this.BaseDao.Init()
|
||||
}
|
||||
|
||||
//创建用户
|
||||
func (this *UserDao) Create(user *User) *User {
|
||||
|
||||
if user == nil {
|
||||
panic("参数不能为nil")
|
||||
panic(result.BadRequest("user cannot be nil"))
|
||||
}
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
@ -59,7 +58,6 @@ func (this *UserDao) CheckByUuid(uuid string) *User {
|
||||
return entity
|
||||
}
|
||||
|
||||
//查询用户。
|
||||
func (this *UserDao) FindByUsername(username string) *User {
|
||||
|
||||
var user = &User{}
|
||||
@ -74,7 +72,6 @@ func (this *UserDao) FindByUsername(username string) *User {
|
||||
return user
|
||||
}
|
||||
|
||||
//显示用户列表。
|
||||
func (this *UserDao) Page(page int, pageSize int, username string, email string, phone string, status string, sortArray []builder.OrderPair) *Pager {
|
||||
|
||||
var wp = &builder.WherePair{}
|
||||
@ -114,7 +111,6 @@ func (this *UserDao) Page(page int, pageSize int, username string, email string,
|
||||
return pager
|
||||
}
|
||||
|
||||
//查询某个用户名是否已经有用户了
|
||||
func (this *UserDao) CountByUsername(username string) int {
|
||||
var count int
|
||||
db := core.CONTEXT.GetDB().
|
||||
@ -125,7 +121,6 @@ func (this *UserDao) CountByUsername(username string) int {
|
||||
return count
|
||||
}
|
||||
|
||||
//保存用户
|
||||
func (this *UserDao) Save(user *User) *User {
|
||||
|
||||
user.UpdateTime = time.Now()
|
||||
|
@ -6,21 +6,27 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
//游客身份
|
||||
//guest
|
||||
USER_ROLE_GUEST = "GUEST"
|
||||
//普通注册用户
|
||||
//normal user
|
||||
USER_ROLE_USER = "USER"
|
||||
//管理员
|
||||
//administrator
|
||||
USER_ROLE_ADMINISTRATOR = "ADMINISTRATOR"
|
||||
)
|
||||
|
||||
const (
|
||||
//正常状态
|
||||
//ok
|
||||
USER_STATUS_OK = "OK"
|
||||
//被禁用
|
||||
//disabled
|
||||
USER_STATUS_DISABLED = "DISABLED"
|
||||
)
|
||||
|
||||
const (
|
||||
//username pattern
|
||||
USERNAME_PATTERN = `^[0-9a-z_]+$`
|
||||
USERNAME_DEMO = "demo"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Base
|
||||
Role string `json:"role" gorm:"type:varchar(45)"`
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"github.com/eyebluecn/tank/code/tool/cache"
|
||||
"github.com/eyebluecn/tank/code/tool/result"
|
||||
"github.com/eyebluecn/tank/code/tool/util"
|
||||
uuid "github.com/nu7hatch/gouuid"
|
||||
gouuid "github.com/nu7hatch/gouuid"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@ -16,7 +16,7 @@ type UserService struct {
|
||||
userDao *UserDao
|
||||
sessionDao *SessionDao
|
||||
|
||||
//操作文件的锁。
|
||||
//file lock
|
||||
locker *cache.Table
|
||||
}
|
||||
|
||||
@ -33,31 +33,27 @@ func (this *UserService) Init() {
|
||||
this.sessionDao = b
|
||||
}
|
||||
|
||||
//创建一个用于存储用户文件锁的缓存。
|
||||
//create a lock cache.
|
||||
this.locker = cache.NewTable()
|
||||
}
|
||||
|
||||
//对某个用户进行加锁。加锁阶段用户是不允许操作文件的。
|
||||
//lock a user's operation. If lock, user cannot operate file.
|
||||
func (this *UserService) MatterLock(userUuid string) {
|
||||
//如果已经是锁住的状态,直接报错
|
||||
|
||||
//去缓存中捞取
|
||||
cacheItem, err := this.locker.Value(userUuid)
|
||||
if err != nil {
|
||||
this.logger.Error("error while get cache" + err.Error())
|
||||
}
|
||||
|
||||
//当前被锁住了。
|
||||
if cacheItem != nil && cacheItem.Data() != nil {
|
||||
panic(result.BadRequest("file is being operating, retry later"))
|
||||
}
|
||||
|
||||
//添加一把新锁,有效期为12小时
|
||||
duration := 12 * time.Hour
|
||||
this.locker.Add(userUuid, duration, true)
|
||||
}
|
||||
|
||||
//对某个用户解锁,解锁后用户可以操作文件。
|
||||
//unlock
|
||||
func (this *UserService) MatterUnlock(userUuid string) {
|
||||
|
||||
exist := this.locker.Exists(userUuid)
|
||||
@ -65,58 +61,53 @@ func (this *UserService) MatterUnlock(userUuid string) {
|
||||
_, err := this.locker.Delete(userUuid)
|
||||
this.PanicError(err)
|
||||
} else {
|
||||
this.logger.Error("%s已经不存在matter锁了,解锁错误。", userUuid)
|
||||
this.logger.Error("unlock error. %s has no matter lock ", userUuid)
|
||||
}
|
||||
}
|
||||
|
||||
//装载session信息,如果session没有了根据cookie去装填用户信息。
|
||||
//在所有的路由最初会调用这个方法
|
||||
//1. 支持cookie形式 2.支持入参传入username和password 3.支持Basic Auth
|
||||
//load session to SessionCache. This method will be invoked in every request.
|
||||
//authorize by 1. cookie 2. username and password in request form. 3. Basic Auth
|
||||
func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
//登录身份有效期以数据库中记录的为准
|
||||
|
||||
//验证用户是否已经登录。
|
||||
sessionId := util.GetSessionUuidFromRequest(request, core.COOKIE_AUTH_KEY)
|
||||
|
||||
if sessionId != "" {
|
||||
|
||||
//去缓存中捞取
|
||||
cacheItem, err := core.CONTEXT.GetSessionCache().Value(sessionId)
|
||||
if err != nil {
|
||||
this.logger.Error("获取缓存时出错了" + err.Error())
|
||||
this.logger.Error("occur error will get session cache %s", err.Error())
|
||||
}
|
||||
|
||||
//缓存中没有,尝试去数据库捞取
|
||||
//if no cache. try to find in db.
|
||||
if cacheItem == nil || cacheItem.Data() == nil {
|
||||
session := this.sessionDao.FindByUuid(sessionId)
|
||||
if session != nil {
|
||||
duration := session.ExpireTime.Sub(time.Now())
|
||||
if duration <= 0 {
|
||||
this.logger.Error("登录信息已过期")
|
||||
this.logger.Error("login info has expired.")
|
||||
} else {
|
||||
user := this.userDao.FindByUuid(session.UserUuid)
|
||||
if user != nil {
|
||||
//将用户装填进缓存中
|
||||
core.CONTEXT.GetSessionCache().Add(sessionId, duration, user)
|
||||
} else {
|
||||
this.logger.Error("没有找到对应的user %s", session.UserUuid)
|
||||
this.logger.Error("no user with sessionId %s", session.UserUuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//再尝试读取一次,这次从 USERNAME_KEY PASSWORD_KEY 中装填用户登录信息
|
||||
//try to auth by USERNAME_KEY PASSWORD_KEY
|
||||
cacheItem, err := core.CONTEXT.GetSessionCache().Value(sessionId)
|
||||
if err != nil {
|
||||
this.logger.Error("获取缓存时出错了" + err.Error())
|
||||
this.logger.Error("occur error will get session cache %s", err.Error())
|
||||
}
|
||||
|
||||
if cacheItem == nil || cacheItem.Data() == nil {
|
||||
username := request.FormValue(core.USERNAME_KEY)
|
||||
password := request.FormValue(core.PASSWORD_KEY)
|
||||
|
||||
//try to read from BasicAuth
|
||||
if username == "" || password == "" {
|
||||
username, password, _ = request.BasicAuth()
|
||||
}
|
||||
@ -125,19 +116,18 @@ func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Req
|
||||
|
||||
user := this.userDao.FindByUsername(username)
|
||||
if user == nil {
|
||||
this.logger.Error("%s 用户名或密码错误", core.USERNAME_KEY)
|
||||
this.logger.Error("%s no such user in db.", username)
|
||||
} else {
|
||||
|
||||
if !util.MatchBcrypt(password, user.Password) {
|
||||
this.logger.Error("%s 用户名或密码错误", core.USERNAME_KEY)
|
||||
this.logger.Error("%s password error", username)
|
||||
} else {
|
||||
//装填一个临时的session用作后续使用。
|
||||
this.logger.Info("准备装载一个临时的用作。")
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
|
||||
this.logger.Info("load a temp session by username and password.")
|
||||
timeUUID, _ := gouuid.NewV4()
|
||||
uuidStr := string(timeUUID.String())
|
||||
request.Form[core.COOKIE_AUTH_KEY] = []string{uuidStr}
|
||||
|
||||
//将用户装填进缓存中
|
||||
core.CONTEXT.GetSessionCache().Add(uuidStr, 10*time.Second, user)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user