Finish the mirror feature. Finish the prototype of zip compress.
This commit is contained in:
@ -72,11 +72,6 @@ func (this *AlienService) PreviewOrDownload(
|
||||
|
||||
matter := this.matterDao.CheckByUuid(uuid)
|
||||
|
||||
//判断是否是文件夹
|
||||
if matter.Dir {
|
||||
panic("不支持下载文件夹")
|
||||
}
|
||||
|
||||
if matter.Name != filename {
|
||||
panic("文件信息错误")
|
||||
}
|
||||
@ -117,21 +112,33 @@ func (this *AlienService) PreviewOrDownload(
|
||||
}
|
||||
}
|
||||
|
||||
//对图片处理。
|
||||
needProcess, imageResizeM, imageResizeW, imageResizeH := this.imageCacheService.ResizeParams(request)
|
||||
if needProcess {
|
||||
//文件夹下载
|
||||
if matter.Dir {
|
||||
|
||||
//如果是图片,那么能用缓存就用缓存
|
||||
imageCache := this.imageCacheDao.FindByMatterUuidAndMode(matter.Uuid, fmt.Sprintf("%s_%d_%d", imageResizeM, imageResizeW, imageResizeH))
|
||||
if imageCache == nil {
|
||||
imageCache = this.imageCacheService.cacheImage(writer, request, matter)
|
||||
}
|
||||
this.logger.Info("准备下载文件夹 %s", matter.Name)
|
||||
|
||||
//直接使用缓存中的信息
|
||||
this.matterService.DownloadFile(writer, request, GetUserCacheRootDir(imageCache.Username)+imageCache.Path, imageCache.Name, withContentDisposition)
|
||||
//目标地点
|
||||
this.matterService.AtomicDownloadDirectory(writer, request, matter)
|
||||
|
||||
} else {
|
||||
this.matterService.DownloadFile(writer, request, matter.AbsolutePath(), matter.Name, withContentDisposition)
|
||||
|
||||
//对图片处理。
|
||||
needProcess, imageResizeM, imageResizeW, imageResizeH := this.imageCacheService.ResizeParams(request)
|
||||
if needProcess {
|
||||
|
||||
//如果是图片,那么能用缓存就用缓存
|
||||
imageCache := this.imageCacheDao.FindByMatterUuidAndMode(matter.Uuid, fmt.Sprintf("%s_%d_%d", imageResizeM, imageResizeW, imageResizeH))
|
||||
if imageCache == nil {
|
||||
imageCache = this.imageCacheService.cacheImage(writer, request, matter)
|
||||
}
|
||||
|
||||
//直接使用缓存中的信息
|
||||
this.matterService.DownloadFile(writer, request, GetUserCacheRootDir(imageCache.Username)+imageCache.Path, imageCache.Name, withContentDisposition)
|
||||
|
||||
} else {
|
||||
this.matterService.DownloadFile(writer, request, matter.AbsolutePath(), matter.Name, withContentDisposition)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//文件下载次数加一,为了加快访问速度,异步进行
|
||||
|
@ -59,6 +59,7 @@ func (this *BaseBean) findUser(writer http.ResponseWriter, request *http.Request
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
//获取当前登录的用户,找不到就返回登录错误
|
||||
|
@ -128,10 +128,7 @@ func (this *InstallController) getCreateSQLFromFile(tableName string) string {
|
||||
//1. 从当前安装目录db下去寻找建表文件。
|
||||
homePath := util.GetHomePath()
|
||||
filePath := homePath + "/db/" + tableName + ".sql"
|
||||
exists, err := util.PathExists(filePath)
|
||||
if err != nil {
|
||||
panic(result.Server("从安装目录判断建表语句文件是否存在时出错!"))
|
||||
}
|
||||
exists := util.PathExists(filePath)
|
||||
|
||||
//2. 从GOPATH下面去找,因为可能是开发环境
|
||||
if !exists {
|
||||
@ -140,10 +137,7 @@ func (this *InstallController) getCreateSQLFromFile(tableName string) string {
|
||||
|
||||
filePath1 := filePath
|
||||
filePath = build.Default.GOPATH + "/src/tank/build/db/" + tableName + ".sql"
|
||||
exists, err = util.PathExists(filePath)
|
||||
if err != nil {
|
||||
panic(result.Server("从GOPATH判断建表语句文件是否存在时出错!"))
|
||||
}
|
||||
exists = util.PathExists(filePath)
|
||||
|
||||
if !exists {
|
||||
panic(result.Server("%s 或 %s 均不存在,请检查你的安装情况。", filePath1, filePath))
|
||||
|
@ -66,6 +66,9 @@ func (this *MatterController) RegisterRoutes() map[string]func(writer http.Respo
|
||||
routeMap["/api/matter/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
||||
routeMap["/api/matter/page"] = this.Wrap(this.Page, USER_ROLE_USER)
|
||||
|
||||
//本地文件映射
|
||||
routeMap["/api/matter/mirror"] = this.Wrap(this.Mirror, USER_ROLE_USER)
|
||||
|
||||
return routeMap
|
||||
}
|
||||
|
||||
@ -443,3 +446,27 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req
|
||||
|
||||
return this.Success(nil)
|
||||
}
|
||||
|
||||
//将本地文件映射到蓝眼云盘中去。
|
||||
func (this *MatterController) Mirror(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
srcPath := request.FormValue("srcPath")
|
||||
destPath := request.FormValue("destPath")
|
||||
overwriteStr := request.FormValue("overwrite")
|
||||
|
||||
if srcPath == "" {
|
||||
panic(result.BadRequest("srcPath必填"))
|
||||
}
|
||||
|
||||
overwrite := false
|
||||
if overwriteStr == TRUE {
|
||||
overwrite = true
|
||||
}
|
||||
|
||||
user := this.userDao.checkUser(writer, request)
|
||||
|
||||
this.matterService.AtomicMirror(srcPath, destPath, overwrite, user)
|
||||
|
||||
return this.Success(nil)
|
||||
|
||||
}
|
||||
|
@ -163,6 +163,40 @@ func (this *MatterDao) CountByUserUuidAndPuuidAndDirAndName(userUuid string, puu
|
||||
return count
|
||||
}
|
||||
|
||||
//统计某个用户的某个文件夹下的某个名字的文件(或文件夹)数量。
|
||||
func (this *MatterDao) FindByUserUuidAndPuuidAndDirAndName(userUuid string, puuid string, dir bool, name string) *Matter {
|
||||
|
||||
var matter = &Matter{}
|
||||
|
||||
var wp = &builder.WherePair{}
|
||||
|
||||
if puuid != "" {
|
||||
wp = wp.And(&builder.WherePair{Query: "puuid = ?", Args: []interface{}{puuid}})
|
||||
}
|
||||
|
||||
if userUuid != "" {
|
||||
wp = wp.And(&builder.WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}})
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
wp = wp.And(&builder.WherePair{Query: "name = ?", Args: []interface{}{name}})
|
||||
}
|
||||
|
||||
wp = wp.And(&builder.WherePair{Query: "dir = ?", Args: []interface{}{dir}})
|
||||
|
||||
db := core.CONTEXT.GetDB().Where(wp.Query, wp.Args...).First(matter)
|
||||
|
||||
if db.Error != nil {
|
||||
if db.Error.Error() == result.DB_ERROR_NOT_FOUND {
|
||||
return nil
|
||||
} else {
|
||||
this.PanicError(db.Error)
|
||||
}
|
||||
}
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
//获取某个用户的某个文件夹下的某个名字的文件(或文件夹)列表
|
||||
func (this *MatterDao) ListByUserUuidAndPuuidAndDirAndName(userUuid string, puuid string, dir bool, name string) []*Matter {
|
||||
|
||||
@ -318,6 +352,8 @@ func (this *MatterDao) CountBetweenTime(startTime time.Time, endTime time.Time)
|
||||
|
||||
//获取一段时间中文件总大小
|
||||
func (this *MatterDao) SizeBetweenTime(startTime time.Time, endTime time.Time) int64 {
|
||||
|
||||
//TODO: 所有函数汇总的SQL均需要先count询问,再处理。
|
||||
var size int64
|
||||
db := core.CONTEXT.GetDB().Model(&Matter{}).Where("create_time >= ? AND create_time <= ?", startTime, endTime).Select("SUM(size)")
|
||||
this.PanicError(db.Error)
|
||||
@ -360,6 +396,28 @@ func (this *MatterDao) checkByUserUuidAndPath(userUuid string, path string) *Mat
|
||||
return matter
|
||||
}
|
||||
|
||||
//获取一个文件夹中文件总大小
|
||||
func (this *MatterDao) SumSizeByUserUuidAndPath(userUuid string, path string) int64 {
|
||||
|
||||
var wp = &builder.WherePair{Query: "user_uuid = ? AND path like ?", Args: []interface{}{userUuid, path + "%"}}
|
||||
|
||||
var count int64
|
||||
db := core.CONTEXT.GetDB().Model(&Matter{}).Where(wp.Query, wp.Args...).Count(&count)
|
||||
if count == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var sumSize int64
|
||||
db = core.CONTEXT.GetDB().Model(&Matter{}).Where(wp.Query, wp.Args...).Select("SUM(size)")
|
||||
this.PanicError(db.Error)
|
||||
row := db.Row()
|
||||
err := row.Scan(&sumSize)
|
||||
util.PanicError(err)
|
||||
|
||||
return sumSize
|
||||
|
||||
}
|
||||
|
||||
//执行清理操作
|
||||
func (this *MatterDao) Cleanup() {
|
||||
this.logger.Info("[MatterDao]执行清理:清除数据库中所有Matter记录。删除磁盘中所有Matter文件。")
|
||||
|
@ -3,7 +3,6 @@ package rest
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/eyebluecn/tank/code/core"
|
||||
|
||||
"github.com/eyebluecn/tank/code/tool/util"
|
||||
)
|
||||
|
||||
@ -12,6 +11,8 @@ const (
|
||||
MATTER_ROOT = "root"
|
||||
//cache文件夹名称
|
||||
MATTER_CACHE = "cache"
|
||||
//压缩文件的临时目录
|
||||
MATTER_ZIP = "zip"
|
||||
//matter名称最大长度
|
||||
MATTER_NAME_MAX_LENGTH = 200
|
||||
//matter文件夹最大深度
|
||||
@ -80,3 +81,11 @@ func GetUserCacheRootDir(username string) (rootDirPath string) {
|
||||
|
||||
return rootDirPath
|
||||
}
|
||||
|
||||
//获取到用户压缩临时文件的根目录。
|
||||
func GetUserZipRootDir(username string) (rootDirPath string) {
|
||||
|
||||
rootDirPath = fmt.Sprintf("%s/%s/%s", core.CONFIG.MatterPath(), username, MATTER_ZIP)
|
||||
|
||||
return rootDirPath
|
||||
}
|
||||
|
@ -1,15 +1,21 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"github.com/eyebluecn/tank/code/core"
|
||||
"github.com/eyebluecn/tank/code/tool/builder"
|
||||
"github.com/eyebluecn/tank/code/tool/download"
|
||||
"github.com/eyebluecn/tank/code/tool/result"
|
||||
"github.com/eyebluecn/tank/code/tool/util"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
/**
|
||||
@ -69,6 +75,132 @@ func (this *MatterService) DownloadFile(
|
||||
download.DownloadFile(writer, request, filePath, filename, withContentDisposition)
|
||||
}
|
||||
|
||||
//下载文件夹
|
||||
func (this *MatterService) AtomicDownloadDirectory(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
matter *Matter) {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.BadRequest("matter不能为nil"))
|
||||
}
|
||||
|
||||
if !matter.Dir {
|
||||
panic(result.BadRequest("matter 只能是文件夹"))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(matter.UserUuid)
|
||||
defer this.userService.MatterUnlock(matter.UserUuid)
|
||||
|
||||
//验证文件夹中文件总大小。
|
||||
sumSize := this.matterDao.SumSizeByUserUuidAndPath(matter.UserUuid, matter.Path)
|
||||
this.logger.Info("文件夹 %s 大小为 %s", matter.Name, util.HumanFileSize(sumSize))
|
||||
|
||||
//TODO: 文件夹下载的大小限制
|
||||
//准备zip放置的目录。
|
||||
destZipDirPath := fmt.Sprintf("%s/%d", GetUserZipRootDir(matter.Username), time.Now().UnixNano()/1e6)
|
||||
util.MakeDirAll(destZipDirPath)
|
||||
|
||||
destZipName := fmt.Sprintf("%s.zip", matter.Name)
|
||||
|
||||
destZipPath := fmt.Sprintf("%s/%s", destZipDirPath, destZipName)
|
||||
|
||||
//destZipFile, err := os.Create(destZipPath)
|
||||
//util.PanicError(err)
|
||||
//
|
||||
//defer func() {
|
||||
// err := destZipFile.Close()
|
||||
// util.PanicError(err)
|
||||
//}()
|
||||
//
|
||||
//zipWriter := zip.NewWriter(destZipFile)
|
||||
//defer func() {
|
||||
// err := zipWriter.Close()
|
||||
// util.PanicError(err)
|
||||
//}()
|
||||
|
||||
//this.zipCompress(matter, GetUserFileRootDir(matter.Username), zipWriter)
|
||||
|
||||
util.Zip(matter.AbsolutePath(), destZipPath)
|
||||
|
||||
//下载
|
||||
download.DownloadFile(writer, request, destZipPath, destZipName, true)
|
||||
|
||||
//TODO: 删除临时压缩文件
|
||||
|
||||
}
|
||||
|
||||
//zip压缩一个matter.
|
||||
func (this *MatterService) zipCompress(matter *Matter, prefix string, zipWriter *zip.Writer) {
|
||||
|
||||
if matter == nil {
|
||||
panic(result.BadRequest("matter不能为nil"))
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(matter.AbsolutePath())
|
||||
this.PanicError(err)
|
||||
|
||||
fmt.Println("遍历文件: " + matter.AbsolutePath())
|
||||
|
||||
if matter.Dir {
|
||||
|
||||
//获取下一级的文件。
|
||||
prefix = prefix + "/" + matter.Name
|
||||
|
||||
sortArray := []builder.OrderPair{
|
||||
{
|
||||
Key: "path",
|
||||
Value: "ASC",
|
||||
},
|
||||
}
|
||||
matters := this.matterDao.List(matter.Uuid, matter.UserUuid, sortArray)
|
||||
|
||||
// 通过文件信息,创建 zip 的文件信息
|
||||
fileHeader, err := zip.FileInfoHeader(fileInfo)
|
||||
this.PanicError(err)
|
||||
|
||||
//写入头信息。目录无需写入内容。目录的头部要去掉斜杠,尾部要加上斜杠。
|
||||
fileHeader.Name = strings.TrimPrefix(prefix+"/", string(filepath.Separator))
|
||||
|
||||
fmt.Println("文件夹头: " + fileHeader.Name)
|
||||
|
||||
// 写入文件信息,并返回一个 Write 结构
|
||||
_, err = zipWriter.CreateHeader(fileHeader)
|
||||
this.PanicError(err)
|
||||
|
||||
for _, subMatter := range matters {
|
||||
this.zipCompress(subMatter, prefix, zipWriter)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
fileHeader, err := zip.FileInfoHeader(fileInfo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//第一个斜杠不需要。
|
||||
fileHeader.Name = strings.TrimPrefix(prefix+"/"+matter.Name, string(filepath.Separator))
|
||||
|
||||
fmt.Println("文件头部: " + fileHeader.Name)
|
||||
|
||||
writer, err := zipWriter.CreateHeader(fileHeader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
file, err := os.Open(matter.AbsolutePath())
|
||||
_, err = io.Copy(writer, file)
|
||||
defer func() {
|
||||
err := file.Close()
|
||||
this.PanicError(err)
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//删除文件
|
||||
func (this *MatterService) AtomicDelete(matter *Matter) {
|
||||
|
||||
@ -117,8 +249,7 @@ func (this *MatterService) Upload(file io.Reader, user *User, dirMatter *Matter,
|
||||
util.MakeDirAll(dirAbsolutePath)
|
||||
|
||||
//如果文件已经存在了,那么直接覆盖。
|
||||
exist, err := util.PathExists(fileAbsolutePath)
|
||||
this.PanicError(err)
|
||||
exist := util.PathExists(fileAbsolutePath)
|
||||
if exist {
|
||||
this.logger.Error("%s已经存在,将其删除", fileAbsolutePath)
|
||||
removeError := os.Remove(fileAbsolutePath)
|
||||
@ -214,12 +345,10 @@ func (this *MatterService) createDirectory(dirMatter *Matter, name string, user
|
||||
panic(result.BadRequest(`名称中不能包含以下特殊符号:< > | * ? / \`))
|
||||
}
|
||||
|
||||
//判断同级文件夹中是否有同名的文件夹
|
||||
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, true, name)
|
||||
|
||||
if count > 0 {
|
||||
|
||||
panic(result.BadRequest("%s 已经存在了,请使用其他名称。", name))
|
||||
//判断同级文件夹中是否有同名的文件夹。存在了直接返回即可。
|
||||
matter := this.matterDao.FindByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, true, name)
|
||||
if matter != nil {
|
||||
return matter
|
||||
}
|
||||
|
||||
parts := strings.Split(dirMatter.Path, "/")
|
||||
@ -240,7 +369,7 @@ func (this *MatterService) createDirectory(dirMatter *Matter, name string, user
|
||||
this.logger.Info("Create Directory: %s", dirPath)
|
||||
|
||||
//数据库中创建文件夹。
|
||||
matter := &Matter{
|
||||
matter = &Matter{
|
||||
Puuid: dirMatter.Uuid,
|
||||
UserUuid: user.Uuid,
|
||||
Username: user.Username,
|
||||
@ -569,7 +698,96 @@ func (this *MatterService) AtomicRename(matter *Matter, name string, user *User)
|
||||
return
|
||||
}
|
||||
|
||||
//根据一个文件夹路径,依次创建,找到最后一个文件夹的matter,如果中途出错,返回err.
|
||||
//将本地文件映射到蓝眼云盘中去。
|
||||
func (this *MatterService) AtomicMirror(srcPath string, destPath string, overwrite bool, user *User) {
|
||||
|
||||
if user == nil {
|
||||
panic(result.BadRequest("user cannot be nil"))
|
||||
}
|
||||
|
||||
//操作锁
|
||||
this.userService.MatterLock(user.Uuid)
|
||||
defer this.userService.MatterUnlock(user.Uuid)
|
||||
|
||||
//验证参数。
|
||||
if destPath == "" {
|
||||
panic(result.BadRequest("dest 参数必填"))
|
||||
}
|
||||
|
||||
destDirMatter := this.CreateDirectories(user, destPath)
|
||||
|
||||
this.mirror(srcPath, destDirMatter, overwrite, user)
|
||||
}
|
||||
|
||||
//将本地文件/文件夹映射到蓝眼云盘中去。
|
||||
func (this *MatterService) mirror(srcPath string, destDirMatter *Matter, overwrite bool, user *User) {
|
||||
|
||||
if user == nil {
|
||||
panic(result.BadRequest("user cannot be nil"))
|
||||
}
|
||||
|
||||
fileStat, err := os.Stat(srcPath)
|
||||
if err != nil {
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
panic(result.BadRequest("srcPath %s not exist", srcPath))
|
||||
} else {
|
||||
|
||||
panic(result.BadRequest("srcPath err %s %s", srcPath, err.Error()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.logger.Info("mirror srcPath = %s destPath = %s", srcPath, destDirMatter.Path)
|
||||
|
||||
if fileStat.IsDir() {
|
||||
|
||||
//判断当前文件夹下,文件是否已经存在了。
|
||||
srcDirMatter := this.matterDao.FindByUserUuidAndPuuidAndDirAndName(user.Uuid, destDirMatter.Uuid, true, fileStat.Name())
|
||||
|
||||
if srcDirMatter == nil {
|
||||
srcDirMatter = this.createDirectory(destDirMatter, fileStat.Name(), user)
|
||||
}
|
||||
|
||||
fileInfos, err := ioutil.ReadDir(srcPath)
|
||||
this.PanicError(err)
|
||||
|
||||
//递归处理本文件夹下的文件或文件夹
|
||||
for _, fileInfo := range fileInfos {
|
||||
|
||||
path := fmt.Sprintf("%s/%s", srcPath, fileInfo.Name())
|
||||
this.mirror(path, srcDirMatter, overwrite, user)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//判断当前文件夹下,文件是否已经存在了。
|
||||
matter := this.matterDao.FindByUserUuidAndPuuidAndDirAndName(user.Uuid, destDirMatter.Uuid, false, fileStat.Name())
|
||||
if matter != nil {
|
||||
//如果是覆盖,那么删除之前的文件
|
||||
if overwrite {
|
||||
this.matterDao.Delete(matter)
|
||||
} else {
|
||||
//直接完成。
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//准备直接从本地上传了。
|
||||
file, err := os.Open(srcPath)
|
||||
this.PanicError(err)
|
||||
defer func() {
|
||||
err := file.Close()
|
||||
this.PanicError(err)
|
||||
}()
|
||||
|
||||
this.Upload(file, user, destDirMatter, fileStat.Name(), true)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//根据一个文件夹路径,依次创建,找到最后一个文件夹的matter,如果中途出错,返回err. 如果存在了那就直接返回即可。
|
||||
func (this *MatterService) CreateDirectories(user *User, dirPath string) *Matter {
|
||||
|
||||
if dirPath == "" {
|
||||
|
@ -36,6 +36,7 @@ func (this *PreferenceController) RegisterRoutes() map[string]func(writer http.R
|
||||
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
||||
|
||||
//每个Controller需要主动注册自己的路由。
|
||||
routeMap["/api/preference/ping"] = this.Wrap(this.Ping, USER_ROLE_GUEST)
|
||||
routeMap["/api/preference/fetch"] = this.Wrap(this.Fetch, USER_ROLE_GUEST)
|
||||
routeMap["/api/preference/edit"] = this.Wrap(this.Edit, USER_ROLE_ADMINISTRATOR)
|
||||
routeMap["/api/preference/system_cleanup"] = this.Wrap(this.SystemCleanup, USER_ROLE_ADMINISTRATOR)
|
||||
@ -43,6 +44,13 @@ func (this *PreferenceController) RegisterRoutes() map[string]func(writer http.R
|
||||
return routeMap
|
||||
}
|
||||
|
||||
//简单验证蓝眼云盘服务是否已经启动了。
|
||||
func (this *PreferenceController) Ping(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
return this.Success(nil)
|
||||
|
||||
}
|
||||
|
||||
//查看某个偏好设置的详情。
|
||||
func (this *PreferenceController) Fetch(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
|
@ -42,28 +42,30 @@ func (this *UserController) RegisterRoutes() map[string]func(writer http.Respons
|
||||
|
||||
//使用用户名和密码进行登录。
|
||||
//参数:
|
||||
// @email:邮箱
|
||||
// @username:用户名(也可以输入邮箱)
|
||||
// @password:密码
|
||||
func (this *UserController) Login(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||
|
||||
email := request.FormValue("email")
|
||||
username := request.FormValue("username")
|
||||
password := request.FormValue("password")
|
||||
|
||||
if "" == email || "" == password {
|
||||
if "" == username || "" == password {
|
||||
|
||||
panic(result.BadRequest("请输入邮箱和密码"))
|
||||
panic(result.BadRequest("请输入用户名和密码"))
|
||||
}
|
||||
|
||||
user := this.userDao.FindByEmail(email)
|
||||
user := this.userDao.FindByUsername(username)
|
||||
if user == nil {
|
||||
|
||||
panic(result.BadRequest("邮箱或密码错误"))
|
||||
|
||||
} else {
|
||||
if !util.MatchBcrypt(password, user.Password) {
|
||||
|
||||
panic(result.BadRequest("邮箱或密码错误"))
|
||||
user = this.userDao.FindByEmail(username)
|
||||
if user == nil {
|
||||
panic(result.BadRequest("用户名或密码错误"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if !util.MatchBcrypt(password, user.Password) {
|
||||
|
||||
panic(result.BadRequest("用户名或密码错误"))
|
||||
}
|
||||
|
||||
//登录成功,设置Cookie。有效期30天。
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"github.com/eyebluecn/tank/code/core"
|
||||
"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"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@ -76,36 +78,68 @@ func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Req
|
||||
//登录身份有效期以数据库中记录的为准
|
||||
|
||||
//验证用户是否已经登录。
|
||||
sessionCookie, err := request.Cookie(core.COOKIE_AUTH_KEY)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sessionId := util.GetSessionUuidFromRequest(request, core.COOKIE_AUTH_KEY)
|
||||
|
||||
sessionId := sessionCookie.Value
|
||||
if sessionId != "" {
|
||||
|
||||
//去缓存中捞取
|
||||
cacheItem, err := core.CONTEXT.GetSessionCache().Value(sessionId)
|
||||
if err != nil {
|
||||
this.logger.Error("获取缓存时出错了" + err.Error())
|
||||
}
|
||||
//去缓存中捞取
|
||||
cacheItem, err := core.CONTEXT.GetSessionCache().Value(sessionId)
|
||||
if err != nil {
|
||||
this.logger.Error("获取缓存时出错了" + err.Error())
|
||||
}
|
||||
|
||||
//缓存中没有,尝试去数据库捞取
|
||||
if cacheItem == nil || cacheItem.Data() == nil {
|
||||
session := this.sessionDao.FindByUuid(sessionCookie.Value)
|
||||
if session != nil {
|
||||
duration := session.ExpireTime.Sub(time.Now())
|
||||
if duration <= 0 {
|
||||
this.logger.Error("登录信息已过期")
|
||||
} else {
|
||||
user := this.userDao.FindByUuid(session.UserUuid)
|
||||
if user != nil {
|
||||
//将用户装填进缓存中
|
||||
core.CONTEXT.GetSessionCache().Add(sessionCookie.Value, duration, user)
|
||||
//缓存中没有,尝试去数据库捞取
|
||||
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("登录信息已过期")
|
||||
} else {
|
||||
this.logger.Error("没有找到对应的user " + session.UserUuid)
|
||||
user := this.userDao.FindByUuid(session.UserUuid)
|
||||
if user != nil {
|
||||
//将用户装填进缓存中
|
||||
core.CONTEXT.GetSessionCache().Add(sessionId, duration, user)
|
||||
} else {
|
||||
this.logger.Error("没有找到对应的user %s", session.UserUuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//再尝试读取一次,这次从 USERNAME_KEY PASSWORD_KEY 中装填用户登录信息
|
||||
cacheItem, err := core.CONTEXT.GetSessionCache().Value(sessionId)
|
||||
if err != nil {
|
||||
this.logger.Error("获取缓存时出错了" + err.Error())
|
||||
}
|
||||
|
||||
if cacheItem == nil || cacheItem.Data() == nil {
|
||||
username := request.FormValue(core.USERNAME_KEY)
|
||||
password := request.FormValue(core.PASSWORD_KEY)
|
||||
|
||||
if username != "" && password != "" {
|
||||
|
||||
user := this.userDao.FindByUsername(username)
|
||||
if user == nil {
|
||||
this.logger.Error("%s 用户名或密码错误", core.USERNAME_KEY)
|
||||
} else {
|
||||
|
||||
if !util.MatchBcrypt(password, user.Password) {
|
||||
this.logger.Error("%s 用户名或密码错误", core.USERNAME_KEY)
|
||||
} else {
|
||||
//装填一个临时的session用作后续使用。
|
||||
this.logger.Info("准备装载一个临时的用作。")
|
||||
timeUUID, _ := uuid.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