Finish the second step of work.

This commit is contained in:
zicla
2018-12-05 21:22:31 +08:00
parent ea1bd27aa8
commit b7e8a3c1a1
11 changed files with 182 additions and 93 deletions

View File

@ -14,10 +14,10 @@ type IBase interface {
}
type Base struct {
Uuid string `gorm:"primary_key" json:"uuid"`
Sort int64 `json:"sort"`
UpdateTime time.Time `json:"updateTime"`
CreateTime time.Time `json:"createTime"`
Uuid string `json:"uuid" gorm:"type:char(36);primary_key;unique"`
Sort int64 `json:"sort" gorm:"type:bigint(20) not null"`
UpdateTime time.Time `json:"updateTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"`
CreateTime time.Time `json:"createTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
}
//将 Struct 转换成map[string]interface{}类型

View File

@ -5,16 +5,16 @@ package rest
*/
type Dashboard struct {
Base
InvokeNum int64 `json:"invokeNum"`
TotalInvokeNum int64 `json:"totalInvokeNum"`
Uv int64 `json:"uv"`
TotalUv int64 `json:"totalUv"`
MatterNum int64 `json:"matterNum"`
TotalMatterNum int64 `json:"totalMatterNum"`
FileSize int64 `json:"fileSize"`
TotalFileSize int64 `json:"totalFileSize"`
AvgCost int64 `json:"avgCost"`
Dt string `json:"dt"`
InvokeNum int64 `json:"invokeNum" gorm:"type:bigint(20) not null"` //当日访问量
TotalInvokeNum int64 `json:"totalInvokeNum" gorm:"type:bigint(20) not null;default:0"` //截至目前总访问量
Uv int64 `json:"uv" gorm:"type:bigint(20) not null;default:0"` //当日UV
TotalUv int64 `json:"totalUv" gorm:"type:bigint(20) not null;default:0"` //截至目前总UV
MatterNum int64 `json:"matterNum" gorm:"type:bigint(20) not null;default:0"` //文件数量
TotalMatterNum int64 `json:"totalMatterNum" gorm:"type:bigint(20) not null;default:0"` //截至目前文件数量
FileSize int64 `json:"fileSize" gorm:"type:bigint(20) not null;default:0"` //当日文件大小
TotalFileSize int64 `json:"totalFileSize" gorm:"type:bigint(20) not null;default:0"` //截至目前文件总大小
AvgCost int64 `json:"avgCost" gorm:"type:bigint(20) not null;default:0"` //请求平均耗时 ms
Dt string `json:"dt" gorm:"type:varchar(45) not null;index:idx_dt"` //日期
}
// set File's table name to be `profiles`

View File

@ -6,10 +6,10 @@ import (
type DownloadToken struct {
Base
UserUuid string `json:"userUuid"`
MatterUuid string `json:"matterUuid"`
ExpireTime time.Time `json:"expireTime"`
Ip string `json:"ip"`
UserUuid string `json:"userUuid" gorm:"type:char(36) not null"`
MatterUuid string `json:"matterUuid" gorm:"type:char(36) not null;index:idx_mu"`
ExpireTime time.Time `json:"expireTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
Ip string `json:"ip" gorm:"type:varchar(128) not null"`
}
func (DownloadToken) TableName() string {

View File

@ -5,13 +5,13 @@ package rest
*/
type Footprint struct {
Base
UserUuid string `json:"userUuid"`
Ip string `json:"ip"`
Host string `json:"host"`
Uri string `json:"uri"`
Params string `json:"params"`
Cost int64 `json:"cost"`
Success bool `json:"success"`
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
Ip string `json:"ip" gorm:"type:varchar(128) not null;index:idx_dt"`
Host string `json:"host" gorm:"type:varchar(45) not null"`
Uri string `json:"uri" gorm:"type:varchar(255) not null"`
Params string `json:"params" gorm:"type:text"`
Cost int64 `json:"cost" gorm:"type:bigint(20) not null;default:0"`
Success bool `json:"success" gorm:"type:tinyint(1) not null;default:0"`
}
// set File's table name to be `profiles`

View File

@ -5,13 +5,13 @@ package rest
*/
type ImageCache struct {
Base
UserUuid string `json:"userUuid"`
MatterUuid string `json:"matterUuid"`
Mode string `json:"mode"`
Md5 string `json:"md5"`
Size int64 `json:"size"`
Path string `json:"path"`
Matter *Matter `gorm:"-" json:"matter"`
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
MatterUuid string `json:"matterUuid" gorm:"type:char(36);index:idx_mu"`
Mode string `json:"mode" gorm:"type:varchar(512)"`
Md5 string `json:"md5" gorm:"type:varchar(45)"`
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
Path string `json:"path" gorm:"type:varchar(512)"`
Matter *Matter `json:"matter" gorm:"-"`
}
// set File's table name to be `profiles`

View File

@ -3,10 +3,13 @@ package rest
import (
"fmt"
"github.com/jinzhu/gorm"
"github.com/nu7hatch/gouuid"
"go/build"
"io/ioutil"
"net/http"
"regexp"
"strconv"
"time"
)
//安装程序的接口,只有安装阶段可以访问。
@ -64,7 +67,9 @@ func (this *InstallController) RegisterRoutes() map[string]func(writer http.Resp
//每个Controller需要主动注册自己的路由。
routeMap["/api/install/verify"] = this.Wrap(this.Verify, USER_ROLE_GUEST)
routeMap["/api/install/table/info/list"] = this.Wrap(this.InstallTableInfoList, USER_ROLE_GUEST)
routeMap["/api/install/table/info/list"] = this.Wrap(this.TableInfoList, USER_ROLE_GUEST)
routeMap["/api/install/create/table"] = this.Wrap(this.CreateTable, USER_ROLE_GUEST)
routeMap["/api/install/create/admin"] = this.Wrap(this.CreateAdmin, USER_ROLE_GUEST)
return routeMap
}
@ -143,27 +148,34 @@ func (this *InstallController) getCreateSQLFromFile(tableName string) string {
}
//根据表名获取建表SQL语句
func (this *InstallController) getCreateSQLFromDb(db *gorm.DB, base IBase) (bool, string) {
func (this *InstallController) getTableMeta(gormDb *gorm.DB, entity IBase) (bool, []*gorm.StructField, []*gorm.StructField) {
var hasTable = true
var tableName = base.TableName()
hasTable = db.HasTable(base)
if !hasTable {
return false, ""
//挣扎一下,尝试获取建表语句。
db := gormDb.Unscoped()
scope := db.NewScope(entity)
tableName := scope.TableName()
modelStruct := scope.GetModelStruct()
allFields := modelStruct.StructFields
var missingFields = make([]*gorm.StructField, 0)
if !scope.Dialect().HasTable(tableName) {
missingFields = append(missingFields, allFields...)
return false, allFields, missingFields
} else {
for _, field := range allFields {
if !scope.Dialect().HasColumn(tableName, field.DBName) {
if field.IsNormal {
missingFields = append(missingFields, field)
}
}
}
return true, allFields, missingFields
}
// Scan
type Result struct {
Table string
CreateTable string
}
//读取建表语句。
var result = &Result{}
db1 := db.Exec("SHOW CREATE TABLE " + tableName).Scan(result)
this.PanicError(db1.Error)
return true, result.CreateTable
}
//验证数据库连接
@ -180,7 +192,7 @@ func (this *InstallController) Verify(writer http.ResponseWriter, request *http.
}
//获取需要安装的数据库表
func (this *InstallController) InstallTableInfoList(writer http.ResponseWriter, request *http.Request) *WebResult {
func (this *InstallController) TableInfoList(writer http.ResponseWriter, request *http.Request) *WebResult {
var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, UploadToken{}, &User{}}
var installTableInfos []*InstallTableInfo
@ -190,12 +202,12 @@ func (this *InstallController) InstallTableInfoList(writer http.ResponseWriter,
for _, iBase := range tableNames {
exist, sql := this.getCreateSQLFromDb(db, iBase)
exist, allFields, missingFields := this.getTableMeta(db, iBase)
installTableInfos = append(installTableInfos, &InstallTableInfo{
Name: iBase.TableName(),
CreateSql: this.getCreateSQLFromFile(iBase.TableName()),
TableExist: exist,
ExistCreateSql: sql,
Name: iBase.TableName(),
TableExist: exist,
AllFields: allFields,
MissingFields: missingFields,
})
}
@ -203,3 +215,78 @@ func (this *InstallController) InstallTableInfoList(writer http.ResponseWriter,
return this.Success(installTableInfos)
}
//创建缺失数据库和表
func (this *InstallController) CreateTable(writer http.ResponseWriter, request *http.Request) *WebResult {
var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, UploadToken{}, &User{}}
var installTableInfos []*InstallTableInfo
db := this.openDbConnection(writer, request)
defer this.closeDbConnection(db)
for _, iBase := range tableNames {
//补全缺失字段或者创建数据库表
db1 := db.AutoMigrate(iBase)
this.PanicError(db1.Error)
exist, allFields, missingFields := this.getTableMeta(db, iBase)
installTableInfos = append(installTableInfos, &InstallTableInfo{
Name: iBase.TableName(),
TableExist: exist,
AllFields: allFields,
MissingFields: missingFields,
})
}
return this.Success(installTableInfos)
}
//创建管理员
func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request *http.Request) *WebResult {
db := this.openDbConnection(writer, request)
defer this.closeDbConnection(db)
adminUsername := request.FormValue("adminUsername")
adminEmail := request.FormValue("adminEmail")
adminPassword := request.FormValue("adminPassword")
//验证超级管理员的信息
if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, adminUsername); !m {
this.PanicBadRequest(`超级管理员用户名必填,且只能包含字母,数字和'_''`)
}
if len(adminPassword) < 6 {
this.PanicBadRequest(`超级管理员密码长度至少为6位`)
}
if adminEmail == "" {
this.PanicBadRequest(`超级管理员邮箱必填`)
}
user := &User{}
timeUUID, _ := uuid.NewV4()
user.Uuid = string(timeUUID.String())
user.CreateTime = time.Now()
user.UpdateTime = time.Now()
user.LastTime = time.Now()
user.Sort = time.Now().UnixNano() / 1e6
user.Role = USER_ROLE_ADMINISTRATOR
user.Username = adminUsername
user.Password = GetBcrypt(adminPassword)
user.Email = adminEmail
user.Phone = ""
user.Gender = USER_GENDER_UNKNOWN
user.SizeLimit = -1
user.Status = USER_STATUS_OK
db.Create(user)
return this.Success("OK")
}

View File

@ -1,11 +1,13 @@
package rest
import "github.com/jinzhu/gorm"
/**
* 表名对应的表结构
*/
type InstallTableInfo struct {
Name string `json:"name"`
CreateSql string `json:"createSql"`
TableExist bool `json:"tableExist"`
ExistCreateSql string `json:"existCreateSql"`
Name string `json:"name"`
TableExist bool `json:"tableExist"`
AllFields []*gorm.StructField `json:"allFields"`
MissingFields []*gorm.StructField `json:"missingFields"`
}

View File

@ -5,17 +5,17 @@ package rest
*/
type Matter struct {
Base
Puuid string `json:"puuid"`
UserUuid string `json:"userUuid"`
Dir bool `json:"dir"`
Alien bool `json:"alien"`
Name string `json:"name"`
Md5 string `json:"md5"`
Size int64 `json:"size"`
Privacy bool `json:"privacy"`
Path string `json:"path"`
Times int64 `json:"times"`
Parent *Matter `gorm:"-" json:"parent"`
Puuid string `json:"puuid" gorm:"type:char(36);index:idx_puuid"`
UserUuid string `json:"userUuid" gorm:"type:char(36);index:idx_uu"`
Dir bool `json:"dir" gorm:"type:tinyint(1) not null;default:0"`
Alien bool `json:"alien" gorm:"type:tinyint(1) not null;default:0"`
Name string `json:"name" gorm:"type:varchar(255) not null"`
Md5 string `json:"md5" gorm:"type:varchar(45)"`
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"`
Path string `json:"path" gorm:"type:varchar(512)"`
Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"`
Parent *Matter `json:"parent" gorm:"-"`
}
// set File's table name to be `profiles`

View File

@ -2,12 +2,12 @@ package rest
type Preference struct {
Base
Name string `json:"name"`
LogoUrl string `json:"logoUrl"`
FaviconUrl string `json:"faviconUrl"`
FooterLine1 string `json:"footerLine1"`
FooterLine2 string `json:"footerLine2"`
Version string `json:"version"`
Name string `json:"name" gorm:"type:varchar(45)"`
LogoUrl string `json:"logoUrl" gorm:"type:varchar(255)"`
FaviconUrl string `json:"faviconUrl" gorm:"type:varchar(255)"`
FooterLine1 string `json:"footerLine1" gorm:"type:varchar(1024)"`
FooterLine2 string `json:"footerLine2" gorm:"type:varchar(1024)"`
Version string `json:"version" gorm:"type:varchar(45)"`
}
// set File's table name to be `profiles`

View File

@ -6,9 +6,9 @@ import (
type Session struct {
Base
UserUuid string `json:"userUuid"`
Ip string `json:"ip"`
ExpireTime time.Time `json:"expireTime"`
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
Ip string `json:"ip" gorm:"type:varchar(128) not null"`
ExpireTime time.Time `json:"expireTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
}
// set User's table name to be `profiles`

View File

@ -28,18 +28,18 @@ const (
type User struct {
Base
Role string `json:"role"`
Username string `json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
Gender string `json:"gender"`
City string `json:"city"`
AvatarUrl string `json:"avatarUrl"`
LastIp string `json:"lastIp"`
LastTime time.Time `json:"lastTime"`
SizeLimit int64 `json:"sizeLimit"`
Status string `json:"status"`
Role string `json:"role" gorm:"type:varchar(45)"`
Username string `json:"username" gorm:"type:varchar(45) not null;unique"`
Password string `json:"-" gorm:"type:varchar(255)"`
Email string `json:"email" gorm:"type:varchar(45) not null;unique"`
Phone string `json:"phone" gorm:"type:varchar(45)"`
Gender string `json:"gender" gorm:"type:varchar(45)"`
City string `json:"city" gorm:"type:varchar(45)"`
AvatarUrl string `json:"avatarUrl" gorm:"type:varchar(255)"`
LastIp string `json:"lastIp" gorm:"type:varchar(128)"`
LastTime time.Time `json:"lastTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
SizeLimit int64 `json:"sizeLimit" gorm:"type:bigint(20) not null;default:-1"`
Status string `json:"status" gorm:"type:varchar(45)"`
}
// set User's table name to be `profiles`