diff --git a/go.mod b/go.mod
index b2870a80..c716d2c7 100644
--- a/go.mod
+++ b/go.mod
@@ -16,4 +16,5 @@ require (
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.25.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
)
diff --git a/internal/web/actions/default/settings/database/index.go b/internal/web/actions/default/settings/database/index.go
index 0c8d28d4..20bd43ef 100644
--- a/internal/web/actions/default/settings/database/index.go
+++ b/internal/web/actions/default/settings/database/index.go
@@ -1,15 +1,87 @@
package profile
-import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/go-yaml/yaml"
+ "github.com/iwind/TeaGo/Tea"
+ "github.com/iwind/TeaGo/dbs"
+ "github.com/iwind/TeaGo/maps"
+ "io/ioutil"
+ "net/url"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
- this.Nav("", "", "")
+ this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct{}) {
+ this.Data["error"] = ""
+
+ configFile := Tea.ConfigFile("api_db.yaml")
+ data, err := ioutil.ReadFile(configFile)
+ if err != nil {
+ this.Data["error"] = "read config file failed: api_db.yaml: " + err.Error()
+ this.Show()
+ return
+ }
+
+ config := &dbs.Config{}
+ err = yaml.Unmarshal(data, config)
+ if err != nil {
+ this.Data["error"] = "parse config file failed: api_db.yaml: " + err.Error()
+ this.Show()
+ return
+ }
+
+ if config.DBs == nil {
+ this.Data["error"] = "can not find valid database config: api_db.yaml"
+ this.Show()
+ return
+ }
+
+ dbConfig, ok := config.DBs[config.Default.DB]
+ if !ok {
+ this.Data["error"] = "can not find valid database config: api_db.yaml"
+ this.Show()
+ return
+ }
+ dsn := dbConfig.Dsn
+ dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
+ dsnURL, err := url.Parse("mysql://" + dsn)
+ if err != nil {
+ this.Data["error"] = "parse dsn failed: " + err.Error()
+ this.Show()
+ return
+ }
+
+ host := dsnURL.Host
+ port := "3306"
+ index := strings.LastIndex(dsnURL.Host, ":")
+ if index > 0 {
+ host = dsnURL.Host[:index]
+ port = dsnURL.Host[index+1:]
+ }
+
+ password, _ := dsnURL.User.Password()
+ if len(password) > 0 {
+ password = strings.Repeat("*", len(password))
+ }
+ this.Data["dbConfig"] = maps.Map{
+ "host": host,
+ "port": port,
+ "username": dsnURL.User.Username(),
+ "password": password,
+ "database": filepath.Base(dsnURL.Path),
+ }
+
+ // TODO 测试连接
+
this.Show()
}
diff --git a/internal/web/actions/default/settings/database/init.go b/internal/web/actions/default/settings/database/init.go
index 7a4a9887..d8c7173b 100644
--- a/internal/web/actions/default/settings/database/init.go
+++ b/internal/web/actions/default/settings/database/init.go
@@ -13,6 +13,7 @@ func init() {
Helper(settingutils.NewHelper("database")).
Prefix("/settings/database").
Get("", new(IndexAction)).
+ GetPost("/update", new(UpdateAction)).
EndAll()
})
}
diff --git a/internal/web/actions/default/settings/database/update.go b/internal/web/actions/default/settings/database/update.go
new file mode 100644
index 00000000..a6b294ae
--- /dev/null
+++ b/internal/web/actions/default/settings/database/update.go
@@ -0,0 +1,139 @@
+package profile
+
+import (
+ "fmt"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/Tea"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/dbs"
+ "github.com/iwind/TeaGo/maps"
+ "gopkg.in/yaml.v3"
+ "io/ioutil"
+ "net/url"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+type UpdateAction struct {
+ actionutils.ParentAction
+}
+
+func (this *UpdateAction) Init() {
+ this.Nav("", "", "update")
+}
+
+func (this *UpdateAction) RunGet(params struct{}) {
+ this.Data["dbConfig"] = maps.Map{
+ "host": "",
+ "port": "",
+ "username": "",
+ "password": "",
+ "database": "",
+ }
+
+ configFile := Tea.ConfigFile("api_db.yaml")
+ data, err := ioutil.ReadFile(configFile)
+ if err != nil {
+ return
+ }
+
+ config := &dbs.Config{}
+ err = yaml.Unmarshal(data, config)
+ if err != nil {
+ this.Show()
+ return
+ }
+
+ if config.DBs == nil {
+ this.Show()
+ return
+ }
+
+ dbConfig, ok := config.DBs[config.Default.DB]
+ if !ok {
+ this.Show()
+ return
+ }
+ dsn := dbConfig.Dsn
+ dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
+ dsnURL, err := url.Parse("mysql://" + dsn)
+ if err != nil {
+ this.Show()
+ return
+ }
+
+ host := dsnURL.Host
+ port := "3306"
+ index := strings.LastIndex(dsnURL.Host, ":")
+ if index > 0 {
+ host = dsnURL.Host[:index]
+ port = dsnURL.Host[index+1:]
+ }
+
+ password, _ := dsnURL.User.Password()
+ this.Data["dbConfig"] = maps.Map{
+ "host": host,
+ "port": port,
+ "username": dsnURL.User.Username(),
+ "password": password,
+ "database": filepath.Base(dsnURL.Path),
+ }
+
+ this.Show()
+}
+
+func (this *UpdateAction) RunPost(params struct {
+ Host string
+ Port int32
+ Database string
+ Username string
+ Password string
+
+ Must *actions.Must
+}) {
+ params.Must.
+ Field("host", params.Host).
+ Require("请输入主机地址").
+ Match(`^[\w\.-]+$`, "主机地址中不能包含特殊字符").
+ Field("port", params.Port).
+ Gt(0, "端口需要大于0").
+ Lt(65535, "端口需要小于65535").
+ Field("database", params.Database).
+ Require("请输入数据库名称").
+ Match(`^[\w\.-]+$`, "数据库名称中不能包含特殊字符").
+ Field("username", params.Username).
+ Require("请输入连接数据库的用户名").
+ Match(`^[\w\.-]+$`, "用户名中不能包含特殊字符")
+
+ if len(params.Password) > 0 {
+ params.Must.
+ Field("password", params.Password).
+ Match(`^[\w\.-]+$`, "密码中不能包含特殊字符")
+ }
+
+ // 保存
+ dsn := params.Username + ":" + params.Password + "@tcp(" + params.Host + ":" + fmt.Sprintf("%d", params.Port) + ")/" + params.Database
+
+ configFile := Tea.ConfigFile("api_db.yaml")
+ template := `default:
+ db: "prod"
+ prefix: ""
+
+dbs:
+ prod:
+ driver: "mysql"
+ dsn: "` + dsn + `?charset=utf8mb4&timeout=30s"
+ prefix: "edge"
+ models:
+ package: internal/web/models
+`
+ err := ioutil.WriteFile(configFile, []byte(template), 0666)
+ if err != nil {
+ this.Fail("保存配置失败:" + err.Error())
+ }
+
+ // TODO 让本地的节点生效
+
+ this.Success()
+}
diff --git a/web/views/@default/settings/database/@menu.html b/web/views/@default/settings/database/@menu.html
new file mode 100644
index 00000000..1e2542eb
--- /dev/null
+++ b/web/views/@default/settings/database/@menu.html
@@ -0,0 +1,5 @@
+
此功能暂未开放,敬请期待。
\ No newline at end of file + +| 主机地址 | +{{dbConfig.host}} | +
| 数据库端口 | +{{dbConfig.port}} | +
| 数据库名称 | +{{dbConfig.database}} | +
| 用户名 | ++ {{dbConfig.username}} + 不使用用户名。 + | +
| 密码 | ++ {{dbConfig.password}} + 不使用密码。 + | +