Finish the second step of work.
This commit is contained in:
@ -14,10 +14,10 @@ type IBase interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Base struct {
|
type Base struct {
|
||||||
Uuid string `gorm:"primary_key" json:"uuid"`
|
Uuid string `json:"uuid" gorm:"type:char(36);primary_key;unique"`
|
||||||
Sort int64 `json:"sort"`
|
Sort int64 `json:"sort" gorm:"type:bigint(20) not null"`
|
||||||
UpdateTime time.Time `json:"updateTime"`
|
UpdateTime time.Time `json:"updateTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"`
|
||||||
CreateTime time.Time `json:"createTime"`
|
CreateTime time.Time `json:"createTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//将 Struct 转换成map[string]interface{}类型
|
//将 Struct 转换成map[string]interface{}类型
|
||||||
|
@ -5,16 +5,16 @@ package rest
|
|||||||
*/
|
*/
|
||||||
type Dashboard struct {
|
type Dashboard struct {
|
||||||
Base
|
Base
|
||||||
InvokeNum int64 `json:"invokeNum"`
|
InvokeNum int64 `json:"invokeNum" gorm:"type:bigint(20) not null"` //当日访问量
|
||||||
TotalInvokeNum int64 `json:"totalInvokeNum"`
|
TotalInvokeNum int64 `json:"totalInvokeNum" gorm:"type:bigint(20) not null;default:0"` //截至目前总访问量
|
||||||
Uv int64 `json:"uv"`
|
Uv int64 `json:"uv" gorm:"type:bigint(20) not null;default:0"` //当日UV
|
||||||
TotalUv int64 `json:"totalUv"`
|
TotalUv int64 `json:"totalUv" gorm:"type:bigint(20) not null;default:0"` //截至目前总UV
|
||||||
MatterNum int64 `json:"matterNum"`
|
MatterNum int64 `json:"matterNum" gorm:"type:bigint(20) not null;default:0"` //文件数量
|
||||||
TotalMatterNum int64 `json:"totalMatterNum"`
|
TotalMatterNum int64 `json:"totalMatterNum" gorm:"type:bigint(20) not null;default:0"` //截至目前文件数量
|
||||||
FileSize int64 `json:"fileSize"`
|
FileSize int64 `json:"fileSize" gorm:"type:bigint(20) not null;default:0"` //当日文件大小
|
||||||
TotalFileSize int64 `json:"totalFileSize"`
|
TotalFileSize int64 `json:"totalFileSize" gorm:"type:bigint(20) not null;default:0"` //截至目前文件总大小
|
||||||
AvgCost int64 `json:"avgCost"`
|
AvgCost int64 `json:"avgCost" gorm:"type:bigint(20) not null;default:0"` //请求平均耗时 ms
|
||||||
Dt string `json:"dt"`
|
Dt string `json:"dt" gorm:"type:varchar(45) not null;index:idx_dt"` //日期
|
||||||
}
|
}
|
||||||
|
|
||||||
// set File's table name to be `profiles`
|
// set File's table name to be `profiles`
|
||||||
|
@ -6,10 +6,10 @@ import (
|
|||||||
|
|
||||||
type DownloadToken struct {
|
type DownloadToken struct {
|
||||||
Base
|
Base
|
||||||
UserUuid string `json:"userUuid"`
|
UserUuid string `json:"userUuid" gorm:"type:char(36) not null"`
|
||||||
MatterUuid string `json:"matterUuid"`
|
MatterUuid string `json:"matterUuid" gorm:"type:char(36) not null;index:idx_mu"`
|
||||||
ExpireTime time.Time `json:"expireTime"`
|
ExpireTime time.Time `json:"expireTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
|
||||||
Ip string `json:"ip"`
|
Ip string `json:"ip" gorm:"type:varchar(128) not null"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (DownloadToken) TableName() string {
|
func (DownloadToken) TableName() string {
|
||||||
|
@ -5,13 +5,13 @@ package rest
|
|||||||
*/
|
*/
|
||||||
type Footprint struct {
|
type Footprint struct {
|
||||||
Base
|
Base
|
||||||
UserUuid string `json:"userUuid"`
|
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
|
||||||
Ip string `json:"ip"`
|
Ip string `json:"ip" gorm:"type:varchar(128) not null;index:idx_dt"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host" gorm:"type:varchar(45) not null"`
|
||||||
Uri string `json:"uri"`
|
Uri string `json:"uri" gorm:"type:varchar(255) not null"`
|
||||||
Params string `json:"params"`
|
Params string `json:"params" gorm:"type:text"`
|
||||||
Cost int64 `json:"cost"`
|
Cost int64 `json:"cost" gorm:"type:bigint(20) not null;default:0"`
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success" gorm:"type:tinyint(1) not null;default:0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set File's table name to be `profiles`
|
// set File's table name to be `profiles`
|
||||||
|
@ -5,13 +5,13 @@ package rest
|
|||||||
*/
|
*/
|
||||||
type ImageCache struct {
|
type ImageCache struct {
|
||||||
Base
|
Base
|
||||||
UserUuid string `json:"userUuid"`
|
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
|
||||||
MatterUuid string `json:"matterUuid"`
|
MatterUuid string `json:"matterUuid" gorm:"type:char(36);index:idx_mu"`
|
||||||
Mode string `json:"mode"`
|
Mode string `json:"mode" gorm:"type:varchar(512)"`
|
||||||
Md5 string `json:"md5"`
|
Md5 string `json:"md5" gorm:"type:varchar(45)"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path" gorm:"type:varchar(512)"`
|
||||||
Matter *Matter `gorm:"-" json:"matter"`
|
Matter *Matter `json:"matter" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set File's table name to be `profiles`
|
// set File's table name to be `profiles`
|
||||||
|
@ -3,10 +3,13 @@ package rest
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/nu7hatch/gouuid"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//安装程序的接口,只有安装阶段可以访问。
|
//安装程序的接口,只有安装阶段可以访问。
|
||||||
@ -64,7 +67,9 @@ func (this *InstallController) RegisterRoutes() map[string]func(writer http.Resp
|
|||||||
|
|
||||||
//每个Controller需要主动注册自己的路由。
|
//每个Controller需要主动注册自己的路由。
|
||||||
routeMap["/api/install/verify"] = this.Wrap(this.Verify, USER_ROLE_GUEST)
|
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
|
return routeMap
|
||||||
}
|
}
|
||||||
@ -143,27 +148,34 @@ func (this *InstallController) getCreateSQLFromFile(tableName string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//根据表名获取建表SQL语句
|
//根据表名获取建表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()
|
db := gormDb.Unscoped()
|
||||||
hasTable = db.HasTable(base)
|
scope := db.NewScope(entity)
|
||||||
if !hasTable {
|
|
||||||
return false, ""
|
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 tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, UploadToken{}, &User{}}
|
||||||
var installTableInfos []*InstallTableInfo
|
var installTableInfos []*InstallTableInfo
|
||||||
@ -190,12 +202,12 @@ func (this *InstallController) InstallTableInfoList(writer http.ResponseWriter,
|
|||||||
|
|
||||||
for _, iBase := range tableNames {
|
for _, iBase := range tableNames {
|
||||||
|
|
||||||
exist, sql := this.getCreateSQLFromDb(db, iBase)
|
exist, allFields, missingFields := this.getTableMeta(db, iBase)
|
||||||
installTableInfos = append(installTableInfos, &InstallTableInfo{
|
installTableInfos = append(installTableInfos, &InstallTableInfo{
|
||||||
Name: iBase.TableName(),
|
Name: iBase.TableName(),
|
||||||
CreateSql: this.getCreateSQLFromFile(iBase.TableName()),
|
TableExist: exist,
|
||||||
TableExist: exist,
|
AllFields: allFields,
|
||||||
ExistCreateSql: sql,
|
MissingFields: missingFields,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -203,3 +215,78 @@ func (this *InstallController) InstallTableInfoList(writer http.ResponseWriter,
|
|||||||
return this.Success(installTableInfos)
|
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")
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package rest
|
package rest
|
||||||
|
|
||||||
|
import "github.com/jinzhu/gorm"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表名对应的表结构
|
* 表名对应的表结构
|
||||||
*/
|
*/
|
||||||
type InstallTableInfo struct {
|
type InstallTableInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CreateSql string `json:"createSql"`
|
TableExist bool `json:"tableExist"`
|
||||||
TableExist bool `json:"tableExist"`
|
AllFields []*gorm.StructField `json:"allFields"`
|
||||||
ExistCreateSql string `json:"existCreateSql"`
|
MissingFields []*gorm.StructField `json:"missingFields"`
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,17 @@ package rest
|
|||||||
*/
|
*/
|
||||||
type Matter struct {
|
type Matter struct {
|
||||||
Base
|
Base
|
||||||
Puuid string `json:"puuid"`
|
Puuid string `json:"puuid" gorm:"type:char(36);index:idx_puuid"`
|
||||||
UserUuid string `json:"userUuid"`
|
UserUuid string `json:"userUuid" gorm:"type:char(36);index:idx_uu"`
|
||||||
Dir bool `json:"dir"`
|
Dir bool `json:"dir" gorm:"type:tinyint(1) not null;default:0"`
|
||||||
Alien bool `json:"alien"`
|
Alien bool `json:"alien" gorm:"type:tinyint(1) not null;default:0"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name" gorm:"type:varchar(255) not null"`
|
||||||
Md5 string `json:"md5"`
|
Md5 string `json:"md5" gorm:"type:varchar(45)"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
|
||||||
Privacy bool `json:"privacy"`
|
Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path" gorm:"type:varchar(512)"`
|
||||||
Times int64 `json:"times"`
|
Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"`
|
||||||
Parent *Matter `gorm:"-" json:"parent"`
|
Parent *Matter `json:"parent" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set File's table name to be `profiles`
|
// set File's table name to be `profiles`
|
||||||
|
@ -2,12 +2,12 @@ package rest
|
|||||||
|
|
||||||
type Preference struct {
|
type Preference struct {
|
||||||
Base
|
Base
|
||||||
Name string `json:"name"`
|
Name string `json:"name" gorm:"type:varchar(45)"`
|
||||||
LogoUrl string `json:"logoUrl"`
|
LogoUrl string `json:"logoUrl" gorm:"type:varchar(255)"`
|
||||||
FaviconUrl string `json:"faviconUrl"`
|
FaviconUrl string `json:"faviconUrl" gorm:"type:varchar(255)"`
|
||||||
FooterLine1 string `json:"footerLine1"`
|
FooterLine1 string `json:"footerLine1" gorm:"type:varchar(1024)"`
|
||||||
FooterLine2 string `json:"footerLine2"`
|
FooterLine2 string `json:"footerLine2" gorm:"type:varchar(1024)"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version" gorm:"type:varchar(45)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set File's table name to be `profiles`
|
// set File's table name to be `profiles`
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
Base
|
Base
|
||||||
UserUuid string `json:"userUuid"`
|
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
|
||||||
Ip string `json:"ip"`
|
Ip string `json:"ip" gorm:"type:varchar(128) not null"`
|
||||||
ExpireTime time.Time `json:"expireTime"`
|
ExpireTime time.Time `json:"expireTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set User's table name to be `profiles`
|
// set User's table name to be `profiles`
|
||||||
|
@ -28,18 +28,18 @@ const (
|
|||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Base
|
Base
|
||||||
Role string `json:"role"`
|
Role string `json:"role" gorm:"type:varchar(45)"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username" gorm:"type:varchar(45) not null;unique"`
|
||||||
Password string `json:"-"`
|
Password string `json:"-" gorm:"type:varchar(255)"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email" gorm:"type:varchar(45) not null;unique"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone" gorm:"type:varchar(45)"`
|
||||||
Gender string `json:"gender"`
|
Gender string `json:"gender" gorm:"type:varchar(45)"`
|
||||||
City string `json:"city"`
|
City string `json:"city" gorm:"type:varchar(45)"`
|
||||||
AvatarUrl string `json:"avatarUrl"`
|
AvatarUrl string `json:"avatarUrl" gorm:"type:varchar(255)"`
|
||||||
LastIp string `json:"lastIp"`
|
LastIp string `json:"lastIp" gorm:"type:varchar(128)"`
|
||||||
LastTime time.Time `json:"lastTime"`
|
LastTime time.Time `json:"lastTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
|
||||||
SizeLimit int64 `json:"sizeLimit"`
|
SizeLimit int64 `json:"sizeLimit" gorm:"type:bigint(20) not null;default:-1"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status" gorm:"type:varchar(45)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set User's table name to be `profiles`
|
// set User's table name to be `profiles`
|
||||||
|
Reference in New Issue
Block a user