349 lines
8.7 KiB
Go
349 lines
8.7 KiB
Go
package storage
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
_ "github.com/go-sql-driver/mysql"
|
|
"github.com/phachon/mm-wiki/app/utils"
|
|
"github.com/phachon/mm-wiki/global"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
Data = NewData()
|
|
|
|
installChan = make(chan int, 1)
|
|
|
|
InstallDir = ""
|
|
|
|
RootDir = ""
|
|
|
|
CopyRight = global.SYSTEM_COPYRIGHT
|
|
)
|
|
|
|
const License_Disagree = 0 // 协议不同意
|
|
const License_Agree = 1 // 协议同意
|
|
|
|
const Env_NotAccess = 0 // 环境检测不通过
|
|
const Env_Access = 1 // 环境检测通过
|
|
|
|
const Sys_NotAccess = 0 // 系统配置不通过
|
|
const Sys_Access = 1 // 系统配置通过
|
|
|
|
const Database_NotAccess = 0 // 数据库配置不通过
|
|
const Database_Access = 1 // 数据库配置通过
|
|
|
|
const Install_Ready = 0 // 安装准备阶段
|
|
const Install_Start = 1 // 安装开始
|
|
const Install_End = 2 // 安装完成
|
|
|
|
const Install_Default = 0 // 默认
|
|
const Install_Failed = 1 // 安装失败
|
|
const Install_Success = 2 // 安装成功
|
|
|
|
var defaultSystemConf = map[string]string{
|
|
"addr": "0.0.0.0",
|
|
"port": "8080",
|
|
"document_dir": "",
|
|
}
|
|
|
|
var defaultDatabaseConf = map[string]string{
|
|
"host": "127.0.0.1",
|
|
"port": "3306",
|
|
"name": "mm_wiki",
|
|
"user": "",
|
|
"pass": "",
|
|
"conn_max_idle": "30",
|
|
"conn_max_connection": "200",
|
|
"admin_name": "",
|
|
"admin_pass": "",
|
|
}
|
|
|
|
func NewData() *data {
|
|
return &data{
|
|
License: License_Disagree,
|
|
Env: Env_NotAccess,
|
|
System: Sys_NotAccess,
|
|
Database: Database_NotAccess,
|
|
SystemConf: defaultSystemConf,
|
|
DatabaseConf: defaultDatabaseConf,
|
|
Status: Install_Ready,
|
|
Result: "",
|
|
IsSuccess: Install_Default,
|
|
}
|
|
}
|
|
|
|
type data struct {
|
|
License int
|
|
Env int
|
|
System int
|
|
Database int
|
|
SystemConf map[string]string
|
|
DatabaseConf map[string]string
|
|
Status int
|
|
Result string
|
|
IsSuccess int
|
|
}
|
|
|
|
// check db
|
|
func checkDB() (err error) {
|
|
|
|
host := Data.DatabaseConf["host"]
|
|
port := Data.DatabaseConf["port"]
|
|
user := Data.DatabaseConf["user"]
|
|
pass := Data.DatabaseConf["pass"]
|
|
|
|
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer db.Close()
|
|
|
|
err = db.Ping()
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// create db
|
|
func createDB() (err error) {
|
|
host := Data.DatabaseConf["host"]
|
|
port := Data.DatabaseConf["port"]
|
|
user := Data.DatabaseConf["user"]
|
|
pass := Data.DatabaseConf["pass"]
|
|
name := Data.DatabaseConf["name"]
|
|
|
|
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer db.Close()
|
|
_, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + name + " CHARACTER SET utf8")
|
|
if err != nil {
|
|
return
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// create table
|
|
func createTable() (err error) {
|
|
|
|
host := Data.DatabaseConf["host"]
|
|
port := Data.DatabaseConf["port"]
|
|
user := Data.DatabaseConf["user"]
|
|
pass := Data.DatabaseConf["pass"]
|
|
name := Data.DatabaseConf["name"]
|
|
|
|
sqlBytes, err := ioutil.ReadFile(filepath.Join(RootDir, "docs/databases/table.sql"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sqlTable := string(sqlBytes)
|
|
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/"+name+"?charset=utf8&multiStatements=true")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer db.Close()
|
|
_, err = db.Exec(sqlTable)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// create admin
|
|
func createAdmin() (err error) {
|
|
host := Data.DatabaseConf["host"]
|
|
port := Data.DatabaseConf["port"]
|
|
user := Data.DatabaseConf["user"]
|
|
pass := Data.DatabaseConf["pass"]
|
|
name := Data.DatabaseConf["name"]
|
|
adminName := Data.DatabaseConf["admin_name"]
|
|
adminPass := utils.NewEncrypt().Md5Encode(Data.DatabaseConf["admin_pass"])
|
|
|
|
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/"+name+"?charset=utf8")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer db.Close()
|
|
stmt, err := db.Prepare("INSERT mw_user SET username=?,password=?,given_name=?,role_id=?, create_time=?,update_time=?")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer stmt.Close()
|
|
_, err = stmt.Exec(adminName, adminPass, adminName, 1, time.Now().Unix(), time.Now().Unix())
|
|
return
|
|
}
|
|
|
|
// write database install data
|
|
func writeInstallData() (err error) {
|
|
host := Data.DatabaseConf["host"]
|
|
port := Data.DatabaseConf["port"]
|
|
user := Data.DatabaseConf["user"]
|
|
pass := Data.DatabaseConf["pass"]
|
|
name := Data.DatabaseConf["name"]
|
|
|
|
sqlBytes, err := ioutil.ReadFile(filepath.Join(RootDir, "docs/databases/data.sql"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sqlTable := string(sqlBytes)
|
|
db, err := sql.Open("mysql", user+":"+pass+"@tcp("+host+":"+port+")/"+name+"?charset=utf8&multiStatements=true")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer db.Close()
|
|
_, err = db.Exec(sqlTable)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// insert version
|
|
stmt, err := db.Prepare("INSERT mw_config SET `name`=?,`key`=?,`value`=?,create_time=?,update_time=?;")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer stmt.Close()
|
|
_, err = stmt.Exec("系统版本号", "system_version", global.SYSTEM_VERSION, time.Now().Unix(), time.Now().Unix())
|
|
return err
|
|
}
|
|
|
|
// write conf
|
|
func makeConf() (err error) {
|
|
|
|
templateConf, err := utils.NewFile().GetFileContents(filepath.Join(RootDir, "conf/template.conf"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
// replace conf tag
|
|
templateConf = strings.Replace(templateConf, "#httpaddr#", Data.SystemConf["addr"], 1)
|
|
templateConf = strings.Replace(templateConf, "#httpport#", Data.SystemConf["port"], 1)
|
|
templateConf = strings.Replace(templateConf, "#document_dir#", Data.SystemConf["document_dir"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.host#", Data.DatabaseConf["host"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.port#", Data.DatabaseConf["port"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.name#", Data.DatabaseConf["name"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.user#", Data.DatabaseConf["user"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.pass#", Data.DatabaseConf["pass"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.conn_max_idle#", Data.DatabaseConf["conn_max_idle"], 1)
|
|
templateConf = strings.Replace(templateConf, "#db.conn_max_connection#", Data.DatabaseConf["conn_max_connection"], 1)
|
|
|
|
logFilename := strings.Replace(filepath.Join(RootDir, "logs/mm-wiki.log"), `\`, `/`, -1)
|
|
templateConf = strings.Replace(templateConf, "#log.filename#", logFilename, 1)
|
|
|
|
fileObject, err := os.OpenFile(filepath.Join(RootDir, "conf/mm-wiki.conf"), os.O_RDWR|os.O_CREATE, 0777)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer fileObject.Close()
|
|
|
|
_, err = fileObject.Write([]byte(templateConf))
|
|
return
|
|
}
|
|
|
|
func installFailed(err string) {
|
|
Data.Result = err
|
|
Data.Status = Install_End
|
|
Data.IsSuccess = Install_Failed
|
|
log.Println(err)
|
|
}
|
|
|
|
func installSuccess() {
|
|
|
|
Data.Status = Install_End
|
|
Data.IsSuccess = Install_Success
|
|
result := map[string]string{
|
|
"cmd": "",
|
|
"url": "http://127.0.0.1:" + Data.SystemConf["port"],
|
|
}
|
|
if runtime.GOOS == "windows" {
|
|
result["cmd"] = "mm-wiki.exe --conf conf/mm-wiki.conf"
|
|
} else {
|
|
result["cmd"] = "./mm-wiki --conf conf/mm-wiki.conf"
|
|
}
|
|
resByte, _ := json.Marshal(result)
|
|
Data.Result = string(resByte)
|
|
|
|
// create install lock file
|
|
file, _ := os.Create(filepath.Join(RootDir, "./install.lock"))
|
|
file.Close()
|
|
}
|
|
|
|
func StartInstall() {
|
|
installChan <- 1
|
|
}
|
|
|
|
func ListenInstall() {
|
|
|
|
go func() {
|
|
defer func() {
|
|
err := recover()
|
|
if err != nil {
|
|
log.Println(fmt.Sprintf("install crash: %v", err))
|
|
}
|
|
}()
|
|
for {
|
|
select {
|
|
case <-installChan:
|
|
Data.Status = Install_Start
|
|
// 开始安装
|
|
log.Println("mm-wiki start install")
|
|
// 检查db
|
|
err := checkDB()
|
|
if err != nil {
|
|
installFailed("连接数据库出错:" + err.Error())
|
|
continue
|
|
}
|
|
log.Println("database connect success")
|
|
// 创建数据库
|
|
err = createDB()
|
|
if err != nil {
|
|
installFailed("创建数据库出错:" + err.Error())
|
|
continue
|
|
}
|
|
log.Println("create database success")
|
|
// 创建表
|
|
err = createTable()
|
|
if err != nil {
|
|
installFailed("创建表出错:" + err.Error())
|
|
continue
|
|
}
|
|
log.Println("create table success")
|
|
// 创建超级管理员
|
|
err = createAdmin()
|
|
if err != nil {
|
|
installFailed("创建管理员账号出错:" + err.Error())
|
|
continue
|
|
}
|
|
log.Println("create admin user success")
|
|
// 写入安装数据
|
|
err = writeInstallData()
|
|
if err != nil {
|
|
installFailed("导入安装数据出错:" + err.Error())
|
|
continue
|
|
}
|
|
log.Println("write install data success")
|
|
// 写入 conf 文件
|
|
err = makeConf()
|
|
if err != nil {
|
|
installFailed("生成配置文件出错:" + err.Error())
|
|
continue
|
|
}
|
|
log.Println("make conf file success")
|
|
installSuccess()
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func init() {
|
|
ListenInstall()
|
|
}
|