From fe432e9a8f64e1f58f9eeb57a75c9e81988aa70f Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Sun, 11 Oct 2020 16:20:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=9C=A8=E7=BA=BF=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=95=B0=E6=8D=AE=E5=BA=93=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + .../default/settings/database/index.go | 76 +++++++++- .../actions/default/settings/database/init.go | 1 + .../default/settings/database/update.go | 139 ++++++++++++++++++ .../@default/settings/database/@menu.html | 5 + .../@default/settings/database/index.html | 37 ++++- .../@default/settings/database/update.html | 44 ++++++ .../@default/settings/database/update.js | 3 + 8 files changed, 303 insertions(+), 3 deletions(-) create mode 100644 internal/web/actions/default/settings/database/update.go create mode 100644 web/views/@default/settings/database/@menu.html create mode 100644 web/views/@default/settings/database/update.html create mode 100644 web/views/@default/settings/database/update.js 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 diff --git a/web/views/@default/settings/database/index.html b/web/views/@default/settings/database/index.html index 79a92a06..8c3ddcee 100644 --- a/web/views/@default/settings/database/index.html +++ b/web/views/@default/settings/database/index.html @@ -1,3 +1,38 @@ {$layout} +{$template "menu"} -

此功能暂未开放,敬请期待。

\ No newline at end of file +

{{error}}

+
+ + + + + + + + + + + + + + + + + + + + + +
主机地址{{dbConfig.host}}
数据库端口{{dbConfig.port}}
数据库名称{{dbConfig.database}}
用户名 + {{dbConfig.username}} + 不使用用户名。 +
密码 + {{dbConfig.password}} + 不使用密码。 +
+
+ +
+

在这里可以设置API节点可以使用的数据库。

+
\ No newline at end of file diff --git a/web/views/@default/settings/database/update.html b/web/views/@default/settings/database/update.html new file mode 100644 index 00000000..a349f53f --- /dev/null +++ b/web/views/@default/settings/database/update.html @@ -0,0 +1,44 @@ +{$layout} +{$template "menu"} + +
+ + + + + + + + + + + + + + + + + + + + + +
主机地址 * + +
数据库端口 * + +
数据库名称 * + +
用户名 * + +

用来连接数据库的用户名。

+
密码 + +

用来连接数据库的密码。

+
+ +
+ +
+

修改数据库配置后需要重新配置API节点。

+
diff --git a/web/views/@default/settings/database/update.js b/web/views/@default/settings/database/update.js new file mode 100644 index 00000000..2df83624 --- /dev/null +++ b/web/views/@default/settings/database/update.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.success = NotifySuccess("保存成功", "/settings/database") +}) \ No newline at end of file