Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b1a9f9a45 | ||
|
|
7a86ecb44b | ||
|
|
89a113431a | ||
|
|
ce62d0769b | ||
|
|
a72dc2e011 | ||
|
|
91ca2d6b6b | ||
|
|
0de6fa5ce8 | ||
|
|
84e2628769 | ||
|
|
fc28798c9f | ||
|
|
24c21c5513 | ||
|
|
8445e811a5 | ||
|
|
d54621d500 | ||
|
|
ef045e90f2 | ||
|
|
5205136809 | ||
|
|
179a7760fa | ||
|
|
640e69524c | ||
|
|
3620ab3dc6 | ||
|
|
5789b1afb9 | ||
|
|
6f9f9dfb6f | ||
|
|
171bafce6a | ||
|
|
7c7fecab26 | ||
|
|
7afdf5a2d9 | ||
|
|
ee9718ac77 | ||
|
|
15e10182da | ||
|
|
4341c5b738 | ||
|
|
cf9b31b8eb | ||
|
|
564d440cd1 | ||
|
|
bad9231ab3 | ||
|
|
a78333c490 | ||
|
|
ace44173ec | ||
|
|
5155ce97af | ||
|
|
e2bf3ba1a4 | ||
|
|
9abc65bd2b | ||
|
|
a99156ea49 | ||
|
|
d35db163ae | ||
|
|
e7b0f0df90 | ||
|
|
eab09fa37a | ||
|
|
ec3f89ecf5 | ||
|
|
d58106c7ca | ||
|
|
5da924118d | ||
|
|
51e37f0c52 | ||
|
|
7e9e764322 | ||
|
|
75e41fff4d | ||
|
|
8a9842edaf | ||
|
|
4e8629d74a | ||
|
|
2e02aa556e | ||
|
|
974c95c20a | ||
|
|
3c0e6a900b | ||
|
|
fb420f8fce | ||
|
|
705e80f6c7 |
@@ -83,6 +83,20 @@ func main() {
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("debug", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "debug"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var isDebug = maps.NewMap(reply.Params).GetBool("debug")
|
||||
if isDebug {
|
||||
fmt.Println("debug on")
|
||||
} else {
|
||||
fmt.Println("debug off")
|
||||
}
|
||||
}
|
||||
})
|
||||
app.Run(func() {
|
||||
nodes.NewAPINode().Start()
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package accesslogs
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package teaconst
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.3.7"
|
||||
Version = "0.4.1"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,8 +18,8 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.3.7"
|
||||
UserNodeVersion = "0.2.1"
|
||||
NodeVersion = "0.4.1"
|
||||
UserNodeVersion = "0.3.1"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.3"
|
||||
DNSNodeVersion = "0.2.1"
|
||||
|
||||
@@ -6,4 +6,5 @@ var (
|
||||
IsPlus = false
|
||||
MaxNodes int32 = 0
|
||||
NodeId int64 = 0
|
||||
Debug = false
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
acmeutils "github.com/TeaOSLab/EdgeAPI/internal/acme"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
@@ -400,6 +401,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
client := utils.SharedHttpClient(5 * time.Second)
|
||||
req, err := http.NewRequest(http.MethodPost, task.AuthURL, bytes.NewReader(authJSON))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||
if err != nil {
|
||||
remotelogs.Error("ACME", "parse auth url failed '"+task.AuthURL+"': "+err.Error())
|
||||
} else {
|
||||
|
||||
76
internal/db/models/api_method_stat_dao.go
Normal file
76
internal/db/models/api_method_stat_dao.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type APIMethodStatDAO dbs.DAO
|
||||
|
||||
func NewAPIMethodStatDAO() *APIMethodStatDAO {
|
||||
return dbs.NewDAO(&APIMethodStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeAPIMethodStats",
|
||||
Model: new(APIMethodStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*APIMethodStatDAO)
|
||||
}
|
||||
|
||||
var SharedAPIMethodStatDAO *APIMethodStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedAPIMethodStatDAO = NewAPIMethodStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateStat 记录统计数据
|
||||
func (this *APIMethodStatDAO) CreateStat(tx *dbs.Tx, method string, tag string, costMs float64) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
return this.Query(tx).
|
||||
Param("costMs", costMs).
|
||||
InsertOrUpdateQuickly(map[string]interface{}{
|
||||
"apiNodeId": teaconst.NodeId,
|
||||
"method": method,
|
||||
"tag": tag,
|
||||
"costMs": costMs,
|
||||
"peekMs": costMs,
|
||||
"countCalls": 1,
|
||||
"day": day,
|
||||
}, map[string]interface{}{
|
||||
"costMs": dbs.SQL("(costMs*countCalls+:costMs)/(countCalls+1)"),
|
||||
"peekMs": dbs.SQL("IF(peekMs>:costMs, peekMs, :costMs)"),
|
||||
"countCalls": dbs.SQL("countCalls+1"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindAllStatsWithDay 查询当前统计
|
||||
func (this *APIMethodStatDAO) FindAllStatsWithDay(tx *dbs.Tx, day string) (result []*APIMethodStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("day", day).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllStatsWithDay 统计当天数量
|
||||
func (this *APIMethodStatDAO) CountAllStatsWithDay(tx *dbs.Tx, day string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("day", day).
|
||||
Count()
|
||||
}
|
||||
|
||||
// Clean 清理数据
|
||||
func (this *APIMethodStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
_, err := this.Query(tx).
|
||||
Param("day", day).
|
||||
Where("day<:day").
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
19
internal/db/models/api_method_stat_dao_test.go
Normal file
19
internal/db/models/api_method_stat_dao_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAPIMethodStatDAO_CreateStat(t *testing.T) {
|
||||
var dao = NewAPIMethodStatDAO()
|
||||
var tx *dbs.Tx
|
||||
|
||||
err := dao.CreateStat(tx, "/pb.Hello/World", "tag", 1.123)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
28
internal/db/models/api_method_stat_model.go
Normal file
28
internal/db/models/api_method_stat_model.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
// APIMethodStat API方法统计
|
||||
type APIMethodStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ApiNodeId uint32 `field:"apiNodeId"` // API节点ID
|
||||
Method string `field:"method"` // 方法
|
||||
Tag string `field:"tag"` // 标签方法
|
||||
CostMs float64 `field:"costMs"` // 耗时Ms
|
||||
PeekMs float64 `field:"peekMs"` // 峰值耗时
|
||||
CountCalls uint64 `field:"countCalls"` // 调用次数
|
||||
Day string `field:"day"` // 日期
|
||||
}
|
||||
|
||||
type APIMethodStatOperator struct {
|
||||
Id interface{} // ID
|
||||
ApiNodeId interface{} // API节点ID
|
||||
Method interface{} // 方法
|
||||
Tag interface{} // 标签方法
|
||||
CostMs interface{} // 耗时Ms
|
||||
PeekMs interface{} // 峰值耗时
|
||||
CountCalls interface{} // 调用次数
|
||||
Day interface{} // 日期
|
||||
}
|
||||
|
||||
func NewAPIMethodStatOperator() *APIMethodStatOperator {
|
||||
return &APIMethodStatOperator{}
|
||||
}
|
||||
1
internal/db/models/api_method_stat_model_ext.go
Normal file
1
internal/db/models/api_method_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -62,7 +62,15 @@ func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// FindEnabledAPINode 查找启用中的条目
|
||||
func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, error) {
|
||||
func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64, cacheMap *utils.CacheMap) (*APINode, error) {
|
||||
var cacheKey = this.Table + ":FindEnabledAPINode:" + types.String(id)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*APINode), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", APINodeStateEnabled).
|
||||
@@ -70,6 +78,11 @@ func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, erro
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*APINode), err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package authority
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogD
|
||||
}
|
||||
|
||||
// 创建表格
|
||||
_, err = db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` blob COMMENT '请求内容',\n `responseBody` blob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||
_, err = db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -233,6 +233,8 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
|
||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
size int64,
|
||||
day string,
|
||||
clusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
reverse bool,
|
||||
hasError bool,
|
||||
@@ -253,18 +255,18 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
size = 1000
|
||||
}
|
||||
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
if err != nil || int64(len(result)) < size {
|
||||
return
|
||||
}
|
||||
|
||||
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
hasMore = len(moreResult) > 0
|
||||
return
|
||||
}
|
||||
|
||||
// 读取往前的单页访问日志
|
||||
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, size int64, day string, serverId int64, reverse bool, hasError bool, firewallPolicyId int64, firewallRuleGroupId int64, firewallRuleSetId int64, hasFirewallPolicy bool, userId int64, keyword string, ip string, domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, size int64, day string, clusterId int64, nodeId int64, serverId int64, reverse bool, hasError bool, firewallPolicyId int64, firewallRuleGroupId int64, firewallRuleSetId int64, hasFirewallPolicy bool, userId int64, keyword string, ip string, domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||
if size <= 0 {
|
||||
return nil, lastRequestId, nil
|
||||
}
|
||||
@@ -318,6 +320,30 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
query := dao.Query(tx)
|
||||
|
||||
// 条件
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else if clusterId > 0 {
|
||||
nodeIds, err := SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
remotelogs.Error("DBNODE", err.Error())
|
||||
return
|
||||
}
|
||||
if len(nodeIds) > 0 {
|
||||
sort.Slice(nodeIds, func(i, j int) bool {
|
||||
return nodeIds[i] < nodeIds[j]
|
||||
})
|
||||
var nodeIdStrings = []string{}
|
||||
for _, subNodeId := range nodeIds {
|
||||
nodeIdStrings = append(nodeIdStrings, types.String(subNodeId))
|
||||
}
|
||||
|
||||
query.Where("nodeId IN (" + strings.Join(nodeIdStrings, ",") + ")")
|
||||
query.Reuse(false)
|
||||
} else {
|
||||
// 如果没有节点,则直接返回空
|
||||
return
|
||||
}
|
||||
}
|
||||
if serverId > 0 {
|
||||
query.Attr("serverId", serverId)
|
||||
} else if userId > 0 && len(serverIds) > 0 {
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page(t *testing.T) {
|
||||
times := 0 // 防止循环次数太多
|
||||
for {
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -111,7 +111,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -136,7 +136,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
|
||||
times := 0 // 防止循环次数太多
|
||||
for {
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -300,9 +300,13 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
}
|
||||
|
||||
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, keyword string) (int64, error) {
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT cachePolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
@@ -311,9 +315,13 @@ func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, key
|
||||
}
|
||||
|
||||
// ListEnabledHTTPCachePolicies 列出单页的缓存策略
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT cachePolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
|
||||
@@ -130,6 +130,16 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
|
||||
if len(outboundJSON) > 0 {
|
||||
op.Outbound = outboundJSON
|
||||
}
|
||||
op.UseLocalFirewall = true
|
||||
|
||||
{
|
||||
synFloodJSON, err := json.Marshal(firewallconfigs.DefaultSYNFloodConfig())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.SynFlood = synFloodJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
return types.Int64(op.Id), err
|
||||
}
|
||||
@@ -249,7 +259,7 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
|
||||
}
|
||||
|
||||
// UpdateFirewallPolicy 修改策略
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte, blockOptionsJSON []byte, mode firewallconfigs.FirewallMode) error {
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte, blockOptionsJSON []byte, mode firewallconfigs.FirewallMode, useLocalFirewall bool, synFloodConfig *firewallconfigs.SYNFloodConfig) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -272,6 +282,18 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
if len(blockOptionsJSON) > 0 {
|
||||
op.BlockOptions = blockOptionsJSON
|
||||
}
|
||||
|
||||
if synFloodConfig != nil {
|
||||
synFloodConfigJSON, err := json.Marshal(synFloodConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.SynFlood = synFloodConfigJSON
|
||||
} else {
|
||||
op.SynFlood = "null"
|
||||
}
|
||||
|
||||
op.UseLocalFirewall = useLocalFirewall
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -281,8 +303,12 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
}
|
||||
|
||||
// CountAllEnabledFirewallPolicies 计算所有可用的策略数量
|
||||
func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, keyword string) (int64, error) {
|
||||
func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT httpFirewallPolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
@@ -296,8 +322,12 @@ func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, k
|
||||
}
|
||||
|
||||
// ListEnabledFirewallPolicies 列出单页的策略
|
||||
func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*HTTPFirewallPolicy, err error) {
|
||||
func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) (result []*HTTPFirewallPolicy, err error) {
|
||||
query := this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT httpFirewallPolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
@@ -339,6 +369,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.Name = policy.Name
|
||||
config.Description = policy.Description
|
||||
config.UseLocalFirewall = policy.UseLocalFirewall == 1
|
||||
|
||||
if len(policy.Mode) == 0 {
|
||||
policy.Mode = firewallconfigs.FirewallModeDefend
|
||||
@@ -411,6 +442,16 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
config.BlockOptions = blockAction
|
||||
}
|
||||
|
||||
// syn flood
|
||||
if len(policy.SynFlood) > 0 {
|
||||
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
|
||||
err = json.Unmarshal([]byte(policy.SynFlood), synFloodConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.SYNFlood = synFloodConfig
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
@@ -2,39 +2,43 @@ package models
|
||||
|
||||
// HTTPFirewallPolicy HTTP防火墙
|
||||
type HTTPFirewallPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Inbound string `field:"inbound"` // 入站规则
|
||||
Outbound string `field:"outbound"` // 出站规则
|
||||
BlockOptions string `field:"blockOptions"` // BLOCK选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Inbound string `field:"inbound"` // 入站规则
|
||||
Outbound string `field:"outbound"` // 出站规则
|
||||
BlockOptions string `field:"blockOptions"` // BLOCK选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||
SynFlood string `field:"synFlood"` // SynFlood防御设置
|
||||
}
|
||||
|
||||
type HTTPFirewallPolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
GroupId interface{} // 服务分组ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Inbound interface{} // 入站规则
|
||||
Outbound interface{} // 出站规则
|
||||
BlockOptions interface{} // BLOCK选项
|
||||
Mode interface{} // 模式
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
GroupId interface{} // 服务分组ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Inbound interface{} // 入站规则
|
||||
Outbound interface{} // 出站规则
|
||||
BlockOptions interface{} // BLOCK选项
|
||||
Mode interface{} // 模式
|
||||
UseLocalFirewall interface{} // 是否自动使用本地防火墙
|
||||
SynFlood interface{} // SynFlood防御设置
|
||||
}
|
||||
|
||||
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {
|
||||
|
||||
@@ -434,6 +434,18 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
}
|
||||
}
|
||||
|
||||
// 请求脚本
|
||||
if len(web.RequestScripts) > 0 {
|
||||
var requestScriptsConfig = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
if len(web.RequestScripts) > 0 {
|
||||
err = json.Unmarshal([]byte(web.RequestScripts), requestScriptsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.RequestScripts = requestScriptsConfig
|
||||
}
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
@@ -1119,6 +1131,43 @@ func (this *HTTPWebDAO) FindWebRequestLimit(tx *dbs.Tx, webId int64) (*servercon
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// UpdateWebRequestScripts 修改服务的请求脚本设置
|
||||
func (this *HTTPWebDAO) UpdateWebRequestScripts(tx *dbs.Tx, webId int64, config *serverconfigs.HTTPRequestScriptsConfig) error {
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(webId).
|
||||
Set("requestScripts", configJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// FindWebRequestScripts 查找服务的脚本设置
|
||||
func (this *HTTPWebDAO) FindWebRequestScripts(tx *dbs.Tx, webId int64) (*serverconfigs.HTTPRequestScriptsConfig, error) {
|
||||
configString, err := this.Query(tx).
|
||||
Pk(webId).
|
||||
Result("requestScripts").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
if len(configString) == 0 {
|
||||
return config, nil
|
||||
}
|
||||
err = json.Unmarshal([]byte(configString), config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
|
||||
// server
|
||||
|
||||
@@ -34,6 +34,7 @@ type HTTPWeb struct {
|
||||
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
|
||||
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
||||
RequestLimit string `field:"requestLimit"` // 请求限制
|
||||
RequestScripts string `field:"requestScripts"` // 请求脚本
|
||||
}
|
||||
|
||||
type HTTPWebOperator struct {
|
||||
@@ -69,6 +70,7 @@ type HTTPWebOperator struct {
|
||||
RemoteAddr interface{} // 客户端IP配置
|
||||
MergeSlashes interface{} // 是否合并路径中的斜杠
|
||||
RequestLimit interface{} // 请求限制
|
||||
RequestScripts interface{} // 请求脚本
|
||||
}
|
||||
|
||||
func NewHTTPWebOperator() *HTTPWebOperator {
|
||||
|
||||
@@ -2,6 +2,8 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
@@ -19,6 +21,20 @@ const (
|
||||
IPItemStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
var ticker = time.NewTicker(1 * time.Minute)
|
||||
for range ticker.C {
|
||||
err := SharedIPItemDAO.CleanExpiredIPItems(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("IPItemDAO", "clean expired ip items failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type IPItemType = string
|
||||
|
||||
const (
|
||||
@@ -156,7 +172,7 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
||||
return 0, err
|
||||
}
|
||||
|
||||
op := NewIPItemOperator()
|
||||
var op = NewIPItemOperator()
|
||||
op.ListId = listId
|
||||
op.IpFrom = ipFrom
|
||||
op.IpTo = ipTo
|
||||
@@ -179,6 +195,11 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
||||
op.SourceHTTPFirewallRuleGroupId = sourceHTTPFirewallRuleGroupId
|
||||
op.SourceHTTPFirewallRuleSetId = sourceHTTPFirewallRuleSetId
|
||||
|
||||
var autoAdded = listId == firewallconfigs.GlobalListId || sourceNodeId > 0 || sourceServerId > 0 || sourceHTTPFirewallPolicyId > 0
|
||||
if autoAdded {
|
||||
op.IsRead = 0
|
||||
}
|
||||
|
||||
op.State = IPItemStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -186,8 +207,8 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
||||
}
|
||||
itemId := types.Int64(op.Id)
|
||||
|
||||
// 全局名单不需要即时更新,防止数量过多而导致性能问题
|
||||
if listId == firewallconfigs.GlobalListId {
|
||||
// 自动加入名单不需要即时更新,防止数量过多而导致性能问题
|
||||
if autoAdded {
|
||||
return itemId, nil
|
||||
}
|
||||
|
||||
@@ -286,35 +307,6 @@ func (this *IPItemDAO) ListIPItemsWithListId(tx *dbs.Tx, listId int64, keyword s
|
||||
|
||||
// ListIPItemsAfterVersion 根据版本号查找IP列表
|
||||
func (this *IPItemDAO) ListIPItemsAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*IPItem, err error) {
|
||||
// 将过期的设置为已删除,这样是为了在 expiredAt<UNIX_TIMESTAMP()边缘节点让过期的IP有一个执行删除的机会
|
||||
ones, _, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Where("(expiredAt>0 AND expiredAt<=:timestamp)").
|
||||
Param("timestamp", time.Now().Unix()).
|
||||
State(IPItemStateEnabled).
|
||||
Limit(100).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var expiredId = one.GetInt64("id")
|
||||
newVersion, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = this.Query(tx).
|
||||
Pk(expiredId).
|
||||
Set("state", IPItemStateDisabled).
|
||||
Set("expiredAt", 0).
|
||||
Set("version", newVersion).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
// 这里不要设置状态参数,因为我们要知道哪些是删除的
|
||||
Gt("version", version).
|
||||
@@ -379,7 +371,7 @@ func (this *IPItemDAO) ExistsEnabledItem(tx *dbs.Tx, itemId int64) (bool, error)
|
||||
}
|
||||
|
||||
// CountAllEnabledIPItems 计算数量
|
||||
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64) (int64, error) {
|
||||
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
if len(ip) > 0 {
|
||||
query.Attr("ipFrom", ip)
|
||||
@@ -389,6 +381,9 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int6
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
if unread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
return query.
|
||||
State(IPItemStateEnabled).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
@@ -397,7 +392,7 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int6
|
||||
}
|
||||
|
||||
// ListAllEnabledIPItems 搜索所有IP
|
||||
func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, offset int64, size int64) (result []*IPItem, err error) {
|
||||
func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool, offset int64, size int64) (result []*IPItem, err error) {
|
||||
var query = this.Query(tx)
|
||||
if len(ip) > 0 {
|
||||
query.Attr("ipFrom", ip)
|
||||
@@ -407,6 +402,9 @@ func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
if unread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
_, err = query.
|
||||
State(IPItemStateEnabled).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
@@ -419,6 +417,59 @@ func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateItemsRead 设置所有未已读
|
||||
func (this *IPItemDAO) UpdateItemsRead(tx *dbs.Tx) error {
|
||||
return this.Query(tx).
|
||||
Attr("isRead", 0).
|
||||
Set("isRead", 1).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CleanExpiredIPItems 清除过期数据
|
||||
func (this *IPItemDAO) CleanExpiredIPItems(tx *dbs.Tx) error {
|
||||
// 删除 N 天之前过期的数据
|
||||
_, err := this.Query(tx).
|
||||
Where("expiredAt<=:timestamp").
|
||||
State(IPItemStateDisabled).
|
||||
Param("timestamp", time.Now().Unix()-7*86400). // N 天之前过期的
|
||||
Limit(10000). // 限制条数,防止数量过多导致超时
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将过期的设置为已删除,这样是为了在 expiredAt<UNIX_TIMESTAMP()边缘节点让过期的IP有一个执行删除的机会
|
||||
ones, _, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Where("(expiredAt>0 AND expiredAt<=:timestamp)").
|
||||
Param("timestamp", time.Now().Unix()).
|
||||
State(IPItemStateEnabled).
|
||||
Limit(500).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var expiredId = one.GetInt64("id")
|
||||
newVersion, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 这里不重置过期时间用于清理
|
||||
_, err = this.Query(tx).
|
||||
Pk(expiredId).
|
||||
Set("state", IPItemStateDisabled).
|
||||
Set("version", newVersion).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
// 获取ListId
|
||||
@@ -445,7 +496,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -453,7 +504,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
} else {
|
||||
clusterIds, err := SharedNodeClusterDAO.FindAllEnabledNodeClusterIds(tx)
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -505,7 +556,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
|
||||
if len(resultClusterIds) > 0 {
|
||||
for _, clusterId := range resultClusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
||||
@@ -27,3 +31,34 @@ func TestIPItemDAO_DisableIPItemsWithListId(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_ListIPItemsAfterVersion(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
_, err := SharedIPItemDAO.ListIPItemsAfterVersion(tx, 0, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_CreateManyIPs(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
var dao = NewIPItemDAO()
|
||||
var n = 10
|
||||
for i := 0; i < n; i++ {
|
||||
itemId, err := dao.CreateIPItem(tx, firewallconfigs.GlobalListId, "192."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255)), "", time.Now().Unix()+86400, "test", IPItemTypeIPv4, "warning", 0, 0, 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = itemId
|
||||
/**err = dao.Query(tx).Pk(itemId).Set("state", 0).UpdateQuickly()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}**/
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type IPItem struct {
|
||||
SourceHTTPFirewallPolicyId uint32 `field:"sourceHTTPFirewallPolicyId"` // 来源策略ID
|
||||
SourceHTTPFirewallRuleGroupId uint32 `field:"sourceHTTPFirewallRuleGroupId"` // 来源规则集分组ID
|
||||
SourceHTTPFirewallRuleSetId uint32 `field:"sourceHTTPFirewallRuleSetId"` // 来源规则集ID
|
||||
IsRead uint8 `field:"isRead"` // 是否已读
|
||||
}
|
||||
|
||||
type IPItemOperator struct {
|
||||
@@ -47,6 +48,7 @@ type IPItemOperator struct {
|
||||
SourceHTTPFirewallPolicyId interface{} // 来源策略ID
|
||||
SourceHTTPFirewallRuleGroupId interface{} // 来源规则集分组ID
|
||||
SourceHTTPFirewallRuleSetId interface{} // 来源规则集ID
|
||||
IsRead interface{} // 是否已读
|
||||
}
|
||||
|
||||
func NewIPItemOperator() *IPItemOperator {
|
||||
|
||||
@@ -284,7 +284,7 @@ func (this *IPListDAO) NotifyUpdate(tx *dbs.Tx, listId int64, taskType NodeTaskT
|
||||
|
||||
if len(resultClusterIds) > 0 {
|
||||
for _, clusterId := range resultClusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, taskType)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, taskType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ func (this *MetricItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64, isPublic bool)
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -346,7 +346,7 @@ func (this *MetricItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64, isPublic bool)
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ func (this *NSDomainDAO) NotifyUpdate(tx *dbs.Tx, domainId int64) error {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
return models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeDomainChanged)
|
||||
return models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeDomainChanged)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -199,7 +199,7 @@ func (this *NSKeyDAO) NotifyUpdate(tx *dbs.Tx, keyId int64) error {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeKeyChanged)
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeKeyChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ func (this *NSRecordDAO) NotifyUpdate(tx *dbs.Tx, recordId int64) error {
|
||||
}
|
||||
|
||||
if clusterId > 0 {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeRecordChanged)
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeRecordChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func (this *NSRouteDAO) NotifyUpdate(tx *dbs.Tx) error {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeRouteChanged)
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeRouteChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
}
|
||||
|
||||
// UpdateCluster 修改集群
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, nodeTCPMaxConnections int32) error {
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, nodeTCPMaxConnections int32, autoOpenPorts bool) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -198,6 +198,7 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
|
||||
nodeTCPMaxConnections = 0
|
||||
}
|
||||
op.NodeTCPMaxConnections = nodeTCPMaxConnections
|
||||
op.AutoOpenPorts = autoOpenPorts
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -274,7 +275,7 @@ func (this *NodeClusterDAO) FindAllAPINodeAddrsWithCluster(tx *dbs.Tx, clusterId
|
||||
return nil, err
|
||||
}
|
||||
for _, apiNodeId := range apiNodeIds {
|
||||
apiNode, err := SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId)
|
||||
apiNode, err := SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -887,7 +888,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
||||
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId").
|
||||
Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts").
|
||||
Find()
|
||||
if err != nil || cluster == nil {
|
||||
return nil, err
|
||||
@@ -900,7 +901,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
}
|
||||
|
||||
// NotifyDNSUpdate 通知DNS更新
|
||||
|
||||
@@ -177,5 +177,5 @@ func (this *NodeClusterMetricItemDAO) ExistsClusterItem(tx *dbs.Tx, clusterId in
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterMetricItemDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ type NodeCluster struct {
|
||||
TimeZone string `field:"timeZone"` // 时区
|
||||
NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数
|
||||
NodeTCPMaxConnections uint32 `field:"nodeTCPMaxConnections"` // TCP最大连接数
|
||||
AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口
|
||||
}
|
||||
|
||||
type NodeClusterOperator struct {
|
||||
@@ -59,6 +60,7 @@ type NodeClusterOperator struct {
|
||||
TimeZone interface{} // 时区
|
||||
NodeMaxThreads interface{} // 节点最大线程数
|
||||
NodeTCPMaxConnections interface{} // TCP最大连接数
|
||||
AutoOpenPorts interface{} // 是否自动尝试开放端口
|
||||
}
|
||||
|
||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||
|
||||
@@ -518,11 +518,11 @@ func (this *NodeDAO) FindAllEnabledNodeIdsWithClusterId(tx *dbs.Tx, clusterId in
|
||||
func (this *NodeDAO) FindAllInactiveNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Result("id", "name", "status").
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("isOn", true). // 只监控启用的节点
|
||||
Attr("isInstalled", true). // 只监控已经安装的节点
|
||||
Attr("isActive", true). // 当前已经在线的
|
||||
Where("(status IS NULL OR (JSON_EXTRACT(status, '$.isActive')=false AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>10) OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>120)").
|
||||
Attr("isActive", false).
|
||||
Result("id", "name").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
@@ -827,6 +827,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
if clusterIndex == 0 {
|
||||
config.MaxThreads = int(nodeCluster.NodeMaxThreads)
|
||||
config.TCPMaxConnections = int(nodeCluster.NodeTCPMaxConnections)
|
||||
config.AutoOpenPorts = nodeCluster.AutoOpenPorts == 1
|
||||
}
|
||||
|
||||
clusterIndex++
|
||||
@@ -916,6 +917,18 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
|
||||
config.MetricItems = metricItems
|
||||
|
||||
// 产品
|
||||
adminUIConfig, err := SharedSysSettingDAO.ReadAdminUIConfig(tx, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if adminUIConfig != nil {
|
||||
config.ProductConfig = &nodeconfigs.ProductConfig{
|
||||
Name: adminUIConfig.ProductName,
|
||||
Version: adminUIConfig.Version,
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -1458,7 +1471,7 @@ func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, NodeTaskTypeConfigChanged, 0)
|
||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeConfigChanged, 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package models
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ func (this *NodeLogDAO) DeleteExpiredLogs(tx *dbs.Tx, days int) error {
|
||||
// CountNodeLogs 计算节点日志数量
|
||||
func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
role string,
|
||||
nodeClusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
originId int64,
|
||||
@@ -142,7 +143,8 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
dayTo string,
|
||||
keyword string,
|
||||
level string,
|
||||
isUnread bool) (int64, error) {
|
||||
isUnread bool,
|
||||
tag string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if len(role) > 0 {
|
||||
query.Attr("role", role)
|
||||
@@ -150,11 +152,16 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId > 0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
if nodeClusterId > 0 {
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE clusterId=:nodeClusterId AND state=1)")
|
||||
query.Param("nodeClusterId", nodeClusterId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId > 0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
}
|
||||
}
|
||||
}
|
||||
if serverId > 0 {
|
||||
@@ -181,6 +188,9 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
if isUnread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
if len(tag) > 0 {
|
||||
query.Like("tag", "%"+tag+"%")
|
||||
}
|
||||
|
||||
return query.Count()
|
||||
}
|
||||
@@ -188,6 +198,7 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
// ListNodeLogs 列出单页日志
|
||||
func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
role string,
|
||||
nodeClusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
originId int64,
|
||||
@@ -198,6 +209,7 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
level string,
|
||||
fixedState configutils.BoolState,
|
||||
isUnread bool,
|
||||
tag string,
|
||||
offset int64,
|
||||
size int64) (result []*NodeLog, err error) {
|
||||
query := this.Query(tx)
|
||||
@@ -207,11 +219,16 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId>0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
if nodeClusterId > 0 {
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE clusterId=:nodeClusterId AND state=1)")
|
||||
query.Param("nodeClusterId", nodeClusterId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId>0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
}
|
||||
}
|
||||
}
|
||||
if serverId > 0 {
|
||||
@@ -240,11 +257,19 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
}
|
||||
if len(level) > 0 {
|
||||
query.Attr("level", level)
|
||||
var pieces = strings.Split(level, ",")
|
||||
if len(pieces) == 1 {
|
||||
query.Attr("level", pieces[0])
|
||||
} else {
|
||||
query.Attr("level", pieces)
|
||||
}
|
||||
}
|
||||
if isUnread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
if len(tag) > 0 {
|
||||
query.Like("tag", "%"+tag+"%")
|
||||
}
|
||||
_, err = query.
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package models
|
||||
|
||||
// 区域计费设置
|
||||
// NodePriceItem 区域计费设置
|
||||
type NodePriceItem struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package models
|
||||
|
||||
// 节点区域
|
||||
// NodeRegion 节点区域
|
||||
type NodeRegion struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
func (this *NodeRegion) DecodePriceMap() map[int64]float64 {
|
||||
var m = map[int64]float64{}
|
||||
if len(this.Prices) == 0 {
|
||||
return m
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(this.Prices), &m)
|
||||
if err != nil {
|
||||
// 忽略错误
|
||||
return m
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func init() {
|
||||
}
|
||||
|
||||
// CreateNodeTask 创建单个节点任务
|
||||
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, taskType NodeTaskType, version int64) error {
|
||||
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, serverId int64, taskType NodeTaskType, version int64) error {
|
||||
if clusterId <= 0 || nodeId <= 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -60,6 +60,7 @@ func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64
|
||||
"role": role,
|
||||
"clusterId": clusterId,
|
||||
"nodeId": nodeId,
|
||||
"serverId": serverId,
|
||||
"type": taskType,
|
||||
"uniqueId": uniqueId,
|
||||
"updatedAt": updatedAt,
|
||||
@@ -80,17 +81,18 @@ func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64
|
||||
}
|
||||
|
||||
// CreateClusterTask 创建集群任务
|
||||
func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId int64, taskType NodeTaskType) error {
|
||||
func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId int64, serverId int64, taskType NodeTaskType) error {
|
||||
if clusterId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
uniqueId := role + "@" + types.String(clusterId) + "@cluster@" + taskType
|
||||
uniqueId := role + "@" + types.String(clusterId) + "@" + types.String(serverId) + "@cluster@" + taskType
|
||||
updatedAt := time.Now().Unix()
|
||||
_, _, err := this.Query(tx).
|
||||
InsertOrUpdate(maps.Map{
|
||||
"role": role,
|
||||
"clusterId": clusterId,
|
||||
"serverId": serverId,
|
||||
"nodeId": 0,
|
||||
"type": taskType,
|
||||
"uniqueId": uniqueId,
|
||||
@@ -112,7 +114,7 @@ func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId in
|
||||
}
|
||||
|
||||
// ExtractNodeClusterTask 分解边缘节点集群任务
|
||||
func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, taskType NodeTaskType) error {
|
||||
func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, serverId int64, taskType NodeTaskType) error {
|
||||
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, clusterId, true, configutils.BoolStateYes)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -131,7 +133,7 @@ func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, tas
|
||||
|
||||
var version = time.Now().UnixNano()
|
||||
for _, nodeId := range nodeIds {
|
||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, taskType, version)
|
||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, serverId, taskType, version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -170,7 +172,7 @@ func (this *NodeTaskDAO) ExtractNSClusterTask(tx *dbs.Tx, clusterId int64, taskT
|
||||
|
||||
var version = time.Now().UnixNano()
|
||||
for _, nodeId := range nodeIds {
|
||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleDNS, clusterId, nodeId, taskType, version)
|
||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleDNS, clusterId, nodeId, 0, taskType, version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -202,7 +204,8 @@ func (this *NodeTaskDAO) ExtractAllClusterTasks(tx *dbs.Tx, role string) error {
|
||||
clusterId := int64(one.(*NodeTask).ClusterId)
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
err = this.ExtractNodeClusterTask(tx, clusterId, one.(*NodeTask).Type)
|
||||
var nodeTask = one.(*NodeTask)
|
||||
err = this.ExtractNodeClusterTask(tx, clusterId, int64(nodeTask.ServerId), nodeTask.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ func TestNodeTaskDAO_CreateNodeTask(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, 1, 2, NodeTaskTypeConfigChanged, 0)
|
||||
err := SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, 1, 2, 0, NodeTaskTypeConfigChanged, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func TestNodeTaskDAO_CreateClusterTask(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, 1, NodeTaskTypeConfigChanged)
|
||||
err := SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, 1, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func TestNodeTaskDAO_ExtractClusterTask(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedNodeTaskDAO.ExtractNodeClusterTask(tx, 1, NodeTaskTypeConfigChanged)
|
||||
err := SharedNodeTaskDAO.ExtractNodeClusterTask(tx, 1, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ type NodeTask struct {
|
||||
Role string `field:"role"` // 节点角色
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
Type string `field:"type"` // 任务类型
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID:nodeId@type
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
@@ -21,6 +22,7 @@ type NodeTaskOperator struct {
|
||||
Role interface{} // 节点角色
|
||||
NodeId interface{} // 节点ID
|
||||
ClusterId interface{} // 集群ID
|
||||
ServerId interface{} // 服务ID
|
||||
Type interface{} // 任务类型
|
||||
UniqueId interface{} // 唯一ID:nodeId@type
|
||||
UpdatedAt interface{} // 修改时间
|
||||
|
||||
@@ -57,12 +57,10 @@ func (this *NodeValueDAO) CreateValue(tx *dbs.Tx, clusterId int64, role nodeconf
|
||||
|
||||
// Clean 清除数据
|
||||
func (this *NodeValueDAO) Clean(tx *dbs.Tx) error {
|
||||
// 删除N天之前的所有数据
|
||||
expiredDays := 2
|
||||
day := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -expiredDays))
|
||||
var hour = timeutil.Format("YmdH", time.Now().Add(-2*time.Hour))
|
||||
_, err := this.Query(tx).
|
||||
Where("day<=:day").
|
||||
Param("day", day).
|
||||
Where("hour<=:hour").
|
||||
Param("hour", hour).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestNodeValueDAO_CreateValue(t *testing.T) {
|
||||
dao := NewNodeValueDAO()
|
||||
var dao = NewNodeValueDAO()
|
||||
m := maps.Map{
|
||||
"hello": "world12344",
|
||||
}
|
||||
@@ -20,3 +20,12 @@ func TestNodeValueDAO_CreateValue(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestNodeValueDAO_Clean(t *testing.T) {
|
||||
var dao = NewNodeValueDAO()
|
||||
err := dao.Clean(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -195,5 +195,5 @@ func (this *NSClusterDAO) FindClusterRecursion(tx *dbs.Tx, clusterId int64) ([]b
|
||||
|
||||
// NotifyUpdate 通知更改
|
||||
func (this *NSClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, NSNodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, NSNodeTaskTypeConfigChanged)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,20 @@ func (this *OriginDAO) FindOriginName(tx *dbs.Tx, id int64) (string, error) {
|
||||
}
|
||||
|
||||
// CreateOrigin 创建源站
|
||||
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32, domains []string) (originId int64, err error) {
|
||||
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
adminId int64,
|
||||
userId int64,
|
||||
name string,
|
||||
addrJSON string,
|
||||
description string,
|
||||
weight int32, isOn bool,
|
||||
connTimeout *shared.TimeDuration,
|
||||
readTimeout *shared.TimeDuration,
|
||||
idleTimeout *shared.TimeDuration,
|
||||
maxConns int32,
|
||||
maxIdleConns int32,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string) (originId int64, err error) {
|
||||
op := NewOriginOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
@@ -133,6 +146,15 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
||||
}
|
||||
op.Weight = weight
|
||||
|
||||
// cert
|
||||
if certRef != nil {
|
||||
certRefJSON, err := json.Marshal(certRef)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Cert = certRefJSON
|
||||
}
|
||||
|
||||
if len(domains) > 0 {
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
@@ -152,7 +174,20 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
||||
}
|
||||
|
||||
// UpdateOrigin 修改源站
|
||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32, domains []string) error {
|
||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
originId int64,
|
||||
name string,
|
||||
addrJSON string,
|
||||
description string,
|
||||
weight int32,
|
||||
isOn bool,
|
||||
connTimeout *shared.TimeDuration,
|
||||
readTimeout *shared.TimeDuration,
|
||||
idleTimeout *shared.TimeDuration,
|
||||
maxConns int32,
|
||||
maxIdleConns int32,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string) error {
|
||||
if originId <= 0 {
|
||||
return errors.New("invalid originId")
|
||||
}
|
||||
@@ -201,6 +236,17 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, add
|
||||
op.IsOn = isOn
|
||||
op.Version = dbs.SQL("version+1")
|
||||
|
||||
// cert
|
||||
if certRef != nil {
|
||||
certRefJSON, err := json.Marshal(certRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Cert = certRefJSON
|
||||
} else {
|
||||
op.Cert = dbs.SQL("NULL")
|
||||
}
|
||||
|
||||
if len(domains) > 0 {
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
|
||||
@@ -80,7 +80,17 @@ func (this *PlanDAO) FindPlanName(tx *dbs.Tx, id int64) (string, error) {
|
||||
}
|
||||
|
||||
// CreatePlan 创建套餐
|
||||
func (this *PlanDAO) CreatePlan(tx *dbs.Tx, name string, clusterId int64, trafficLimitJSON []byte, featuresJSON []byte, priceType serverconfigs.PlanPriceType, trafficPriceJSON []byte, monthlyPrice float32, seasonallyPrice float32, yearlyPrice float32) (int64, error) {
|
||||
func (this *PlanDAO) CreatePlan(tx *dbs.Tx,
|
||||
name string,
|
||||
clusterId int64,
|
||||
trafficLimitJSON []byte,
|
||||
featuresJSON []byte,
|
||||
priceType serverconfigs.PlanPriceType,
|
||||
trafficPriceJSON []byte,
|
||||
bandwidthPriceJSON []byte,
|
||||
monthlyPrice float32,
|
||||
seasonallyPrice float32,
|
||||
yearlyPrice float32) (int64, error) {
|
||||
var op = NewPlanOperator()
|
||||
op.Name = name
|
||||
op.ClusterId = clusterId
|
||||
@@ -94,6 +104,9 @@ func (this *PlanDAO) CreatePlan(tx *dbs.Tx, name string, clusterId int64, traffi
|
||||
if len(trafficPriceJSON) > 0 {
|
||||
op.TrafficPrice = trafficPriceJSON
|
||||
}
|
||||
if len(bandwidthPriceJSON) > 0 {
|
||||
op.BandwidthPrice = bandwidthPriceJSON
|
||||
}
|
||||
if monthlyPrice >= 0 {
|
||||
op.MonthlyPrice = monthlyPrice
|
||||
}
|
||||
@@ -109,7 +122,19 @@ func (this *PlanDAO) CreatePlan(tx *dbs.Tx, name string, clusterId int64, traffi
|
||||
}
|
||||
|
||||
// UpdatePlan 修改套餐
|
||||
func (this *PlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool, clusterId int64, trafficLimitJSON []byte, featuresJSON []byte, priceType serverconfigs.PlanPriceType, trafficPriceJSON []byte, monthlyPrice float32, seasonallyPrice float32, yearlyPrice float32) error {
|
||||
func (this *PlanDAO) UpdatePlan(tx *dbs.Tx,
|
||||
planId int64,
|
||||
name string,
|
||||
isOn bool,
|
||||
clusterId int64,
|
||||
trafficLimitJSON []byte,
|
||||
featuresJSON []byte,
|
||||
priceType serverconfigs.PlanPriceType,
|
||||
trafficPriceJSON []byte,
|
||||
bandwidthPriceJSON []byte,
|
||||
monthlyPrice float32,
|
||||
seasonallyPrice float32,
|
||||
yearlyPrice float32) error {
|
||||
if planId <= 0 {
|
||||
return errors.New("invalid planId")
|
||||
}
|
||||
@@ -138,6 +163,9 @@ func (this *PlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool
|
||||
if len(trafficPriceJSON) > 0 {
|
||||
op.TrafficPrice = trafficPriceJSON
|
||||
}
|
||||
if len(bandwidthPriceJSON) > 0 {
|
||||
op.BandwidthPrice = bandwidthPriceJSON
|
||||
}
|
||||
if monthlyPrice >= 0 {
|
||||
op.MonthlyPrice = monthlyPrice
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@ type Plan struct {
|
||||
TrafficLimit string `field:"trafficLimit"` // 流量限制
|
||||
Features string `field:"features"` // 允许的功能
|
||||
TrafficPrice string `field:"trafficPrice"` // 流量价格设定
|
||||
BandwidthPrice string `field:"bandwidthPrice"` // 带宽价格
|
||||
MonthlyPrice float64 `field:"monthlyPrice"` // 月付
|
||||
SeasonallyPrice float64 `field:"seasonallyPrice"` // 季付
|
||||
YearlyPrice float64 `field:"yearlyPrice"` // 年付
|
||||
@@ -25,6 +26,7 @@ type PlanOperator struct {
|
||||
TrafficLimit interface{} // 流量限制
|
||||
Features interface{} // 允许的功能
|
||||
TrafficPrice interface{} // 流量价格设定
|
||||
BandwidthPrice interface{} // 带宽价格
|
||||
MonthlyPrice interface{} // 月付
|
||||
SeasonallyPrice interface{} // 季付
|
||||
YearlyPrice interface{} // 年付
|
||||
|
||||
@@ -1 +1,38 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
)
|
||||
|
||||
// DecodeTrafficPrice 流量价格配置
|
||||
func (this *Plan) DecodeTrafficPrice() *serverconfigs.PlanTrafficPriceConfig {
|
||||
var config = &serverconfigs.PlanTrafficPriceConfig{}
|
||||
|
||||
if len(this.TrafficPrice) == 0 {
|
||||
return config
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(this.TrafficPrice), config)
|
||||
if err != nil {
|
||||
// 忽略错误
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// DecodeBandwidthPrice 带宽价格配置
|
||||
func (this *Plan) DecodeBandwidthPrice() *serverconfigs.PlanBandwidthPriceConfig {
|
||||
var config = &serverconfigs.PlanBandwidthPriceConfig{}
|
||||
|
||||
if len(this.BandwidthPrice) == 0 {
|
||||
return config
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(this.BandwidthPrice), config)
|
||||
if err != nil {
|
||||
// 忽略错误
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableRegionCity 启用条目
|
||||
func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -47,7 +47,7 @@ func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableRegionCity 禁用条目
|
||||
func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -56,7 +56,7 @@ func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledRegionCity 查找启用中的条目
|
||||
func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionCity, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -68,7 +68,7 @@ func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionC
|
||||
return result.(*RegionCity), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindRegionCityName 根据主键查找名称
|
||||
func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -76,7 +76,7 @@ func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, er
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 根据数据ID查找城市
|
||||
// FindCityWithDataId 根据数据ID查找城市
|
||||
func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("dataId", dataId).
|
||||
@@ -84,7 +84,7 @@ func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64,
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// 创建城市
|
||||
// CreateCity 创建城市
|
||||
func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string, dataId string) (int64, error) {
|
||||
op := NewRegionCityOperator()
|
||||
op.ProvinceId = provinceId
|
||||
@@ -105,7 +105,7 @@ func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string,
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 根据城市名查找城市ID
|
||||
// FindCityIdWithNameCacheable 根据城市名查找城市ID
|
||||
func (this *RegionCityDAO) FindCityIdWithNameCacheable(tx *dbs.Tx, provinceId int64, cityName string) (int64, error) {
|
||||
key := cityName + "@" + numberutils.FormatInt64(provinceId)
|
||||
|
||||
@@ -132,3 +132,12 @@ func (this *RegionCityDAO) FindCityIdWithNameCacheable(tx *dbs.Tx, provinceId in
|
||||
|
||||
return cityId, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledCities 获取所有城市信息
|
||||
func (this *RegionCityDAO) FindAllEnabledCities(tx *dbs.Tx) (result []*RegionCity, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(RegionCityStateEnabled).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package regions
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
)
|
||||
|
||||
func (this *RegionCity) DecodeCodes() []string {
|
||||
if len(this.Codes) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
result := []string{}
|
||||
err := json.Unmarshal([]byte(this.Codes), &result)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableRegionProvider 启用条目
|
||||
func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -45,7 +45,7 @@ func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableRegionProvider 禁用条目
|
||||
func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -54,8 +54,8 @@ func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) erro
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id uint32) (*RegionProvider, error) {
|
||||
// FindEnabledRegionProvider 查找启用中的条目
|
||||
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (*RegionProvider, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", RegionProviderStateEnabled).
|
||||
@@ -66,7 +66,7 @@ func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id uint32)
|
||||
return result.(*RegionProvider), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindRegionProviderName 根据主键查找名称
|
||||
func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -74,7 +74,7 @@ func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (st
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 根据服务商名称查找服务商ID
|
||||
// FindProviderIdWithNameCacheable 根据服务商名称查找服务商ID
|
||||
func (this *RegionProviderDAO) FindProviderIdWithNameCacheable(tx *dbs.Tx, providerName string) (int64, error) {
|
||||
SharedCacheLocker.RLock()
|
||||
providerId, ok := regionProviderNameAndIdCacheMap[providerName]
|
||||
@@ -100,7 +100,7 @@ func (this *RegionProviderDAO) FindProviderIdWithNameCacheable(tx *dbs.Tx, provi
|
||||
return providerId, nil
|
||||
}
|
||||
|
||||
// 创建Provider
|
||||
// CreateProvider 创建Provider
|
||||
func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, error) {
|
||||
op := NewRegionProviderOperator()
|
||||
op.Name = name
|
||||
@@ -112,3 +112,12 @@ func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, e
|
||||
op.Codes = codesJSON
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// FindAllEnabledProviders 查找所有服务商
|
||||
func (this *RegionProviderDAO) FindAllEnabledProviders(tx *dbs.Tx) (result []*RegionProvider, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(RegionProviderStateEnabled).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package regions
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
)
|
||||
|
||||
func (this *RegionProvider) DecodeCodes() []string {
|
||||
if len(this.Codes) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
result := []string{}
|
||||
err := json.Unmarshal([]byte(this.Codes), &result)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
108
internal/db/models/server_bill_dao.go
Normal file
108
internal/db/models/server_bill_dao.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ServerBillDAO dbs.DAO
|
||||
|
||||
func NewServerBillDAO() *ServerBillDAO {
|
||||
return dbs.NewDAO(&ServerBillDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeServerBills",
|
||||
Model: new(ServerBill),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*ServerBillDAO)
|
||||
}
|
||||
|
||||
var SharedServerBillDAO *ServerBillDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedServerBillDAO = NewServerBillDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOrUpdateServerBill 创建账单
|
||||
func (this *ServerBillDAO) CreateOrUpdateServerBill(tx *dbs.Tx,
|
||||
userId int64,
|
||||
serverId int64,
|
||||
month string,
|
||||
userPlanId int64,
|
||||
planId int64,
|
||||
totalTrafficBytes int64,
|
||||
bandwidthPercentileBytes int64,
|
||||
bandwidthPercentile int,
|
||||
priceType string,
|
||||
fee float64) error {
|
||||
fee = math.Floor(fee*100) / 100
|
||||
return this.Query(tx).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"serverId": serverId,
|
||||
"month": month,
|
||||
"priceType": priceType,
|
||||
"amount": fee,
|
||||
"userPlanId": userPlanId,
|
||||
"planId": planId,
|
||||
"totalTrafficBytes": totalTrafficBytes,
|
||||
"bandwidthPercentileBytes": bandwidthPercentileBytes,
|
||||
"bandwidthPercentile": bandwidthPercentile,
|
||||
"createdAt": time.Now().Unix(),
|
||||
}, maps.Map{
|
||||
"userId": userId,
|
||||
"priceType": priceType,
|
||||
"amount": fee,
|
||||
"userPlanId": userPlanId,
|
||||
"planId": planId,
|
||||
"totalTrafficBytes": totalTrafficBytes,
|
||||
"bandwidthPercentileBytes": bandwidthPercentileBytes,
|
||||
"bandwidthPercentile": bandwidthPercentile,
|
||||
"createdAt": time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
// SumUserMonthlyAmount 计算总费用
|
||||
func (this *ServerBillDAO) SumUserMonthlyAmount(tx *dbs.Tx, userId int64, month string) (float64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("month", month).
|
||||
Sum("amount", 0)
|
||||
}
|
||||
|
||||
// CountServerBills 计算总账单数量
|
||||
func (this *ServerBillDAO) CountServerBills(tx *dbs.Tx, userId int64, month string) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if len(month) > 0 {
|
||||
query.Attr("month", month)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListServerBills 列出单页账单
|
||||
func (this *ServerBillDAO) ListServerBills(tx *dbs.Tx, userId int64, month string, offset int64, size int64) (result []*ServerBill, err error) {
|
||||
var query = this.Query(tx)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if len(month) > 0 {
|
||||
query.Attr("month", month)
|
||||
}
|
||||
_, err = query.
|
||||
Desc("serverId").
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
20
internal/db/models/server_bill_dao_test.go
Normal file
20
internal/db/models/server_bill_dao_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServerBillDAO_CreateOrUpdateServerBill(t *testing.T) {
|
||||
var dao = NewServerBillDAO()
|
||||
var tx *dbs.Tx
|
||||
var month = timeutil.Format("Y02")
|
||||
err := dao.CreateOrUpdateServerBill(tx, 1, 2, month, 4, 5, 6, 7, 95, "", 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
36
internal/db/models/server_bill_model.go
Normal file
36
internal/db/models/server_bill_model.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package models
|
||||
|
||||
// ServerBill 服务账单
|
||||
type ServerBill struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
Amount float64 `field:"amount"` // 金额
|
||||
Month string `field:"month"` // 月份
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UserPlanId uint32 `field:"userPlanId"` // 用户套餐ID
|
||||
PlanId uint32 `field:"planId"` // 套餐ID
|
||||
TotalTrafficBytes uint64 `field:"totalTrafficBytes"` // 总流量
|
||||
BandwidthPercentileBytes uint64 `field:"bandwidthPercentileBytes"` // 带宽百分位字节
|
||||
BandwidthPercentile uint8 `field:"bandwidthPercentile"` // 带宽百分位
|
||||
PriceType string `field:"priceType"` // 计费类型
|
||||
}
|
||||
|
||||
type ServerBillOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
Amount interface{} // 金额
|
||||
Month interface{} // 月份
|
||||
CreatedAt interface{} // 创建时间
|
||||
UserPlanId interface{} // 用户套餐ID
|
||||
PlanId interface{} // 套餐ID
|
||||
TotalTrafficBytes interface{} // 总流量
|
||||
BandwidthPercentileBytes interface{} // 带宽百分位字节
|
||||
BandwidthPercentile interface{} // 带宽百分位
|
||||
PriceType interface{} // 计费类型
|
||||
}
|
||||
|
||||
func NewServerBillOperator() *ServerBillOperator {
|
||||
return &ServerBillOperator{}
|
||||
}
|
||||
1
internal/db/models/server_bill_model_ext.go
Normal file
1
internal/db/models/server_bill_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -12,7 +12,9 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -24,7 +26,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerDailyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
err := SharedServerDailyStatDAO.Clean(nil, 60) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
|
||||
if err != nil {
|
||||
logs.Println("ServerDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -130,15 +132,15 @@ func (this *ServerDailyStatDAO) SaveStats(tx *dbs.Tx, stats []*pb.ServerDailySta
|
||||
return nil
|
||||
}
|
||||
|
||||
// SumUserMonthly 根据用户计算某月合计
|
||||
// SumServerMonthlyWithRegion 根据服务计算某月合计
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumUserMonthly(tx *dbs.Tx, userId int64, regionId int64, month string) (int64, error) {
|
||||
func (this *ServerDailyStatDAO) SumServerMonthlyWithRegion(tx *dbs.Tx, serverId int64, regionId int64, month string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
return query.Between("day", month+"01", month+"32").
|
||||
Attr("userId", userId).
|
||||
Attr("serverId", serverId).
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
@@ -156,16 +158,6 @@ func (this *ServerDailyStatDAO) SumUserMonthlyWithoutPlan(tx *dbs.Tx, userId int
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
// SumUserMonthlyFee 计算用户某个月费用
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumUserMonthlyFee(tx *dbs.Tx, userId int64, month string) (float64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Between("day", month+"01", month+"32").
|
||||
Gt("fee", 0).
|
||||
Sum("fee", 0)
|
||||
}
|
||||
|
||||
// SumUserMonthlyPeek 获取某月带宽峰值
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumUserMonthlyPeek(tx *dbs.Tx, userId int64, regionId int64, month string) (int64, error) {
|
||||
@@ -195,6 +187,15 @@ func (this *ServerDailyStatDAO) SumUserDaily(tx *dbs.Tx, userId int64, regionId
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
// SumUserMonthly 获取某月流量总和
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumUserMonthly(tx *dbs.Tx, userId int64, month string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Between("day", month+"01", month+"31").
|
||||
Attr("userId", userId).
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
// SumUserDailyPeek 获取某天带宽峰值
|
||||
// day 格式为YYYYMMDD
|
||||
func (this *ServerDailyStatDAO) SumUserDailyPeek(tx *dbs.Tx, userId int64, regionId int64, day string) (int64, error) {
|
||||
@@ -339,6 +340,59 @@ func (this *ServerDailyStatDAO) SumMonthlyStat(tx *dbs.Tx, serverId int64, month
|
||||
return
|
||||
}
|
||||
|
||||
// SumMonthlyBytes 获取某月内的流量
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumMonthlyBytes(tx *dbs.Tx, serverId int64, month string) (result int64, err error) {
|
||||
if !regexp.MustCompile(`^\d{6}$`).MatchString(month) {
|
||||
return
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Result("SUM(bytes) AS bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *ServerDailyStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
|
||||
total, err := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var offset int64
|
||||
|
||||
if total > 1 {
|
||||
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||
}
|
||||
result, err = this.Query(tx).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Offset(offset).
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
|
||||
// 因为是5分钟统计,所以需要除以300
|
||||
result = result / 300
|
||||
return
|
||||
}
|
||||
|
||||
// FindDailyStats 按天统计
|
||||
func (this *ServerDailyStatDAO) FindDailyStats(tx *dbs.Tx, serverId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
@@ -428,6 +482,25 @@ func (this *ServerDailyStatDAO) FindTopUserStats(tx *dbs.Tx, hourFrom string, ho
|
||||
return
|
||||
}
|
||||
|
||||
// FindDistinctServerIds 查找所有有流量的服务ID列表
|
||||
// dayFrom YYYYMMDD
|
||||
// dayTo YYYYMMDD
|
||||
func (this *ServerDailyStatDAO) FindDistinctServerIds(tx *dbs.Tx, dayFrom string, dayTo string) (serverIds []int64, err error) {
|
||||
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||
dayTo = strings.ReplaceAll(dayTo, "-", "")
|
||||
ones, _, err := this.Query(tx).
|
||||
Result("DISTINCT(serverId) AS serverId").
|
||||
Between("day", dayFrom, dayTo).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
serverIds = append(serverIds, one.GetInt64("serverId"))
|
||||
}
|
||||
return serverIds, nil
|
||||
}
|
||||
|
||||
// UpdateStatFee 设置费用
|
||||
func (this *ServerDailyStatDAO) UpdateStatFee(tx *dbs.Tx, statId int64, fee float32) error {
|
||||
return this.Query(tx).
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestServerDailyStatDAO_SaveStats2(t *testing.T) {
|
||||
func TestServerDailyStatDAO_SumUserMonthly(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
bytes, err := NewServerDailyStatDAO().SumUserMonthly(tx, 1, 1, timeutil.Format("Ym"))
|
||||
bytes, err := NewServerDailyStatDAO().SumUserMonthly(tx, 1, timeutil.Format("Ym"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -68,9 +68,28 @@ func TestServerDailyStatDAO_SumMinutelyRequests(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
|
||||
stat, err := NewServerDailyStatDAO().SumMinutelyStat(tx, 23, timeutil.Format("Ymd") + "1435")
|
||||
stat, err := NewServerDailyStatDAO().SumMinutelyStat(tx, 23, timeutil.Format("Ymd")+"1435")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
logs.PrintAsJSON(stat, t)
|
||||
}
|
||||
|
||||
func TestServerDailyStatDAO_FindDistinctPlanServerIdsBetweenDay(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
serverIds, err := NewServerDailyStatDAO().FindDistinctServerIds(tx, timeutil.Format("Ym01"), timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(serverIds)
|
||||
}
|
||||
|
||||
func TestServerDailyStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
var dao = NewServerDailyStatDAO()
|
||||
result, err := dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("result:", result)
|
||||
}
|
||||
|
||||
@@ -221,6 +221,7 @@ func (this *ServerDAO) CreateServer(tx *dbs.Tx,
|
||||
op.DnsName = dnsName
|
||||
|
||||
op.UserPlanId = userPlanId
|
||||
op.LastUserPlanId = userPlanId
|
||||
|
||||
op.Version = 1
|
||||
op.IsOn = 1
|
||||
@@ -1262,9 +1263,13 @@ func (this *ServerDAO) CountAllEnabledServersWithNodeClusterId(tx *dbs.Tx, clust
|
||||
}
|
||||
|
||||
// CountAllEnabledServersWithGroupId 计算使用某个分组的服务数量
|
||||
func (this *ServerDAO) CountAllEnabledServersWithGroupId(tx *dbs.Tx, groupId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
func (this *ServerDAO) CountAllEnabledServersWithGroupId(tx *dbs.Tx, groupId int64, userId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(ServerStateEnabled)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
return query.
|
||||
Where("JSON_CONTAINS(groupIds, :groupId)").
|
||||
Param("groupId", numberutils.FormatInt64(groupId)).
|
||||
Count()
|
||||
@@ -1496,11 +1501,11 @@ func (this *ServerDAO) UpdateUserServersClusterId(tx *dbs.Tx, userId int64, oldC
|
||||
}
|
||||
|
||||
if oldClusterId > 0 {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, NodeTaskTypeConfigChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1511,11 +1516,11 @@ func (this *ServerDAO) UpdateUserServersClusterId(tx *dbs.Tx, userId int64, oldC
|
||||
}
|
||||
|
||||
if newClusterId > 0 {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, NodeTaskTypeConfigChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2238,6 +2243,7 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
|
||||
err = this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("userPlanId", userPlanId).
|
||||
Set("lastUserPlanId", userPlanId).
|
||||
Set("clusterId", plan.ClusterId).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
@@ -2246,6 +2252,19 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
|
||||
return this.NotifyUpdate(tx, serverId)
|
||||
}
|
||||
|
||||
// FindServerLastUserPlanIdAndUserId 查找最后使用的套餐
|
||||
func (this *ServerDAO) FindServerLastUserPlanIdAndUserId(tx *dbs.Tx, serverId int64) (userPlanId int64, userId int64, err error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("lastUserPlanId", "userId").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return int64(one.(*Server).LastUserPlanId), int64(one.(*Server).UserId), nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 同步集群
|
||||
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
// 创建任务
|
||||
@@ -2256,7 +2275,7 @@ func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
if clusterId == 0 {
|
||||
return nil
|
||||
}
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, serverId, NodeTaskTypeConfigChanged)
|
||||
}
|
||||
|
||||
// NotifyDNSUpdate 通知DNS更新
|
||||
|
||||
@@ -77,10 +77,11 @@ func (this *ServerGroupDAO) FindServerGroupName(tx *dbs.Tx, id int64) (string, e
|
||||
}
|
||||
|
||||
// CreateGroup 创建分组
|
||||
func (this *ServerGroupDAO) CreateGroup(tx *dbs.Tx, name string) (groupId int64, err error) {
|
||||
func (this *ServerGroupDAO) CreateGroup(tx *dbs.Tx, name string, userId int64) (groupId int64, err error) {
|
||||
op := NewServerGroupOperator()
|
||||
op.State = ServerGroupStateEnabled
|
||||
op.Name = name
|
||||
op.UserId = userId
|
||||
op.IsOn = true
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -102,9 +103,15 @@ func (this *ServerGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, name string)
|
||||
}
|
||||
|
||||
// FindAllEnabledGroups 查找所有分组
|
||||
func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ServerGroup, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(ServerGroupStateEnabled).
|
||||
func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx, userId int64) (result []*ServerGroup, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(ServerGroupStateEnabled)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
query.Attr("userId", 0)
|
||||
}
|
||||
_, err = query.
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
@@ -113,9 +120,13 @@ func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ServerGr
|
||||
}
|
||||
|
||||
// UpdateGroupOrders 修改分组排序
|
||||
func (this *ServerGroupDAO) UpdateGroupOrders(tx *dbs.Tx, groupIds []int64) error {
|
||||
func (this *ServerGroupDAO) UpdateGroupOrders(tx *dbs.Tx, groupIds []int64, userId int64) error {
|
||||
for index, groupId := range groupIds {
|
||||
_, err := this.Query(tx).
|
||||
var query = this.Query(tx)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
_, err := query.
|
||||
Pk(groupId).
|
||||
Set("order", len(groupIds)-index).
|
||||
Update()
|
||||
@@ -383,6 +394,22 @@ func (this *ServerGroupDAO) FindEnabledGroupIdWithReverseProxyId(tx *dbs.Tx, rev
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// CheckUserGroup 检查用户分组
|
||||
func (this *ServerGroupDAO) CheckUserGroup(tx *dbs.Tx, userId int64, groupId int64) error {
|
||||
b, err := this.Query(tx).
|
||||
Pk(groupId).
|
||||
Attr("userId", userId).
|
||||
State(ServerGroupStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
|
||||
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
|
||||
|
||||
@@ -43,6 +43,7 @@ type Server struct {
|
||||
TrafficLimitStatus string `field:"trafficLimitStatus"` // 流量限制状态
|
||||
TotalTraffic float64 `field:"totalTraffic"` // 总流量
|
||||
UserPlanId uint32 `field:"userPlanId"` // 所属套餐ID
|
||||
LastUserPlanId uint32 `field:"lastUserPlanId"` // 上一次使用的套餐
|
||||
}
|
||||
|
||||
type ServerOperator struct {
|
||||
@@ -87,6 +88,7 @@ type ServerOperator struct {
|
||||
TrafficLimitStatus interface{} // 流量限制状态
|
||||
TotalTraffic interface{} // 总流量
|
||||
UserPlanId interface{} // 所属套餐ID
|
||||
LastUserPlanId interface{} // 上一次使用的套餐
|
||||
}
|
||||
|
||||
func NewServerOperator() *ServerOperator {
|
||||
|
||||
@@ -25,7 +25,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerDomainHourlyStatDAO.Clean(nil, 7) // 只保留7天
|
||||
err := SharedServerDomainHourlyStatDAO.Clean(nil, 7) // 只保留 N 天
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerDomainHourlyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -374,7 +374,9 @@ func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
Table(table).
|
||||
Lt("hour", hour).
|
||||
Delete()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 开锁
|
||||
// Lock 开锁
|
||||
func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool, err error) {
|
||||
maxErrors := 5
|
||||
for {
|
||||
@@ -103,7 +103,7 @@ func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool,
|
||||
}
|
||||
}
|
||||
|
||||
// 解锁
|
||||
// Unlock 解锁
|
||||
func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("key", key).
|
||||
@@ -112,7 +112,7 @@ func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 增加版本号
|
||||
// Increase 增加版本号
|
||||
func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (int64, error) {
|
||||
if tx == nil {
|
||||
var result int64
|
||||
|
||||
@@ -4,9 +4,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/zero"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -138,6 +140,72 @@ func (this *SysSettingDAO) ReadGlobalConfig(tx *dbs.Tx) (*serverconfigs.GlobalCo
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadUserServerConfig 读取用户服务配置
|
||||
func (this *SysSettingDAO) ReadUserServerConfig(tx *dbs.Tx) (*userconfigs.UserServerConfig, error) {
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserServerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) == 0 {
|
||||
return userconfigs.DefaultUserServerConfig(), nil
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserServerConfig()
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadUserFinanceConfig 读取用户服务配置
|
||||
func (this *SysSettingDAO) ReadUserFinanceConfig(tx *dbs.Tx) (*userconfigs.UserFinanceConfig, error) {
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserFinanceConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) == 0 {
|
||||
return userconfigs.DefaultUserFinanceConfig(), nil
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserFinanceConfig()
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadAdminUIConfig 读取管理员界面配置
|
||||
func (this *SysSettingDAO) ReadAdminUIConfig(tx *dbs.Tx, cacheMap *utils.CacheMap) (*systemconfigs.AdminUIConfig, error) {
|
||||
var cacheKey = this.Table + ":ReadAdminUIConfig"
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok && cache != nil {
|
||||
return cache.(*systemconfigs.AdminUIConfig), nil
|
||||
}
|
||||
}
|
||||
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeAdminUIConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) > 0 {
|
||||
var config = &systemconfigs.AdminUIConfig{}
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
return &systemconfigs.AdminUIConfig{}, nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更改
|
||||
func (this *SysSettingDAO) NotifyUpdate(tx *dbs.Tx, code string) error {
|
||||
switch code {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -23,7 +22,7 @@ func init() {
|
||||
|
||||
goman.New(func() {
|
||||
// 自动生成账单任务
|
||||
var ticker = time.NewTicker(1 * time.Minute)
|
||||
var ticker = time.NewTicker(1 * time.Hour)
|
||||
for range ticker.C {
|
||||
// 是否已经生成了,如果已经生成了就跳过
|
||||
var lastMonth = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0))
|
||||
@@ -136,7 +135,7 @@ func (this *UserBillDAO) FindUnpaidBills(tx *dbs.Tx, size int64) (result []*User
|
||||
}
|
||||
|
||||
// CreateBill 创建账单
|
||||
func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType, description string, amount float32, month string) error {
|
||||
func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType, description string, amount float64, month string, canPay bool) error {
|
||||
code, err := this.GenerateBillCode(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -149,9 +148,11 @@ func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType,
|
||||
"amount": amount,
|
||||
"month": month,
|
||||
"code": code,
|
||||
"isPaid": false,
|
||||
"isPaid": amount == 0,
|
||||
"canPay": canPay,
|
||||
}, maps.Map{
|
||||
"amount": amount,
|
||||
"canPay": canPay,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -172,19 +173,22 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(regions) == 0 {
|
||||
return nil
|
||||
|
||||
var priceItems []*NodePriceItem
|
||||
if len(regions) > 0 {
|
||||
priceItems, err = SharedNodePriceItemDAO.FindAllEnabledRegionPrices(tx, NodePriceTypeTraffic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
priceItems, err := SharedNodePriceItemDAO.FindAllEnabledRegionPrices(tx, NodePriceTypeTraffic)
|
||||
// 默认计费方式
|
||||
userFinanceConfig, err := SharedSysSettingDAO.ReadUserFinanceConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(priceItems) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 计算套餐费用
|
||||
// 计算服务套餐费用
|
||||
plans, err := SharedPlanDAO.FindAllEnabledPlans(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -194,54 +198,220 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
planMap[int64(plan.Id)] = plan
|
||||
}
|
||||
|
||||
stats, err := SharedServerDailyStatDAO.FindMonthlyStatsWithPlan(tx, month)
|
||||
var dayFrom = month + "01"
|
||||
var dayTo = month + "32"
|
||||
serverIds, err := SharedServerDailyStatDAO.FindDistinctServerIds(tx, dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, stat := range stats {
|
||||
plan, ok := planMap[int64(stat.PlanId)]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if plan.PriceType != serverconfigs.PlanPriceTypeTraffic {
|
||||
continue
|
||||
}
|
||||
if len(plan.TrafficPrice) == 0 {
|
||||
continue
|
||||
}
|
||||
var priceConfig = &serverconfigs.PlanTrafficPrice{}
|
||||
err = json.Unmarshal([]byte(plan.TrafficPrice), priceConfig)
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
var userIds = []int64{}
|
||||
for _, serverId := range serverIds {
|
||||
// 套餐类型
|
||||
userPlanId, userId, err := SharedServerDAO.FindServerLastUserPlanIdAndUserId(tx, serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if priceConfig.Base > 0 {
|
||||
var fee = priceConfig.Base * (float32(stat.Bytes) / 1024 / 1024 / 1024)
|
||||
err = SharedServerDailyStatDAO.UpdateStatFee(tx, int64(stat.Id), fee)
|
||||
if userId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
userIds = append(userIds, userId)
|
||||
if userPlanId == 0 {
|
||||
// 总流量
|
||||
totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 默认计费方式
|
||||
if userFinanceConfig != nil && userFinanceConfig.IsOn { // 默认计费方式
|
||||
switch userFinanceConfig.PriceType {
|
||||
case serverconfigs.PlanPriceTypeTraffic:
|
||||
var config = userFinanceConfig.TrafficPriceConfig
|
||||
var fee float64 = 0
|
||||
if config != nil && config.Base > 0 {
|
||||
fee = float64(totalTrafficBytes) / 1024 / 1024 / 1024 * float64(config.Base)
|
||||
}
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, userFinanceConfig.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeBandwidth:
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
var config = userFinanceConfig.BandwidthPriceConfig
|
||||
if config != nil {
|
||||
percentile = config.Percentile
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
} else if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var mb = float32(percentileBytes) / 1024 / 1024
|
||||
var price float32
|
||||
if config != nil {
|
||||
price = config.LookupPrice(mb)
|
||||
}
|
||||
var fee = float64(price)
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, userFinanceConfig.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else { // 区域流量计费
|
||||
var fee float64
|
||||
|
||||
for _, region := range regions {
|
||||
var regionId = int64(region.Id)
|
||||
var pricesMap = region.DecodePriceMap()
|
||||
if len(pricesMap) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
trafficBytes, err := SharedServerDailyStatDAO.SumServerMonthlyWithRegion(tx, serverId, regionId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if trafficBytes == 0 {
|
||||
continue
|
||||
}
|
||||
var itemId = SharedNodePriceItemDAO.SearchItemsWithBytes(priceItems, trafficBytes)
|
||||
if itemId == 0 {
|
||||
continue
|
||||
}
|
||||
price, ok := pricesMap[itemId]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if price <= 0 {
|
||||
continue
|
||||
}
|
||||
var regionFee = float64(trafficBytes) / 1000 / 1000 / 1000 * 8 * price
|
||||
fee += regionFee
|
||||
}
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, "", fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
userPlan, err := SharedUserPlanDAO.FindUserPlanWithoutState(tx, userPlanId, cacheMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userPlan == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
plan, ok := planMap[int64(userPlan.PlanId)]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// 总流量
|
||||
totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch plan.PriceType {
|
||||
case serverconfigs.PlanPriceTypePeriod:
|
||||
// 已经在购买套餐的时候付过费,这里不再重复计费
|
||||
var fee float64 = 0
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeTraffic:
|
||||
var config = plan.DecodeTrafficPrice()
|
||||
var fee float64 = 0
|
||||
if config != nil && config.Base > 0 {
|
||||
fee = float64(totalTrafficBytes) / 1024 / 1024 / 1024 * float64(config.Base)
|
||||
}
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeBandwidth:
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
var config = plan.DecodeBandwidthPrice()
|
||||
if config != nil {
|
||||
percentile = config.Percentile
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
} else if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var mb = float32(percentileBytes) / 1024 / 1024
|
||||
var price float32
|
||||
if config != nil {
|
||||
price = config.LookupPrice(mb)
|
||||
}
|
||||
var fee = float64(price)
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 用户
|
||||
offset := int64(0)
|
||||
size := int64(100) // 每次只查询N次,防止由于执行时间过长而锁表
|
||||
for {
|
||||
userIds, err := SharedUserDAO.ListEnabledUserIds(tx, offset, size)
|
||||
// 计算用户费用
|
||||
for _, userId := range userIds {
|
||||
if userId == 0 {
|
||||
continue
|
||||
}
|
||||
amount, err := SharedServerBillDAO.SumUserMonthlyAmount(tx, userId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset += size
|
||||
if len(userIds) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, userId := range userIds {
|
||||
// CDN流量账单
|
||||
err := this.generateTrafficBill(tx, userId, month, regions, priceItems)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = SharedUserBillDAO.CreateBill(tx, userId, BillTypeTraffic, "流量带宽费用", amount, month, month < timeutil.Format("Ym"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,74 +426,11 @@ func (this *UserBillDAO) UpdateUserBillIsPaid(tx *dbs.Tx, billId int64, isPaid b
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// 生成CDN流量账单
|
||||
// month 格式YYYYMM
|
||||
func (this *UserBillDAO) generateTrafficBill(tx *dbs.Tx, userId int64, month string, regions []*NodeRegion, priceItems []*NodePriceItem) error {
|
||||
// 检查是否已经有账单了
|
||||
if month < timeutil.Format("Ym") {
|
||||
b, err := this.ExistBill(tx, userId, BillTypeTraffic, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var cost = float32(0)
|
||||
for _, region := range regions {
|
||||
if len(region.Prices) == 0 || region.Prices == "null" {
|
||||
continue
|
||||
}
|
||||
priceMap := map[string]float32{}
|
||||
err := json.Unmarshal([]byte(region.Prices), &priceMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trafficBytes, err := SharedServerDailyStatDAO.SumUserMonthlyWithoutPlan(tx, userId, int64(region.Id), month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if trafficBytes == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
itemId := SharedNodePriceItemDAO.SearchItemsWithBytes(priceItems, trafficBytes)
|
||||
if itemId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
price, ok := priceMap[numberutils.FormatInt64(itemId)]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// 计算钱
|
||||
// 这里采用1000进制
|
||||
cost += (float32(trafficBytes*8) / 1_000_000_000) * price
|
||||
}
|
||||
|
||||
// 套餐费用
|
||||
planFee, err := SharedServerDailyStatDAO.SumUserMonthlyFee(tx, userId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cost += float32(planFee)
|
||||
|
||||
if cost == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 创建账单
|
||||
return this.CreateBill(tx, userId, BillTypeTraffic, "按流量计费", cost, month)
|
||||
}
|
||||
|
||||
// BillTypeName 获取账单类型名称
|
||||
func (this *UserBillDAO) BillTypeName(billType BillType) string {
|
||||
switch billType {
|
||||
case BillTypeTraffic:
|
||||
return "流量"
|
||||
return "流量带宽"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -7,7 +7,10 @@ type UserBill struct {
|
||||
Type string `field:"type"` // 消费类型
|
||||
Description string `field:"description"` // 描述
|
||||
Amount float64 `field:"amount"` // 消费数额
|
||||
DayFrom string `field:"dayFrom"` // YYYYMMDD
|
||||
DayTo string `field:"dayTo"` // YYYYMMDD
|
||||
Month string `field:"month"` // 帐期YYYYMM
|
||||
CanPay uint8 `field:"canPay"` // 是否可以支付
|
||||
IsPaid uint8 `field:"isPaid"` // 是否已支付
|
||||
PaidAt uint64 `field:"paidAt"` // 支付时间
|
||||
Code string `field:"code"` // 账单编号
|
||||
@@ -20,7 +23,10 @@ type UserBillOperator struct {
|
||||
Type interface{} // 消费类型
|
||||
Description interface{} // 描述
|
||||
Amount interface{} // 消费数额
|
||||
DayFrom interface{} // YYYYMMDD
|
||||
DayTo interface{} // YYYYMMDD
|
||||
Month interface{} // 帐期YYYYMM
|
||||
CanPay interface{} // 是否可以支付
|
||||
IsPaid interface{} // 是否已支付
|
||||
PaidAt interface{} // 支付时间
|
||||
Code interface{} // 账单编号
|
||||
|
||||
@@ -95,6 +95,18 @@ func (this *UserDAO) FindEnabledBasicUser(tx *dbs.Tx, id int64) (*User, error) {
|
||||
return result.(*User), err
|
||||
}
|
||||
|
||||
// FindBasicUserWithoutState 查找用户基本信息,并忽略状态
|
||||
func (this *UserDAO) FindBasicUserWithoutState(tx *dbs.Tx, id int64) (*User, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Result("id", "fullname", "username").
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*User), err
|
||||
}
|
||||
|
||||
// FindUserFullname 获取管理员名称
|
||||
func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
@@ -104,7 +116,18 @@ func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error)
|
||||
}
|
||||
|
||||
// CreateUser 创建用户
|
||||
func (this *UserDAO) CreateUser(tx *dbs.Tx, username string, password string, fullname string, mobile string, tel string, email string, remark string, source string, clusterId int64) (int64, error) {
|
||||
func (this *UserDAO) CreateUser(tx *dbs.Tx, username string,
|
||||
password string,
|
||||
fullname string,
|
||||
mobile string,
|
||||
tel string,
|
||||
email string,
|
||||
remark string,
|
||||
source string,
|
||||
clusterId int64,
|
||||
features []string,
|
||||
registeredIP string,
|
||||
isVerified bool) (int64, error) {
|
||||
op := NewUserOperator()
|
||||
op.Username = username
|
||||
op.Password = stringutil.Md5(password)
|
||||
@@ -112,10 +135,24 @@ func (this *UserDAO) CreateUser(tx *dbs.Tx, username string, password string, fu
|
||||
op.Mobile = mobile
|
||||
op.Tel = tel
|
||||
op.Email = email
|
||||
op.EmailIsVerified = false
|
||||
op.Remark = remark
|
||||
op.Source = source
|
||||
op.ClusterId = clusterId
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
op.IsVerified = isVerified
|
||||
op.RegisteredIP = registeredIP
|
||||
|
||||
// features
|
||||
if len(features) == 0 {
|
||||
op.Features = "[]"
|
||||
} else {
|
||||
featuresJSON, err := json.Marshal(features)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Features = featuresJSON
|
||||
}
|
||||
|
||||
op.IsOn = true
|
||||
op.State = UserStateEnabled
|
||||
@@ -149,13 +186,15 @@ func (this *UserDAO) UpdateUser(tx *dbs.Tx, userId int64, username string, passw
|
||||
}
|
||||
|
||||
// UpdateUserInfo 修改用户基本信息
|
||||
func (this *UserDAO) UpdateUserInfo(tx *dbs.Tx, userId int64, fullname string) error {
|
||||
func (this *UserDAO) UpdateUserInfo(tx *dbs.Tx, userId int64, fullname string, mobile string, email string) error {
|
||||
if userId <= 0 {
|
||||
return errors.New("invalid userId")
|
||||
}
|
||||
op := NewUserOperator()
|
||||
op.Id = userId
|
||||
op.Fullname = fullname
|
||||
op.Mobile = mobile
|
||||
op.Email = email
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
@@ -175,7 +214,7 @@ func (this *UserDAO) UpdateUserLogin(tx *dbs.Tx, userId int64, username string,
|
||||
}
|
||||
|
||||
// CountAllEnabledUsers 计算用户数量
|
||||
func (this *UserDAO) CountAllEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
func (this *UserDAO) CountAllEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string, isVerifying bool) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
query.State(UserStateEnabled)
|
||||
if clusterId > 0 {
|
||||
@@ -185,11 +224,22 @@ func (this *UserDAO) CountAllEnabledUsers(tx *dbs.Tx, clusterId int64, keyword s
|
||||
query.Where("(username LIKE :keyword OR fullname LIKE :keyword OR mobile LIKE :keyword OR email LIKE :keyword OR tel LIKE :keyword OR remark LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
}
|
||||
if isVerifying {
|
||||
query.Attr("isVerified", 0)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// CountAllVerifyingUsers 获取等待审核的用户数
|
||||
func (this *UserDAO) CountAllVerifyingUsers(tx *dbs.Tx) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
query.State(UserStateEnabled)
|
||||
query.Attr("isVerified", 0)
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListEnabledUsers 列出单页用户
|
||||
func (this *UserDAO) ListEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) (result []*User, err error) {
|
||||
func (this *UserDAO) ListEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string, isVerifying bool, offset int64, size int64) (result []*User, err error) {
|
||||
query := this.Query(tx)
|
||||
query.State(UserStateEnabled)
|
||||
if clusterId > 0 {
|
||||
@@ -199,6 +249,9 @@ func (this *UserDAO) ListEnabledUsers(tx *dbs.Tx, clusterId int64, keyword strin
|
||||
query.Where("(username LIKE :keyword OR fullname LIKE :keyword OR mobile LIKE :keyword OR email LIKE :keyword OR tel LIKE :keyword OR remark LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
}
|
||||
if isVerifying {
|
||||
query.Attr("isVerified", 0)
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
@@ -355,3 +408,16 @@ func (this *UserDAO) CountDailyUsers(tx *dbs.Tx, dayFrom string, dayTo string) (
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UpdateUserIsVerified 审核用户
|
||||
func (this *UserDAO) UpdateUserIsVerified(tx *dbs.Tx, userId int64, isRejected bool, rejectReason string) error {
|
||||
if userId <= 0 {
|
||||
return errors.New("invalid userId")
|
||||
}
|
||||
var op = NewUserOperator()
|
||||
op.Id = userId
|
||||
op.IsRejected = isRejected
|
||||
op.RejectReason = rejectReason
|
||||
op.IsVerified = true
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
@@ -2,43 +2,55 @@ package models
|
||||
|
||||
// User 用户
|
||||
type User struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Fullname string `field:"fullname"` // 真实姓名
|
||||
Mobile string `field:"mobile"` // 手机号
|
||||
Tel string `field:"tel"` // 联系电话
|
||||
Remark string `field:"remark"` // 备注
|
||||
Email string `field:"email"` // 邮箱地址
|
||||
AvatarFileId uint64 `field:"avatarFileId"` // 头像文件ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Source string `field:"source"` // 来源
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
Features string `field:"features"` // 允许操作的特征
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Fullname string `field:"fullname"` // 真实姓名
|
||||
Mobile string `field:"mobile"` // 手机号
|
||||
Tel string `field:"tel"` // 联系电话
|
||||
Remark string `field:"remark"` // 备注
|
||||
Email string `field:"email"` // 邮箱地址
|
||||
EmailIsVerified uint8 `field:"emailIsVerified"` // 邮箱是否已验证
|
||||
AvatarFileId uint64 `field:"avatarFileId"` // 头像文件ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Source string `field:"source"` // 来源
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
Features string `field:"features"` // 允许操作的特征
|
||||
RegisteredIP string `field:"registeredIP"` // 注册使用的IP
|
||||
IsRejected uint8 `field:"isRejected"` // 是否已拒绝
|
||||
RejectReason string `field:"rejectReason"` // 拒绝理由
|
||||
IsVerified uint8 `field:"isVerified"` // 是否验证通过
|
||||
RequirePlans uint8 `field:"requirePlans"` // 是否需要购买套餐
|
||||
}
|
||||
|
||||
type UserOperator struct {
|
||||
Id interface{} // ID
|
||||
IsOn interface{} // 是否启用
|
||||
Username interface{} // 用户名
|
||||
Password interface{} // 密码
|
||||
Fullname interface{} // 真实姓名
|
||||
Mobile interface{} // 手机号
|
||||
Tel interface{} // 联系电话
|
||||
Remark interface{} // 备注
|
||||
Email interface{} // 邮箱地址
|
||||
AvatarFileId interface{} // 头像文件ID
|
||||
CreatedAt interface{} // 创建时间
|
||||
Day interface{} // YYYYMMDD
|
||||
UpdatedAt interface{} // 修改时间
|
||||
State interface{} // 状态
|
||||
Source interface{} // 来源
|
||||
ClusterId interface{} // 集群ID
|
||||
Features interface{} // 允许操作的特征
|
||||
Id interface{} // ID
|
||||
IsOn interface{} // 是否启用
|
||||
Username interface{} // 用户名
|
||||
Password interface{} // 密码
|
||||
Fullname interface{} // 真实姓名
|
||||
Mobile interface{} // 手机号
|
||||
Tel interface{} // 联系电话
|
||||
Remark interface{} // 备注
|
||||
Email interface{} // 邮箱地址
|
||||
EmailIsVerified interface{} // 邮箱是否已验证
|
||||
AvatarFileId interface{} // 头像文件ID
|
||||
CreatedAt interface{} // 创建时间
|
||||
Day interface{} // YYYYMMDD
|
||||
UpdatedAt interface{} // 修改时间
|
||||
State interface{} // 状态
|
||||
Source interface{} // 来源
|
||||
ClusterId interface{} // 集群ID
|
||||
Features interface{} // 允许操作的特征
|
||||
RegisteredIP interface{} // 注册使用的IP
|
||||
IsRejected interface{} // 是否已拒绝
|
||||
RejectReason interface{} // 拒绝理由
|
||||
IsVerified interface{} // 是否验证通过
|
||||
RequirePlans interface{} // 是否需要购买套餐
|
||||
}
|
||||
|
||||
func NewUserOperator() *UserOperator {
|
||||
|
||||
@@ -85,6 +85,31 @@ func (this *UserPlanDAO) FindEnabledUserPlan(tx *dbs.Tx, userPlanId int64, cache
|
||||
return result.(*UserPlan), err
|
||||
}
|
||||
|
||||
// FindUserPlanWithoutState 查找套餐,并不检查状态
|
||||
// 防止因为删除套餐而导致计费失败
|
||||
func (this *UserPlanDAO) FindUserPlanWithoutState(tx *dbs.Tx, userPlanId int64, cacheMap *utils.CacheMap) (*UserPlan, error) {
|
||||
var cacheKey = this.Table + ":FindUserPlanWithoutState:" + types.String(userPlanId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*UserPlan), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
Pk(userPlanId).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*UserPlan), err
|
||||
}
|
||||
|
||||
// CountAllEnabledUserPlans 计算套餐数量
|
||||
func (this *UserPlanDAO) CountAllEnabledUserPlans(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int32) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/cloudflare"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
@@ -257,6 +258,7 @@ func (this *CloudFlareProvider) doAPI(method string, apiPath string, args map[st
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Auth-Key", this.apiKey)
|
||||
req.Header.Set("x-Auth-Email", this.email)
|
||||
|
||||
@@ -165,7 +165,7 @@ func (this *CustomHTTPProvider) post(params maps.Map) (respData []byte, err erro
|
||||
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
req.Header.Set("Timestamp", timestamp)
|
||||
req.Header.Set("Token", fmt.Sprintf("%x", sha1.Sum([]byte(this.secret+"@"+timestamp))))
|
||||
req.Header.Set("User-Agent", "GoEdge/"+teaconst.Version)
|
||||
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||
|
||||
resp, err := customHTTPClient.Do(req)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,19 +9,30 @@ import (
|
||||
|
||||
var SharedDeployManager = NewDeployManager()
|
||||
|
||||
// DeployManager 节点部署文件管理器
|
||||
// 如果节点部署文件有变化,需要重启API节点以便于生效
|
||||
type DeployManager struct {
|
||||
dir string
|
||||
dir string
|
||||
nodeFiles []*DeployFile
|
||||
nsNodeFiles []*DeployFile
|
||||
}
|
||||
|
||||
// NewDeployManager 节点部署文件管理器
|
||||
// NewDeployManager 获取新节点部署文件管理器
|
||||
func NewDeployManager() *DeployManager {
|
||||
return &DeployManager{
|
||||
var manager = &DeployManager{
|
||||
dir: Tea.Root + "/deploy",
|
||||
}
|
||||
manager.LoadNodeFiles()
|
||||
manager.LoadNSNodeFiles()
|
||||
return manager
|
||||
}
|
||||
|
||||
// LoadNodeFiles 加载所有边缘节点文件
|
||||
func (this *DeployManager) LoadNodeFiles() []*DeployFile {
|
||||
if len(this.nodeFiles) > 0 {
|
||||
return this.nodeFiles
|
||||
}
|
||||
|
||||
keyMap := map[string]*DeployFile{} // key => File
|
||||
|
||||
reg := regexp.MustCompile(`^edge-node-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
|
||||
@@ -52,6 +63,9 @@ func (this *DeployManager) LoadNodeFiles() []*DeployFile {
|
||||
for _, v := range keyMap {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
this.nodeFiles = result
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -67,6 +81,10 @@ func (this *DeployManager) FindNodeFile(os string, arch string) *DeployFile {
|
||||
|
||||
// LoadNSNodeFiles 加载所有NS节点安装文件
|
||||
func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
||||
if len(this.nsNodeFiles) > 0 {
|
||||
return this.nsNodeFiles
|
||||
}
|
||||
|
||||
keyMap := map[string]*DeployFile{} // key => File
|
||||
|
||||
reg := regexp.MustCompile(`^edge-dns-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
|
||||
@@ -97,6 +115,9 @@ func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
||||
for _, v := range keyMap {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
this.nsNodeFiles = result
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/events"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/setup"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/go-yaml/yaml"
|
||||
@@ -214,10 +216,10 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
|
||||
var rpcServer *grpc.Server
|
||||
if tlsConfig == nil {
|
||||
remotelogs.Println("API_NODE", "listening GRPC http://"+listener.Addr().String()+" ...")
|
||||
rpcServer = grpc.NewServer(grpc.MaxRecvMsgSize(128 * 1024 * 1024))
|
||||
rpcServer = grpc.NewServer(grpc.MaxRecvMsgSize(128*1024*1024), grpc.UnaryInterceptor(this.unaryInterceptor))
|
||||
} else {
|
||||
logs.Println("[API_NODE]listening GRPC https://" + listener.Addr().String() + " ...")
|
||||
rpcServer = grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)), grpc.MaxRecvMsgSize(128*1024*1024))
|
||||
rpcServer = grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)), grpc.MaxRecvMsgSize(128*1024*1024), grpc.UnaryInterceptor(this.unaryInterceptor))
|
||||
}
|
||||
this.registerServices(rpcServer)
|
||||
err := rpcServer.Serve(listener)
|
||||
@@ -572,6 +574,11 @@ func (this *APINode) listenSock() error {
|
||||
"result": result,
|
||||
},
|
||||
})
|
||||
case "debug":
|
||||
teaconst.Debug = !teaconst.Debug
|
||||
_ = cmd.Reply(&gosock.Command{
|
||||
Params: map[string]interface{}{"debug": teaconst.Debug},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -588,3 +595,29 @@ func (this *APINode) listenSock() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 服务过滤器
|
||||
func (this *APINode) unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
if teaconst.Debug {
|
||||
var before = time.Now()
|
||||
var traceCtx = rpc.NewContext(ctx)
|
||||
resp, err = handler(traceCtx, req)
|
||||
|
||||
var costMs = time.Since(before).Seconds() * 1000
|
||||
statErr := models.SharedAPIMethodStatDAO.CreateStat(nil, info.FullMethod, "", costMs)
|
||||
if statErr != nil {
|
||||
remotelogs.Error("API_NODE", "create method stat failed: "+statErr.Error())
|
||||
}
|
||||
|
||||
var tagMap = traceCtx.TagMap()
|
||||
for tag, tagCostMs := range tagMap {
|
||||
statErr = models.SharedAPIMethodStatDAO.CreateStat(nil, info.FullMethod, tag, tagCostMs)
|
||||
if statErr != nil {
|
||||
remotelogs.Error("API_NODE", "create method stat failed: "+statErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
@@ -63,6 +63,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterAPINodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.APIMethodStatService{}).(*services.APIMethodStatService)
|
||||
pb.RegisterAPIMethodStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
||||
pb.RegisterOriginServiceServer(server, instance)
|
||||
@@ -263,6 +268,16 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterRegionProvinceServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionCityService{}).(*services.RegionCityService)
|
||||
pb.RegisterRegionCityServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionProviderService{}).(*services.RegionProviderService)
|
||||
pb.RegisterRegionProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
||||
pb.RegisterIPListServiceServer(server, instance)
|
||||
@@ -333,6 +348,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterUserBillServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerBillService{}).(*services.ServerBillService)
|
||||
pb.RegisterServerBillServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
||||
pb.RegisterUserNodeServiceServer(server, instance)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package nodes
|
||||
|
||||
|
||||
46
internal/rpc/context.go
Normal file
46
internal/rpc/context.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
context.Context
|
||||
|
||||
tagMap map[string]time.Time
|
||||
costMap map[string]float64 // tag => costMs
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
func NewContext(ctx context.Context) *Context {
|
||||
return &Context{
|
||||
Context: ctx,
|
||||
tagMap: map[string]time.Time{},
|
||||
costMap: map[string]float64{},
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Context) Begin(tag string) {
|
||||
this.locker.Lock()
|
||||
this.tagMap[tag] = time.Now()
|
||||
this.locker.Unlock()
|
||||
}
|
||||
|
||||
func (this *Context) End(tag string) {
|
||||
this.locker.Lock()
|
||||
begin, ok := this.tagMap[tag]
|
||||
if ok {
|
||||
this.costMap[tag] = time.Since(begin).Seconds() * 1000
|
||||
}
|
||||
this.locker.Unlock()
|
||||
}
|
||||
|
||||
func (this *Context) TagMap() map[string]float64 {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
return this.costMap
|
||||
}
|
||||
@@ -477,7 +477,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 默认集群
|
||||
this.BeginTag(ctx, "SharedNodeClusterDAO.ListEnabledClusters")
|
||||
nodeClusters, err := models.SharedNodeClusterDAO.ListEnabledClusters(tx, "", 0, 1)
|
||||
this.EndTag(ctx, "SharedNodeClusterDAO.ListEnabledClusters")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -486,84 +488,108 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
}
|
||||
|
||||
// 集群数
|
||||
this.BeginTag(ctx, "SharedNodeClusterDAO.CountAllEnabledClusters")
|
||||
countClusters, err := models.SharedNodeClusterDAO.CountAllEnabledClusters(tx, "")
|
||||
this.EndTag(ctx, "SharedNodeClusterDAO.CountAllEnabledClusters")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountNodeClusters = countClusters
|
||||
|
||||
// 节点数
|
||||
this.BeginTag(ctx, "SharedNodeDAO.CountAllEnabledNodes")
|
||||
countNodes, err := models.SharedNodeDAO.CountAllEnabledNodes(tx)
|
||||
this.EndTag(ctx, "SharedNodeDAO.CountAllEnabledNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountNodes = countNodes
|
||||
|
||||
// 离线节点
|
||||
this.BeginTag(ctx, "SharedNodeDAO.CountAllEnabledOfflineNodes")
|
||||
countOfflineNodes, err := models.SharedNodeDAO.CountAllEnabledOfflineNodes(tx)
|
||||
this.EndTag(ctx, "SharedNodeDAO.CountAllEnabledOfflineNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountOfflineNodes = countOfflineNodes
|
||||
|
||||
// 服务数
|
||||
this.BeginTag(ctx, "SharedServerDAO.CountAllEnabledServers")
|
||||
countServers, err := models.SharedServerDAO.CountAllEnabledServers(tx)
|
||||
this.EndTag(ctx, "SharedServerDAO.CountAllEnabledServers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountServers = countServers
|
||||
|
||||
this.BeginTag(ctx, "SharedServerDAO.CountAllEnabledServersMatch")
|
||||
countAuditingServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", 0, 0, configutils.BoolStateYes, nil)
|
||||
this.EndTag(ctx, "SharedServerDAO.CountAllEnabledServersMatch")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountAuditingServers = countAuditingServers
|
||||
|
||||
// 用户数
|
||||
countUsers, err := models.SharedUserDAO.CountAllEnabledUsers(tx, 0, "")
|
||||
this.BeginTag(ctx, "SharedUserDAO.CountAllEnabledUsers")
|
||||
countUsers, err := models.SharedUserDAO.CountAllEnabledUsers(tx, 0, "", false)
|
||||
this.EndTag(ctx, "SharedUserDAO.CountAllEnabledUsers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountUsers = countUsers
|
||||
|
||||
// API节点数
|
||||
this.BeginTag(ctx, "SharedAPINodeDAO.CountAllEnabledAndOnAPINodes")
|
||||
countAPINodes, err := models.SharedAPINodeDAO.CountAllEnabledAndOnAPINodes(tx)
|
||||
this.EndTag(ctx, "SharedAPINodeDAO.CountAllEnabledAndOnAPINodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountAPINodes = countAPINodes
|
||||
|
||||
// 离线API节点
|
||||
this.BeginTag(ctx, "SharedAPINodeDAO.CountAllEnabledAndOnOfflineAPINodes")
|
||||
countOfflineAPINodes, err := models.SharedAPINodeDAO.CountAllEnabledAndOnOfflineAPINodes(tx)
|
||||
this.EndTag(ctx, "SharedAPINodeDAO.CountAllEnabledAndOnOfflineAPINodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountOfflineAPINodes = countOfflineAPINodes
|
||||
|
||||
// 数据库节点数
|
||||
this.BeginTag(ctx, "SharedDBNodeDAO.CountAllEnabledNodes")
|
||||
countDBNodes, err := models.SharedDBNodeDAO.CountAllEnabledNodes(tx)
|
||||
this.EndTag(ctx, "SharedDBNodeDAO.CountAllEnabledNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountDBNodes = countDBNodes
|
||||
|
||||
// 用户节点数
|
||||
this.BeginTag(ctx, "SharedUserNodeDAO.CountAllEnabledAndOnUserNodes")
|
||||
countUserNodes, err := models.SharedUserNodeDAO.CountAllEnabledAndOnUserNodes(tx)
|
||||
this.EndTag(ctx, "SharedUserNodeDAO.CountAllEnabledAndOnUserNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountUserNodes = countUserNodes
|
||||
|
||||
// 离线用户节点数
|
||||
this.BeginTag(ctx, "SharedUserNodeDAO.CountAllEnabledAndOnOfflineNodes")
|
||||
countOfflineUserNodes, err := models.SharedUserNodeDAO.CountAllEnabledAndOnOfflineNodes(tx)
|
||||
this.EndTag(ctx, "SharedUserNodeDAO.CountAllEnabledAndOnOfflineNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountOfflineUserNodes = countOfflineUserNodes
|
||||
|
||||
// 按日流量统计
|
||||
this.BeginTag(ctx, "SharedTrafficDailyStatDAO.FindDailyStats")
|
||||
dayFrom := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
|
||||
dailyTrafficStats, err := stats.SharedTrafficDailyStatDAO.FindDailyStats(tx, dayFrom, timeutil.Format("Ymd"))
|
||||
this.EndTag(ctx, "SharedTrafficDailyStatDAO.FindDailyStats")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -582,7 +608,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
// 小时流量统计
|
||||
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||
hourTo := timeutil.Format("YmdH")
|
||||
this.BeginTag(ctx, "SharedTrafficHourlyStatDAO.FindHourlyStats")
|
||||
hourlyTrafficStats, err := stats.SharedTrafficHourlyStatDAO.FindHourlyStats(tx, hourFrom, hourTo)
|
||||
this.EndTag(ctx, "SharedTrafficHourlyStatDAO.FindHourlyStats")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -609,7 +637,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.NodeVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedNodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := models.SharedNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedNodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -622,7 +652,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.MonitorNodeVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedMonitorNodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := models.SharedMonitorNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedMonitorNodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -635,7 +667,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.AuthorityNodeVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedAuthorityNodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := authority.SharedAuthorityNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedAuthorityNodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -648,7 +682,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.UserNodeVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedUserNodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := models.SharedUserNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedUserNodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -665,7 +701,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: apiVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedAPINodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := models.SharedAPINodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedAPINodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -678,7 +716,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.DNSNodeVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedNSNodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := models.SharedNSNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedNSNodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -691,7 +731,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||
NewVersion: teaconst.ReportNodeVersion,
|
||||
}
|
||||
this.BeginTag(ctx, "SharedReportNodeDAO.CountAllLowerVersionNodes")
|
||||
countNodes, err := models.SharedReportNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
||||
this.EndTag(ctx, "SharedReportNodeDAO.CountAllLowerVersionNodes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -700,7 +742,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
}
|
||||
|
||||
// 域名排行
|
||||
this.BeginTag(ctx, "SharedServerDomainHourlyStatDAO.FindTopDomainStats")
|
||||
topDomainStats, err := stats.SharedServerDomainHourlyStatDAO.FindTopDomainStats(tx, hourFrom, hourTo, 10)
|
||||
this.EndTag(ctx, "SharedServerDomainHourlyStatDAO.FindTopDomainStats")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -715,7 +759,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
|
||||
// 节点排行
|
||||
if isPlus {
|
||||
this.BeginTag(ctx, "SharedNodeTrafficHourlyStatDAO.FindTopNodeStats")
|
||||
topNodeStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindTopNodeStats(tx, "node", hourFrom, hourTo, 10)
|
||||
this.EndTag(ctx, "SharedNodeTrafficHourlyStatDAO.FindTopNodeStats")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -738,7 +784,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
|
||||
// 地区流量排行
|
||||
if isPlus {
|
||||
this.BeginTag(ctx, "SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes")
|
||||
totalCountryBytes, err := stats.SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes(tx, timeutil.Format("Ymd"))
|
||||
this.EndTag(ctx, "SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -767,7 +815,9 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
}
|
||||
|
||||
// 指标数据
|
||||
this.BeginTag(ctx, "findMetricDataCharts")
|
||||
pbCharts, err := this.findMetricDataCharts(tx)
|
||||
this.EndTag(ctx, "findMetricDataCharts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
83
internal/rpc/services/service_api_method_stat.go
Normal file
83
internal/rpc/services/service_api_method_stat.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
// APIMethodStatService API方法统计服务
|
||||
type APIMethodStatService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// FindAPIMethodStatsWithDay 查找某天的统计
|
||||
func (this *APIMethodStatService) FindAPIMethodStatsWithDay(ctx context.Context, req *pb.FindAPIMethodStatsWithDayRequest) (*pb.FindAPIMethodStatsWithDayResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var day = req.Day
|
||||
if len(day) == 0 {
|
||||
day = timeutil.Format("Ymd")
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
stats, err := models.SharedAPIMethodStatDAO.FindAllStatsWithDay(tx, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbStats = []*pb.APIMethodStat{}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
for _, stat := range stats {
|
||||
apiNode, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, int64(stat.ApiNodeId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if apiNode == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pbStats = append(pbStats, &pb.APIMethodStat{
|
||||
Id: int64(stat.Id),
|
||||
ApiNodeId: int64(stat.ApiNodeId),
|
||||
Method: stat.Method,
|
||||
Tag: stat.Tag,
|
||||
CostMs: float32(stat.CostMs),
|
||||
PeekMs: float32(stat.PeekMs),
|
||||
CountCalls: int64(stat.CountCalls),
|
||||
ApiNode: &pb.APINode{
|
||||
Id: int64(apiNode.Id),
|
||||
Name: apiNode.Name,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAPIMethodStatsWithDayResponse{
|
||||
ApiMethodStats: pbStats,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CountAPIMethodStatsWithDay 检查是否有统计数据
|
||||
func (this *APIMethodStatService) CountAPIMethodStatsWithDay(ctx context.Context, req *pb.CountAPIMethodStatsWithDayRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var day = req.Day
|
||||
if len(day) == 0 {
|
||||
day = timeutil.Format("Ymd")
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedAPIMethodStatDAO.CountAllStatsWithDay(tx, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
@@ -189,7 +189,7 @@ func (this *APINodeService) FindEnabledAPINode(ctx context.Context, req *pb.Find
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
node, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, req.ApiNodeId)
|
||||
node, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, req.ApiNodeId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -241,7 +241,7 @@ func (this *APINodeService) FindCurrentAPINode(ctx context.Context, req *pb.Find
|
||||
|
||||
var nodeId = teaconst.NodeId
|
||||
var tx *dbs.Tx
|
||||
node, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, nodeId)
|
||||
node, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, nodeId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -295,3 +295,14 @@ func (this *APINodeService) CountAllEnabledAPINodesWithSSLCertId(ctx context.Con
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// DebugAPINode 修改调试模式状态
|
||||
func (this *APINodeService) DebugAPINode(ctx context.Context, req *pb.DebugAPINodeRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
teaconst.Debug = req.Debug
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/authority"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/encrypt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -102,6 +103,11 @@ func (this *BaseService) ValidateAuthorityNode(ctx context.Context) (nodeId int6
|
||||
|
||||
// ValidateNodeId 获取节点ID
|
||||
func (this *BaseService) ValidateNodeId(ctx context.Context, roles ...rpcutils.UserType) (role rpcutils.UserType, nodeIntId int64, err error) {
|
||||
// 默认包含大部分节点
|
||||
if len(roles) == 0 {
|
||||
roles = []rpcutils.UserType{rpcutils.UserTypeNode, rpcutils.UserTypeCluster, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser, rpcutils.UserTypeDNS, rpcutils.UserTypeReport, rpcutils.UserTypeMonitor, rpcutils.UserTypeLog}
|
||||
}
|
||||
|
||||
if ctx == nil {
|
||||
err = errors.New("context should not be nil")
|
||||
role = rpcutils.UserTypeNone
|
||||
@@ -231,3 +237,25 @@ func (this *BaseService) RunTx(callback func(tx *dbs.Tx) error) error {
|
||||
}
|
||||
return db.RunTx(callback)
|
||||
}
|
||||
|
||||
// BeginTag 开始标签统计
|
||||
func (this *BaseService) BeginTag(ctx context.Context, name string) {
|
||||
if !teaconst.Debug {
|
||||
return
|
||||
}
|
||||
traceCtx, ok := ctx.(*rpc.Context)
|
||||
if ok {
|
||||
traceCtx.Begin(name)
|
||||
}
|
||||
}
|
||||
|
||||
// EndTag 结束标签统计
|
||||
func (this *BaseService) EndTag(ctx context.Context, name string) {
|
||||
if !teaconst.Debug {
|
||||
return
|
||||
}
|
||||
traceCtx, ok := ctx.(*rpc.Context)
|
||||
if ok {
|
||||
traceCtx.End(name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,3 +299,21 @@ func (this *FirewallService) NotifyHTTPFirewallEvent(ctx context.Context, req *p
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountFirewallDailyBlocks 读取当前Block动作次数
|
||||
func (this *FirewallService) CountFirewallDailyBlocks(ctx context.Context, req *pb.CountFirewallDailyBlocksRequest) (*pb.CountFirewallDailyBlocksResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var day = timeutil.Format("Ymd")
|
||||
countDailyBlock, err := stats.SharedServerHTTPFirewallDailyStatDAO.SumDailyCount(tx, 0, 0, "block", day, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.CountFirewallDailyBlocksResponse{
|
||||
CountBlocks: countDailyBlock,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func (this *HTTPAccessLogService) ListHTTPAccessLogs(ctx context.Context, req *p
|
||||
}
|
||||
}
|
||||
|
||||
accessLogs, requestId, hasMore, err := models.SharedHTTPAccessLogDAO.ListAccessLogs(tx, req.RequestId, req.Size, req.Day, req.ServerId, req.Reverse, req.HasError, req.FirewallPolicyId, req.FirewallRuleGroupId, req.FirewallRuleSetId, req.HasFirewallPolicy, req.UserId, req.Keyword, req.Ip, req.Domain)
|
||||
accessLogs, requestId, hasMore, err := models.SharedHTTPAccessLogDAO.ListAccessLogs(tx, req.RequestId, req.Size, req.Day, req.NodeClusterId, req.NodeId, req.ServerId, req.Reverse, req.HasError, req.FirewallPolicyId, req.FirewallRuleGroupId, req.FirewallRuleSetId, req.HasFirewallPolicy, req.UserId, req.Keyword, req.Ip, req.Domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func (this *HTTPCachePolicyService) CountAllEnabledHTTPCachePolicies(ctx context
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := models.SharedHTTPCachePolicyDAO.CountAllEnabledHTTPCachePolicies(tx, req.Keyword)
|
||||
count, err := models.SharedHTTPCachePolicyDAO.CountAllEnabledHTTPCachePolicies(tx, req.NodeClusterId, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func (this *HTTPCachePolicyService) ListEnabledHTTPCachePolicies(ctx context.Con
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
cachePolicies, err := models.SharedHTTPCachePolicyDAO.ListEnabledHTTPCachePolicies(tx, req.Keyword, req.Offset, req.Size)
|
||||
cachePolicies, err := models.SharedHTTPCachePolicyDAO.ListEnabledHTTPCachePolicies(tx, req.NodeClusterId, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -37,13 +37,14 @@ func (this *HTTPFirewallPolicyService) FindAllEnabledHTTPFirewallPolicies(ctx co
|
||||
result := []*pb.HTTPFirewallPolicy{}
|
||||
for _, p := range policies {
|
||||
result = append(result, &pb.HTTPFirewallPolicy{
|
||||
Id: int64(p.Id),
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
IsOn: p.IsOn == 1,
|
||||
InboundJSON: []byte(p.Inbound),
|
||||
OutboundJSON: []byte(p.Outbound),
|
||||
Mode: p.Mode,
|
||||
Id: int64(p.Id),
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
IsOn: p.IsOn == 1,
|
||||
InboundJSON: []byte(p.Inbound),
|
||||
OutboundJSON: []byte(p.Outbound),
|
||||
Mode: p.Mode,
|
||||
UseLocalFirewall: p.UseLocalFirewall == 1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -284,7 +285,15 @@ func (this *HTTPFirewallPolicyService) UpdateHTTPFirewallPolicy(ctx context.Cont
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = models.SharedHTTPFirewallPolicyDAO.UpdateFirewallPolicy(tx, req.HttpFirewallPolicyId, req.IsOn, req.Name, req.Description, inboundConfigJSON, outboundConfigJSON, req.BlockOptionsJSON, req.Mode)
|
||||
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
|
||||
if len(req.SynFloodJSON) > 0 {
|
||||
err = json.Unmarshal(req.SynFloodJSON, synFloodConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedHTTPFirewallPolicyDAO.UpdateFirewallPolicy(tx, req.HttpFirewallPolicyId, req.IsOn, req.Name, req.Description, inboundConfigJSON, outboundConfigJSON, req.BlockOptionsJSON, req.Mode, req.UseLocalFirewall, synFloodConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -352,7 +361,7 @@ func (this *HTTPFirewallPolicyService) CountAllEnabledHTTPFirewallPolicies(ctx c
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := models.SharedHTTPFirewallPolicyDAO.CountAllEnabledFirewallPolicies(tx, req.Keyword)
|
||||
count, err := models.SharedHTTPFirewallPolicyDAO.CountAllEnabledFirewallPolicies(tx, req.NodeClusterId, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -369,7 +378,7 @@ func (this *HTTPFirewallPolicyService) ListEnabledHTTPFirewallPolicies(ctx conte
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
policies, err := models.SharedHTTPFirewallPolicyDAO.ListEnabledFirewallPolicies(tx, req.Keyword, req.Offset, req.Size)
|
||||
policies, err := models.SharedHTTPFirewallPolicyDAO.ListEnabledFirewallPolicies(tx, req.NodeClusterId, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -377,13 +386,14 @@ func (this *HTTPFirewallPolicyService) ListEnabledHTTPFirewallPolicies(ctx conte
|
||||
result := []*pb.HTTPFirewallPolicy{}
|
||||
for _, p := range policies {
|
||||
result = append(result, &pb.HTTPFirewallPolicy{
|
||||
Id: int64(p.Id),
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
IsOn: p.IsOn == 1,
|
||||
InboundJSON: []byte(p.Inbound),
|
||||
OutboundJSON: []byte(p.Outbound),
|
||||
Mode: p.Mode,
|
||||
Id: int64(p.Id),
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
IsOn: p.IsOn == 1,
|
||||
InboundJSON: []byte(p.Inbound),
|
||||
OutboundJSON: []byte(p.Outbound),
|
||||
Mode: p.Mode,
|
||||
UseLocalFirewall: p.UseLocalFirewall == 1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -468,12 +478,14 @@ func (this *HTTPFirewallPolicyService) FindEnabledHTTPFirewallPolicy(ctx context
|
||||
}
|
||||
return &pb.FindEnabledHTTPFirewallPolicyResponse{HttpFirewallPolicy: &pb.HTTPFirewallPolicy{
|
||||
Id: int64(policy.Id),
|
||||
ServerId: int64(policy.ServerId),
|
||||
Name: policy.Name,
|
||||
Description: policy.Description,
|
||||
IsOn: policy.IsOn == 1,
|
||||
InboundJSON: []byte(policy.Inbound),
|
||||
OutboundJSON: []byte(policy.Outbound),
|
||||
Mode: policy.Mode,
|
||||
SynFloodJSON: []byte(policy.SynFlood),
|
||||
}}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -704,3 +704,46 @@ func (this *HTTPWebService) FindHTTPWebRequestLimit(ctx context.Context, req *pb
|
||||
|
||||
return &pb.FindHTTPWebRequestLimitResponse{RequestLimitJSON: configJSON}, nil
|
||||
}
|
||||
|
||||
// UpdateHTTPWebRequestScripts 修改请求脚本
|
||||
func (this *HTTPWebService) UpdateHTTPWebRequestScripts(ctx context.Context, req *pb.UpdateHTTPWebRequestScriptsRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var config = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
err = json.Unmarshal(req.RequestScriptsJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = models.SharedHTTPWebDAO.UpdateWebRequestScripts(tx, req.HttpWebId, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindHTTPWebRequestScripts 查找请求脚本
|
||||
func (this *HTTPWebService) FindHTTPWebRequestScripts(ctx context.Context, req *pb.FindHTTPWebRequestScriptsRequest) (*pb.FindHTTPWebRequestScriptsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
config, err := models.SharedHTTPWebDAO.FindWebRequestScripts(tx, req.HttpWebId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindHTTPWebRequestScriptsResponse{
|
||||
RequestScriptsJSON: configJSON,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -280,6 +280,7 @@ func (this *IPItemService) ListIPItemsWithListId(ctx context.Context, req *pb.Li
|
||||
SourceHTTPFirewallPolicy: pbSourcePolicy,
|
||||
SourceHTTPFirewallRuleGroup: pbSourceGroup,
|
||||
SourceHTTPFirewallRuleSet: pbSourceSet,
|
||||
IsRead: item.IsRead == 1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -483,7 +484,7 @@ func (this *IPItemService) CountAllEnabledIPItems(ctx context.Context, req *pb.C
|
||||
if req.GlobalOnly {
|
||||
listId = firewallconfigs.GlobalListId
|
||||
}
|
||||
count, err := models.SharedIPItemDAO.CountAllEnabledIPItems(tx, req.Ip, listId)
|
||||
count, err := models.SharedIPItemDAO.CountAllEnabledIPItems(tx, req.Ip, listId, req.Unread)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -503,7 +504,7 @@ func (this *IPItemService) ListAllEnabledIPItems(ctx context.Context, req *pb.Li
|
||||
if req.GlobalOnly {
|
||||
listId = firewallconfigs.GlobalListId
|
||||
}
|
||||
items, err := models.SharedIPItemDAO.ListAllEnabledIPItems(tx, req.Ip, listId, req.Offset, req.Size)
|
||||
items, err := models.SharedIPItemDAO.ListAllEnabledIPItems(tx, req.Ip, listId, req.Unread, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -565,6 +566,22 @@ func (this *IPItemService) ListAllEnabledIPItems(ctx context.Context, req *pb.Li
|
||||
}
|
||||
}
|
||||
|
||||
// 节点
|
||||
var pbSourceNode *pb.Node
|
||||
if item.SourceNodeId > 0 {
|
||||
node, err := models.SharedNodeDAO.FindEnabledBasicNode(tx, int64(item.SourceNodeId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if node != nil {
|
||||
pbSourceNode = &pb.Node{
|
||||
Id: int64(node.Id),
|
||||
Name: node.Name,
|
||||
NodeCluster: &pb.NodeCluster{Id: int64(node.ClusterId)},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pbItem = &pb.IPItem{
|
||||
Id: int64(item.Id),
|
||||
IpFrom: item.IpFrom,
|
||||
@@ -586,6 +603,8 @@ func (this *IPItemService) ListAllEnabledIPItems(ctx context.Context, req *pb.Li
|
||||
SourceHTTPFirewallPolicy: pbSourcePolicy,
|
||||
SourceHTTPFirewallRuleGroup: pbSourceGroup,
|
||||
SourceHTTPFirewallRuleSet: pbSourceSet,
|
||||
SourceNode: pbSourceNode,
|
||||
IsRead: item.IsRead == 1,
|
||||
}
|
||||
|
||||
// 所属名单
|
||||
@@ -656,3 +675,18 @@ func (this *IPItemService) ListAllEnabledIPItems(ctx context.Context, req *pb.Li
|
||||
|
||||
return &pb.ListAllEnabledIPItemsResponse{Results: results}, nil
|
||||
}
|
||||
|
||||
// UpdateIPItemsRead 设置所有为已读
|
||||
func (this *IPItemService) UpdateIPItemsRead(ctx context.Context, req *pb.UpdateIPItemsReadRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedIPItemDAO.UpdateItemsRead(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (this *NodeClusterService) UpdateNodeCluster(ctx context.Context, req *pb.U
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.NodeTCPMaxConnections)
|
||||
err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.NodeTCPMaxConnections, req.AutoOpenPorts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -163,6 +163,7 @@ func (this *NodeClusterService) FindEnabledNodeCluster(ctx context.Context, req
|
||||
TimeZone: cluster.TimeZone,
|
||||
NodeMaxThreads: int32(cluster.NodeMaxThreads),
|
||||
NodeTCPMaxConnections: int32(cluster.NodeTCPMaxConnections),
|
||||
AutoOpenPorts: cluster.AutoOpenPorts == 1,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
@@ -196,7 +197,7 @@ func (this *NodeClusterService) FindAPINodesWithNodeCluster(ctx context.Context,
|
||||
if len(apiNodeIds) > 0 {
|
||||
apiNodes := []*pb.APINode{}
|
||||
for _, apiNodeId := range apiNodeIds {
|
||||
apiNode, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId)
|
||||
apiNode, err := models.SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func (this *NodeLogService) CountNodeLogs(ctx context.Context, req *pb.CountNode
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeLogDAO.CountNodeLogs(tx, req.Role, req.NodeId, req.ServerId, req.OriginId, req.DayFrom, req.DayTo, req.Keyword, req.Level, req.IsUnread)
|
||||
count, err := models.SharedNodeLogDAO.CountNodeLogs(tx, req.Role, req.NodeClusterId, req.NodeId, req.ServerId, req.OriginId, req.DayFrom, req.DayTo, req.Keyword, req.Level, req.IsUnread, req.Tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func (this *NodeLogService) ListNodeLogs(ctx context.Context, req *pb.ListNodeLo
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
logs, err := models.SharedNodeLogDAO.ListNodeLogs(tx, req.Role, req.NodeId, req.ServerId, req.OriginId, req.AllServers, req.DayFrom, req.DayTo, req.Keyword, req.Level, types.Int8(req.FixedState), req.IsUnread, req.Offset, req.Size)
|
||||
logs, err := models.SharedNodeLogDAO.ListNodeLogs(tx, req.Role, req.NodeClusterId, req.NodeId, req.ServerId, req.OriginId, req.AllServers, req.DayFrom, req.DayTo, req.Keyword, req.Level, types.Int8(req.FixedState), req.IsUnread, req.Tag, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ func (this *NodeTaskService) FindNodeTasks(ctx context.Context, req *pb.FindNode
|
||||
Type: task.Type,
|
||||
Version: int64(task.Version),
|
||||
IsPrimary: primaryNodeId == nodeId,
|
||||
ServerId: int64(task.ServerId),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -137,6 +138,7 @@ func (this *NodeTaskService) FindNodeClusterTasks(ctx context.Context, req *pb.F
|
||||
IsOk: task.IsOk == 1,
|
||||
Error: task.Error,
|
||||
UpdatedAt: int64(task.UpdatedAt),
|
||||
ServerId: int64(task.ServerId),
|
||||
Node: &pb.Node{
|
||||
Id: int64(task.NodeId),
|
||||
Name: nodeName,
|
||||
@@ -261,6 +263,7 @@ func (this *NodeTaskService) FindNotifyingNodeTasks(ctx context.Context, req *pb
|
||||
Error: task.Error,
|
||||
UpdatedAt: int64(task.UpdatedAt),
|
||||
Node: &pb.Node{Id: int64(task.NodeId)},
|
||||
ServerId: int64(task.ServerId),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
@@ -58,7 +59,20 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.Domains)
|
||||
// cert
|
||||
var certRef *sslconfigs.SSLCertRef
|
||||
if len(req.CertRefJSON) > 0 {
|
||||
certRef = &sslconfigs.SSLCertRef{}
|
||||
err = json.Unmarshal(req.CertRefJSON, certRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if certRef.CertId <= 0 {
|
||||
certRef = nil
|
||||
}
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -112,7 +126,20 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.Domains)
|
||||
// cert
|
||||
var certRef *sslconfigs.SSLCertRef
|
||||
if len(req.CertRefJSON) > 0 {
|
||||
certRef = &sslconfigs.SSLCertRef{}
|
||||
err = json.Unmarshal(req.CertRefJSON, certRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if certRef.CertId <= 0 {
|
||||
certRef = nil
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package services
|
||||
|
||||
|
||||
70
internal/rpc/services/service_region_city.go
Normal file
70
internal/rpc/services/service_region_city.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// RegionCityService 城市相关服务
|
||||
type RegionCityService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// FindAllEnabledRegionCities 查找所有城市
|
||||
func (this *RegionCityService) FindAllEnabledRegionCities(ctx context.Context, req *pb.FindAllEnabledRegionCitiesRequest) (*pb.FindAllEnabledRegionCitiesResponse, error) {
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
cities, err := regions.SharedRegionCityDAO.FindAllEnabledCities(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbCities = []*pb.RegionCity{}
|
||||
for _, city := range cities {
|
||||
pbCities = append(pbCities, &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledRegionCitiesResponse{
|
||||
RegionCities: pbCities,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledRegionCity 查找单个城市信息
|
||||
func (this *RegionCityService) FindEnabledRegionCity(ctx context.Context, req *pb.FindEnabledRegionCityRequest) (*pb.FindEnabledRegionCityResponse, error) {
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
city, err := regions.SharedRegionCityDAO.FindEnabledRegionCity(tx, req.RegionCityId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if city == nil {
|
||||
return &pb.FindEnabledRegionCityResponse{
|
||||
RegionCity: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledRegionCityResponse{
|
||||
RegionCity: &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
@@ -16,7 +15,7 @@ type RegionCountryService struct {
|
||||
// FindAllEnabledRegionCountries 查找所有的国家列表
|
||||
func (this *RegionCountryService) FindAllEnabledRegionCountries(ctx context.Context, req *pb.FindAllEnabledRegionCountriesRequest) (*pb.FindAllEnabledRegionCountriesResponse, error) {
|
||||
// 校验请求
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeNode)
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -47,29 +46,29 @@ func (this *RegionCountryService) FindAllEnabledRegionCountries(ctx context.Cont
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledRegionCountriesResponse{
|
||||
Countries: result,
|
||||
RegionCountries: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledRegionCountry 查找单个国家信息
|
||||
func (this *RegionCountryService) FindEnabledRegionCountry(ctx context.Context, req *pb.FindEnabledRegionCountryRequest) (*pb.FindEnabledRegionCountryResponse, error) {
|
||||
// 校验请求
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeNode)
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
country, err := regions.SharedRegionCountryDAO.FindEnabledRegionCountry(tx, req.CountryId)
|
||||
country, err := regions.SharedRegionCountryDAO.FindEnabledRegionCountry(tx, req.RegionCountryId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if country == nil {
|
||||
return &pb.FindEnabledRegionCountryResponse{Country: nil}, nil
|
||||
return &pb.FindEnabledRegionCountryResponse{RegionCountry: nil}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledRegionCountryResponse{Country: &pb.RegionCountry{
|
||||
return &pb.FindEnabledRegionCountryResponse{RegionCountry: &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Name: country.Name,
|
||||
Codes: country.DecodeCodes(),
|
||||
|
||||
68
internal/rpc/services/service_region_provider.go
Normal file
68
internal/rpc/services/service_region_provider.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// RegionProviderService ISP相关服务
|
||||
type RegionProviderService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// FindAllEnabledRegionProviders 查找所有ISP
|
||||
func (this *RegionProviderService) FindAllEnabledRegionProviders(ctx context.Context, req *pb.FindAllEnabledRegionProvidersRequest) (*pb.FindAllEnabledRegionProvidersResponse, error) {
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
providers, err := regions.SharedRegionProviderDAO.FindAllEnabledProviders(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbProviders = []*pb.RegionProvider{}
|
||||
for _, provider := range providers {
|
||||
pbProviders = append(pbProviders, &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Name: provider.Name,
|
||||
Codes: provider.DecodeCodes(),
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledRegionProvidersResponse{
|
||||
RegionProviders: pbProviders,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledRegionProvider 查找单个ISP信息
|
||||
func (this *RegionProviderService) FindEnabledRegionProvider(ctx context.Context, req *pb.FindEnabledRegionProviderRequest) (*pb.FindEnabledRegionProviderResponse, error) {
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
provider, err := regions.SharedRegionProviderDAO.FindEnabledRegionProvider(tx, req.RegionProviderId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if provider == nil {
|
||||
return &pb.FindEnabledRegionProviderResponse{
|
||||
RegionProvider: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledRegionProviderResponse{
|
||||
RegionProvider: &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Name: provider.Name,
|
||||
Codes: provider.DecodeCodes(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
@@ -15,14 +14,14 @@ type RegionProvinceService struct {
|
||||
// FindAllEnabledRegionProvincesWithCountryId 查找所有省份
|
||||
func (this *RegionProvinceService) FindAllEnabledRegionProvincesWithCountryId(ctx context.Context, req *pb.FindAllEnabledRegionProvincesWithCountryIdRequest) (*pb.FindAllEnabledRegionProvincesWithCountryIdResponse, error) {
|
||||
// 校验请求
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeNode)
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
provinces, err := regions.SharedRegionProvinceDAO.FindAllEnabledProvincesWithCountryId(tx, req.CountryId)
|
||||
provinces, err := regions.SharedRegionProvinceDAO.FindAllEnabledProvincesWithCountryId(tx, req.RegionCountryId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -36,30 +35,30 @@ func (this *RegionProvinceService) FindAllEnabledRegionProvincesWithCountryId(ct
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledRegionProvincesWithCountryIdResponse{
|
||||
Provinces: result,
|
||||
RegionProvinces: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledRegionProvince 查找单个省份信息
|
||||
func (this *RegionProvinceService) FindEnabledRegionProvince(ctx context.Context, req *pb.FindEnabledRegionProvinceRequest) (*pb.FindEnabledRegionProvinceResponse, error) {
|
||||
// 校验请求
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeNode)
|
||||
_, _, err := this.ValidateNodeId(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
province, err := regions.SharedRegionProvinceDAO.FindEnabledRegionProvince(tx, req.ProvinceId)
|
||||
province, err := regions.SharedRegionProvinceDAO.FindEnabledRegionProvince(tx, req.RegionProvinceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if province == nil {
|
||||
return &pb.FindEnabledRegionProvinceResponse{Province: nil}, nil
|
||||
return &pb.FindEnabledRegionProvinceResponse{RegionProvince: nil}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledRegionProvinceResponse{
|
||||
Province: &pb.RegionProvince{
|
||||
RegionProvince: &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
@@ -71,6 +72,20 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe
|
||||
if nodeClusterId > 0 {
|
||||
req.NodeClusterId = nodeClusterId
|
||||
}
|
||||
|
||||
// 服务分组
|
||||
for _, groupId := range req.ServerGroupIds {
|
||||
err := models.SharedServerGroupDAO.CheckUserGroup(tx, userId, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 增加默认分组
|
||||
config, err := models.SharedSysSettingDAO.ReadUserServerConfig(tx)
|
||||
if err == nil && config.GroupId > 0 && !lists.ContainsInt64(req.ServerGroupIds, config.GroupId) {
|
||||
req.ServerGroupIds = append(req.ServerGroupIds, config.GroupId)
|
||||
}
|
||||
} else if req.UserId > 0 {
|
||||
// 集群
|
||||
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, req.UserId)
|
||||
@@ -691,6 +706,7 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
|
||||
AuditingResult: auditingResult,
|
||||
CreatedAt: int64(server.CreatedAt),
|
||||
DnsName: server.DnsName,
|
||||
UserPlanId: int64(server.UserPlanId),
|
||||
NodeCluster: &pb.NodeCluster{
|
||||
Id: int64(server.ClusterId),
|
||||
Name: clusterName,
|
||||
@@ -1085,14 +1101,14 @@ func (this *ServerService) CountAllEnabledServersWithNodeClusterId(ctx context.C
|
||||
// CountAllEnabledServersWithServerGroupId 计算使用某个分组的服务数量
|
||||
func (this *ServerService) CountAllEnabledServersWithServerGroupId(ctx context.Context, req *pb.CountAllEnabledServersWithServerGroupIdRequest) (*pb.RPCCountResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := models.SharedServerDAO.CountAllEnabledServersWithGroupId(tx, req.ServerGroupId)
|
||||
count, err := models.SharedServerDAO.CountAllEnabledServersWithGroupId(tx, req.ServerGroupId, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1908,3 +1924,29 @@ func (this *ServerService) FindServerUserPlan(ctx context.Context, req *pb.FindS
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ComposeServerConfig 获取服务配置
|
||||
func (this *ServerService) ComposeServerConfig(ctx context.Context, req *pb.ComposeServerConfigRequest) (*pb.ComposeServerConfigResponse, error) {
|
||||
_, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
serverConfig, err := models.SharedServerDAO.ComposeServerConfigWithServerId(tx, req.ServerId, true)
|
||||
if err != nil {
|
||||
if err == models.ErrNotFound {
|
||||
return &pb.ComposeServerConfigResponse{ServerConfigJSON: nil}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if serverConfig == nil {
|
||||
return &pb.ComposeServerConfigResponse{ServerConfigJSON: nil}, nil
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(serverConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.ComposeServerConfigResponse{ServerConfigJSON: configJSON}, nil
|
||||
}
|
||||
|
||||
132
internal/rpc/services/service_server_bill.go
Normal file
132
internal/rpc/services/service_server_bill.go
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// ServerBillService 服务账单相关服务
|
||||
type ServerBillService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CountAllServerBills 查询服务账单数量
|
||||
func (this *ServerBillService) CountAllServerBills(ctx context.Context, req *pb.CountAllServerBillsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedServerBillDAO.CountServerBills(tx, req.UserId, req.Month)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListServerBills 查询服务账单列表
|
||||
func (this *ServerBillService) ListServerBills(ctx context.Context, req *pb.ListServerBillsRequest) (*pb.ListServerBillsResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
serverBills, err := models.SharedServerBillDAO.ListServerBills(tx, req.UserId, req.Month, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbServerBills = []*pb.ServerBill{}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
for _, bill := range serverBills {
|
||||
// user
|
||||
user, err := models.SharedUserDAO.FindBasicUserWithoutState(tx, int64(bill.UserId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbUser = &pb.User{Id: int64(bill.UserId)}
|
||||
if user != nil {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(bill.UserId),
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
// plan
|
||||
var pbPlan *pb.Plan
|
||||
if bill.PlanId > 0 {
|
||||
plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(bill.PlanId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if plan != nil {
|
||||
pbPlan = &pb.Plan{
|
||||
Id: int64(plan.Id),
|
||||
Name: plan.Name,
|
||||
PriceType: plan.PriceType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// user plan
|
||||
var pbUserPlan *pb.UserPlan
|
||||
if bill.UserPlanId > 0 {
|
||||
userPlan, err := models.SharedUserPlanDAO.FindEnabledUserPlan(tx, int64(bill.UserPlanId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userPlan != nil {
|
||||
pbUserPlan = &pb.UserPlan{
|
||||
Id: int64(userPlan.Id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// server
|
||||
var pbServer *pb.Server
|
||||
if bill.ServerId > 0 {
|
||||
server, err := models.SharedServerDAO.FindEnabledServerBasic(tx, int64(bill.ServerId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if server != nil {
|
||||
pbServer = &pb.Server{Id: int64(bill.ServerId), Name: server.Name}
|
||||
}
|
||||
}
|
||||
|
||||
pbServerBills = append(pbServerBills, &pb.ServerBill{
|
||||
Id: int64(bill.Id),
|
||||
UserId: int64(bill.UserId),
|
||||
ServerId: int64(bill.ServerId),
|
||||
Amount: float32(bill.Amount),
|
||||
PriceType: bill.PriceType,
|
||||
CreatedAt: int64(bill.CreatedAt),
|
||||
UserPlanId: int64(bill.UserPlanId),
|
||||
PlanId: int64(bill.PlanId),
|
||||
TotalTrafficBytes: int64(bill.TotalTrafficBytes),
|
||||
BandwidthPercentileBytes: int64(bill.BandwidthPercentileBytes),
|
||||
BandwidthPercentile: int32(bill.BandwidthPercentile),
|
||||
User: pbUser,
|
||||
Plan: pbPlan,
|
||||
UserPlan: pbUserPlan,
|
||||
Server: pbServer,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListServerBillsResponse{ServerBills: pbServerBills}, nil
|
||||
}
|
||||
@@ -16,14 +16,14 @@ type ServerGroupService struct {
|
||||
// CreateServerGroup 创建分组
|
||||
func (this *ServerGroupService) CreateServerGroup(ctx context.Context, req *pb.CreateServerGroupRequest) (*pb.CreateServerGroupResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
groupId, err := models.SharedServerGroupDAO.CreateGroup(tx, req.Name)
|
||||
groupId, err := models.SharedServerGroupDAO.CreateGroup(tx, req.Name, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -33,13 +33,21 @@ func (this *ServerGroupService) CreateServerGroup(ctx context.Context, req *pb.C
|
||||
// UpdateServerGroup 修改分组
|
||||
func (this *ServerGroupService) UpdateServerGroup(ctx context.Context, req *pb.UpdateServerGroupRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 检查用户权限
|
||||
if userId > 0 {
|
||||
err = models.SharedServerGroupDAO.CheckUserGroup(tx, userId, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedServerGroupDAO.UpdateGroup(tx, req.ServerGroupId, req.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -51,13 +59,21 @@ func (this *ServerGroupService) UpdateServerGroup(ctx context.Context, req *pb.U
|
||||
// DeleteServerGroup 删除分组
|
||||
func (this *ServerGroupService) DeleteServerGroup(ctx context.Context, req *pb.DeleteServerGroupRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 检查用户权限
|
||||
if userId > 0 {
|
||||
err = models.SharedServerGroupDAO.CheckUserGroup(tx, userId, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedServerGroupDAO.DisableServerGroup(tx, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -69,14 +85,14 @@ func (this *ServerGroupService) DeleteServerGroup(ctx context.Context, req *pb.D
|
||||
// FindAllEnabledServerGroups 查询所有分组
|
||||
func (this *ServerGroupService) FindAllEnabledServerGroups(ctx context.Context, req *pb.FindAllEnabledServerGroupsRequest) (*pb.FindAllEnabledServerGroupsResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
groups, err := models.SharedServerGroupDAO.FindAllEnabledGroups(tx)
|
||||
groups, err := models.SharedServerGroupDAO.FindAllEnabledGroups(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -93,14 +109,14 @@ func (this *ServerGroupService) FindAllEnabledServerGroups(ctx context.Context,
|
||||
// UpdateServerGroupOrders 修改分组排序
|
||||
func (this *ServerGroupService) UpdateServerGroupOrders(ctx context.Context, req *pb.UpdateServerGroupOrdersRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
err = models.SharedServerGroupDAO.UpdateGroupOrders(tx, req.ServerGroupIds)
|
||||
err = models.SharedServerGroupDAO.UpdateGroupOrders(tx, req.ServerGroupIds, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -110,7 +126,7 @@ func (this *ServerGroupService) UpdateServerGroupOrders(ctx context.Context, req
|
||||
// FindEnabledServerGroup 查找单个分组信息
|
||||
func (this *ServerGroupService) FindEnabledServerGroup(ctx context.Context, req *pb.FindEnabledServerGroupRequest) (*pb.FindEnabledServerGroupResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,6 +143,13 @@ func (this *ServerGroupService) FindEnabledServerGroup(ctx context.Context, req
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 检查用户权限
|
||||
if userId > 0 && int64(group.UserId) != userId {
|
||||
return &pb.FindEnabledServerGroupResponse{
|
||||
ServerGroup: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledServerGroupResponse{
|
||||
ServerGroup: &pb.ServerGroup{
|
||||
Id: int64(group.Id),
|
||||
@@ -354,13 +377,30 @@ func (this *ServerGroupService) UpdateServerGroupUDPReverseProxy(ctx context.Con
|
||||
// FindEnabledServerGroupConfigInfo 取得分组的配置概要信息
|
||||
func (this *ServerGroupService) FindEnabledServerGroupConfigInfo(ctx context.Context, req *pb.FindEnabledServerGroupConfigInfoRequest) (*pb.FindEnabledServerGroupConfigInfoResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 检查用户权限
|
||||
if userId > 0 {
|
||||
if req.ServerId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if req.ServerGroupId > 0 {
|
||||
err = models.SharedServerGroupDAO.CheckUserGroup(tx, userId, req.ServerGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var group *models.ServerGroup
|
||||
if req.ServerGroupId > 0 {
|
||||
group, err = models.SharedServerGroupDAO.FindEnabledServerGroup(tx, req.ServerGroupId)
|
||||
|
||||
@@ -37,7 +37,7 @@ func (this *ServerRegionProviderMonthlyStatService) FindTopServerRegionProviderM
|
||||
pbStat := &pb.FindTopServerRegionProviderMonthlyStatsResponse_Stat{
|
||||
Count: int64(stat.Count),
|
||||
}
|
||||
provider, err := regions.SharedRegionProviderDAO.FindEnabledRegionProvider(tx, stat.ProviderId)
|
||||
provider, err := regions.SharedRegionProviderDAO.FindEnabledRegionProvider(tx, int64(stat.ProviderId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
}
|
||||
result.CountInactiveNodes = countInactiveNodes
|
||||
|
||||
countUsers, err := models.SharedUserDAO.CountAllEnabledUsers(tx, req.NodeClusterId, "")
|
||||
countUsers, err := models.SharedUserDAO.CountAllEnabledUsers(tx, req.NodeClusterId, "", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user