Kick off tank 2.0

This commit is contained in:
zicla 2018-11-22 21:16:53 +08:00
parent 55124ed7e8
commit 90a0e04590
9 changed files with 470 additions and 4 deletions

112
build/doc/db.sql Normal file
View File

@ -0,0 +1,112 @@
CREATE TABLE `tank20_download_token` (
`uuid` char(36) NOT NULL,
`user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid',
`matter_uuid` char(36) DEFAULT NULL COMMENT '文件标识',
`expire_time` timestamp NULL DEFAULT NULL COMMENT '授权访问的次数',
`ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip',
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='下载的token表';
CREATE TABLE `tank20_image_cache` (
`uuid` char(36) NOT NULL,
`user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id',
`matter_uuid` char(36) DEFAULT NULL,
`uri` varchar(512) DEFAULT NULL COMMENT '请求的uri',
`md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值',
`size` bigint(20) DEFAULT '0' COMMENT '文件大小',
`path` varchar(255) DEFAULT NULL,
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`),
UNIQUE KEY `uri_UNIQUE` (`uri`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图片缓存表';
CREATE TABLE `tank20_matter` (
`uuid` char(36) NOT NULL,
`puuid` varchar(45) DEFAULT NULL COMMENT '上一级的uuid',
`user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id',
`dir` tinyint(1) DEFAULT '0' COMMENT '是否是文件夹',
`alien` tinyint(1) DEFAULT '0',
`name` varchar(255) DEFAULT NULL COMMENT '文件名称',
`md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值',
`size` bigint(20) DEFAULT '0' COMMENT '文件大小',
`privacy` tinyint(1) DEFAULT '0' COMMENT '文件是否是公有的',
`path` varchar(255) DEFAULT NULL,
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='file表';
CREATE TABLE `tank20_preference` (
`uuid` char(36) NOT NULL,
`name` varchar(45) DEFAULT NULL COMMENT '网站名称',
`logo_url` varchar(255) DEFAULT NULL,
`favicon_url` varchar(255) DEFAULT NULL,
`footer_line1` varchar(1024) DEFAULT NULL,
`footer_line2` varchar(1024) DEFAULT NULL,
`version` varchar(45) DEFAULT NULL,
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='网站偏好设置表';
CREATE TABLE `tank20_session` (
`uuid` char(36) NOT NULL,
`authentication` char(36) DEFAULT NULL COMMENT '认证身份存放在cookie中',
`user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid',
`ip` varchar(45) DEFAULT NULL COMMENT '用户的ip地址',
`expire_time` timestamp NULL DEFAULT NULL,
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='session表';
CREATE TABLE `tank20_upload_token` (
`uuid` char(36) NOT NULL,
`user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid',
`folder_uuid` char(36) DEFAULT NULL,
`matter_uuid` char(36) DEFAULT NULL,
`filename` varchar(255) DEFAULT NULL COMMENT '文件后缀名的过滤,可以只允许用户上传特定格式的文件。',
`privacy` tinyint(1) DEFAULT '1',
`size` bigint(20) DEFAULT '0',
`expire_time` timestamp NULL DEFAULT NULL,
`ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip',
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='上传的token表';
CREATE TABLE `tank20_user` (
`uuid` char(36) NOT NULL,
`role` varchar(45) DEFAULT 'USER',
`username` varchar(255) DEFAULT NULL COMMENT '昵称',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
`email` varchar(45) DEFAULT NULL COMMENT '邮箱',
`phone` varchar(45) DEFAULT NULL COMMENT '电话',
`gender` varchar(45) DEFAULT 'UNKNOWN' COMMENT '性别,默认未知',
`city` varchar(45) DEFAULT NULL COMMENT '城市',
`avatar_url` varchar(255) DEFAULT NULL COMMENT '头像链接',
`last_time` datetime DEFAULT NULL COMMENT '上次登录使劲按',
`last_ip` varchar(45) DEFAULT NULL,
`size_limit` int(11) DEFAULT '-1' COMMENT '该账号上传文件的大小限制单位byte。<0 表示不设限制',
`status` varchar(45) DEFAULT 'OK',
`sort` bigint(20) DEFAULT NULL,
`modify_time` timestamp NULL DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `id_UNIQUE` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表描述';

View File

@ -424,6 +424,10 @@ func (this *AlienController) Download(writer http.ResponseWriter, request *http.
}
}
//缓存
//对图片做缩放处理。
imageProcess := request.FormValue("imageProcess")
if imageProcess == "resize" {

View File

@ -16,8 +16,8 @@ const (
//用户身份的cookie字段名
COOKIE_AUTH_KEY = "_ak"
//数据库表前缀 tank100表示当前应用版本是tank:1.0.x版数据库结构发生变化必然是中型升级
TABLE_PREFIX = "tank10_"
//数据库表前缀 tank200表示当前应用版本是tank:2.0.x版数据库结构发生变化必然是中型升级
TABLE_PREFIX = "tank20_"
//当前版本
VERSION = "1.0.5"

View File

@ -99,6 +99,11 @@ func (this *Context) registerBeans() {
//downloadToken
this.registerBean(new(DownloadTokenDao))
//imageCache
this.registerBean(new(ImageCacheController))
this.registerBean(new(ImageCacheDao))
this.registerBean(new(ImageCacheService))
//matter
this.registerBean(new(MatterController))
this.registerBean(new(MatterDao))

View File

@ -0,0 +1,158 @@
package rest
import (
"net/http"
"strconv"
"strings"
)
type ImageCacheController struct {
BaseController
imageCacheDao *ImageCacheDao
imageCacheService *ImageCacheService
}
//初始化方法
func (this *ImageCacheController) Init(context *Context) {
this.BaseController.Init(context)
//手动装填本实例的Bean. 这里必须要用中间变量方可。
b := context.GetBean(this.imageCacheDao)
if b, ok := b.(*ImageCacheDao); ok {
this.imageCacheDao = b
}
b = context.GetBean(this.imageCacheService)
if b, ok := b.(*ImageCacheService); ok {
this.imageCacheService = b
}
}
//注册自己的路由。
func (this *ImageCacheController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
//每个Controller需要主动注册自己的路由。
routeMap["/api/image/cache/delete"] = this.Wrap(this.Delete, USER_ROLE_USER)
routeMap["/api/image/cache/delete/batch"] = this.Wrap(this.DeleteBatch, USER_ROLE_USER)
routeMap["/api/image/cache/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
routeMap["/api/image/cache/page"] = this.Wrap(this.Page, USER_ROLE_USER)
return routeMap
}
//查看某个文件的详情。
func (this *ImageCacheController) Detail(writer http.ResponseWriter, request *http.Request) *WebResult {
uuid := request.FormValue("uuid")
if uuid == "" {
return this.Error("文件的uuid必填")
}
imageCache := this.imageCacheService.Detail(uuid)
//验证当前之人是否有权限查看这么详细。
user := this.checkUser(writer, request)
if user.Role != USER_ROLE_ADMINISTRATOR {
if imageCache.UserUuid != user.Uuid {
panic("没有权限查看该文件")
}
}
return this.Success(imageCache)
}
//按照分页的方式获取某个文件夹下文件和子文件夹的列表,通常情况下只有一页。
func (this *ImageCacheController) Page(writer http.ResponseWriter, request *http.Request) *WebResult {
//如果是根目录那么就传入root.
pageStr := request.FormValue("page")
pageSizeStr := request.FormValue("pageSize")
userUuid := request.FormValue("userUuid")
orderCreateTime := request.FormValue("orderCreateTime")
orderSize := request.FormValue("orderSize")
user := this.checkUser(writer, request)
if user.Role != USER_ROLE_ADMINISTRATOR {
userUuid = user.Uuid
}
var page int
if pageStr != "" {
page, _ = strconv.Atoi(pageStr)
}
pageSize := 200
if pageSizeStr != "" {
tmp, err := strconv.Atoi(pageSizeStr)
if err == nil {
pageSize = tmp
}
}
sortArray := []OrderPair{
{
key: "create_time",
value: orderCreateTime,
},
{
key: "size",
value: orderSize,
},
}
pager := this.imageCacheDao.Page(page, pageSize, userUuid, sortArray)
return this.Success(pager)
}
//删除一个文件
func (this *ImageCacheController) Delete(writer http.ResponseWriter, request *http.Request) *WebResult {
uuid := request.FormValue("uuid")
if uuid == "" {
return this.Error("文件的uuid必填")
}
imageCache := this.imageCacheDao.FindByUuid(uuid)
//判断文件的所属人是否正确
user := this.checkUser(writer, request)
if user.Role != USER_ROLE_ADMINISTRATOR && imageCache.UserUuid != user.Uuid {
return this.Error(RESULT_CODE_UNAUTHORIZED)
}
this.imageCacheDao.Delete(imageCache)
return this.Success("删除成功!")
}
//删除一系列文件。
func (this *ImageCacheController) DeleteBatch(writer http.ResponseWriter, request *http.Request) *WebResult {
uuids := request.FormValue("uuids")
if uuids == "" {
return this.Error("文件的uuids必填")
}
uuidArray := strings.Split(uuids, ",")
for _, uuid := range uuidArray {
imageCache := this.imageCacheDao.FindByUuid(uuid)
//判断文件的所属人是否正确
user := this.checkUser(writer, request)
if user.Role != USER_ROLE_ADMINISTRATOR && imageCache.UserUuid != user.Uuid {
return this.Error(RESULT_CODE_UNAUTHORIZED)
}
this.imageCacheDao.Delete(imageCache)
}
return this.Success("删除成功!")
}

142
rest/image_cache_dao.go Normal file
View File

@ -0,0 +1,142 @@
package rest
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/nu7hatch/gouuid"
"os"
"time"
)
type ImageCacheDao struct {
BaseDao
}
//按照Id查询文件
func (this *ImageCacheDao) FindByUuid(uuid string) *ImageCache {
// Read
var imageCache ImageCache
db := this.context.DB.Where(&ImageCache{Base: Base{Uuid: uuid}}).First(&imageCache)
if db.Error != nil {
return nil
}
return &imageCache
}
//按照Id查询文件
func (this *ImageCacheDao) CheckByUuid(uuid string) *ImageCache {
// Read
var imageCache ImageCache
db := this.context.DB.Where(&ImageCache{Base: Base{Uuid: uuid}}).First(&imageCache)
this.PanicError(db.Error)
return &imageCache
}
//按照名字查询文件夹
func (this *ImageCacheDao) FindByUri(uri string) *ImageCache {
var wp = &WherePair{}
wp = wp.And(&WherePair{Query: "uri = ?", Args: []interface{}{uri}})
var imageCache = &ImageCache{}
db := this.context.DB.Model(&ImageCache{}).Where(wp.Query, wp.Args...).First(imageCache)
if db.Error != nil {
return nil
}
return imageCache
}
//按照id和userUuid来查找。找不到抛异常。
func (this *ImageCacheDao) CheckByUuidAndUserUuid(uuid string, userUuid string) *ImageCache {
// Read
var imageCache = &ImageCache{}
db := this.context.DB.Where(&ImageCache{Base: Base{Uuid: uuid}, UserUuid: userUuid}).First(imageCache)
this.PanicError(db.Error)
return imageCache
}
//获取某个用户的某个文件夹下的某个名字的文件(或文件夹)列表
func (this *ImageCacheDao) ListByUserUuidAndPuuidAndDirAndName(userUuid string) []*ImageCache {
var imageCaches []*ImageCache
db := this.context.DB.
Where(ImageCache{UserUuid: userUuid}).
Find(&imageCaches)
this.PanicError(db.Error)
return imageCaches
}
//获取某个文件夹下所有的文件和子文件
func (this *ImageCacheDao) Page(page int, pageSize int, userUuid string, sortArray []OrderPair) *Pager {
var wp = &WherePair{}
if userUuid != "" {
wp = wp.And(&WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}})
}
var conditionDB *gorm.DB
conditionDB = this.context.DB.Model(&ImageCache{}).Where(wp.Query, wp.Args...)
count := 0
db := conditionDB.Count(&count)
this.PanicError(db.Error)
var imageCaches []*ImageCache
db = conditionDB.Order(this.GetSortString(sortArray)).Offset(page * pageSize).Limit(pageSize).Find(&imageCaches)
this.PanicError(db.Error)
pager := NewPager(page, pageSize, count, imageCaches)
return pager
}
//创建
func (this *ImageCacheDao) Create(imageCache *ImageCache) *ImageCache {
timeUUID, _ := uuid.NewV4()
imageCache.Uuid = string(timeUUID.String())
imageCache.CreateTime = time.Now()
imageCache.ModifyTime = time.Now()
db := this.context.DB.Create(imageCache)
this.PanicError(db.Error)
return imageCache
}
//修改一个文件
func (this *ImageCacheDao) Save(imageCache *ImageCache) *ImageCache {
imageCache.ModifyTime = time.Now()
db := this.context.DB.Save(imageCache)
this.PanicError(db.Error)
return imageCache
}
//删除一个文件,数据库中删除,物理磁盘上删除。
func (this *ImageCacheDao) Delete(imageCache *ImageCache) {
db := this.context.DB.Delete(&imageCache)
this.PanicError(db.Error)
//删除文件
err := os.Remove(CONFIG.MatterPath + imageCache.Path)
if err != nil {
LogError(fmt.Sprintf("删除磁盘上的文件出错,不做任何处理"))
//this.PanicError(err)
}
}

20
rest/image_cache_model.go Normal file
View File

@ -0,0 +1,20 @@
package rest
/**
* 图片缓存对于那些处理过的图片统一管理在这里
*/
type ImageCache struct {
Base
UserUuid string `json:"userUuid"`
MatterUuid string `json:"matterUuid"`
Uri string `json:"name"`
Md5 string `json:"md5"`
Size int64 `json:"size"`
Path string `json:"path"`
Matter *Matter `gorm:"-" json:"matter"`
}
// set File's table name to be `profiles`
func (ImageCache) TableName() string {
return TABLE_PREFIX + "image_cache"
}

View File

@ -0,0 +1,26 @@
package rest
//@Service
type ImageCacheService struct {
Bean
imageCacheDao *ImageCacheDao
}
//初始化方法
func (this *ImageCacheService) Init(context *Context) {
//手动装填本实例的Bean. 这里必须要用中间变量方可。
b := context.GetBean(this.imageCacheDao)
if b, ok := b.(*ImageCacheDao); ok {
this.imageCacheDao = b
}
}
//获取某个文件的详情,会把父级依次倒着装进去。如果中途出错,直接抛出异常。
func (this *ImageCacheService) Detail(uuid string) *ImageCache {
imageCache := this.imageCacheDao.CheckByUuid(uuid)
return imageCache
}

View File

@ -230,9 +230,8 @@ func (this *MatterDao) Delete(matter *Matter) {
if err != nil {
LogError(fmt.Sprintf("删除磁盘上的文件出错,不做任何处理"))
//this.PanicError(err)
}
this.PanicError(err)
}
}