feat: install configuration files and initialize basic information

This commit is contained in:
LinkinStar 2022-11-04 15:59:21 +08:00
parent 23b4a44ce3
commit 9c8838a1b0
7 changed files with 120 additions and 42 deletions

View File

@ -1,6 +1,7 @@
package conf
import (
"bytes"
"path/filepath"
"github.com/answerdev/answer/internal/base/data"
@ -11,28 +12,28 @@ import (
"github.com/answerdev/answer/internal/service/service_config"
"github.com/answerdev/answer/pkg/writer"
"github.com/segmentfault/pacman/contrib/conf/viper"
"sigs.k8s.io/yaml"
"gopkg.in/yaml.v3"
)
// AllConfig all config
type AllConfig struct {
Debug bool `json:"debug" mapstructure:"debug"`
Data *Data `json:"data" mapstructure:"data"`
Server *Server `json:"server" mapstructure:"server"`
I18n *translator.I18n `json:"i18n" mapstructure:"i18n"`
Swaggerui *router.SwaggerConfig `json:"swaggerui" mapstructure:"swaggerui"`
ServiceConfig *service_config.ServiceConfig `json:"service_config" mapstructure:"service_config"`
Debug bool `json:"debug" mapstructure:"debug" yaml:"debug"`
Server *Server `json:"server" mapstructure:"server" yaml:"server"`
Data *Data `json:"data" mapstructure:"data" yaml:"data"`
I18n *translator.I18n `json:"i18n" mapstructure:"i18n" yaml:"i18n"`
ServiceConfig *service_config.ServiceConfig `json:"service_config" mapstructure:"service_config" yaml:"service_config"`
Swaggerui *router.SwaggerConfig `json:"swaggerui" mapstructure:"swaggerui" yaml:"swaggerui"`
}
// Server server config
type Server struct {
HTTP *server.HTTP `json:"http" mapstructure:"http"`
HTTP *server.HTTP `json:"http" mapstructure:"http" yaml:"http"`
}
// Data data config
type Data struct {
Database *data.Database `json:"database" mapstructure:"database"`
Cache *data.CacheConf `json:"cache" mapstructure:"cache"`
Database *data.Database `json:"database" mapstructure:"database" yaml:"database"`
Cache *data.CacheConf `json:"cache" mapstructure:"cache" yaml:"cache"`
}
// ReadConfig read config
@ -53,9 +54,11 @@ func ReadConfig(configFilePath string) (c *AllConfig, err error) {
// RewriteConfig rewrite config file path
func RewriteConfig(configFilePath string, allConfig *AllConfig) error {
content, err := yaml.Marshal(allConfig)
if err != nil {
buf := bytes.Buffer{}
enc := yaml.NewEncoder(&buf)
enc.SetIndent(2)
if err := enc.Encode(allConfig); err != nil {
return err
}
return writer.ReplaceFile(configFilePath, string(content))
return writer.ReplaceFile(configFilePath, buf.String())
}

View File

@ -2,14 +2,14 @@ package data
// Database database config
type Database struct {
Driver string `json:"driver" mapstructure:"driver"`
Connection string `json:"connection" mapstructure:"connection"`
ConnMaxLifeTime int `json:"conn_max_life_time" mapstructure:"conn_max_life_time"`
MaxOpenConn int `json:"max_open_conn" mapstructure:"max_open_conn"`
MaxIdleConn int `json:"max_idle_conn" mapstructure:"max_idle_conn"`
Driver string `json:"driver" mapstructure:"driver" yaml:"driver"`
Connection string `json:"connection" mapstructure:"connection" yaml:"connection"`
ConnMaxLifeTime int `json:"conn_max_life_time" mapstructure:"conn_max_life_time" yaml:"conn_max_life_time,omitempty"`
MaxOpenConn int `json:"max_open_conn" mapstructure:"max_open_conn" yaml:"max_open_conn,omitempty"`
MaxIdleConn int `json:"max_idle_conn" mapstructure:"max_idle_conn" yaml:"max_idle_conn,omitempty"`
}
// CacheConf cache
type CacheConf struct {
FilePath string `json:"file_path" mapstructure:"file_path"`
FilePath string `json:"file_path" mapstructure:"file_path" yaml:"file_path"`
}

View File

@ -2,5 +2,5 @@ package translator
// I18n i18n config
type I18n struct {
BundleDir string `json:"bundle_dir" mapstructure:"bundle_dir"`
BundleDir string `json:"bundle_dir" mapstructure:"bundle_dir" yaml:"bundle_dir"`
}

View File

@ -1,6 +1,9 @@
package install
import (
"os"
"time"
"github.com/answerdev/answer/configs"
"github.com/answerdev/answer/internal/base/conf"
"github.com/answerdev/answer/internal/base/data"
@ -15,11 +18,6 @@ import (
"github.com/segmentfault/pacman/log"
)
// 1、校验配置文件 post installation/config-file/check
//2、校验数据库 post installation/db/check
//3、创建配置文件和数据库 post installation/init
//4、配置网站基本信息和超级管理员信息 post installation/base-info
// LangOptions get installation language options
// @Summary get installation language options
// @Description get installation language options
@ -63,6 +61,7 @@ func CheckConfigFile(ctx *gin.Context) {
// @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) {
@ -76,7 +75,7 @@ func CheckDatabase(ctx *gin.Context) {
Driver: req.DbType,
Connection: req.GetConnection(),
}
resp.ConnectionSuccess = cli.CheckDB(dataConf, true)
resp.ConnectionSuccess = cli.CheckDB(dataConf, false)
if !resp.ConnectionSuccess {
handler.HandleResponse(ctx, errors.BadRequest(reason.DatabaseConnectionFailed), schema.ErrTypeAlert)
return
@ -90,6 +89,7 @@ func CheckDatabase(ctx *gin.Context) {
// @Tags installation
// @Accept json
// @Produce json
// @Param data body install.CheckDatabaseReq true "CheckDatabaseReq"
// @Success 200 {object} handler.RespBody{data=install.CheckConfigFileResp{}}
// @Router /installation/init [post]
func InitEnvironment(ctx *gin.Context) {
@ -137,6 +137,7 @@ func InitEnvironment(ctx *gin.Context) {
// @Tags installation
// @Accept json
// @Produce json
// @Param data body install.InitBaseInfoReq true "InitBaseInfoReq"
// @Success 200 {object} handler.RespBody{data=install.CheckConfigFileResp{}}
// @Router /installation/base-info [post]
func InitBaseInfo(ctx *gin.Context) {
@ -145,8 +146,31 @@ func InitBaseInfo(ctx *gin.Context) {
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.ServiceConfig.WebHost = req.SiteURL
if err := conf.RewriteConfig(confPath, c); err != nil {
log.Errorf("rewrite config failed %s", err)
handler.HandleResponse(ctx, errors.BadRequest(reason.ReadConfigFailed), nil)
return
}
err = migrations.UpdateInstallInfo(c.Data.Database, req.Language, req.SiteName, req.SiteURL, req.ContactEmail,
req.AdminName, req.AdminPassword, req.AdminEmail)
if err != nil {
log.Error(err)
handler.HandleResponse(ctx, errors.BadRequest(reason.InstallConfigFailed), nil)
return
}
handler.HandleResponse(ctx, nil, nil)
go func() {
time.Sleep(1 * time.Second)
os.Exit(0)
}()
return
}

View File

@ -5,6 +5,7 @@ import (
"github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/entity"
"golang.org/x/crypto/bcrypt"
"xorm.io/xorm"
)
@ -55,11 +56,6 @@ func InitDB(dataConf *data.Database) (err error) {
return fmt.Errorf("init admin user failed: %s", err)
}
err = initSiteInfo(engine)
if err != nil {
return fmt.Errorf("init site info failed: %s", err)
}
err = initConfigTable(engine)
if err != nil {
return fmt.Errorf("init config table: %s", err)
@ -82,12 +78,67 @@ func initAdminUser(engine *xorm.Engine) error {
return err
}
func initSiteInfo(engine *xorm.Engine) error {
func initSiteInfo(engine *xorm.Engine, language, siteName, siteURL, contactEmail string) error {
_, err := engine.InsertOne(&entity.SiteInfo{
Type: "interface",
Content: `{"logo":"","theme":"black","language":"en_US"}`,
Content: fmt.Sprintf(`{"logo":"","theme":"black","language":%s}`, language),
Status: 1,
})
if err != nil {
return err
}
_, err = engine.InsertOne(&entity.SiteInfo{
Type: "general",
Content: fmt.Sprintf(`{"name":"%s","site_url":"%s","contact_email":"%s"}`,
siteName, siteURL, contactEmail),
Status: 1,
})
return err
}
func updateAdminInfo(engine *xorm.Engine, adminName, adminPassword, adminEmail string) error {
generateFromPassword, err := bcrypt.GenerateFromPassword([]byte(adminPassword), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("")
}
adminPassword = string(generateFromPassword)
// update admin info
_, err = engine.ID("1").Update(&entity.User{
Username: adminName,
Pass: adminPassword,
EMail: adminEmail,
DisplayName: "admin",
})
if err != nil {
return fmt.Errorf("update admin user info failed: %s", err)
}
return nil
}
// UpdateInstallInfo update some init data about the admin interface and admin password
func UpdateInstallInfo(dataConf *data.Database, language string,
siteName string,
siteURL string,
contactEmail string,
adminName string,
adminPassword string,
adminEmail string) error {
engine, err := data.NewDB(false, dataConf)
if err != nil {
return fmt.Errorf("database connection error: %s", err)
}
err = updateAdminInfo(engine, adminName, adminPassword, adminEmail)
if err != nil {
return fmt.Errorf("update admin info failed: %s", err)
}
err = initSiteInfo(engine, language, siteName, siteURL, contactEmail)
if err != nil {
return fmt.Errorf("init site info failed: %s", err)
}
return err
}

View File

@ -2,8 +2,8 @@ package router
// SwaggerConfig struct describes configure for the Swagger API endpoint
type SwaggerConfig struct {
Show bool `json:"show"`
Protocol string `json:"protocol"`
Host string `json:"host"`
Address string `json:"address"`
Show bool `json:"show" mapstructure:"show" yaml:"show"`
Protocol string `json:"protocol" mapstructure:"protocol" yaml:"protocol"`
Host string `json:"host" mapstructure:"host" yaml:"host"`
Address string `json:"address" mapstructure:"address" yaml:"address"`
}

View File

@ -1,7 +1,7 @@
package service_config
type ServiceConfig struct {
SecretKey string `json:"secret_key" mapstructure:"secret_key"`
WebHost string `json:"web_host" mapstructure:"web_host"`
UploadPath string `json:"upload_path" mapstructure:"upload_path"`
SecretKey string `json:"secret_key" mapstructure:"secret_key" yaml:"secret_key"`
WebHost string `json:"web_host" mapstructure:"web_host" yaml:"web_host"`
UploadPath string `json:"upload_path" mapstructure:"upload_path" yaml:"upload_path"`
}