1.4.5.2
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type CleanAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CleanAction) Init() {
|
||||
this.Nav("", "", "clean")
|
||||
}
|
||||
|
||||
func (this *CleanAction) RunGet(params struct {
|
||||
OrderTable string
|
||||
OrderSize string
|
||||
}) {
|
||||
this.Data["orderTable"] = params.OrderTable
|
||||
this.Data["orderSize"] = params.OrderSize
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CleanAction) RunPost(params struct {
|
||||
OrderTable string
|
||||
OrderSize string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
tablesResp, err := this.RPC().DBRPC().FindAllDBTables(this.AdminContext(), &pb.FindAllDBTablesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var tables = tablesResp.DbTables
|
||||
|
||||
// 排序
|
||||
switch params.OrderTable {
|
||||
case "asc":
|
||||
sort.Slice(tables, func(i, j int) bool {
|
||||
return tables[i].Name < tables[j].Name
|
||||
})
|
||||
case "desc":
|
||||
sort.Slice(tables, func(i, j int) bool {
|
||||
return tables[i].Name > tables[j].Name
|
||||
})
|
||||
}
|
||||
|
||||
switch params.OrderSize {
|
||||
case "asc":
|
||||
sort.Slice(tables, func(i, j int) bool {
|
||||
return tables[i].DataLength+tables[i].IndexLength < tables[j].DataLength+tables[j].IndexLength
|
||||
})
|
||||
case "desc":
|
||||
sort.Slice(tables, func(i, j int) bool {
|
||||
return tables[i].DataLength+tables[i].IndexLength > tables[j].DataLength+tables[j].IndexLength
|
||||
})
|
||||
}
|
||||
|
||||
var tableMaps = []maps.Map{}
|
||||
for _, table := range tables {
|
||||
if !table.IsBaseTable || (!table.CanClean && !table.CanDelete) {
|
||||
continue
|
||||
}
|
||||
tableMaps = append(tableMaps, maps.Map{
|
||||
"name": table.Name,
|
||||
"rows": table.Rows,
|
||||
"size": numberutils.FormatBytes(table.DataLength + table.IndexLength),
|
||||
"canDelete": table.CanDelete,
|
||||
"canClean": table.CanClean,
|
||||
"comment": table.Comment,
|
||||
})
|
||||
}
|
||||
this.Data["tables"] = tableMaps
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CleanSettingAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CleanSettingAction) Init() {
|
||||
this.Nav("", "", "cleanSetting")
|
||||
}
|
||||
|
||||
func (this *CleanSettingAction) RunGet(params struct{}) {
|
||||
// 读取设置
|
||||
configResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeDatabaseConfigSetting})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var config = systemconfigs.NewDatabaseConfig()
|
||||
if len(configResp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(configResp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CleanSettingAction) RunPost(params struct {
|
||||
ServerAccessLogCleanDays int
|
||||
ServerBandwidthStatCleanDays int
|
||||
UserBandwidthStatCleanDays int
|
||||
UserPlanBandwidthStatCleanDays int
|
||||
ServerDailyStatCleanDays int
|
||||
ServerDomainHourlyStatCleanDays int
|
||||
TrafficDailyStatCleanDays int
|
||||
TrafficHourlyStatCleanDays int
|
||||
NodeClusterTrafficDailyStatCleanDays int
|
||||
NodeTrafficDailyStatCleanDays int
|
||||
NodeTrafficHourlyStatCleanDays int
|
||||
HttpCacheTaskCleanDays int
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Database_LogUpdateCleanDays)
|
||||
|
||||
// 读取设置
|
||||
configResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeDatabaseConfigSetting})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var config = systemconfigs.NewDatabaseConfig()
|
||||
if len(configResp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(configResp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if params.ServerAccessLogCleanDays < 0 {
|
||||
params.ServerAccessLogCleanDays = 0
|
||||
}
|
||||
config.ServerAccessLog.Clean.Days = params.ServerAccessLogCleanDays
|
||||
|
||||
if params.ServerBandwidthStatCleanDays < 0 {
|
||||
params.ServerBandwidthStatCleanDays = 0
|
||||
}
|
||||
config.ServerBandwidthStat.Clean.Days = params.ServerBandwidthStatCleanDays
|
||||
|
||||
if params.UserBandwidthStatCleanDays < 0 {
|
||||
params.UserBandwidthStatCleanDays = 0
|
||||
}
|
||||
config.UserBandwidthStat.Clean.Days = params.UserBandwidthStatCleanDays
|
||||
|
||||
if params.UserPlanBandwidthStatCleanDays < 0 {
|
||||
params.UserPlanBandwidthStatCleanDays = 0
|
||||
}
|
||||
config.UserPlanBandwidthStat.Clean.Days = params.UserPlanBandwidthStatCleanDays
|
||||
|
||||
if params.ServerDailyStatCleanDays < 0 {
|
||||
params.ServerDailyStatCleanDays = 0
|
||||
}
|
||||
config.ServerDailyStat.Clean.Days = params.ServerDailyStatCleanDays
|
||||
|
||||
if params.ServerDomainHourlyStatCleanDays < 0 {
|
||||
params.ServerDomainHourlyStatCleanDays = 0
|
||||
}
|
||||
config.ServerDomainHourlyStat.Clean.Days = params.ServerDomainHourlyStatCleanDays
|
||||
|
||||
if params.TrafficDailyStatCleanDays < 0 {
|
||||
params.TrafficDailyStatCleanDays = 0
|
||||
}
|
||||
config.TrafficDailyStat.Clean.Days = params.TrafficDailyStatCleanDays
|
||||
|
||||
if params.TrafficHourlyStatCleanDays < 0 {
|
||||
params.TrafficHourlyStatCleanDays = 0
|
||||
}
|
||||
config.TrafficHourlyStat.Clean.Days = params.TrafficHourlyStatCleanDays
|
||||
|
||||
if params.NodeClusterTrafficDailyStatCleanDays < 0 {
|
||||
params.NodeClusterTrafficDailyStatCleanDays = 0
|
||||
}
|
||||
config.NodeClusterTrafficDailyStat.Clean.Days = params.NodeClusterTrafficDailyStatCleanDays
|
||||
|
||||
if params.NodeTrafficDailyStatCleanDays < 0 {
|
||||
params.NodeTrafficDailyStatCleanDays = 0
|
||||
}
|
||||
config.NodeTrafficDailyStat.Clean.Days = params.NodeTrafficDailyStatCleanDays
|
||||
|
||||
if params.NodeTrafficHourlyStatCleanDays < 0 {
|
||||
params.NodeTrafficHourlyStatCleanDays = 0
|
||||
}
|
||||
config.NodeTrafficHourlyStat.Clean.Days = params.NodeTrafficHourlyStatCleanDays
|
||||
|
||||
if params.HttpCacheTaskCleanDays < 0 {
|
||||
params.HttpCacheTaskCleanDays = 0
|
||||
}
|
||||
config.HTTPCacheTask.Clean.Days = params.HttpCacheTaskCleanDays
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeDatabaseConfigSetting,
|
||||
ValueJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteTableAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteTableAction) RunPost(params struct {
|
||||
Table string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Database_LogDeleteTable, params.Table)
|
||||
|
||||
_, err := this.RPC().DBRPC().DeleteDBTable(this.AdminContext(), &pb.DeleteDBTableRequest{DbTable: params.Table})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"gopkg.in/yaml.v3"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
this.Data["error"] = ""
|
||||
|
||||
var configFile = Tea.ConfigFile("api_db.yaml")
|
||||
data, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
this.Data["error"] = "read config file failed: api_db.yaml: " + err.Error()
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
// new config
|
||||
var config = &configs.SimpleDBConfig{}
|
||||
err = yaml.Unmarshal(data, config)
|
||||
if err == nil && len(config.Host) > 0 {
|
||||
host, port, splitErr := net.SplitHostPort(config.Host)
|
||||
if splitErr != nil {
|
||||
port = "3306"
|
||||
}
|
||||
var password = config.Password
|
||||
if len(password) > 0 {
|
||||
password = strings.Repeat("*", len(password))
|
||||
}
|
||||
this.Data["dbConfig"] = maps.Map{
|
||||
"host": host,
|
||||
"port": port,
|
||||
"username": config.User,
|
||||
"password": password,
|
||||
"database": config.Database,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
this.parseOldConfig(data)
|
||||
}
|
||||
|
||||
func (this *IndexAction) parseOldConfig(data []byte) {
|
||||
var 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"] = "no database configured in config file: api_db.yaml"
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
var dbConfig *dbs.DBConfig
|
||||
for _, db := range config.DBs {
|
||||
dbConfig = db
|
||||
break
|
||||
}
|
||||
if dbConfig == nil {
|
||||
this.Data["error"] = "no database configured in config file: api_db.yaml"
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
var dsn = dbConfig.Dsn
|
||||
cfg, err := mysql.ParseDSN(dsn)
|
||||
if err != nil {
|
||||
this.Data["error"] = "parse dsn error: " + err.Error()
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
var host = cfg.Addr
|
||||
var port = "3306"
|
||||
var index = strings.LastIndex(host, ":")
|
||||
if index > 0 {
|
||||
port = host[index+1:]
|
||||
host = host[:index]
|
||||
}
|
||||
|
||||
var password = cfg.Passwd
|
||||
if len(password) > 0 {
|
||||
password = strings.Repeat("*", len(password))
|
||||
}
|
||||
|
||||
this.Data["dbConfig"] = maps.Map{
|
||||
"host": host,
|
||||
"port": port,
|
||||
"username": cfg.User,
|
||||
"password": password,
|
||||
"database": cfg.DBName,
|
||||
}
|
||||
|
||||
// TODO 测试连接
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(settingutils.NewAdvancedHelper("database")).
|
||||
Prefix("/settings/database").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
GetPost("/clean", new(CleanAction)).
|
||||
GetPost("/cleanSetting", new(CleanSettingAction)).
|
||||
GetPost("/truncateTable", new(TruncateTableAction)).
|
||||
GetPost("/deleteTable", new(DeleteTableAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type TruncateTableAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TruncateTableAction) RunPost(params struct {
|
||||
Table string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Database_LogTruncateTable, params.Table)
|
||||
|
||||
_, err := this.RPC().DBRPC().TruncateDBTable(this.AdminContext(), &pb.TruncateDBTableRequest{DbTable: params.Table})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"gopkg.in/yaml.v3"
|
||||
"net"
|
||||
"os"
|
||||
"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 := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// new config
|
||||
var config = &configs.SimpleDBConfig{}
|
||||
err = yaml.Unmarshal(data, config)
|
||||
if err == nil && len(config.Host) > 0 {
|
||||
host, port, splitErr := net.SplitHostPort(config.Host)
|
||||
if splitErr != nil {
|
||||
port = "3306"
|
||||
}
|
||||
|
||||
this.Data["dbConfig"] = maps.Map{
|
||||
"host": host,
|
||||
"port": port,
|
||||
"username": config.User,
|
||||
"password": config.Password,
|
||||
"database": config.Database,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
this.parseOldConfig(data)
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
Host string
|
||||
Port int32
|
||||
Database string
|
||||
Username string
|
||||
Password string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Database_LogUpdateAPINodeDatabaseConfig)
|
||||
|
||||
params.Must.
|
||||
Field("host", params.Host).
|
||||
Require("请输入主机地址").
|
||||
Expect(func() (message string, success bool) {
|
||||
// 是否为IP
|
||||
if net.ParseIP(params.Host) != nil {
|
||||
success = true
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^[\w.-]+$`).MatchString(params.Host) {
|
||||
message = "主机地址中不能包含特殊字符"
|
||||
success = false
|
||||
return
|
||||
}
|
||||
success = true
|
||||
return
|
||||
}).
|
||||
Field("port", params.Port).
|
||||
Gt(0, "端口需要大于0").
|
||||
Lt(65535, "端口需要小于65535").
|
||||
Field("database", params.Database).
|
||||
Require("请输入数据库名称").
|
||||
Match(`^[\w\.-]+$`, "数据库名称中不能包含特殊字符").
|
||||
Field("username", params.Username).
|
||||
Require("请输入连接数据库的用户名").
|
||||
Match(`^[\w\.-]+$`, "用户名中不能包含特殊字符")
|
||||
|
||||
var config = &configs.SimpleDBConfig{
|
||||
User: params.Username,
|
||||
Password: params.Password,
|
||||
Database: params.Database,
|
||||
Host: configutils.QuoteIP(params.Host) + ":" + fmt.Sprintf("%d", params.Port),
|
||||
}
|
||||
configYAML, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 保存
|
||||
|
||||
var configFile = Tea.ConfigFile("api_db.yaml")
|
||||
err = os.WriteFile(configFile, configYAML, 0666)
|
||||
if err != nil {
|
||||
this.Fail("保存配置失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 思考是否让本地的API节点生效
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) parseOldConfig(data []byte) {
|
||||
var config = &dbs.Config{}
|
||||
err := yaml.Unmarshal(data, config)
|
||||
if err != nil {
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
if config.DBs == nil {
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
var dbConfig *dbs.DBConfig
|
||||
for _, db := range config.DBs {
|
||||
dbConfig = db
|
||||
break
|
||||
}
|
||||
if dbConfig == nil {
|
||||
this.Data["dbConfig"] = maps.Map{
|
||||
"host": "",
|
||||
"port": "",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"database": "",
|
||||
}
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
var dsn = dbConfig.Dsn
|
||||
cfg, err := mysql.ParseDSN(dsn)
|
||||
if err != nil {
|
||||
this.Data["dbConfig"] = maps.Map{
|
||||
"host": "",
|
||||
"port": "",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"database": "",
|
||||
}
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
|
||||
var host = cfg.Addr
|
||||
var port = "3306"
|
||||
var index = strings.LastIndex(cfg.Addr, ":")
|
||||
if index > 0 {
|
||||
host = cfg.Addr[:index]
|
||||
port = cfg.Addr[index+1:]
|
||||
}
|
||||
|
||||
this.Data["dbConfig"] = maps.Map{
|
||||
"host": host,
|
||||
"port": port,
|
||||
"username": cfg.User,
|
||||
"password": cfg.Passwd,
|
||||
"database": cfg.DBName,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
Reference in New Issue
Block a user