1316 lines
40 KiB
Go
1316 lines
40 KiB
Go
package setup
|
||
|
||
import (
|
||
"encoding/json"
|
||
"github.com/TeaOSLab/EdgeAPI/internal/acme"
|
||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||
"github.com/iwind/TeaGo/dbs"
|
||
"github.com/iwind/TeaGo/lists"
|
||
"github.com/iwind/TeaGo/maps"
|
||
"github.com/iwind/TeaGo/rands"
|
||
"github.com/iwind/TeaGo/types"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
type upgradeVersion struct {
|
||
version string
|
||
f func(db *dbs.DB) error
|
||
}
|
||
|
||
var upgradeFuncs = []*upgradeVersion{
|
||
{
|
||
"0.0.3", upgradeV0_0_3,
|
||
},
|
||
{
|
||
"0.0.5", upgradeV0_0_5,
|
||
},
|
||
{
|
||
"0.0.6", upgradeV0_0_6,
|
||
},
|
||
{
|
||
"0.0.9", upgradeV0_0_9,
|
||
},
|
||
{
|
||
"0.0.10", upgradeV0_0_10,
|
||
},
|
||
{
|
||
"0.2.5", upgradeV0_2_5,
|
||
},
|
||
{
|
||
"0.2.8.1", upgradeV0_2_8_1,
|
||
},
|
||
{
|
||
"0.3.0", upgradeV0_3_0,
|
||
},
|
||
{
|
||
"0.3.1", upgradeV0_3_1,
|
||
},
|
||
{
|
||
"0.3.2", upgradeV0_3_2,
|
||
},
|
||
{
|
||
"0.3.3", upgradeV0_3_3,
|
||
},
|
||
{
|
||
"0.3.7", upgradeV0_3_7,
|
||
},
|
||
{
|
||
"0.4.0", upgradeV0_4_0,
|
||
},
|
||
{
|
||
"0.4.1", upgradeV0_4_1,
|
||
},
|
||
{
|
||
"0.4.5", upgradeV0_4_5,
|
||
},
|
||
{
|
||
"0.4.7", upgradeV0_4_7,
|
||
},
|
||
{
|
||
"0.4.8", upgradeV0_4_8,
|
||
},
|
||
{
|
||
"0.4.9", upgradeV0_4_9,
|
||
},
|
||
{
|
||
"0.4.11", upgradeV0_4_11,
|
||
},
|
||
{
|
||
"0.5.3", upgradeV0_5_3,
|
||
},
|
||
{
|
||
"0.5.6", upgradeV0_5_6,
|
||
},
|
||
{
|
||
"0.5.8", upgradeV0_5_8,
|
||
},
|
||
{
|
||
"1.2.1", upgradeV1_2_1,
|
||
},
|
||
{
|
||
"1.2.9", upgradeV1_2_9,
|
||
},
|
||
{
|
||
"1.2.10", upgradeV1_2_10,
|
||
},
|
||
{
|
||
"1.3.2", upgradeV1_3_2,
|
||
},
|
||
{
|
||
"1.3.4", upgradeV1_3_4,
|
||
},
|
||
{
|
||
"1.4.4", upgradeV1_4_4,
|
||
},
|
||
{
|
||
"1.4.8", upgradeV1_4_8,
|
||
},
|
||
{
|
||
"1.4.9", upgradeV1_4_9,
|
||
},
|
||
}
|
||
|
||
// UpgradeSQLData 升级SQL数据
|
||
func UpgradeSQLData(db *dbs.DB) error {
|
||
version, err := db.FindCol(0, "SELECT version FROM edgeVersions")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
var versionString = types.String(version)
|
||
if len(versionString) > 0 {
|
||
for _, f := range upgradeFuncs {
|
||
if CompareVersion(versionString, f.version) >= 0 {
|
||
continue
|
||
}
|
||
err = f.f(db)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// v0.0.3
|
||
func upgradeV0_0_3(db *dbs.DB) error {
|
||
// 获取第一个管理员
|
||
adminIdCol, err := db.FindCol(0, "SELECT id FROM edgeAdmins ORDER BY id ASC LIMIT 1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
adminId := types.Int64(adminIdCol)
|
||
if adminId <= 0 {
|
||
return errors.New("'edgeAdmins' table should not be empty")
|
||
}
|
||
|
||
// 升级edgeDNSProviders
|
||
_, err = db.Exec("UPDATE edgeDNSProviders SET adminId=? WHERE adminId=0 AND userId=0", adminId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 升级edgeDNSDomains
|
||
_, err = db.Exec("UPDATE edgeDNSDomains SET adminId=? WHERE adminId=0 AND userId=0", adminId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 升级edgeSSLCerts
|
||
_, err = db.Exec("UPDATE edgeSSLCerts SET adminId=? WHERE adminId=0 AND userId=0", adminId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 升级edgeNodeClusters
|
||
_, err = db.Exec("UPDATE edgeNodeClusters SET adminId=? WHERE adminId=0 AND userId=0", adminId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 升级edgeNodes
|
||
_, err = db.Exec("UPDATE edgeNodes SET adminId=? WHERE adminId=0 AND userId=0", adminId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 升级edgeNodeGrants
|
||
_, err = db.Exec("UPDATE edgeNodeGrants SET adminId=? WHERE adminId=0", adminId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.0.5
|
||
func upgradeV0_0_5(db *dbs.DB) error {
|
||
// 升级edgeACMETasks
|
||
_, err := db.Exec("UPDATE edgeACMETasks SET authType=? WHERE authType IS NULL OR LENGTH(authType)=0", acme.AuthTypeDNS)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.0.6
|
||
func upgradeV0_0_6(db *dbs.DB) error {
|
||
stmt, err := db.Prepare("SELECT COUNT(*) FROM edgeAPITokens WHERE role='user'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer func() {
|
||
_ = stmt.Close()
|
||
}()
|
||
col, err := stmt.FindCol(0)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
count := types.Int(col)
|
||
if count > 0 {
|
||
return nil
|
||
}
|
||
|
||
nodeId := rands.HexString(32)
|
||
secret := rands.String(32)
|
||
_, err = db.Exec("INSERT INTO edgeAPITokens (nodeId, secret, role) VALUES (?, ?, ?)", nodeId, secret, "user")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.0.9
|
||
func upgradeV0_0_9(db *dbs.DB) error {
|
||
// firewall policies
|
||
var tx *dbs.Tx
|
||
dbs.NotifyReady()
|
||
policies, err := models.NewHTTPFirewallPolicyDAO().FindAllEnabledFirewallPolicies(tx)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, policy := range policies {
|
||
if policy.ServerId > 0 {
|
||
continue
|
||
}
|
||
policyId := int64(policy.Id)
|
||
webIds, err := models.NewHTTPWebDAO().FindAllWebIdsWithHTTPFirewallPolicyId(tx, policyId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
serverIds := []int64{}
|
||
for _, webId := range webIds {
|
||
serverId, err := models.NewServerDAO().FindEnabledServerIdWithWebId(tx, webId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if serverId > 0 && !lists.ContainsInt64(serverIds, serverId) {
|
||
serverIds = append(serverIds, serverId)
|
||
}
|
||
}
|
||
if len(serverIds) == 1 {
|
||
err = models.NewHTTPFirewallPolicyDAO().UpdateFirewallPolicyServerId(tx, policyId, serverIds[0])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.0.10
|
||
func upgradeV0_0_10(db *dbs.DB) error {
|
||
return nil
|
||
}
|
||
|
||
// v0.2.5
|
||
func upgradeV0_2_5(db *dbs.DB) error {
|
||
// 鏇存柊鐢ㄦ埛
|
||
_, err := db.Exec("UPDATE edgeUsers SET day=FROM_UNIXTIME(createdAt,'%Y%m%d') WHERE day IS NULL OR LENGTH(day)=0")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 更新防火墙规则
|
||
ones, _, err := db.FindOnes("SELECT id, actions, action, actionOptions FROM edgeHTTPFirewallRuleSets WHERE actions IS NULL OR LENGTH(actions)=0")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
oneId := one.GetInt64("id")
|
||
action := one.GetString("action")
|
||
options := one.GetString("actionOptions")
|
||
var optionsMap = maps.Map{}
|
||
if len(options) > 0 {
|
||
_ = json.Unmarshal([]byte(options), &optionsMap)
|
||
}
|
||
var actions = []*firewallconfigs.HTTPFirewallActionConfig{
|
||
{
|
||
Code: action,
|
||
Options: optionsMap,
|
||
},
|
||
}
|
||
actionsJSON, err := json.Marshal(actions)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeHTTPFirewallRuleSets SET actions=? WHERE id=?", string(actionsJSON), oneId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.3.0
|
||
func upgradeV0_3_0(db *dbs.DB) error {
|
||
// 升级健康检查
|
||
ones, _, err := db.FindOnes("SELECT id,healthCheck FROM edgeNodeClusters WHERE state=1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var clusterId = one.GetInt64("id")
|
||
var healthCheck = one.GetString("healthCheck")
|
||
if len(healthCheck) == 0 {
|
||
continue
|
||
}
|
||
var config = &serverconfigs.HealthCheckConfig{}
|
||
err = json.Unmarshal([]byte(healthCheck), config)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
if config.CountDown <= 1 {
|
||
config.CountDown = 3
|
||
configJSON, err := json.Marshal(config)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
_, err = db.Exec("UPDATE edgeNodeClusters SET healthCheck=? WHERE id=?", string(configJSON), clusterId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// v0.3.1
|
||
func upgradeV0_3_1(db *dbs.DB) error {
|
||
// 娓呯┖鍩熷悕缁熻锛屽凡浣跨敤鍒嗚〃浠f浛
|
||
// 鍥犱负鍙兘鏈夋潈闄愰棶棰橈紝鎵€浠ユ垜浠拷鐣ラ敊璇? _, _ = db.Exec("TRUNCATE table edgeServerDomainHourlyStats")
|
||
|
||
// 鍗囩骇APIToken
|
||
ones, _, err := db.FindOnes("SELECT uniqueId,secret FROM edgeNodeClusters")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var uniqueId = one.GetString("uniqueId")
|
||
var secret = one.GetString("secret")
|
||
tokenOne, err := db.FindOne("SELECT id FROM edgeAPITokens WHERE nodeId=? LIMIT 1", uniqueId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(tokenOne) == 0 {
|
||
_, err = db.Exec("INSERT INTO edgeAPITokens (nodeId, secret, role, state) VALUES (?, ?, 'cluster', 1)", uniqueId, secret)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.3.2
|
||
func upgradeV0_3_2(db *dbs.DB) error {
|
||
// gzip => compression
|
||
|
||
type HTTPGzipRef struct {
|
||
IsPrior bool `yaml:"isPrior" json:"isPrior"` // 鏄惁瑕嗙洊
|
||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
||
GzipId int64 `yaml:"gzipId" json:"gzipId"` // 使用的配置ID
|
||
}
|
||
|
||
webOnes, _, err := db.FindOnes("SELECT id, gzip FROM edgeHTTPWebs WHERE gzip IS NOT NULL AND compression IS NULL")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, webOne := range webOnes {
|
||
var gzipRef = &HTTPGzipRef{}
|
||
err = json.Unmarshal([]byte(webOne.GetString("gzip")), gzipRef)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
if gzipRef == nil || gzipRef.GzipId <= 0 {
|
||
continue
|
||
}
|
||
var webId = webOne.GetInt("id")
|
||
|
||
var compressionConfig = &serverconfigs.HTTPCompressionConfig{
|
||
UseDefaultTypes: true,
|
||
}
|
||
compressionConfig.IsPrior = gzipRef.IsPrior
|
||
compressionConfig.IsOn = gzipRef.IsOn
|
||
|
||
gzipOne, err := db.FindOne("SELECT * FROM edgeHTTPGzips WHERE id=?", gzipRef.GzipId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(gzipOne) == 0 {
|
||
continue
|
||
}
|
||
|
||
level := gzipOne.GetInt("level")
|
||
if level <= 0 {
|
||
continue
|
||
}
|
||
if level > 0 && level <= 10 {
|
||
compressionConfig.Level = types.Int8(level)
|
||
} else if level > 10 {
|
||
compressionConfig.Level = 10
|
||
}
|
||
|
||
var minLengthBytes = []byte(gzipOne.GetString("minLength"))
|
||
if len(minLengthBytes) > 0 {
|
||
var sizeCapacity = &shared.SizeCapacity{}
|
||
err = json.Unmarshal(minLengthBytes, sizeCapacity)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
compressionConfig.MinLength = sizeCapacity
|
||
}
|
||
|
||
var maxLengthBytes = []byte(gzipOne.GetString("maxLength"))
|
||
if len(maxLengthBytes) > 0 {
|
||
var sizeCapacity = &shared.SizeCapacity{}
|
||
err = json.Unmarshal(maxLengthBytes, sizeCapacity)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
compressionConfig.MaxLength = sizeCapacity
|
||
}
|
||
|
||
var condsBytes = []byte(gzipOne.GetString("conds"))
|
||
if len(condsBytes) > 0 {
|
||
var conds = &shared.HTTPRequestCondsConfig{}
|
||
err = json.Unmarshal(condsBytes, conds)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
compressionConfig.Conds = conds
|
||
}
|
||
|
||
configJSON, err := json.Marshal(compressionConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeHTTPWebs SET compression=? WHERE id=?", string(configJSON), webId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 鏇存柊鏈嶅姟绔彛
|
||
var serverDAO = models.NewServerDAO()
|
||
ones, err := serverDAO.Query(nil).
|
||
ResultPk().
|
||
FindAll()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var serverId = int64(one.(*models.Server).Id)
|
||
err = serverDAO.NotifyServerPortsUpdate(nil, serverId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.3.3
|
||
func upgradeV0_3_3(db *dbs.DB) error {
|
||
// 鍗囩骇CC璇锋眰鏁癈ode
|
||
_, err := db.Exec("UPDATE edgeHTTPFirewallRuleSets SET code='8002' WHERE name='CC璇锋眰鏁? AND code='8001'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 娓呴櫎鑺傜偣
|
||
// 鍒犻櫎7澶╀互鍓嶇殑info鏃ュ織
|
||
err = models.NewNodeLogDAO().DeleteExpiredLogsWithLevel(nil, "info", 7)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.3.7
|
||
func upgradeV0_3_7(db *dbs.DB) error {
|
||
// 淇敼鎵€鏈塭dgeNodeGrants涓殑su涓?
|
||
_, err := db.Exec("UPDATE edgeNodeGrants SET su=0 WHERE su=1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// WAF棰勭疆鍒嗙粍
|
||
_, err = db.Exec("UPDATE edgeHTTPFirewallRuleGroups SET isTemplate=1 WHERE LENGTH(code)>0")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.4.0
|
||
func upgradeV0_4_0(db *dbs.DB) error {
|
||
// 鍗囩骇SYN Flood閰嶇疆
|
||
synFloodJSON, err := json.Marshal(firewallconfigs.NewSYNFloodConfig())
|
||
if err == nil {
|
||
_, err := db.Exec("UPDATE edgeHTTPFirewallPolicies SET synFlood=? WHERE synFlood IS NULL AND state=1", string(synFloodJSON))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.4.1
|
||
func upgradeV0_4_1(db *dbs.DB) error {
|
||
// 鍗囩骇 servers.lastUserPlanId
|
||
_, err := db.Exec("UPDATE edgeServers SET lastUserPlanId=userPlanId WHERE userPlanId>0")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 鎵ц鍩熷悕缁熻娓呯悊
|
||
err = stats.NewServerDomainHourlyStatDAO().CleanDays(nil, 7)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.4.5
|
||
func upgradeV0_4_5(db *dbs.DB) error {
|
||
// 鍗囩骇璁块棶鏃ュ織鑷姩鍒嗚〃
|
||
{
|
||
var dao = models.NewSysSettingDAO()
|
||
valueJSON, err := dao.ReadSetting(nil, systemconfigs.SettingCodeAccessLogQueue)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(valueJSON) > 0 {
|
||
var config = &serverconfigs.AccessLogQueueConfig{}
|
||
err = json.Unmarshal(valueJSON, config)
|
||
if err == nil && config.RowsPerTable == 0 {
|
||
config.EnableAutoPartial = true
|
||
config.RowsPerTable = 500_000
|
||
configJSON, err := json.Marshal(config)
|
||
if err == nil {
|
||
err = dao.UpdateSetting(nil, systemconfigs.SettingCodeAccessLogQueue, configJSON)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 鍗囩骇涓€涓槻SQL娉ㄥ叆瑙勫垯
|
||
{
|
||
ones, _, err := db.FindOnes(`SELECT id FROM edgeHTTPFirewallRules WHERE value=?`, "(updatexml|extractvalue|ascii|ord|char|chr|count|concat|rand|floor|substr|length|len|user|database|benchmark|analyse)\\s*\\(")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var ruleId = one.GetInt64("id")
|
||
_, err = db.Exec(`UPDATE edgeHTTPFirewallRules SET value=? WHERE id=? LIMIT 1`, `\b(updatexml|extractvalue|ascii|ord|char|chr|count|concat|rand|floor|substr|length|len|user|database|benchmark|analyse)\s*\(.*\)`, ruleId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.4.7
|
||
func upgradeV0_4_7(db *dbs.DB) error {
|
||
// 鍗囩骇 edgeServers 涓殑 plainServerNames
|
||
{
|
||
ones, _, err := db.FindOnes("SELECT id,serverNames FROM edgeServers WHERE state=1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var serverId = one.GetInt64("id")
|
||
var serverNamesJSON = one.GetBytes("serverNames")
|
||
if len(serverNamesJSON) > 0 {
|
||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||
err = json.Unmarshal(serverNamesJSON, &serverNames)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
plainServerNamesJSON, err := json.Marshal(serverconfigs.PlainServerNames(serverNames))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeServers SET plainServerNames=? WHERE id=?", plainServerNamesJSON, serverId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.4.8
|
||
func upgradeV0_4_8(db *dbs.DB) error {
|
||
// 璁剧疆edgeIPLists涓殑serverId
|
||
{
|
||
firewallPolicyOnes, _, err := db.FindOnes("SELECT inbound,serverId FROM edgeHTTPFirewallPolicies WHERE serverId>0")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range firewallPolicyOnes {
|
||
var inboundBytes = one.GetBytes("inbound")
|
||
var serverId = one.GetInt64("serverId")
|
||
|
||
var listIds = []int64{}
|
||
|
||
if len(inboundBytes) > 0 {
|
||
var inbound = &firewallconfigs.HTTPFirewallInboundConfig{}
|
||
err = json.Unmarshal(inboundBytes, inbound)
|
||
if err == nil { // we ignore errors
|
||
if inbound.AllowListRef != nil && inbound.AllowListRef.ListId > 0 {
|
||
listIds = append(listIds, inbound.AllowListRef.ListId)
|
||
}
|
||
if inbound.DenyListRef != nil && inbound.DenyListRef.ListId > 0 {
|
||
listIds = append(listIds, inbound.DenyListRef.ListId)
|
||
}
|
||
if inbound.GreyListRef != nil && inbound.GreyListRef.ListId > 0 {
|
||
listIds = append(listIds, inbound.GreyListRef.ListId)
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(listIds) == 0 {
|
||
continue
|
||
}
|
||
for _, listId := range listIds {
|
||
isPublicCol, err := db.FindCol(0, "SELECT isPublic FROM edgeIPLists WHERE id=? LIMIT 1", listId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
var isPublic = types.Bool(isPublicCol)
|
||
if !isPublic {
|
||
_, err = db.Exec("UPDATE edgeIPLists SET serverId=? WHERE id=?", serverId, listId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v0.4.11
|
||
func upgradeV0_4_11(db *dbs.DB) error {
|
||
// 鍗囩骇ns绔彛
|
||
{
|
||
// TCP
|
||
{
|
||
var config = &serverconfigs.TCPProtocolConfig{}
|
||
config.IsOn = true
|
||
config.Listen = []*serverconfigs.NetworkAddressConfig{
|
||
{
|
||
Protocol: serverconfigs.ProtocolTCP,
|
||
PortRange: "53",
|
||
},
|
||
}
|
||
configJSON, err := json.Marshal(config)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeNSClusters SET tcp=? WHERE tcp IS NULL", configJSON)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// UDP
|
||
{
|
||
var config = &serverconfigs.UDPProtocolConfig{}
|
||
config.IsOn = true
|
||
config.Listen = []*serverconfigs.NetworkAddressConfig{
|
||
{
|
||
Protocol: serverconfigs.ProtocolUDP,
|
||
PortRange: "53",
|
||
},
|
||
}
|
||
configJSON, err := json.Marshal(config)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeNSClusters SET udp=? WHERE udp IS NULL", configJSON)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// v1.2.1
|
||
func upgradeV1_2_1(db *dbs.DB) error {
|
||
// upgrade generated USER-xxx in old versions
|
||
ones, _, err := db.FindOnes("SELECT id, username, clusterId FROM edgeUsers WHERE username LIKE 'USER-%'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var userId = one.GetInt64("id")
|
||
var clusterId = one.GetInt64("clusterId")
|
||
var username = one.GetString("username")
|
||
if clusterId <= 0 {
|
||
defaultClusterIdValue, err := db.FindCol(0, "SELECT id FROM edgeNodeClusters WHERE state=1 ORDER BY id ASC LIMIT 1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
var defaultClusterId = types.Int64(defaultClusterIdValue)
|
||
if defaultClusterId > 0 {
|
||
_, err = db.Exec("UPDATE edgeUsers SET username=?, clusterId=? WHERE id=?", strings.ReplaceAll(username, "-", "_"), defaultClusterId, userId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 1.2.10
|
||
func upgradeV1_2_10(db *dbs.DB) error {
|
||
{
|
||
type OldGlobalConfig struct {
|
||
// HTTP & HTTPS鐩稿叧閰嶇疆
|
||
HTTPAll struct {
|
||
DomainAuditingIsOn bool `yaml:"domainAuditingIsOn" json:"domainAuditingIsOn"` // 域名是否需要审核
|
||
DomainAuditingPrompt string `yaml:"domainAuditingPrompt" json:"domainAuditingPrompt"` // 域名审核提示
|
||
} `yaml:"httpAll" json:"httpAll"`
|
||
|
||
TCPAll struct {
|
||
PortRangeMin int `yaml:"portRangeMin" json:"portRangeMin"` // 最小端口
|
||
PortRangeMax int `yaml:"portRangeMax" json:"portRangeMax"` // 最大端口
|
||
DenyPorts []int `yaml:"denyPorts" json:"denyPorts"` // 禁止端口
|
||
} `yaml:"tcpAll" json:"tcpAll"`
|
||
}
|
||
|
||
globalConfigValue, err := db.FindCol(0, "SELECT value FROM edgeSysSettings WHERE code='serverGlobalConfig'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
var globalConfigString = types.String(globalConfigValue)
|
||
if len(globalConfigString) > 0 {
|
||
var oldGlobalConfig = &OldGlobalConfig{}
|
||
err = json.Unmarshal([]byte(globalConfigString), oldGlobalConfig)
|
||
if err == nil { // we ignore error
|
||
ones, _, err := db.FindOnes("SELECT id,globalServerConfig FROM edgeNodeClusters")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, one := range ones {
|
||
var id = one.GetInt64("id")
|
||
var globalServerConfigData = []byte(one.GetString("globalServerConfig"))
|
||
if len(globalServerConfigData) > 32 {
|
||
var globalServerConfig = &serverconfigs.GlobalServerConfig{}
|
||
err = json.Unmarshal(globalServerConfigData, globalServerConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
globalServerConfig.HTTPAll.DomainAuditingIsOn = oldGlobalConfig.HTTPAll.DomainAuditingIsOn
|
||
globalServerConfig.HTTPAll.DomainAuditingPrompt = oldGlobalConfig.HTTPAll.DomainAuditingPrompt
|
||
|
||
globalServerConfig.TCPAll.DenyPorts = oldGlobalConfig.TCPAll.DenyPorts
|
||
globalServerConfig.TCPAll.PortRangeMin = oldGlobalConfig.TCPAll.PortRangeMin
|
||
globalServerConfig.TCPAll.PortRangeMax = oldGlobalConfig.TCPAll.PortRangeMax
|
||
|
||
globalServerConfigJSON, err := json.Marshal(globalServerConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeNodeClusters SET globalServerConfig=? WHERE id=?", globalServerConfigJSON, id)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 1.3.2
|
||
func upgradeV1_3_2(db *dbs.DB) error {
|
||
// waf
|
||
{
|
||
var disableSet = func(setId int64) error {
|
||
_, err := db.Exec("UPDATE edgeHTTPFirewallRuleSets SET state=0 WHERE id=?", setId)
|
||
return err
|
||
}
|
||
|
||
var addRuleToGroup = func(groupId int64, setCode string, setName string, actions []*firewallconfigs.HTTPFirewallActionConfig, ruleParam string, ruleOperator string, value string) error {
|
||
actionsJSON, err := json.Marshal(actions)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// rule
|
||
ruleResult, err := db.Exec("INSERT INTO edgeHTTPFirewallRules (isOn, param, operator, value, isCaseInsensitive, state) VALUES (1, ?, ?, ?, 0, 1)", ruleParam, ruleOperator, value)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
ruleId, err := ruleResult.LastInsertId()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
var ruleRefs = []*firewallconfigs.HTTPFirewallRuleRef{
|
||
{
|
||
IsOn: true,
|
||
RuleId: ruleId,
|
||
},
|
||
}
|
||
ruleRefsJSON, err := json.Marshal(ruleRefs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// set
|
||
setResult, err := db.Exec("INSERT INTO edgeHTTPFirewallRuleSets (isOn, code, name, rules, connector, state, actions) VALUES (1, ?, ?, ?, 'or', 1, ?)", setCode, setName, ruleRefsJSON, actionsJSON)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
setId, err := setResult.LastInsertId()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
var setRefs = []*firewallconfigs.HTTPFirewallRuleSetRef{
|
||
{
|
||
IsOn: true,
|
||
SetId: setId,
|
||
},
|
||
}
|
||
setRefsJSON, err := json.Marshal(setRefs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// group
|
||
_, err = db.Exec("UPDATE edgeHTTPFirewallRuleGroups SET sets=? WHERE id=?", setRefsJSON, groupId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// sql injection
|
||
{
|
||
ruleGroups, _, err := db.FindOnes("SELECT id, sets FROM edgeHTTPFirewallRuleGroups WHERE code='sqlInjection' AND state=1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, ruleGroup := range ruleGroups {
|
||
var setsJSON = ruleGroup.GetBytes("sets")
|
||
if len(setsJSON) == 0 {
|
||
continue
|
||
}
|
||
|
||
var setRefs = []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||
err = json.Unmarshal(setsJSON, &setRefs)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
if len(setRefs) != 5 {
|
||
continue
|
||
}
|
||
|
||
var isChanged = false
|
||
for setIndex, setRef := range setRefs {
|
||
set, setErr := db.FindOne("SELECT id, rules, isOn, actions FROM edgeHTTPFirewallRuleSets WHERE id=? AND state=1", setRef.SetId)
|
||
if setErr != nil {
|
||
return setErr
|
||
}
|
||
if set == nil {
|
||
isChanged = true
|
||
break
|
||
}
|
||
var rulesJSON = set.GetBytes("rules")
|
||
if len(rulesJSON) == 0 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
var ruleRefs = []*firewallconfigs.HTTPFirewallRuleRef{}
|
||
err = json.Unmarshal(rulesJSON, &ruleRefs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(ruleRefs) < 1 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
|
||
var actionsJSON = set.GetBytes("actions")
|
||
if len(actionsJSON) == 0 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
var actions = []*firewallconfigs.HTTPFirewallActionConfig{}
|
||
err = json.Unmarshal(actionsJSON, &actions)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if !(len(actions) == 1 && actions[0].Code == firewallconfigs.HTTPFirewallActionBlock) {
|
||
isChanged = true
|
||
break
|
||
}
|
||
|
||
var rules = []maps.Map{}
|
||
for _, ruleRef := range ruleRefs {
|
||
rule, ruleErr := db.FindOne("SELECT * FROM edgeHTTPFirewallRules WHERE id=? AND state=1", ruleRef.RuleId)
|
||
if ruleErr != nil {
|
||
return ruleErr
|
||
}
|
||
if rule == nil {
|
||
isChanged = true
|
||
break
|
||
}
|
||
rules = append(rules, rule)
|
||
}
|
||
if isChanged {
|
||
break
|
||
}
|
||
if len(rules) < 1 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
|
||
switch setIndex {
|
||
case 0:
|
||
var rule = rules[0]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `union[\s/\*]+select`) {
|
||
isChanged = true
|
||
}
|
||
case 1:
|
||
var rule = rules[0]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `/\*(!|\x00)`) {
|
||
isChanged = true
|
||
}
|
||
case 2:
|
||
if len(rules) != 4 {
|
||
isChanged = true
|
||
} else {
|
||
{
|
||
var rule = rules[0]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `\s(and|or|rlike)\s+(if|updatexml)\s*\(`) {
|
||
isChanged = true
|
||
}
|
||
}
|
||
|
||
{
|
||
var rule = rules[1]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `\s+(and|or|rlike)\s+(select|case)\s+`) {
|
||
isChanged = true
|
||
}
|
||
}
|
||
|
||
{
|
||
var rule = rules[2]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `\s+(and|or|procedure)\s+[\w\p{L}]+\s*=\s*[\w\p{L}]+(\s|$|--|#)`) {
|
||
isChanged = true
|
||
}
|
||
}
|
||
|
||
{
|
||
var rule = rules[3]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `\(\s*case\s+when\s+[\w\p{L}]+\s*=\s*[\w\p{L}]+\s+then\s+`) {
|
||
isChanged = true
|
||
}
|
||
}
|
||
}
|
||
case 3:
|
||
var rule = rules[0]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `\b(updatexml|extractvalue|ascii|ord|char|chr|count|concat|rand|floor|substr|length|len|user|database|benchmark|analyse)\s*\(.*\)`) {
|
||
isChanged = true
|
||
}
|
||
case 4:
|
||
var rule = rules[0]
|
||
if !(rule.GetString("param") == "${requestAll}" && rule.GetString("operator") == "match" && rule.GetString("value") == `;\s*(declare|use|drop|create|exec|delete|update|insert)\s`) {
|
||
isChanged = true
|
||
}
|
||
}
|
||
}
|
||
if isChanged {
|
||
continue
|
||
}
|
||
|
||
for _, setRef := range setRefs {
|
||
err = disableSet(setRef.SetId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
err = addRuleToGroup(ruleGroup.GetInt64("id"), "7010", "SQL注入检测", []*firewallconfigs.HTTPFirewallActionConfig{
|
||
{
|
||
Code: firewallconfigs.HTTPFirewallActionPage,
|
||
Options: maps.Map{"status": 403, "body": ""},
|
||
},
|
||
}, "${requestAll}", firewallconfigs.HTTPFirewallRuleOperatorContainsSQLInjection, "")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
// xss
|
||
{
|
||
ruleGroups, _, err := db.FindOnes("SELECT id, sets FROM edgeHTTPFirewallRuleGroups WHERE code='xss' AND state=1")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
for _, ruleGroup := range ruleGroups {
|
||
var setsJSON = ruleGroup.GetBytes("sets")
|
||
if len(setsJSON) == 0 {
|
||
continue
|
||
}
|
||
|
||
var setRefs = []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||
err = json.Unmarshal(setsJSON, &setRefs)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
if len(setRefs) != 3 {
|
||
continue
|
||
}
|
||
|
||
var isChanged = false
|
||
for setIndex, setRef := range setRefs {
|
||
set, setErr := db.FindOne("SELECT id, rules, isOn, actions FROM edgeHTTPFirewallRuleSets WHERE id=? AND state=1", setRef.SetId)
|
||
if setErr != nil {
|
||
return setErr
|
||
}
|
||
if set == nil {
|
||
isChanged = true
|
||
break
|
||
}
|
||
var rulesJSON = set.GetBytes("rules")
|
||
if len(rulesJSON) == 0 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
var ruleRefs = []*firewallconfigs.HTTPFirewallRuleRef{}
|
||
err = json.Unmarshal(rulesJSON, &ruleRefs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(ruleRefs) != 1 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
|
||
var actionsJSON = set.GetBytes("actions")
|
||
if len(actionsJSON) == 0 {
|
||
isChanged = true
|
||
break
|
||
}
|
||
var actions = []*firewallconfigs.HTTPFirewallActionConfig{}
|
||
err = json.Unmarshal(actionsJSON, &actions)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if !(len(actions) == 1 && actions[0].Code == firewallconfigs.HTTPFirewallActionBlock) {
|
||
isChanged = true
|
||
break
|
||
}
|
||
|
||
rule, ruleErr := db.FindOne("SELECT * FROM edgeHTTPFirewallRules WHERE id=? AND state=1", ruleRefs[0].RuleId)
|
||
if ruleErr != nil {
|
||
return ruleErr
|
||
}
|
||
if rule == nil {
|
||
isChanged = true
|
||
break
|
||
}
|
||
|
||
switch setIndex {
|
||
case 0:
|
||
if !(rule.GetString("param") == "${requestURI}" && rule.GetString("operator") == "match" && rule.GetString("value") == `(onmouseover|onmousemove|onmousedown|onmouseup|onerror|onload|onclick|ondblclick|onkeydown|onkeyup|onkeypress)\s*=`) {
|
||
isChanged = true
|
||
}
|
||
case 1:
|
||
if !(rule.GetString("param") == "${requestURI}" && rule.GetString("operator") == "match" && rule.GetString("value") == `(alert|eval|prompt|confirm)\s*\(`) {
|
||
isChanged = true
|
||
}
|
||
case 2:
|
||
if !(rule.GetString("param") == "${requestURI}" && rule.GetString("operator") == "match" && rule.GetString("value") == `<(script|iframe|link)`) {
|
||
isChanged = true
|
||
}
|
||
}
|
||
}
|
||
if isChanged {
|
||
continue
|
||
}
|
||
|
||
for _, setRef := range setRefs {
|
||
err = disableSet(setRef.SetId)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
err = addRuleToGroup(ruleGroup.GetInt64("id"), "1010", "XSS攻击检测", []*firewallconfigs.HTTPFirewallActionConfig{
|
||
{
|
||
Code: firewallconfigs.HTTPFirewallActionPage,
|
||
Options: maps.Map{"status": 403, "body": ""},
|
||
},
|
||
}, "${requestAll}", firewallconfigs.HTTPFirewallRuleOperatorContainsXSS, "")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// user register config
|
||
|
||
var newAddedFeatureCodes = []string{
|
||
userconfigs.UserFeatureCodeServerOptimization,
|
||
userconfigs.UserFeatureCodeServerAuth,
|
||
userconfigs.UserFeatureCodeServerWebsocket,
|
||
userconfigs.UserFeatureCodeServerHTTP3,
|
||
userconfigs.UserFeatureCodeServerCC,
|
||
userconfigs.UserFeatureCodeServerReferers,
|
||
userconfigs.UserFeatureCodeServerUserAgent,
|
||
userconfigs.UserFeatureCodeServerRequestLimit,
|
||
userconfigs.UserFeatureCodeServerCompression,
|
||
userconfigs.UserFeatureCodeServerRewriteRules,
|
||
userconfigs.UserFeatureCodeServerHostRedirects,
|
||
userconfigs.UserFeatureCodeServerHTTPHeaders,
|
||
userconfigs.UserFeatureCodeServerPages,
|
||
}
|
||
|
||
{
|
||
value, err := db.FindCol(0, "SELECT value FROM edgeSysSettings WHERE code=?", systemconfigs.SettingCodeUserRegisterConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if value != nil {
|
||
var valueString = types.String(value)
|
||
if valueString != "null" && len(valueString) > 0 {
|
||
var registerConfig = &userconfigs.UserRegisterConfig{}
|
||
err = json.Unmarshal([]byte(valueString), registerConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if len(registerConfig.Features) > 0 {
|
||
var newFeatureCodes = registerConfig.Features
|
||
var changed = false
|
||
for _, featureCode := range newAddedFeatureCodes {
|
||
if !lists.ContainsString(newFeatureCodes, featureCode) {
|
||
newFeatureCodes = append(newFeatureCodes, featureCode)
|
||
changed = true
|
||
}
|
||
}
|
||
|
||
if changed {
|
||
registerConfig.Features = newFeatureCodes
|
||
registerConfigJSON, err := json.Marshal(registerConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = db.Exec("UPDATE edgeSysSettings SET value=? WHERE code=?", registerConfigJSON, systemconfigs.SettingCodeUserRegisterConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// user features
|
||
{
|
||
var sqlPieces []string
|
||
for _, featureCode := range newAddedFeatureCodes {
|
||
if strings.Contains(featureCode, "'") {
|
||
continue
|
||
}
|
||
sqlPieces = append(sqlPieces, "'$', '"+featureCode+"'")
|
||
}
|
||
|
||
_, err := db.Exec("UPDATE edgeUsers SET features=JSON_ARRAY_APPEND(features," + strings.Join(sqlPieces, ",") + ") WHERE features IS NOT NULL AND JSON_LENGTH(features)>0 AND NOT JSON_CONTAINS(features, '" + strconv.Quote(newAddedFeatureCodes[0]) + "')")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 1.3.4
|
||
func upgradeV1_3_4(db *dbs.DB) error {
|
||
_, err := db.Exec("DELETE FROM edgeLoginSessions WHERE adminId>0")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 1.4.4
|
||
func upgradeV1_4_4(db *dbs.DB) error {
|
||
// 检查 encryption 字段是否已存在
|
||
col, err := db.FindCol(0, "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='edgeHTTPWebs' AND COLUMN_NAME='encryption'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
var count = types.Int(col)
|
||
if count > 0 {
|
||
// 字段已存在,跳过
|
||
return nil
|
||
}
|
||
|
||
// 添加 encryption 字段到 edgeHTTPWebs 表
|
||
_, err = db.Exec("ALTER TABLE edgeHTTPWebs ADD COLUMN `encryption` json DEFAULT NULL COMMENT '页面动态加密配置' AFTER `optimization`")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 1.4.8
|
||
func upgradeV1_4_8(db *dbs.DB) error {
|
||
err := createHTTPDNSTables(db)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// edgeUsers: 增加 httpdnsClusterIds 字段
|
||
_, alterErr := db.Exec("ALTER TABLE `edgeUsers` ADD COLUMN `httpdnsClusterIds` text DEFAULT NULL")
|
||
if alterErr != nil {
|
||
if strings.Contains(alterErr.Error(), "Duplicate column") {
|
||
return nil
|
||
}
|
||
return alterErr
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 1.4.9
|
||
func upgradeV1_4_9(db *dbs.DB) error {
|
||
_, err := db.Exec("ALTER TABLE `edgeHTTPDNSClusters` ALTER COLUMN `installDir` SET DEFAULT '/root/edge-httpdns'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
_, err = db.Exec("ALTER TABLE `edgeHTTPDNSNodes` ALTER COLUMN `installDir` SET DEFAULT '/root/edge-httpdns'")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func createHTTPDNSTables(db *dbs.DB) error {
|
||
sqls := []string{
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSClusters` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`isOn` tinyint unsigned DEFAULT '1',`isDefault` tinyint unsigned DEFAULT '0',`serviceDomain` varchar(255) DEFAULT NULL,`defaultTTL` int unsigned DEFAULT '30',`fallbackTimeoutMs` int unsigned DEFAULT '300',`installDir` varchar(255) DEFAULT '/root/edge-httpdns',`tlsPolicy` json DEFAULT NULL,`autoRemoteStart` tinyint unsigned DEFAULT '0',`accessLogIsOn` tinyint unsigned DEFAULT '0',`timeZone` varchar(128) NOT NULL DEFAULT '',`createdAt` bigint unsigned DEFAULT '0',`updatedAt` bigint unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),KEY `name` (`name`),KEY `isDefault` (`isDefault`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS集群配置表(默认TTL、回退超时、服务域名等)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSNodes` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`clusterId` bigint unsigned DEFAULT '0',`name` varchar(255) DEFAULT NULL,`isOn` tinyint unsigned DEFAULT '1',`isUp` tinyint unsigned DEFAULT '0',`isInstalled` tinyint unsigned DEFAULT '0',`isActive` tinyint unsigned DEFAULT '0',`uniqueId` varchar(64) DEFAULT NULL,`secret` varchar(64) DEFAULT NULL,`installDir` varchar(255) DEFAULT '/root/edge-httpdns',`status` json DEFAULT NULL,`installStatus` json DEFAULT NULL,`createdAt` bigint unsigned DEFAULT '0',`updatedAt` bigint unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),UNIQUE KEY `uniqueId` (`uniqueId`),KEY `clusterId` (`clusterId`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS节点表(节点基础信息与运行状态)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSApps` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`appId` varchar(64) DEFAULT NULL,`isOn` tinyint unsigned DEFAULT '1',`clusterIdsJSON` text DEFAULT NULL,`sniMode` varchar(64) DEFAULT 'fixed_hide',`userId` bigint unsigned DEFAULT '0',`createdAt` bigint unsigned DEFAULT '0',`updatedAt` bigint unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),UNIQUE KEY `appId` (`appId`),KEY `name` (`name`),KEY `userId` (`userId`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS应用表(应用与集群绑定关系)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSAppSecrets` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`appId` bigint unsigned DEFAULT '0',`signEnabled` tinyint unsigned DEFAULT '0',`signSecret` varchar(255) DEFAULT NULL,`signUpdatedAt` bigint unsigned DEFAULT '0',`updatedAt` bigint unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),UNIQUE KEY `appId` (`appId`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS应用密钥表(请求验签开关与加签Secret)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSDomains` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`appId` bigint unsigned DEFAULT '0',`domain` varchar(255) DEFAULT NULL,`isOn` tinyint unsigned DEFAULT '1',`createdAt` bigint unsigned DEFAULT '0',`updatedAt` bigint unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),UNIQUE KEY `appId_domain` (`appId`,`domain`),KEY `domain` (`domain`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS应用域名表(应用绑定的业务域名)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSCustomRules` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`appId` bigint unsigned DEFAULT '0',`domainId` bigint unsigned DEFAULT '0',`ruleName` varchar(255) DEFAULT NULL,`lineScope` varchar(64) DEFAULT NULL,`lineCarrier` varchar(64) DEFAULT NULL,`lineRegion` varchar(64) DEFAULT NULL,`lineProvince` varchar(64) DEFAULT NULL,`lineContinent` varchar(64) DEFAULT NULL,`lineCountry` varchar(128) DEFAULT NULL,`ttl` int unsigned DEFAULT '30',`isOn` tinyint unsigned DEFAULT '1',`priority` int unsigned DEFAULT '0',`updatedAt` bigint unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),KEY `domainId_isOn_priority` (`domainId`,`isOn`,`priority`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS自定义解析规则表(按线路/地域匹配)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSCustomRuleRecords` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`ruleId` bigint unsigned DEFAULT '0',`recordType` varchar(32) DEFAULT NULL,`recordValue` varchar(255) DEFAULT NULL,`weight` int unsigned DEFAULT '0',`sort` int unsigned DEFAULT '0',`state` tinyint unsigned DEFAULT '1',PRIMARY KEY (`id`),KEY `ruleId` (`ruleId`),KEY `state` (`state`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS自定义规则记录值表(A/AAAA及权重)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSAccessLogs` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`requestId` varchar(128) DEFAULT NULL,`clusterId` bigint unsigned DEFAULT '0',`nodeId` bigint unsigned DEFAULT '0',`appId` varchar(64) DEFAULT NULL,`appName` varchar(255) DEFAULT NULL,`domain` varchar(255) DEFAULT NULL,`qtype` varchar(16) DEFAULT NULL,`clientIP` varchar(64) DEFAULT NULL,`clientRegion` varchar(255) DEFAULT NULL,`carrier` varchar(128) DEFAULT NULL,`sdkVersion` varchar(64) DEFAULT NULL,`os` varchar(64) DEFAULT NULL,`resultIPs` text,`status` varchar(32) DEFAULT NULL,`errorCode` varchar(64) DEFAULT NULL,`costMs` int unsigned DEFAULT '0',`createdAt` bigint unsigned DEFAULT '0',`day` varchar(8) DEFAULT NULL,`summary` text,PRIMARY KEY (`id`),UNIQUE KEY `requestId_nodeId` (`requestId`,`nodeId`),KEY `day_cluster_node_domain_status_createdAt` (`day`,`clusterId`,`nodeId`,`domain`,`status`,`createdAt`),KEY `appId` (`appId`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS访问日志表(解析请求与结果)'",
|
||
"CREATE TABLE IF NOT EXISTS `edgeHTTPDNSRuntimeLogs` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`clusterId` bigint unsigned DEFAULT '0',`nodeId` bigint unsigned DEFAULT '0',`level` varchar(32) DEFAULT NULL,`type` varchar(64) DEFAULT NULL,`module` varchar(64) DEFAULT NULL,`description` text,`count` bigint unsigned DEFAULT '1',`requestId` varchar(128) DEFAULT NULL,`createdAt` bigint unsigned DEFAULT '0',`day` varchar(8) DEFAULT NULL,PRIMARY KEY (`id`),KEY `day_cluster_node_level_createdAt` (`day`,`clusterId`,`nodeId`,`level`,`createdAt`),KEY `requestId` (`requestId`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='HTTPDNS运行日志表(节点运行与异常日志)'",
|
||
}
|
||
for _, sql := range sqls {
|
||
if _, err := db.Exec(sql); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
|