answer/internal/install/install_controller.go

208 lines
6.3 KiB
Go

package install
import (
"net/http"
"os"
"path/filepath"
"time"
"github.com/answerdev/answer/configs"
"github.com/answerdev/answer/internal/base/conf"
"github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/base/translator"
"github.com/answerdev/answer/internal/cli"
"github.com/answerdev/answer/internal/migrations"
"github.com/answerdev/answer/internal/schema"
"github.com/gin-gonic/gin"
"github.com/jinzhu/copier"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
)
// LangOptions get installation language options
// @Summary get installation language options
// @Description get installation language options
// @Tags Lang
// @Produce json
// @Success 200 {object} handler.RespBody{data=[]translator.LangOption}
// @Router /installation/language/options [get]
func LangOptions(ctx *gin.Context) {
handler.HandleResponse(ctx, nil, translator.LanguageOptions)
}
// CheckConfigFileAndRedirectToInstallPage if config file not exist try to redirect to install page
// @Summary if config file not exist try to redirect to install page
// @Description if config file not exist try to redirect to install page
// @Tags installation
// @Accept json
// @Produce json
// @Router / [get]
func CheckConfigFileAndRedirectToInstallPage(ctx *gin.Context) {
if cli.CheckConfigFile(confPath) {
ctx.Redirect(http.StatusFound, "/50x")
} else {
ctx.Redirect(http.StatusFound, "/install")
}
}
// CheckConfigFile check config file if exist when installation
// @Summary check config file if exist when installation
// @Description check config file if exist when installation
// @Tags installation
// @Accept json
// @Produce json
// @Success 200 {object} handler.RespBody{data=install.CheckConfigFileResp{}}
// @Router /installation/config-file/check [post]
func CheckConfigFile(ctx *gin.Context) {
resp := &CheckConfigFileResp{}
resp.ConfigFileExist = cli.CheckConfigFile(confPath)
if !resp.ConfigFileExist {
handler.HandleResponse(ctx, nil, resp)
return
}
allConfig, err := conf.ReadConfig(confPath)
if err != nil {
log.Error(err)
err = errors.BadRequest(reason.ReadConfigFailed)
handler.HandleResponse(ctx, err, nil)
return
}
resp.DBConnectionSuccess = cli.CheckDBConnection(allConfig.Data.Database)
if resp.DBConnectionSuccess {
resp.DbTableExist = cli.CheckDBTableExist(allConfig.Data.Database)
}
handler.HandleResponse(ctx, nil, resp)
}
// CheckDatabase check database if exist when installation
// @Summary check database if exist when installation
// @Description check database if exist when installation
// @Tags installation
// @Accept json
// @Produce json
// @Param data body install.CheckDatabaseReq true "CheckDatabaseReq"
// @Success 200 {object} handler.RespBody{data=install.CheckConfigFileResp{}}
// @Router /installation/db/check [post]
func CheckDatabase(ctx *gin.Context) {
req := &CheckDatabaseReq{}
if handler.BindAndCheck(ctx, req) {
return
}
resp := &CheckDatabaseResp{}
dataConf := &data.Database{
Driver: req.DbType,
Connection: req.GetConnection(),
}
resp.ConnectionSuccess = cli.CheckDBConnection(dataConf)
if !resp.ConnectionSuccess {
handler.HandleResponse(ctx, errors.BadRequest(reason.DatabaseConnectionFailed), schema.ErrTypeAlert)
return
}
handler.HandleResponse(ctx, nil, resp)
}
// InitEnvironment init environment
// @Summary init environment
// @Description init environment
// @Tags installation
// @Accept json
// @Produce json
// @Param data body install.CheckDatabaseReq true "CheckDatabaseReq"
// @Success 200 {object} handler.RespBody{}
// @Router /installation/init [post]
func InitEnvironment(ctx *gin.Context) {
req := &CheckDatabaseReq{}
if handler.BindAndCheck(ctx, req) {
return
}
// check config file if exist
if cli.CheckConfigFile(confPath) {
log.Debug("config file already exists")
handler.HandleResponse(ctx, nil, nil)
return
}
if err := cli.InstallConfigFile(confPath); err != nil {
handler.HandleResponse(ctx, errors.BadRequest(reason.InstallConfigFailed), &InitEnvironmentResp{
Success: false,
CreateConfigFailed: true,
DefaultConfig: string(configs.Config),
ErrType: schema.ErrTypeAlert.ErrType,
})
return
}
c, err := conf.ReadConfig(confPath)
if err != nil {
log.Errorf("read config failed %s", err)
handler.HandleResponse(ctx, errors.BadRequest(reason.ReadConfigFailed), nil)
return
}
c.Data.Database.Driver = req.DbType
c.Data.Database.Connection = req.GetConnection()
c.Data.Cache.FilePath = filepath.Join(cli.CacheDir, cli.DefaultCacheFileName)
c.I18n.BundleDir = cli.I18nPath
c.ServiceConfig.UploadPath = cli.UploadFilePath
if err := conf.RewriteConfig(confPath, c); err != nil {
log.Errorf("rewrite config failed %s", err)
handler.HandleResponse(ctx, errors.BadRequest(reason.ReadConfigFailed), nil)
return
}
handler.HandleResponse(ctx, nil, nil)
}
// InitBaseInfo init base info
// @Summary init base info
// @Description init base info
// @Tags installation
// @Accept json
// @Produce json
// @Param data body install.InitBaseInfoReq true "InitBaseInfoReq"
// @Success 200 {object} handler.RespBody{}
// @Router /installation/base-info [post]
func InitBaseInfo(ctx *gin.Context) {
req := &InitBaseInfoReq{}
if handler.BindAndCheck(ctx, req) {
return
}
req.FormatSiteUrl()
c, err := conf.ReadConfig(confPath)
if err != nil {
log.Errorf("read config failed %s", err)
handler.HandleResponse(ctx, errors.BadRequest(reason.ReadConfigFailed), nil)
return
}
if cli.CheckDBTableExist(c.Data.Database) {
log.Warn("database is already initialized")
handler.HandleResponse(ctx, nil, nil)
return
}
engine, err := data.NewDB(false, c.Data.Database)
if err != nil {
log.Errorf("init database failed %s", err)
handler.HandleResponse(ctx, errors.BadRequest(reason.InstallCreateTableFailed), nil)
}
inputData := &migrations.InitNeedUserInputData{}
_ = copier.Copy(inputData, req)
if err := migrations.NewMentor(ctx, engine, inputData).InitDB(); err != nil {
log.Error("init database error: ", err.Error())
handler.HandleResponse(ctx, errors.BadRequest(reason.InstallConfigFailed), schema.ErrTypeAlert)
return
}
handler.HandleResponse(ctx, nil, nil)
go func() {
time.Sleep(1 * time.Second)
os.Exit(0)
}()
}