Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86b04b2b6b | ||
|
|
7a5ec79ace | ||
|
|
7290ffd2cd | ||
|
|
2f361c5bcc | ||
|
|
500d72aaf3 | ||
|
|
9fc391d1e8 | ||
|
|
c86e3e2047 | ||
|
|
7e72a90f53 | ||
|
|
7692fed38d | ||
|
|
bdd7d2a181 | ||
|
|
118c3f79e4 | ||
|
|
804a33a002 | ||
|
|
fe00588039 | ||
|
|
67aac200a7 | ||
|
|
3e01ad4b68 | ||
|
|
b39690484e | ||
|
|
31a69ecb12 | ||
|
|
94b95beadf | ||
|
|
6143f08cf2 | ||
|
|
73a5814fd6 | ||
|
|
448152d5c2 | ||
|
|
eedb3fb338 | ||
|
|
06f6f68f3a | ||
|
|
903e524e80 | ||
|
|
fa6b4fcaee | ||
|
|
67cc8e515f | ||
|
|
fa29817920 | ||
|
|
794c3bc132 | ||
|
|
9e481d31ac | ||
|
|
4ebc03af75 | ||
|
|
80e2face67 | ||
|
|
815a5187d5 | ||
|
|
1d7bc42fba |
@@ -12,5 +12,5 @@ dbs:
|
||||
|
||||
|
||||
fields:
|
||||
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified", "http2Enabled", "http3Enabled" ]
|
||||
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified", "http2Enabled", "http3Enabled", "enableHTTP2", "retry50X", "autoSystemTuning" ]
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "1.2.8"
|
||||
Version = "1.2.10"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
ProductNameZH = "Edge"
|
||||
|
||||
GlobalProductName = "GoEdge"
|
||||
|
||||
Role = "api"
|
||||
|
||||
EncryptKey = "8f983f4d69b83aaa0d74b21a212f6967"
|
||||
@@ -18,7 +20,7 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "1.2.8"
|
||||
NodeVersion = "1.2.10"
|
||||
|
||||
// SQLVersion SQL版本号
|
||||
SQLVersion = "11"
|
||||
|
||||
@@ -107,9 +107,17 @@ func (this *ACMETaskDAO) DisableAllTasksWithCertId(tx *dbs.Tx, certId int64) err
|
||||
}
|
||||
|
||||
// CountAllEnabledACMETasks 计算所有任务数量
|
||||
func (this *ACMETaskDAO) CountAllEnabledACMETasks(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int64, keyword string) (int64, error) {
|
||||
func (this *ACMETaskDAO) CountAllEnabledACMETasks(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int64, keyword string, userOnly bool) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
query.Attr("userId", userId) // 这个条件必须加上
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
if userOnly {
|
||||
query.Gt("userId", 0)
|
||||
} else {
|
||||
query.Attr("userId", 0)
|
||||
}
|
||||
}
|
||||
if isAvailable || isExpired || expiringDays > 0 {
|
||||
query.Gt("certId", 0)
|
||||
|
||||
@@ -139,9 +147,17 @@ func (this *ACMETaskDAO) CountAllEnabledACMETasks(tx *dbs.Tx, userId int64, isAv
|
||||
}
|
||||
|
||||
// ListEnabledACMETasks 列出单页任务
|
||||
func (this *ACMETaskDAO) ListEnabledACMETasks(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int64, keyword string, offset int64, size int64) (result []*ACMETask, err error) {
|
||||
func (this *ACMETaskDAO) ListEnabledACMETasks(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int64, keyword string, userOnly bool, offset int64, size int64) (result []*ACMETask, err error) {
|
||||
var query = this.Query(tx)
|
||||
query.Attr("userId", userId) // 这个条件必须加上
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
if userOnly {
|
||||
query.Gt("userId", 0)
|
||||
} else {
|
||||
query.Attr("userId", 0)
|
||||
}
|
||||
}
|
||||
if isAvailable || isExpired || expiringDays > 0 {
|
||||
query.Gt("certId", 0)
|
||||
|
||||
@@ -229,8 +245,8 @@ func (this *ACMETaskDAO) UpdateACMETask(tx *dbs.Tx, acmeTaskId int64, acmeUserId
|
||||
return err
|
||||
}
|
||||
|
||||
// CheckACMETask 检查权限
|
||||
func (this *ACMETaskDAO) CheckACMETask(tx *dbs.Tx, userId int64, acmeTaskId int64) (bool, error) {
|
||||
// CheckUserACMETask 检查用户权限
|
||||
func (this *ACMETaskDAO) CheckUserACMETask(tx *dbs.Tx, userId int64, acmeTaskId int64) (bool, error) {
|
||||
var query = this.Query(tx)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
@@ -242,6 +258,15 @@ func (this *ACMETaskDAO) CheckACMETask(tx *dbs.Tx, userId int64, acmeTaskId int6
|
||||
Exist()
|
||||
}
|
||||
|
||||
// FindACMETaskUserId 查找任务所属用户ID
|
||||
func (this *ACMETaskDAO) FindACMETaskUserId(tx *dbs.Tx, taskId int64) (userId int64, err error) {
|
||||
return this.Query(tx).
|
||||
Pk(taskId).
|
||||
Result("userId").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
|
||||
// UpdateACMETaskCert 设置任务关联的证书
|
||||
func (this *ACMETaskDAO) UpdateACMETaskCert(tx *dbs.Tx, taskId int64, certId int64) error {
|
||||
if taskId <= 0 {
|
||||
|
||||
@@ -461,6 +461,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
||||
var protoReg = regexp.MustCompile(`proto:(\S+)`)
|
||||
var schemeReg = regexp.MustCompile(`scheme:(\S+)`)
|
||||
var methodReg = regexp.MustCompile(`(?:method|requestMethod):(\S+)`)
|
||||
var refererReg = regexp.MustCompile(`referer:(\S+)`)
|
||||
|
||||
var count = len(tableQueries)
|
||||
var wg = &sync.WaitGroup{}
|
||||
@@ -613,6 +614,11 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
||||
var matches = methodReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.requestMethod')=:keyword").
|
||||
Param("keyword", strings.ToUpper(matches[1]))
|
||||
} else if refererReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = refererReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.referer') LIKE :keyword").
|
||||
Param("keyword", dbutils.QuoteLike(matches[1]))
|
||||
}
|
||||
if !isSpecialKeyword {
|
||||
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||
|
||||
@@ -279,6 +279,31 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
|
||||
return this.NotifyUpdate(tx, policyId)
|
||||
}
|
||||
|
||||
// UpdateFirewallPolicyInboundRegion 修改入站封禁区域设置
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInboundRegion(tx *dbs.Tx, policyId int64, regionConfig *firewallconfigs.HTTPFirewallRegionConfig) error {
|
||||
var inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||
inboundJSON, err := this.Query(tx).
|
||||
Pk(policyId).
|
||||
Result("inbound").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if IsNotNull(inboundJSON) {
|
||||
err = json.Unmarshal(inboundJSON, inboundConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
inboundConfig.Region = regionConfig
|
||||
newInboundJSON, err := json.Marshal(inboundConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.UpdateFirewallPolicyInbound(tx, policyId, newInboundJSON)
|
||||
}
|
||||
|
||||
// UpdateFirewallPolicy 修改策略
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
|
||||
policyId int64,
|
||||
|
||||
@@ -104,7 +104,7 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
|
||||
return nil, err
|
||||
}
|
||||
for _, setRef := range setRefs {
|
||||
setConfig, err := SharedHTTPFirewallRuleSetDAO.ComposeFirewallRuleSet(tx, setRef.SetId)
|
||||
setConfig, err := SharedHTTPFirewallRuleSetDAO.ComposeFirewallRuleSet(tx, setRef.SetId, forNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func (this *HTTPFirewallRuleSetDAO) FindHTTPFirewallRuleSetName(tx *dbs.Tx, id i
|
||||
}
|
||||
|
||||
// ComposeFirewallRuleSet 组合配置
|
||||
func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int64) (*firewallconfigs.HTTPFirewallRuleSet, error) {
|
||||
func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int64, forNode bool) (*firewallconfigs.HTTPFirewallRuleSet, error) {
|
||||
set, err := this.FindEnabledHTTPFirewallRuleSet(tx, setId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -92,7 +92,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
if set == nil {
|
||||
return nil, nil
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRuleSet{}
|
||||
var config = &firewallconfigs.HTTPFirewallRuleSet{}
|
||||
config.Id = int64(set.Id)
|
||||
config.IsOn = set.IsOn
|
||||
config.Name = set.Name
|
||||
@@ -102,7 +102,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
config.IgnoreLocal = set.IgnoreLocal == 1
|
||||
|
||||
if IsNotNull(set.Rules) {
|
||||
ruleRefs := []*firewallconfigs.HTTPFirewallRuleRef{}
|
||||
var ruleRefs = []*firewallconfigs.HTTPFirewallRuleRef{}
|
||||
err = json.Unmarshal(set.Rules, &ruleRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -128,6 +128,29 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
config.Actions = actionConfigs
|
||||
}
|
||||
|
||||
// 检查各个选项
|
||||
for _, actionConfig := range actionConfigs {
|
||||
if actionConfig.Code == firewallconfigs.HTTPFirewallActionRecordIP { // 记录IP动作
|
||||
if actionConfig.Options != nil {
|
||||
var ipListId = actionConfig.Options.GetInt64("ipListId")
|
||||
if ipListId <= 0 { // default list id
|
||||
if forNode {
|
||||
actionConfig.Options["ipListId"] = firewallconfigs.GlobalListId
|
||||
}
|
||||
actionConfig.Options["ipListIsDeleted"] = false
|
||||
} else {
|
||||
exists, err := SharedIPListDAO.ExistsEnabledIPList(tx, ipListId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
actionConfig.Options["ipListIsDeleted"] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -212,6 +235,28 @@ func (this *HTTPFirewallRuleSetDAO) FindEnabledRuleSetIdWithRuleId(tx *dbs.Tx, r
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindAllEnabledRuleSetIdsWithIPListId 根据IP名单ID查找对应动作的WAF规则集
|
||||
func (this *HTTPFirewallRuleSetDAO) FindAllEnabledRuleSetIdsWithIPListId(tx *dbs.Tx, ipListId int64) (setIds []int64, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
State(HTTPFirewallRuleStateEnabled).
|
||||
Where("JSON_CONTAINS(actions, :jsonQuery)").
|
||||
Param("jsonQuery", maps.Map{
|
||||
"code": firewallconfigs.HTTPFirewallActionRecordIP,
|
||||
"options": maps.Map{
|
||||
"ipListId": ipListId,
|
||||
},
|
||||
}.AsJSON()).
|
||||
ResultPk().
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
setIds = append(setIds, int64(one.(*HTTPFirewallRuleSet).Id))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CheckUserRuleSet 检查用户
|
||||
func (this *HTTPFirewallRuleSetDAO) CheckUserRuleSet(tx *dbs.Tx, userId int64, setId int64) error {
|
||||
groupId, err := SharedHTTPFirewallRuleGroupDAO.FindRuleGroupIdWithRuleSetId(tx, setId)
|
||||
|
||||
@@ -576,6 +576,7 @@ func (this *HTTPWebDAO) CreateWeb(tx *dbs.Tx, adminId int64, userId int64, rootJ
|
||||
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{
|
||||
IsOn: true,
|
||||
Value: "${rawRemoteAddr}",
|
||||
Type: serverconfigs.HTTPRemoteAddrTypeDefault,
|
||||
}
|
||||
remoteAddrConfigJSON, err := json.Marshal(remoteAddrConfig)
|
||||
if err != nil {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -61,12 +62,16 @@ func (this *IPListDAO) EnableIPList(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableIPList 禁用条目
|
||||
func (this *IPListDAO) DisableIPList(tx *dbs.Tx, id int64) error {
|
||||
func (this *IPListDAO) DisableIPList(tx *dbs.Tx, listId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(listId).
|
||||
Set("state", IPListStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, listId, NodeTaskTypeIPListDeleted+"@"+string(maps.Map{"listId": listId}.AsJSON()))
|
||||
}
|
||||
|
||||
// FindEnabledIPList 查找启用中的条目
|
||||
@@ -258,11 +263,35 @@ func (this *IPListDAO) ExistsEnabledIPList(tx *dbs.Tx, listId int64) (bool, erro
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *IPListDAO) NotifyUpdate(tx *dbs.Tx, listId int64, taskType NodeTaskType) error {
|
||||
// WAF策略中的
|
||||
httpFirewallPolicyIds, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdsWithIPListId(tx, listId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resultClusterIds := []int64{}
|
||||
|
||||
// 规则集动作中使用此名单的策略
|
||||
ruleSetIds, err := SharedHTTPFirewallRuleSetDAO.FindAllEnabledRuleSetIdsWithIPListId(tx, listId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, ruleSetId := range ruleSetIds {
|
||||
ruleGroupId, err := SharedHTTPFirewallRuleGroupDAO.FindRuleGroupIdWithRuleSetId(tx, ruleSetId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ruleGroupId > 0 {
|
||||
policyId, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdWithRuleGroupId(tx, ruleGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if policyId > 0 && !lists.ContainsInt64(httpFirewallPolicyIds, policyId) {
|
||||
httpFirewallPolicyIds = append(httpFirewallPolicyIds, policyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查找集群
|
||||
var resultClusterIds = []int64{}
|
||||
for _, policyId := range httpFirewallPolicyIds {
|
||||
// 集群
|
||||
clusterIds, err := SharedNodeClusterDAO.FindAllEnabledNodeClusterIdsWithHTTPFirewallPolicyId(tx, policyId)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"runtime"
|
||||
@@ -27,7 +28,7 @@ func TestIPListDAO_CheckUserIPList(t *testing.T) {
|
||||
|
||||
{
|
||||
err := NewIPListDAO().CheckUserIPList(tx, 1, 100)
|
||||
if err == ErrNotFound {
|
||||
if err != nil && errors.Is(err, ErrNotFound) {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log(err)
|
||||
@@ -36,7 +37,7 @@ func TestIPListDAO_CheckUserIPList(t *testing.T) {
|
||||
|
||||
{
|
||||
err := NewIPListDAO().CheckUserIPList(tx, 1, 85)
|
||||
if err == ErrNotFound {
|
||||
if err != nil && errors.Is(err, ErrNotFound) {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log(err)
|
||||
@@ -45,7 +46,7 @@ func TestIPListDAO_CheckUserIPList(t *testing.T) {
|
||||
|
||||
{
|
||||
err := NewIPListDAO().CheckUserIPList(tx, 1, 17)
|
||||
if err == ErrNotFound {
|
||||
if err != nil && errors.Is(err, ErrNotFound) {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log(err)
|
||||
@@ -53,6 +54,17 @@ func TestIPListDAO_CheckUserIPList(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPListDAO_NotifyUpdate(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = NewIPListDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.NotifyUpdate(tx, 104, NodeTaskTypeIPListDeleted)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIPListDAO_IncreaseVersion(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
@@ -65,4 +77,3 @@ func BenchmarkIPListDAO_IncreaseVersion(b *testing.B) {
|
||||
_, _ = dao.IncreaseVersion(tx)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const (
|
||||
type MessageType = string
|
||||
|
||||
const (
|
||||
MessageTypeAll MessageType = "*"
|
||||
|
||||
// 这里的命名问题(首字母大写)为历史遗留问题,暂不修改
|
||||
|
||||
MessageTypeHealthCheckFailed MessageType = "HealthCheckFailed" // 节点健康检查失败
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -34,7 +32,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableMessageMedia 启用条目
|
||||
func (this *MessageMediaDAO) EnableMessageMedia(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -43,7 +41,7 @@ func (this *MessageMediaDAO) EnableMessageMedia(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableMessageMedia 禁用条目
|
||||
func (this *MessageMediaDAO) DisableMessageMedia(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -52,7 +50,7 @@ func (this *MessageMediaDAO) DisableMessageMedia(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledMessageMedia 查找启用中的条目
|
||||
func (this *MessageMediaDAO) FindEnabledMessageMedia(tx *dbs.Tx, id int64) (*MessageMedia, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -64,7 +62,7 @@ func (this *MessageMediaDAO) FindEnabledMessageMedia(tx *dbs.Tx, id int64) (*Mes
|
||||
return result.(*MessageMedia), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindMessageMediaName 根据主键查找名称
|
||||
func (this *MessageMediaDAO) FindMessageMediaName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -72,7 +70,7 @@ func (this *MessageMediaDAO) FindMessageMediaName(tx *dbs.Tx, id int64) (string,
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 查询所有可用媒介
|
||||
// FindAllEnabledMessageMedias 查询所有可用媒介
|
||||
func (this *MessageMediaDAO) FindAllEnabledMessageMedias(tx *dbs.Tx) (result []*MessageMedia, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(MessageMediaStateEnabled).
|
||||
@@ -82,74 +80,3 @@ func (this *MessageMediaDAO) FindAllEnabledMessageMedias(tx *dbs.Tx) (result []*
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// 设置当前所有可用的媒介
|
||||
func (this *MessageMediaDAO) UpdateMessageMedias(tx *dbs.Tx, mediaMaps []maps.Map) error {
|
||||
// 新的媒介信息
|
||||
mediaTypes := []string{}
|
||||
for index, m := range mediaMaps {
|
||||
order := len(mediaMaps) - index
|
||||
mediaType := m.GetString("type")
|
||||
mediaTypes = append(mediaTypes, mediaType)
|
||||
|
||||
name := m.GetString("name")
|
||||
description := m.GetString("description")
|
||||
userDescription := m.GetString("userDescription")
|
||||
isOn := m.GetBool("isOn")
|
||||
|
||||
mediaId, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Attr("type", mediaType).
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var op = NewMessageMediaOperator()
|
||||
if mediaId > 0 {
|
||||
op.Id = mediaId
|
||||
}
|
||||
op.Name = name
|
||||
op.Type = mediaType
|
||||
op.Description = description
|
||||
op.UserDescription = userDescription
|
||||
op.IsOn = isOn
|
||||
op.Order = order
|
||||
op.State = MessageMediaStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 老的媒介信息
|
||||
ones, err := this.Query(tx).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
mediaType := one.(*MessageMedia).Type
|
||||
if !lists.ContainsString(mediaTypes, mediaType) {
|
||||
err := this.Query(tx).
|
||||
Pk(one.(*MessageMedia).Id).
|
||||
Set("state", MessageMediaStateDisabled).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据类型查找媒介
|
||||
func (this *MessageMediaDAO) FindEnabledMediaWithType(tx *dbs.Tx, mediaType string) (*MessageMedia, error) {
|
||||
one, err := this.Query(tx).
|
||||
Attr("type", mediaType).
|
||||
State(MessageMediaStateEnabled).
|
||||
Find()
|
||||
if one == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*MessageMedia), nil
|
||||
}
|
||||
|
||||
@@ -98,24 +98,6 @@ func (this *MessageReceiverDAO) CreateReceiver(tx *dbs.Tx, role string, clusterI
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// FindAllEnabledReceivers 查询接收人
|
||||
func (this *MessageReceiverDAO) FindAllEnabledReceivers(tx *dbs.Tx, role string, clusterId int64, nodeId int64, serverId int64, messageType string) (result []*MessageReceiver, err error) {
|
||||
query := this.Query(tx)
|
||||
if len(messageType) > 0 {
|
||||
query.Attr("type", []string{"*", messageType}) // *表示所有的
|
||||
}
|
||||
_, err = query.
|
||||
Attr("role", role).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("serverId", serverId).
|
||||
State(MessageReceiverStateEnabled).
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllEnabledReceivers 计算接收人数量
|
||||
func (this *MessageReceiverDAO) CountAllEnabledReceivers(tx *dbs.Tx, role string, clusterId int64, nodeId int64, serverId int64, messageType string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMessageReceiverDAO_FindEnabledBestFitReceivers(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
|
||||
{
|
||||
receivers, err := NewMessageReceiverDAO().FindEnabledBestFitReceivers(tx, nodeconfigs.NodeRoleNode, 18, 1, 2, "*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
logs.PrintAsJSON(receivers, t)
|
||||
}
|
||||
|
||||
{
|
||||
receivers, err := NewMessageReceiverDAO().FindEnabledBestFitReceivers(tx, nodeconfigs.NodeRoleNode, 30, 1, 2, "*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
logs.PrintAsJSON(receivers, t)
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MessageTaskStatus = int
|
||||
|
||||
const (
|
||||
MessageTaskStateEnabled = 1 // 已启用
|
||||
MessageTaskStateDisabled = 0 // 已禁用
|
||||
|
||||
MessageTaskStatusNone MessageTaskStatus = 0 // 普通状态
|
||||
MessageTaskStatusSending MessageTaskStatus = 1 // 发送中
|
||||
MessageTaskStatusSuccess MessageTaskStatus = 2 // 发送成功
|
||||
MessageTaskStatusFailed MessageTaskStatus = 3 // 发送失败
|
||||
)
|
||||
|
||||
type MessageTaskDAO dbs.DAO
|
||||
@@ -94,151 +82,6 @@ func (this *MessageTaskDAO) FindEnabledMessageTask(tx *dbs.Tx, id int64) (*Messa
|
||||
return result.(*MessageTask), err
|
||||
}
|
||||
|
||||
// CreateMessageTask 创建任务
|
||||
func (this *MessageTaskDAO) CreateMessageTask(tx *dbs.Tx, recipientId int64, instanceId int64, user string, subject string, body string, isPrimary bool) (int64, error) {
|
||||
if !teaconst.IsPlus {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var hash = stringutil.Md5(types.String(recipientId) + "@" + types.String(instanceId) + "@" + user + "@" + subject + "@" + types.String(isPrimary))
|
||||
recipientInstanceId, err := SharedMessageRecipientDAO.FindRecipientInstanceId(tx, recipientId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if recipientInstanceId > 0 {
|
||||
hashLifeSeconds, err := SharedMessageMediaInstanceDAO.FindInstanceHashLifeSeconds(tx, recipientInstanceId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if hashLifeSeconds >= 0 { // 意味着此值如果小于0,则不做判断
|
||||
lastMessageAt, err := this.Query(tx).
|
||||
Attr("hash", hash).
|
||||
Result("createdAt").
|
||||
DescPk().
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 对于同一个人N分钟内消息不重复发送
|
||||
if hashLifeSeconds <= 0 {
|
||||
hashLifeSeconds = 60
|
||||
}
|
||||
if lastMessageAt > 0 && time.Now().Unix()-lastMessageAt < int64(hashLifeSeconds) {
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var op = NewMessageTaskOperator()
|
||||
op.RecipientId = recipientId
|
||||
op.InstanceId = instanceId
|
||||
op.Hash = hash
|
||||
op.User = user
|
||||
op.Subject = subject
|
||||
op.Body = body
|
||||
op.IsPrimary = isPrimary
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
op.Status = MessageTaskStatusNone
|
||||
op.State = MessageTaskStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// FindSendingMessageTasks 查找需要发送的任务
|
||||
func (this *MessageTaskDAO) FindSendingMessageTasks(tx *dbs.Tx, size int64) (result []*MessageTask, err error) {
|
||||
if size <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
_, err = this.Query(tx).
|
||||
State(MessageTaskStateEnabled).
|
||||
Attr("status", MessageTaskStatusNone).
|
||||
Where("(recipientId=0 OR recipientId IN (SELECT id FROM "+SharedMessageRecipientDAO.Table+" WHERE state=1 AND isOn=1 AND (timeFrom IS NULL OR timeTo IS NULL OR :time BETWEEN timeFrom AND timeTo)))").
|
||||
Param("time", timeutil.Format("H:i:s")).
|
||||
Desc("isPrimary").
|
||||
AscPk().
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountMessageTasksWithStatus 根据状态计算任务数量
|
||||
func (this *MessageTaskDAO) CountMessageTasksWithStatus(tx *dbs.Tx, status MessageTaskStatus) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(MessageTaskStateEnabled).
|
||||
Attr("status", status).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListMessageTasksWithStatus 根据状态列出单页任务
|
||||
func (this *MessageTaskDAO) ListMessageTasksWithStatus(tx *dbs.Tx, status MessageTaskStatus, offset int64, size int64) (result []*MessageTask, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(MessageTaskStateEnabled).
|
||||
Attr("status", status).
|
||||
Desc("isPrimary").
|
||||
AscPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMessageTaskStatus 设置发送的状态
|
||||
func (this *MessageTaskDAO) UpdateMessageTaskStatus(tx *dbs.Tx, taskId int64, status MessageTaskStatus, result []byte) error {
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid taskId")
|
||||
}
|
||||
var op = NewMessageTaskOperator()
|
||||
op.Id = taskId
|
||||
op.Status = status
|
||||
op.SentAt = time.Now().Unix()
|
||||
if len(result) > 0 {
|
||||
op.Result = result
|
||||
}
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// CreateMessageTasks 从集群、节点或者服务中创建任务
|
||||
func (this *MessageTaskDAO) CreateMessageTasks(tx *dbs.Tx, role nodeconfigs.NodeRole, clusterId int64, nodeId int64, serverId int64, messageType MessageType, subject string, body string) error {
|
||||
if !teaconst.IsPlus {
|
||||
return nil
|
||||
}
|
||||
|
||||
receivers, err := SharedMessageReceiverDAO.FindEnabledBestFitReceivers(tx, role, clusterId, nodeId, serverId, messageType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allRecipientIds := []int64{}
|
||||
for _, receiver := range receivers {
|
||||
if receiver.RecipientId > 0 {
|
||||
allRecipientIds = append(allRecipientIds, int64(receiver.RecipientId))
|
||||
} else if receiver.RecipientGroupId > 0 {
|
||||
recipientIds, err := SharedMessageRecipientDAO.FindAllEnabledAndOnRecipientIdsWithGroup(tx, int64(receiver.RecipientGroupId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allRecipientIds = append(allRecipientIds, recipientIds...)
|
||||
}
|
||||
}
|
||||
|
||||
sentMap := map[int64]bool{} // recipientId => bool 用来检查是否已经发送,防止重复发送给某个接收人
|
||||
for _, recipientId := range allRecipientIds {
|
||||
_, ok := sentMap[recipientId]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
sentMap[recipientId] = true
|
||||
_, err := this.CreateMessageTask(tx, recipientId, 0, "", subject, body, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanExpiredMessageTasks 清理
|
||||
func (this *MessageTaskDAO) CleanExpiredMessageTasks(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
|
||||
14
internal/db/models/message_task_dao_ext.go
Normal file
14
internal/db/models/message_task_dao_ext.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
// CreateMessageTasks 从集群、节点或者服务中创建任务
|
||||
func (this *MessageTaskDAO) CreateMessageTasks(tx *dbs.Tx, role nodeconfigs.NodeRole, clusterId int64, nodeId int64, serverId int64, messageType MessageType, subject string, body string) error {
|
||||
return nil
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
const (
|
||||
MonitorNodeStateEnabled = 1 // 已启用
|
||||
MonitorNodeStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type MonitorNodeDAO dbs.DAO
|
||||
|
||||
func NewMonitorNodeDAO() *MonitorNodeDAO {
|
||||
return dbs.NewDAO(&MonitorNodeDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeMonitorNodes",
|
||||
Model: new(MonitorNode),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*MonitorNodeDAO)
|
||||
}
|
||||
|
||||
var SharedMonitorNodeDAO *MonitorNodeDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedMonitorNodeDAO = NewMonitorNodeDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableMonitorNode 启用条目
|
||||
func (this *MonitorNodeDAO) EnableMonitorNode(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", MonitorNodeStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableMonitorNode 禁用条目
|
||||
func (this *MonitorNodeDAO) DisableMonitorNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("state", MonitorNodeStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleMonitor, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledMonitorNode 查找启用中的条目
|
||||
func (this *MonitorNodeDAO) FindEnabledMonitorNode(tx *dbs.Tx, id int64) (*MonitorNode, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", MonitorNodeStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*MonitorNode), err
|
||||
}
|
||||
|
||||
// FindMonitorNodeName 根据主键查找名称
|
||||
func (this *MonitorNodeDAO) FindMonitorNodeName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// FindAllEnabledMonitorNodes 列出所有可用监控节点
|
||||
func (this *MonitorNodeDAO) FindAllEnabledMonitorNodes(tx *dbs.Tx) (result []*MonitorNode, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(MonitorNodeStateEnabled).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllEnabledMonitorNodes 计算监控节点数量
|
||||
func (this *MonitorNodeDAO) CountAllEnabledMonitorNodes(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(MonitorNodeStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledMonitorNodes 列出单页的监控节点
|
||||
func (this *MonitorNodeDAO) ListEnabledMonitorNodes(tx *dbs.Tx, offset int64, size int64) (result []*MonitorNode, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(MonitorNodeStateEnabled).
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Desc("order").
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CreateMonitorNode 创建监控节点
|
||||
func (this *MonitorNodeDAO) CreateMonitorNode(tx *dbs.Tx, name string, description string, isOn bool) (nodeId int64, err error) {
|
||||
uniqueId, err := this.GenUniqueId(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
secret := rands.String(32)
|
||||
err = NewApiTokenDAO().CreateAPIToken(tx, uniqueId, secret, nodeconfigs.NodeRoleMonitor)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var op = NewMonitorNodeOperator()
|
||||
op.IsOn = isOn
|
||||
op.UniqueId = uniqueId
|
||||
op.Secret = secret
|
||||
op.Name = name
|
||||
op.Description = description
|
||||
op.State = NodeStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// UpdateMonitorNode 修改监控节点
|
||||
func (this *MonitorNodeDAO) UpdateMonitorNode(tx *dbs.Tx, nodeId int64, name string, description string, isOn bool) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
|
||||
var op = NewMonitorNodeOperator()
|
||||
op.Id = nodeId
|
||||
op.Name = name
|
||||
op.Description = description
|
||||
op.IsOn = isOn
|
||||
err := this.Save(tx, op)
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledMonitorNodeWithUniqueId 根据唯一ID获取节点信息
|
||||
func (this *MonitorNodeDAO) FindEnabledMonitorNodeWithUniqueId(tx *dbs.Tx, uniqueId string) (*MonitorNode, error) {
|
||||
result, err := this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Attr("state", MonitorNodeStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*MonitorNode), err
|
||||
}
|
||||
|
||||
// FindEnabledMonitorNodeIdWithUniqueId 根据唯一ID获取节点ID
|
||||
func (this *MonitorNodeDAO) FindEnabledMonitorNodeIdWithUniqueId(tx *dbs.Tx, uniqueId string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Attr("state", MonitorNodeStateEnabled).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// GenUniqueId 生成唯一ID
|
||||
func (this *MonitorNodeDAO) GenUniqueId(tx *dbs.Tx) (string, error) {
|
||||
for {
|
||||
uniqueId := rands.HexString(32)
|
||||
ok, err := this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
return uniqueId, nil
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this *MonitorNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
if statusJSON == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("status", string(statusJSON)).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// CountAllLowerVersionNodes 计算所有节点中低于某个版本的节点数量
|
||||
func (this *MonitorNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(MonitorNodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
Count()
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// MonitorNode 监控节点
|
||||
type MonitorNode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status dbs.JSON `field:"status"` // 运行状态
|
||||
}
|
||||
|
||||
type MonitorNodeOperator struct {
|
||||
Id interface{} // ID
|
||||
IsOn interface{} // 是否启用
|
||||
UniqueId interface{} // 唯一ID
|
||||
Secret interface{} // 密钥
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Order interface{} // 排序
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
AdminId interface{} // 管理员ID
|
||||
Weight interface{} // 权重
|
||||
Status interface{} // 运行状态
|
||||
}
|
||||
|
||||
func NewMonitorNodeOperator() *MonitorNodeOperator {
|
||||
return &MonitorNodeOperator{}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func (this *NodeClusterDAO) FindAllEnableClusterIds(tx *dbs.Tx) (result []int64,
|
||||
}
|
||||
|
||||
// CreateCluster 创建集群
|
||||
func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string, grantId int64, installDir string, dnsDomainId int64, dnsName string, dnsTTL int32, cachePolicyId int64, httpFirewallPolicyId int64, systemServices map[string]maps.Map, globalServerConfig *serverconfigs.GlobalServerConfig, autoInstallNftables bool) (clusterId int64, err error) {
|
||||
func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string, grantId int64, installDir string, dnsDomainId int64, dnsName string, dnsTTL int32, cachePolicyId int64, httpFirewallPolicyId int64, systemServices map[string]maps.Map, globalServerConfig *serverconfigs.GlobalServerConfig, autoInstallNftables bool, autoSystemTuning bool) (clusterId int64, err error) {
|
||||
uniqueId, err := this.GenUniqueId(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -189,6 +189,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
op.UniqueId = uniqueId
|
||||
op.Secret = secret
|
||||
op.AutoInstallNftables = autoInstallNftables
|
||||
op.AutoSystemTuning = autoSystemTuning
|
||||
op.State = NodeClusterStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -199,7 +200,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, autoOpenPorts bool, clockConfig *nodeconfigs.ClockConfig, autoRemoteStart bool, autoInstallTables bool, sshParams *nodeconfigs.SSHParams) error {
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, autoOpenPorts bool, clockConfig *nodeconfigs.ClockConfig, autoRemoteStart bool, autoInstallTables bool, sshParams *nodeconfigs.SSHParams, autoSystemTuning bool) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -226,6 +227,7 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
|
||||
|
||||
op.AutoRemoteStart = autoRemoteStart
|
||||
op.AutoInstallNftables = autoInstallTables
|
||||
op.AutoSystemTuning = autoSystemTuning
|
||||
|
||||
if sshParams != nil {
|
||||
sshParamsJSON, err := json.Marshal(sshParams)
|
||||
@@ -950,11 +952,12 @@ func (this *NodeClusterDAO) GenUniqueId(tx *dbs.Tx) (string, error) {
|
||||
|
||||
// FindLatestNodeClusters 查询最近访问的集群
|
||||
func (this *NodeClusterDAO) FindLatestNodeClusters(tx *dbs.Tx, size int64) (result []*NodeCluster, err error) {
|
||||
itemTable := SharedLatestItemDAO.Table
|
||||
itemType := LatestItemTypeCluster
|
||||
var itemTable = SharedLatestItemDAO.Table
|
||||
var itemType = LatestItemTypeCluster
|
||||
_, err = this.Query(tx).
|
||||
Result(this.Table+".id", this.Table+".name").
|
||||
Join(SharedLatestItemDAO, dbs.QueryJoinRight, this.Table+".id="+itemTable+".itemId AND "+itemTable+".itemType='"+itemType+"'").
|
||||
Where(itemTable + ".updatedAt<=UNIX_TIMESTAMP()"). // VERY IMPORTANT
|
||||
Asc("CEIL((UNIX_TIMESTAMP() - " + itemTable + ".updatedAt) / (7 * 86400))"). // 优先一个星期以内的
|
||||
Desc(itemTable + ".count").
|
||||
State(NodeClusterStateEnabled).
|
||||
@@ -1018,7 +1021,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Result("id", "name", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "cc", "httpPages", "http3", "isOn", "ddosProtection", "clock", "globalServerConfig", "autoInstallNftables").
|
||||
Result("id", "name", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "cc", "httpPages", "http3", "isOn", "ddosProtection", "clock", "globalServerConfig", "autoInstallNftables", "autoSystemTuning").
|
||||
Find()
|
||||
if err != nil || cluster == nil {
|
||||
return nil, err
|
||||
|
||||
@@ -43,6 +43,7 @@ const (
|
||||
NodeClusterField_HttpPages dbs.FieldName = "httpPages" // 自定义页面设置
|
||||
NodeClusterField_Cc dbs.FieldName = "cc" // CC设置
|
||||
NodeClusterField_Http3 dbs.FieldName = "http3" // HTTP3设置
|
||||
NodeClusterField_AutoSystemTuning dbs.FieldName = "autoSystemTuning" // 是否自动调整系统参数
|
||||
)
|
||||
|
||||
// NodeCluster 节点集群
|
||||
@@ -87,6 +88,7 @@ type NodeCluster struct {
|
||||
HttpPages dbs.JSON `field:"httpPages"` // 自定义页面设置
|
||||
Cc dbs.JSON `field:"cc"` // CC设置
|
||||
Http3 dbs.JSON `field:"http3"` // HTTP3设置
|
||||
AutoSystemTuning bool `field:"autoSystemTuning"` // 是否自动调整系统参数
|
||||
}
|
||||
|
||||
type NodeClusterOperator struct {
|
||||
@@ -130,6 +132,7 @@ type NodeClusterOperator struct {
|
||||
HttpPages any // 自定义页面设置
|
||||
Cc any // CC设置
|
||||
Http3 any // HTTP3设置
|
||||
AutoSystemTuning any // 是否自动调整系统参数
|
||||
}
|
||||
|
||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -27,6 +26,7 @@ import (
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -1057,30 +1057,6 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
|
||||
}
|
||||
}
|
||||
|
||||
// 全局设置
|
||||
// TODO 根据用户的不同读取不同的全局设置
|
||||
var settingCacheKey = "SharedSysSettingDAO:" + systemconfigs.SettingCodeServerGlobalConfig
|
||||
settingJSONCache, ok := cacheMap.Get(settingCacheKey)
|
||||
var settingJSON []byte
|
||||
if ok {
|
||||
settingJSON = settingJSONCache.([]byte)
|
||||
} else {
|
||||
settingJSON, err = SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeServerGlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cacheMap.Put(settingCacheKey, settingJSON)
|
||||
}
|
||||
|
||||
if len(settingJSON) > 0 {
|
||||
globalConfig := &serverconfigs.GlobalConfig{}
|
||||
err = json.Unmarshal(settingJSON, globalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.GlobalConfig = globalConfig
|
||||
}
|
||||
|
||||
var clusterIndex = 0
|
||||
config.WebPImagePolicies = map[int64]*nodeconfigs.WebPImagePolicy{}
|
||||
config.UAMPolicies = map[int64]*nodeconfigs.UAMPolicy{}
|
||||
@@ -1242,6 +1218,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
|
||||
// 自动安装nftables
|
||||
if clusterIndex == 0 {
|
||||
config.AutoInstallNftables = nodeCluster.AutoInstallNftables
|
||||
config.AutoSystemTuning = nodeCluster.AutoSystemTuning
|
||||
}
|
||||
|
||||
clusterIndex++
|
||||
@@ -2128,6 +2105,12 @@ func (this *NodeDAO) FindParentNodeConfigs(tx *dbs.Tx, nodeId int64, groupId int
|
||||
Addrs: addrStrings,
|
||||
SecretHash: secretHash,
|
||||
})
|
||||
|
||||
// 排序
|
||||
sort.Slice(parentNodeConfigs, func(i, j int) bool {
|
||||
return parentNodeConfigs[i].Id < parentNodeConfigs[j].Id
|
||||
})
|
||||
|
||||
result[clusterId] = parentNodeConfigs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -19,6 +20,7 @@ const (
|
||||
NodeTaskTypeConfigChanged NodeTaskType = "configChanged" // 节点整体配置变化
|
||||
NodeTaskTypeDDosProtectionChanged NodeTaskType = "ddosProtectionChanged" // 节点DDoS配置变更
|
||||
NodeTaskTypeGlobalServerConfigChanged NodeTaskType = "globalServerConfigChanged" // 全局服务设置变化
|
||||
NodeTaskTypeIPListDeleted NodeTaskType = "ipListDeleted" // IPList被删除
|
||||
NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged" // IP条目变更
|
||||
NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged" // 节点版本变化
|
||||
NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged" // 脚本配置变化
|
||||
@@ -265,6 +267,23 @@ func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int6
|
||||
|
||||
// UpdateNodeTaskDone 修改节点任务的完成状态
|
||||
func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool, errorMessage string) error {
|
||||
if isOk {
|
||||
// 特殊任务删除
|
||||
taskType, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Result("type").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasPrefix(taskType, NodeTaskTypeIPListDeleted+"@") {
|
||||
return this.Query(tx).
|
||||
Pk(taskId).
|
||||
DeleteQuickly()
|
||||
}
|
||||
}
|
||||
|
||||
// 其他任务标记为完成
|
||||
var query = this.Query(tx).
|
||||
Pk(taskId)
|
||||
if !isOk {
|
||||
@@ -274,8 +293,9 @@ func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool,
|
||||
}
|
||||
query.Set("version", version)
|
||||
}
|
||||
|
||||
_, err := query.
|
||||
Set("isDone", 1).
|
||||
Set("isDone", true).
|
||||
Set("isOk", isOk).
|
||||
Set("error", errorMessage).
|
||||
Update()
|
||||
|
||||
@@ -54,3 +54,12 @@ func TestNodeTaskDAO_FindDoingNodeTasks(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeTaskDAO_UpdateNodeTaskDone(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
var dao = models.NewNodeTaskDAO()
|
||||
err := dao.UpdateNodeTaskDone(tx, 1741, true, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,15 +61,28 @@ func (this *PlanDAO) DisablePlan(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// FindEnabledPlan 查找启用中的条目
|
||||
func (this *PlanDAO) FindEnabledPlan(tx *dbs.Tx, id int64) (*Plan, error) {
|
||||
func (this *PlanDAO) FindEnabledPlan(tx *dbs.Tx, planId int64, cacheMap *utils.CacheMap) (*Plan, error) {
|
||||
var cacheKey = this.Table + ":FindEnabledPlan:" + types.String(planId)
|
||||
if cacheMap != nil {
|
||||
cache, _ := cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*Plan), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(planId).
|
||||
Attr("state", PlanStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*Plan), err
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*Plan), nil
|
||||
}
|
||||
|
||||
// FindPlanName 根据主键查找名称
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package models
|
||||
package models_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -2,39 +2,71 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
PlanField_Id dbs.FieldName = "id" // ID
|
||||
PlanField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
PlanField_Name dbs.FieldName = "name" // 套餐名
|
||||
PlanField_ClusterId dbs.FieldName = "clusterId" // 集群ID
|
||||
PlanField_TrafficLimit dbs.FieldName = "trafficLimit" // 流量限制
|
||||
PlanField_Features dbs.FieldName = "features" // 允许的功能
|
||||
PlanField_TrafficPrice dbs.FieldName = "trafficPrice" // 流量价格设定
|
||||
PlanField_BandwidthPrice dbs.FieldName = "bandwidthPrice" // 带宽价格
|
||||
PlanField_MonthlyPrice dbs.FieldName = "monthlyPrice" // 月付
|
||||
PlanField_SeasonallyPrice dbs.FieldName = "seasonallyPrice" // 季付
|
||||
PlanField_YearlyPrice dbs.FieldName = "yearlyPrice" // 年付
|
||||
PlanField_PriceType dbs.FieldName = "priceType" // 价格类型
|
||||
PlanField_Order dbs.FieldName = "order" // 排序
|
||||
PlanField_State dbs.FieldName = "state" // 状态
|
||||
PlanField_TotalServers dbs.FieldName = "totalServers" // 可以绑定的网站数量
|
||||
PlanField_TotalServerNamesPerServer dbs.FieldName = "totalServerNamesPerServer" // 每个网站可以绑定的域名数量
|
||||
PlanField_TotalServerNames dbs.FieldName = "totalServerNames" // 总域名数量
|
||||
PlanField_MonthlyRequests dbs.FieldName = "monthlyRequests" // 每月访问量额度
|
||||
PlanField_DailyRequests dbs.FieldName = "dailyRequests" // 每日访问量额度
|
||||
)
|
||||
|
||||
// Plan 用户套餐
|
||||
type Plan struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 套餐名
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
TrafficLimit dbs.JSON `field:"trafficLimit"` // 流量限制
|
||||
Features dbs.JSON `field:"features"` // 允许的功能
|
||||
TrafficPrice dbs.JSON `field:"trafficPrice"` // 流量价格设定
|
||||
BandwidthPrice dbs.JSON `field:"bandwidthPrice"` // 带宽价格
|
||||
MonthlyPrice float64 `field:"monthlyPrice"` // 月付
|
||||
SeasonallyPrice float64 `field:"seasonallyPrice"` // 季付
|
||||
YearlyPrice float64 `field:"yearlyPrice"` // 年付
|
||||
PriceType string `field:"priceType"` // 价格类型
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 套餐名
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
TrafficLimit dbs.JSON `field:"trafficLimit"` // 流量限制
|
||||
Features dbs.JSON `field:"features"` // 允许的功能
|
||||
TrafficPrice dbs.JSON `field:"trafficPrice"` // 流量价格设定
|
||||
BandwidthPrice dbs.JSON `field:"bandwidthPrice"` // 带宽价格
|
||||
MonthlyPrice float64 `field:"monthlyPrice"` // 月付
|
||||
SeasonallyPrice float64 `field:"seasonallyPrice"` // 季付
|
||||
YearlyPrice float64 `field:"yearlyPrice"` // 年付
|
||||
PriceType string `field:"priceType"` // 价格类型
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
TotalServers uint32 `field:"totalServers"` // 可以绑定的网站数量
|
||||
TotalServerNamesPerServer uint32 `field:"totalServerNamesPerServer"` // 每个网站可以绑定的域名数量
|
||||
TotalServerNames uint32 `field:"totalServerNames"` // 总域名数量
|
||||
MonthlyRequests uint64 `field:"monthlyRequests"` // 每月访问量额度
|
||||
DailyRequests uint64 `field:"dailyRequests"` // 每日访问量额度
|
||||
}
|
||||
|
||||
type PlanOperator struct {
|
||||
Id interface{} // ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 套餐名
|
||||
ClusterId interface{} // 集群ID
|
||||
TrafficLimit interface{} // 流量限制
|
||||
Features interface{} // 允许的功能
|
||||
TrafficPrice interface{} // 流量价格设定
|
||||
BandwidthPrice interface{} // 带宽价格
|
||||
MonthlyPrice interface{} // 月付
|
||||
SeasonallyPrice interface{} // 季付
|
||||
YearlyPrice interface{} // 年付
|
||||
PriceType interface{} // 价格类型
|
||||
Order interface{} // 排序
|
||||
State interface{} // 状态
|
||||
Id any // ID
|
||||
IsOn any // 是否启用
|
||||
Name any // 套餐名
|
||||
ClusterId any // 集群ID
|
||||
TrafficLimit any // 流量限制
|
||||
Features any // 允许的功能
|
||||
TrafficPrice any // 流量价格设定
|
||||
BandwidthPrice any // 带宽价格
|
||||
MonthlyPrice any // 月付
|
||||
SeasonallyPrice any // 季付
|
||||
YearlyPrice any // 年付
|
||||
PriceType any // 价格类型
|
||||
Order any // 排序
|
||||
State any // 状态
|
||||
TotalServers any // 可以绑定的网站数量
|
||||
TotalServerNamesPerServer any // 每个网站可以绑定的域名数量
|
||||
TotalServerNames any // 总域名数量
|
||||
MonthlyRequests any // 每月访问量额度
|
||||
DailyRequests any // 每日访问量额度
|
||||
}
|
||||
|
||||
func NewPlanOperator() *PlanOperator {
|
||||
|
||||
@@ -99,7 +99,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var config = &serverconfigs.ReverseProxyConfig{}
|
||||
var config = serverconfigs.NewReverseProxyConfig()
|
||||
config.Id = int64(reverseProxy.Id)
|
||||
config.IsOn = reverseProxy.IsOn
|
||||
config.RequestHostType = types.Int8(reverseProxy.RequestHostType)
|
||||
@@ -109,6 +109,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
config.StripPrefix = reverseProxy.StripPrefix
|
||||
config.AutoFlush = reverseProxy.AutoFlush == 1
|
||||
config.FollowRedirects = reverseProxy.FollowRedirects == 1
|
||||
config.Retry50X = reverseProxy.Retry50X
|
||||
|
||||
var schedulingConfig = &serverconfigs.SchedulingConfig{}
|
||||
if IsNotNull(reverseProxy.Scheduling) {
|
||||
@@ -218,6 +219,7 @@ func (this *ReverseProxyDAO) CreateReverseProxy(tx *dbs.Tx, adminId int64, userI
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.RequestHostType = serverconfigs.RequestHostTypeProxyServer
|
||||
op.Retry50X = true
|
||||
|
||||
defaultHeaders := []string{"X-Real-IP", "X-Forwarded-For", "X-Forwarded-By", "X-Forwarded-Host", "X-Forwarded-Proto"}
|
||||
defaultHeadersJSON, err := json.Marshal(defaultHeaders)
|
||||
@@ -425,7 +427,8 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
||||
maxConns int32,
|
||||
maxIdleConns int32,
|
||||
proxyProtocolJSON []byte,
|
||||
followRedirects bool) error {
|
||||
followRedirects bool,
|
||||
retry50X bool) error {
|
||||
if reverseProxyId <= 0 {
|
||||
return errors.New("invalid reverseProxyId")
|
||||
}
|
||||
@@ -490,6 +493,8 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
||||
op.ProxyProtocol = proxyProtocolJSON
|
||||
}
|
||||
|
||||
op.Retry50X = retry50X
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -2,6 +2,34 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
ReverseProxyField_Id dbs.FieldName = "id" // ID
|
||||
ReverseProxyField_AdminId dbs.FieldName = "adminId" // 管理员ID
|
||||
ReverseProxyField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
ReverseProxyField_TemplateId dbs.FieldName = "templateId" // 模版ID
|
||||
ReverseProxyField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
ReverseProxyField_Scheduling dbs.FieldName = "scheduling" // 调度算法
|
||||
ReverseProxyField_PrimaryOrigins dbs.FieldName = "primaryOrigins" // 主要源站
|
||||
ReverseProxyField_BackupOrigins dbs.FieldName = "backupOrigins" // 备用源站
|
||||
ReverseProxyField_StripPrefix dbs.FieldName = "stripPrefix" // 去除URL前缀
|
||||
ReverseProxyField_RequestHostType dbs.FieldName = "requestHostType" // 请求Host类型
|
||||
ReverseProxyField_RequestHost dbs.FieldName = "requestHost" // 请求Host
|
||||
ReverseProxyField_RequestHostExcludingPort dbs.FieldName = "requestHostExcludingPort" // 移除请求Host中的域名
|
||||
ReverseProxyField_RequestURI dbs.FieldName = "requestURI" // 请求URI
|
||||
ReverseProxyField_AutoFlush dbs.FieldName = "autoFlush" // 是否自动刷新缓冲区
|
||||
ReverseProxyField_AddHeaders dbs.FieldName = "addHeaders" // 自动添加的Header列表
|
||||
ReverseProxyField_State dbs.FieldName = "state" // 状态
|
||||
ReverseProxyField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
ReverseProxyField_ConnTimeout dbs.FieldName = "connTimeout" // 连接超时时间
|
||||
ReverseProxyField_ReadTimeout dbs.FieldName = "readTimeout" // 读取超时时间
|
||||
ReverseProxyField_IdleTimeout dbs.FieldName = "idleTimeout" // 空闲超时时间
|
||||
ReverseProxyField_MaxConns dbs.FieldName = "maxConns" // 最大并发连接数
|
||||
ReverseProxyField_MaxIdleConns dbs.FieldName = "maxIdleConns" // 最大空闲连接数
|
||||
ReverseProxyField_ProxyProtocol dbs.FieldName = "proxyProtocol" // Proxy Protocol配置
|
||||
ReverseProxyField_FollowRedirects dbs.FieldName = "followRedirects" // 回源跟随
|
||||
ReverseProxyField_Retry50X dbs.FieldName = "retry50X" // 启用50X重试
|
||||
)
|
||||
|
||||
// ReverseProxy 反向代理配置
|
||||
type ReverseProxy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
@@ -28,33 +56,35 @@ type ReverseProxy struct {
|
||||
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
||||
ProxyProtocol dbs.JSON `field:"proxyProtocol"` // Proxy Protocol配置
|
||||
FollowRedirects uint8 `field:"followRedirects"` // 回源跟随
|
||||
Retry50X bool `field:"retry50X"` // 启用50X重试
|
||||
}
|
||||
|
||||
type ReverseProxyOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Scheduling interface{} // 调度算法
|
||||
PrimaryOrigins interface{} // 主要源站
|
||||
BackupOrigins interface{} // 备用源站
|
||||
StripPrefix interface{} // 去除URL前缀
|
||||
RequestHostType interface{} // 请求Host类型
|
||||
RequestHost interface{} // 请求Host
|
||||
RequestHostExcludingPort interface{} // 移除请求Host中的域名
|
||||
RequestURI interface{} // 请求URI
|
||||
AutoFlush interface{} // 是否自动刷新缓冲区
|
||||
AddHeaders interface{} // 自动添加的Header列表
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
ConnTimeout interface{} // 连接超时时间
|
||||
ReadTimeout interface{} // 读取超时时间
|
||||
IdleTimeout interface{} // 空闲超时时间
|
||||
MaxConns interface{} // 最大并发连接数
|
||||
MaxIdleConns interface{} // 最大空闲连接数
|
||||
ProxyProtocol interface{} // Proxy Protocol配置
|
||||
FollowRedirects interface{} // 回源跟随
|
||||
Id any // ID
|
||||
AdminId any // 管理员ID
|
||||
UserId any // 用户ID
|
||||
TemplateId any // 模版ID
|
||||
IsOn any // 是否启用
|
||||
Scheduling any // 调度算法
|
||||
PrimaryOrigins any // 主要源站
|
||||
BackupOrigins any // 备用源站
|
||||
StripPrefix any // 去除URL前缀
|
||||
RequestHostType any // 请求Host类型
|
||||
RequestHost any // 请求Host
|
||||
RequestHostExcludingPort any // 移除请求Host中的域名
|
||||
RequestURI any // 请求URI
|
||||
AutoFlush any // 是否自动刷新缓冲区
|
||||
AddHeaders any // 自动添加的Header列表
|
||||
State any // 状态
|
||||
CreatedAt any // 创建时间
|
||||
ConnTimeout any // 连接超时时间
|
||||
ReadTimeout any // 读取超时时间
|
||||
IdleTimeout any // 空闲超时时间
|
||||
MaxConns any // 最大并发连接数
|
||||
MaxIdleConns any // 最大空闲连接数
|
||||
ProxyProtocol any // Proxy Protocol配置
|
||||
FollowRedirects any // 回源跟随
|
||||
Retry50X any // 启用50X重试
|
||||
}
|
||||
|
||||
func NewReverseProxyOperator() *ReverseProxyOperator {
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
type ServerBandwidthStatDAO dbs.DAO
|
||||
|
||||
const (
|
||||
ServerBandwidthStatTablePartials = 20 // 分表数量
|
||||
ServerBandwidthStatTablePartitions = 20 // 分表数量
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -63,15 +63,15 @@ func init() {
|
||||
}
|
||||
|
||||
// UpdateServerBandwidth 写入数据
|
||||
// 暂时不使用region区分
|
||||
func (this *ServerBandwidthStatDAO) UpdateServerBandwidth(tx *dbs.Tx, userId int64, serverId int64, regionId int64, day string, timeAt string, bytes int64, totalBytes int64, cachedBytes int64, attackBytes int64, countRequests int64, countCachedRequests int64, countAttackRequests int64) error {
|
||||
// 现在不需要把 userPlanId 加入到数据表unique key中,因为只会影响5分钟统计,影响非常有限
|
||||
func (this *ServerBandwidthStatDAO) UpdateServerBandwidth(tx *dbs.Tx, userId int64, serverId int64, regionId int64, userPlanId int64, day string, timeAt string, bandwidthBytes int64, totalBytes int64, cachedBytes int64, attackBytes int64, countRequests int64, countCachedRequests int64, countAttackRequests int64) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("invalid server id '" + types.String(serverId) + "'")
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Param("bytes", bytes).
|
||||
Param("bytes", bandwidthBytes).
|
||||
Param("totalBytes", totalBytes).
|
||||
Param("cachedBytes", cachedBytes).
|
||||
Param("attackBytes", attackBytes).
|
||||
@@ -84,7 +84,7 @@ func (this *ServerBandwidthStatDAO) UpdateServerBandwidth(tx *dbs.Tx, userId int
|
||||
"regionId": regionId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
"bytes": bandwidthBytes,
|
||||
"totalBytes": totalBytes,
|
||||
"avgBytes": totalBytes / 300,
|
||||
"cachedBytes": cachedBytes,
|
||||
@@ -92,6 +92,7 @@ func (this *ServerBandwidthStatDAO) UpdateServerBandwidth(tx *dbs.Tx, userId int
|
||||
"countRequests": countRequests,
|
||||
"countCachedRequests": countCachedRequests,
|
||||
"countAttackRequests": countAttackRequests,
|
||||
"userPlanId": userPlanId,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
"avgBytes": dbs.SQL("(totalBytes+:totalBytes)/300"), // 因为生成SQL语句时会自动将avgBytes排在totalBytes之前,所以这里不用担心先后顺序的问题
|
||||
@@ -379,14 +380,18 @@ func (this *ServerBandwidthStatDAO) FindAllServerStatsWithMonth(tx *dbs.Tx, serv
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int, useAvg bool) (result int64, err error) {
|
||||
func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int, useAvg bool, noPlan bool, minSamples int) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
|
||||
// 如果是100%以上,则快速返回
|
||||
if percentile >= 100 {
|
||||
result, err = this.Query(tx).
|
||||
var query = this.Query(tx)
|
||||
if noPlan {
|
||||
query.Attr("userPlanId", 0)
|
||||
}
|
||||
result, err = query.
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Result(this.bytesField(useAvg)).
|
||||
@@ -398,7 +403,11 @@ func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId i
|
||||
}
|
||||
|
||||
// 总数量
|
||||
total, err := this.Query(tx).
|
||||
var totalQuery = this.Query(tx)
|
||||
if noPlan {
|
||||
totalQuery.Attr("userPlanId", 0)
|
||||
}
|
||||
total, err := totalQuery.
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
@@ -406,7 +415,7 @@ func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId i
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
if total == 0 || total < int64(minSamples) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -417,7 +426,11 @@ func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId i
|
||||
}
|
||||
|
||||
// 查询 nth 位置
|
||||
result, err = this.Query(tx).
|
||||
var query = this.Query(tx)
|
||||
if noPlan {
|
||||
query.Attr("userPlanId", 0)
|
||||
}
|
||||
result, err = query.
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Result(this.bytesField(useAvg)).
|
||||
@@ -745,6 +758,74 @@ func (this *ServerBandwidthStatDAO) SumDailyStat(tx *dbs.Tx, serverId int64, reg
|
||||
return
|
||||
}
|
||||
|
||||
// SumMonthlyBytes 统计某个网站单月总流量
|
||||
func (this *ServerBandwidthStatDAO) SumMonthlyBytes(tx *dbs.Tx, serverId int64, month string, noPlan bool) (int64, error) {
|
||||
if !regexputils.YYYYMM.MatchString(month) {
|
||||
return 0, errors.New("invalid month '" + month + "'")
|
||||
}
|
||||
|
||||
// 兼容以往版本
|
||||
hasFullData, err := this.HasFullData(tx, serverId, month)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if !hasFullData {
|
||||
return SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||
}
|
||||
|
||||
var query = this.Query(tx)
|
||||
if noPlan {
|
||||
query.Attr("userPlanId", 0)
|
||||
}
|
||||
return query.
|
||||
Table(this.partialTable(serverId)).
|
||||
Between("day", month+"01", month+"31").
|
||||
Attr("serverId", serverId).
|
||||
SumInt64("totalBytes", 0)
|
||||
}
|
||||
|
||||
// SumServerMonthlyWithRegion 根据服务计算某月合计
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerBandwidthStatDAO) SumServerMonthlyWithRegion(tx *dbs.Tx, serverId int64, regionId int64, month string, noPlan bool) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
query.Table(this.partialTable(serverId))
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
if noPlan {
|
||||
query.Attr("userPlanId", 0)
|
||||
}
|
||||
return query.Between("day", month+"01", month+"31").
|
||||
Attr("serverId", serverId).
|
||||
SumInt64("totalBytes", 0)
|
||||
}
|
||||
|
||||
// FindDistinctServerIdsWithoutPlanAtPartition 查找没有绑定套餐的有流量网站
|
||||
func (this *ServerBandwidthStatDAO) FindDistinctServerIdsWithoutPlanAtPartition(tx *dbs.Tx, partitionIndex int, month string) (serverIds []int64, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
Table(this.partialTable(int64(partitionIndex))).
|
||||
Between("day", month+"01", month+"31").
|
||||
Attr("userPlanId", 0). // 没有绑定套餐
|
||||
Result("DISTINCT serverId").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var serverId = int64(one.(*ServerBandwidthStat).ServerId)
|
||||
if serverId <= 0 {
|
||||
continue
|
||||
}
|
||||
serverIds = append(serverIds, serverId)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CountPartitions 查看分区数量
|
||||
func (this *ServerBandwidthStatDAO) CountPartitions() int {
|
||||
return ServerBandwidthStatTablePartitions
|
||||
}
|
||||
|
||||
// CleanDays 清理过期数据
|
||||
func (this *ServerBandwidthStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days)) // 保留大约3个月的数据
|
||||
@@ -777,9 +858,9 @@ func (this *ServerBandwidthStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int
|
||||
func (this *ServerBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(ServerBandwidthStatTablePartials)
|
||||
wg.Add(ServerBandwidthStatTablePartitions)
|
||||
var resultErr error
|
||||
for i := 0; i < ServerBandwidthStatTablePartials; i++ {
|
||||
for i := 0; i < ServerBandwidthStatTablePartitions; i++ {
|
||||
var table = this.partialTable(int64(i))
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
@@ -796,7 +877,7 @@ func (this *ServerBandwidthStatDAO) runBatch(f func(table string, locker *sync.M
|
||||
|
||||
// 获取分区表
|
||||
func (this *ServerBandwidthStatDAO) partialTable(serverId int64) string {
|
||||
return this.Table + "_" + types.String(serverId%int64(ServerBandwidthStatTablePartials))
|
||||
return this.Table + "_" + types.String(serverId%int64(ServerBandwidthStatTablePartitions))
|
||||
}
|
||||
|
||||
// 获取字节字段
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
func TestServerBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateServerBandwidth(tx, 1, 1, 0, timeutil.Format("Ymd"), timeutil.FormatTime("Hi", time.Now().Unix()/300*300), 1024, 300, 0, 0, 0, 0, 0)
|
||||
err := dao.UpdateServerBandwidth(tx, 1, 1, 0, 0, timeutil.Format("Ymd"), timeutil.FormatTime("Hi", time.Now().Unix()/300*300), 1024, 300, 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func TestSeverBandwidthStatDAO_InsertManyStats(t *testing.T) {
|
||||
}
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -rands.Int(0, 200)))
|
||||
var minute = fmt.Sprintf("%02d%02d", rands.Int(0, 23), rands.Int(0, 59))
|
||||
err := dao.UpdateServerBandwidth(tx, 1, int64(rands.Int(1, 10000)), 0, day, minute, 1024, 300, 0, 0, 0, 0, 0)
|
||||
err := dao.UpdateServerBandwidth(tx, 1, int64(rands.Int(1, 10000)), 0, 0, day, minute, 1024, 300, 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -44,8 +44,10 @@ func TestSeverBandwidthStatDAO_InsertManyStats(t *testing.T) {
|
||||
func TestServerBandwidthStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95, false))
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95, true))
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95, false, false, 0))
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95, true, false, 0))
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95, true, false, 100))
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95, true, true, 0))
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_FindAllServerStatsWithMonth(t *testing.T) {
|
||||
@@ -114,3 +116,32 @@ func TestServerBandwidthStatDAO_FindBandwidthStatsBetweenDays(t *testing.T) {
|
||||
t.Log(stat.Day, stat.TimeAt, "bytes:", stat.Bytes, "bits:", stat.Bits)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_SumServerMonthlyWithRegion(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
{
|
||||
totalBytes, err := dao.SumServerMonthlyWithRegion(tx, 23, 0, timeutil.Format("Ym"), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("with plan:", totalBytes)
|
||||
}
|
||||
{
|
||||
totalBytes, err := dao.SumServerMonthlyWithRegion(tx, 23, 0, timeutil.Format("Ym"), true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("without plan:", totalBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_SumMonthlyBytes(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
totalBytes, err := dao.SumMonthlyBytes(tx, 23, timeutil.Format("Ym"), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("total bytes:", totalBytes)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
ServerBandwidthStatField_Id dbs.FieldName = "id" // ID
|
||||
ServerBandwidthStatField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
ServerBandwidthStatField_ServerId dbs.FieldName = "serverId" // 服务ID
|
||||
ServerBandwidthStatField_RegionId dbs.FieldName = "regionId" // 区域ID
|
||||
ServerBandwidthStatField_UserPlanId dbs.FieldName = "userPlanId" // 用户套餐ID
|
||||
ServerBandwidthStatField_Day dbs.FieldName = "day" // 日期YYYYMMDD
|
||||
ServerBandwidthStatField_TimeAt dbs.FieldName = "timeAt" // 时间点HHMM
|
||||
ServerBandwidthStatField_Bytes dbs.FieldName = "bytes" // 带宽字节
|
||||
ServerBandwidthStatField_AvgBytes dbs.FieldName = "avgBytes" // 平均流量
|
||||
ServerBandwidthStatField_CachedBytes dbs.FieldName = "cachedBytes" // 缓存的流量
|
||||
ServerBandwidthStatField_AttackBytes dbs.FieldName = "attackBytes" // 攻击流量
|
||||
ServerBandwidthStatField_CountRequests dbs.FieldName = "countRequests" // 请求数
|
||||
ServerBandwidthStatField_CountCachedRequests dbs.FieldName = "countCachedRequests" // 缓存的请求数
|
||||
ServerBandwidthStatField_CountAttackRequests dbs.FieldName = "countAttackRequests" // 攻击请求数
|
||||
ServerBandwidthStatField_TotalBytes dbs.FieldName = "totalBytes" // 总流量
|
||||
)
|
||||
|
||||
// ServerBandwidthStat 服务峰值带宽统计
|
||||
type ServerBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
ServerId uint64 `field:"serverId"` // 服务ID
|
||||
RegionId uint32 `field:"regionId"` // 区域ID
|
||||
UserPlanId uint64 `field:"userPlanId"` // 用户套餐ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHMM
|
||||
Bytes uint64 `field:"bytes"` // 带宽字节
|
||||
@@ -23,6 +44,7 @@ type ServerBandwidthStatOperator struct {
|
||||
UserId any // 用户ID
|
||||
ServerId any // 服务ID
|
||||
RegionId any // 区域ID
|
||||
UserPlanId any // 用户套餐ID
|
||||
Day any // 日期YYYYMMDD
|
||||
TimeAt any // 时间点HHMM
|
||||
Bytes any // 带宽字节
|
||||
|
||||
@@ -119,7 +119,7 @@ func (this *ServerDailyStatDAO) SaveStats(tx *dbs.Tx, stats []*pb.ServerDailySta
|
||||
|
||||
// 更新流量限制状态
|
||||
if stat.CheckTrafficLimiting {
|
||||
trafficLimitConfig, err := SharedServerDAO.CalculateServerTrafficLimitConfig(tx, stat.ServerId, cacheMap)
|
||||
trafficLimitConfig, err := SharedServerDAO.FindServerTrafficLimitConfig(tx, stat.ServerId, cacheMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func (this *ServerDailyStatDAO) SaveStats(tx *dbs.Tx, stats []*pb.ServerDailySta
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerDAO.UpdateServerTrafficLimitStatus(tx, trafficLimitConfig, stat.ServerId, false)
|
||||
err = SharedServerDAO.RenewServerTrafficLimitStatus(tx, trafficLimitConfig, stat.ServerId, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -140,6 +140,7 @@ func (this *ServerDailyStatDAO) SaveStats(tx *dbs.Tx, stats []*pb.ServerDailySta
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// SumCurrentDailyStat 查找当前时刻的数据统计
|
||||
func (this *ServerDailyStatDAO) SumCurrentDailyStat(tx *dbs.Tx, serverId int64) (*ServerDailyStat, error) {
|
||||
var day = timeutil.Format("Ymd")
|
||||
@@ -164,7 +165,7 @@ func (this *ServerDailyStatDAO) SumServerMonthlyWithRegion(tx *dbs.Tx, serverId
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
return query.Between("day", month+"01", month+"32").
|
||||
return query.Between("day", month+"01", month+"31").
|
||||
Attr("serverId", serverId).
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
@@ -178,7 +179,7 @@ func (this *ServerDailyStatDAO) SumUserMonthlyWithoutPlan(tx *dbs.Tx, userId int
|
||||
}
|
||||
return query.
|
||||
Attr("planId", 0).
|
||||
Between("day", month+"01", month+"32").
|
||||
Between("day", month+"01", month+"31").
|
||||
Attr("userId", userId).
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
@@ -190,7 +191,7 @@ func (this *ServerDailyStatDAO) SumUserMonthlyPeek(tx *dbs.Tx, userId int64, reg
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
max, err := query.Between("day", month+"01", month+"32").
|
||||
max, err := query.Between("day", month+"01", month+"31").
|
||||
Attr("userId", userId).
|
||||
Max("bytes", 0)
|
||||
if err != nil {
|
||||
@@ -644,7 +645,7 @@ func (this *ServerDailyStatDAO) FindStatsBetweenDays(tx *dbs.Tx, userId int64, s
|
||||
// month YYYYMM
|
||||
func (this *ServerDailyStatDAO) FindMonthlyStatsWithPlan(tx *dbs.Tx, month string) (result []*ServerDailyStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Between("day", month+"01", month+"32").
|
||||
Between("day", month+"01", month+"31").
|
||||
Gt("planId", 0).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
|
||||
@@ -3,11 +3,13 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -782,7 +784,7 @@ func (this *ServerDAO) CountAllEnabledServers(tx *dbs.Tx) (int64, error) {
|
||||
// 参数:
|
||||
//
|
||||
// groupId 分组ID,如果为-1,则搜索没有分组的服务
|
||||
func (this *ServerDAO) CountAllEnabledServersMatch(tx *dbs.Tx, groupId int64, keyword string, userId int64, clusterId int64, auditingFlag configutils.BoolState, protocolFamilies []string) (int64, error) {
|
||||
func (this *ServerDAO) CountAllEnabledServersMatch(tx *dbs.Tx, groupId int64, keyword string, userId int64, clusterId int64, auditingFlag configutils.BoolState, protocolFamilies []string, userPlanId int64) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
State(ServerStateEnabled)
|
||||
if groupId > 0 {
|
||||
@@ -829,6 +831,10 @@ func (this *ServerDAO) CountAllEnabledServersMatch(tx *dbs.Tx, groupId int64, ke
|
||||
query.Where("(" + strings.Join(protocolConds, " OR ") + ")")
|
||||
}
|
||||
|
||||
if userPlanId > 0 {
|
||||
query.Attr("userPlanId", userPlanId)
|
||||
}
|
||||
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
@@ -1316,12 +1322,13 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, ignoreCer
|
||||
}
|
||||
|
||||
// 套餐是否依然有效
|
||||
plan, err := SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId))
|
||||
plan, err := SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if plan != nil {
|
||||
config.UserPlan = &serverconfigs.UserPlanConfig{
|
||||
Id: int64(userPlan.Id),
|
||||
DayTo: userPlan.DayTo,
|
||||
Plan: &serverconfigs.PlanConfig{
|
||||
Id: int64(plan.Id),
|
||||
@@ -1341,16 +1348,14 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, ignoreCer
|
||||
}
|
||||
}
|
||||
|
||||
if config.TrafficLimit != nil && config.TrafficLimit.IsOn && !config.TrafficLimit.IsEmpty() {
|
||||
if len(server.TrafficLimitStatus) > 0 {
|
||||
var status = &serverconfigs.TrafficLimitStatus{}
|
||||
err := json.Unmarshal(server.TrafficLimitStatus, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status.IsValid() {
|
||||
config.TrafficLimitStatus = status
|
||||
}
|
||||
if len(server.TrafficLimitStatus) > 0 {
|
||||
var status = &serverconfigs.TrafficLimitStatus{}
|
||||
err := json.Unmarshal(server.TrafficLimitStatus, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status.IsValid() {
|
||||
config.TrafficLimitStatus = status
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1794,6 +1799,7 @@ func (this *ServerDAO) FindServerUserId(tx *dbs.Tx, serverId int64) (userId int6
|
||||
}
|
||||
|
||||
// FindServerUserPlanId 查找服务的套餐ID
|
||||
// TODO 需要缓存
|
||||
func (this *ServerDAO) FindServerUserPlanId(tx *dbs.Tx, serverId int64) (userPlanId int64, err error) {
|
||||
return this.Query(tx).
|
||||
Pk(serverId).
|
||||
@@ -2039,11 +2045,12 @@ func (this *ServerDAO) GenDNSName(tx *dbs.Tx) (string, error) {
|
||||
|
||||
// FindLatestServers 查询最近访问的服务
|
||||
func (this *ServerDAO) FindLatestServers(tx *dbs.Tx, size int64) (result []*Server, err error) {
|
||||
itemTable := SharedLatestItemDAO.Table
|
||||
itemType := LatestItemTypeServer
|
||||
var itemTable = SharedLatestItemDAO.Table
|
||||
var itemType = LatestItemTypeServer
|
||||
_, err = this.Query(tx).
|
||||
Result(this.Table+".id", this.Table+".name").
|
||||
Join(SharedLatestItemDAO, dbs.QueryJoinRight, this.Table+".id="+itemTable+".itemId AND "+itemTable+".itemType='"+itemType+"'").
|
||||
Where(itemTable + ".updatedAt<=UNIX_TIMESTAMP()"). // VERY IMPORTANT
|
||||
Asc("CEIL((UNIX_TIMESTAMP() - " + itemTable + ".updatedAt) / (7 * 86400))"). // 优先一个星期以内的
|
||||
Desc(itemTable + ".count").
|
||||
State(NodeClusterStateEnabled).
|
||||
@@ -2306,94 +2313,17 @@ func (this *ServerDAO) FindServerTrafficLimitConfig(tx *dbs.Tx, serverId int64,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var limit = &serverconfigs.TrafficLimitConfig{}
|
||||
if serverOne == nil {
|
||||
return limit, nil
|
||||
}
|
||||
|
||||
var trafficLimit = serverOne.(*Server).TrafficLimit
|
||||
|
||||
if len(trafficLimit) > 0 {
|
||||
err = json.Unmarshal([]byte(trafficLimit), limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, limit)
|
||||
}
|
||||
|
||||
return limit, nil
|
||||
}
|
||||
|
||||
// CalculateServerTrafficLimitConfig 计算服务的流量限制
|
||||
// TODO 优化性能
|
||||
func (this *ServerDAO) CalculateServerTrafficLimitConfig(tx *dbs.Tx, serverId int64, cacheMap *utils.CacheMap) (*serverconfigs.TrafficLimitConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":FindServerTrafficLimitConfig:" + types.String(serverId)
|
||||
result, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return result.(*serverconfigs.TrafficLimitConfig), nil
|
||||
}
|
||||
|
||||
serverOne, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("trafficLimit", "userPlanId").
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var limitConfig = &serverconfigs.TrafficLimitConfig{}
|
||||
if serverOne == nil {
|
||||
return limitConfig, nil
|
||||
}
|
||||
|
||||
var trafficLimit = serverOne.(*Server).TrafficLimit
|
||||
var userPlanId = int64(serverOne.(*Server).UserPlanId)
|
||||
var trafficLimitJSON = serverOne.(*Server).TrafficLimit
|
||||
|
||||
if len(trafficLimit) == 0 {
|
||||
if userPlanId > 0 {
|
||||
userPlan, err := SharedUserPlanDAO.FindEnabledUserPlan(tx, userPlanId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userPlan != nil {
|
||||
planLimit, err := SharedPlanDAO.FindEnabledPlanTrafficLimit(tx, int64(userPlan.PlanId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if planLimit != nil {
|
||||
return planLimit, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return limitConfig, nil
|
||||
}
|
||||
|
||||
err = json.Unmarshal(trafficLimit, limitConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !limitConfig.IsOn {
|
||||
if userPlanId > 0 {
|
||||
userPlan, err := SharedUserPlanDAO.FindEnabledUserPlan(tx, userPlanId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userPlan != nil {
|
||||
planLimit, err := SharedPlanDAO.FindEnabledPlanTrafficLimit(tx, int64(userPlan.PlanId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if planLimit != nil {
|
||||
return planLimit, nil
|
||||
}
|
||||
}
|
||||
if len(trafficLimitJSON) > 0 {
|
||||
err = json.Unmarshal(trafficLimitJSON, limitConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2423,11 +2353,11 @@ func (this *ServerDAO) UpdateServerTrafficLimitConfig(tx *dbs.Tx, serverId int64
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
return this.UpdateServerTrafficLimitStatus(tx, trafficLimitConfig, serverId, true)
|
||||
return this.RenewServerTrafficLimitStatus(tx, trafficLimitConfig, serverId, true)
|
||||
}
|
||||
|
||||
// UpdateServerTrafficLimitStatus 修改服务的流量限制状态
|
||||
func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitConfig *serverconfigs.TrafficLimitConfig, serverId int64, isUpdatingConfig bool) error {
|
||||
// RenewServerTrafficLimitStatus 根据限流配置更新网站的流量限制状态
|
||||
func (this *ServerDAO) RenewServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitConfig *serverconfigs.TrafficLimitConfig, serverId int64, isUpdatingConfig bool) error {
|
||||
if !trafficLimitConfig.IsOn {
|
||||
if isUpdatingConfig {
|
||||
return this.NotifyUpdate(tx, serverId)
|
||||
@@ -2464,9 +2394,11 @@ func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitCo
|
||||
var untilDay = ""
|
||||
|
||||
// daily
|
||||
var dateType = ""
|
||||
if trafficLimitConfig.DailyBytes() > 0 {
|
||||
if server.TrafficDay == timeutil.Format("Ymd") && server.TotalDailyTraffic >= float64(trafficLimitConfig.DailyBytes())/(1<<30) {
|
||||
untilDay = timeutil.Format("Ymd")
|
||||
dateType = "day"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2474,6 +2406,7 @@ func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitCo
|
||||
if server.TrafficMonth == timeutil.Format("Ym") && trafficLimitConfig.MonthlyBytes() > 0 {
|
||||
if server.TotalMonthlyTraffic >= float64(trafficLimitConfig.MonthlyBytes())/(1<<30) {
|
||||
untilDay = timeutil.Format("Ym32")
|
||||
dateType = "month"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2481,12 +2414,17 @@ func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitCo
|
||||
if trafficLimitConfig.TotalBytes() > 0 {
|
||||
if server.TotalTraffic >= float64(trafficLimitConfig.TotalBytes())/(1<<30) {
|
||||
untilDay = "30000101"
|
||||
dateType = "total"
|
||||
}
|
||||
}
|
||||
|
||||
var isChanged = oldStatus.UntilDay != untilDay
|
||||
if isChanged {
|
||||
statusJSON, err := json.Marshal(&serverconfigs.TrafficLimitStatus{UntilDay: untilDay})
|
||||
statusJSON, err := json.Marshal(&serverconfigs.TrafficLimitStatus{
|
||||
UntilDay: untilDay,
|
||||
DateType: dateType,
|
||||
TargetType: serverconfigs.TrafficLimitTargetTraffic,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2507,6 +2445,91 @@ func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitCo
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateServerTrafficLimitStatus 修改网站的流量限制状态
|
||||
func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, serverId int64, day string, planId int64, dateType string, targetType string) error {
|
||||
if !regexputils.YYYYMMDD.MatchString(day) {
|
||||
return errors.New("invalid 'day' format")
|
||||
}
|
||||
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// lookup old status
|
||||
statusJSON, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result(ServerField_TrafficLimitStatus).
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if IsNotNull(statusJSON) {
|
||||
var oldStatus = &serverconfigs.TrafficLimitStatus{}
|
||||
err = json.Unmarshal(statusJSON, oldStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(oldStatus.UntilDay) > 0 && oldStatus.UntilDay >= day /** 如果已经限制,且比当前日期长,则无需重复 **/ {
|
||||
// no need to change
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var status = &serverconfigs.TrafficLimitStatus{
|
||||
UntilDay: day,
|
||||
PlanId: planId,
|
||||
DateType: dateType,
|
||||
TargetType: targetType,
|
||||
}
|
||||
statusJSON, err = json.Marshal(status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set(ServerField_TrafficLimitStatus, statusJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, serverId)
|
||||
}
|
||||
|
||||
// UpdateServersTrafficLimitStatusWithUserPlanId 修改某个套餐下的网站的流量限制状态
|
||||
func (this *ServerDAO) UpdateServersTrafficLimitStatusWithUserPlanId(tx *dbs.Tx, userPlanId int64, day string, planId int64, dateType string, targetType serverconfigs.TrafficLimitTarget) error {
|
||||
if userPlanId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
servers, err := this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Attr("userPlanId", userPlanId).
|
||||
ResultPk().
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, server := range servers {
|
||||
var serverId = int64(server.(*Server).Id)
|
||||
err = this.UpdateServerTrafficLimitStatus(tx, serverId, day, planId, dateType, targetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetServersTrafficLimitStatusWithPlanId 重置网站限流状态
|
||||
func (this *ServerDAO) ResetServersTrafficLimitStatusWithPlanId(tx *dbs.Tx, planId int64) error {
|
||||
return this.Query(tx).
|
||||
Where("JSON_EXTRACT(trafficLimitStatus, '$.planId')=:planId").
|
||||
Param("planId", planId).
|
||||
Set("trafficLimitStatus", dbs.SQL("NULL")).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// IncreaseServerTotalTraffic 增加服务的总流量
|
||||
func (this *ServerDAO) IncreaseServerTotalTraffic(tx *dbs.Tx, serverId int64, bytes int64) error {
|
||||
if serverId <= 0 {
|
||||
@@ -2548,17 +2571,16 @@ func (this *ServerDAO) FindEnabledServerIdWithUserPlanId(tx *dbs.Tx, userPlanId
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindEnabledServerWithUserPlanId 查找使用某个套餐的服务
|
||||
func (this *ServerDAO) FindEnabledServerWithUserPlanId(tx *dbs.Tx, userPlanId int64) (*Server, error) {
|
||||
one, err := this.Query(tx).
|
||||
// FindEnabledServersWithUserPlanId 查找使用某个套餐的网站
|
||||
func (this *ServerDAO) FindEnabledServersWithUserPlanId(tx *dbs.Tx, userPlanId int64) (result []*Server, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Attr("userPlanId", userPlanId).
|
||||
Result("id", "name", "serverNames", "type").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*Server), nil
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateServersClusterIdWithPlanId 修改套餐所在集群
|
||||
@@ -2643,7 +2665,7 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
|
||||
return errors.New("can not find user plan with id '" + types.String(userPlanId) + "'")
|
||||
}
|
||||
|
||||
plan, err := SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId))
|
||||
plan, err := SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2881,6 +2903,89 @@ func (this *ServerDAO) FindEnabledServersWithIds(tx *dbs.Tx, serverIds []int64)
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllServerNamesWithUserId 计算某个用户下的所有域名数
|
||||
func (this *ServerDAO) CountAllServerNamesWithUserId(tx *dbs.Tx, userId int64, userPlanId int64) (int64, error) {
|
||||
if userId <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var query = this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
State(ServerStateEnabled).
|
||||
Where("JSON_TYPE(plainServerNames)='ARRAY'")
|
||||
if userPlanId > 0 {
|
||||
query.Attr("userPlanId", userPlanId)
|
||||
}
|
||||
return query.
|
||||
SumInt64("JSON_LENGTH(plainServerNames)", 0)
|
||||
}
|
||||
|
||||
// CountServerNames 计算某个网站下的所有域名数
|
||||
func (this *ServerDAO) CountServerNames(tx *dbs.Tx, serverId int64) (int64, error) {
|
||||
if serverId <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Result("JSON_LENGTH(plainServerNames)").
|
||||
Pk(serverId).
|
||||
State(ServerStateEnabled).
|
||||
Where("JSON_TYPE(plainServerNames)='ARRAY'").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// CheckServerPlanQuota 检查网站套餐限制
|
||||
func (this *ServerDAO) CheckServerPlanQuota(tx *dbs.Tx, serverId int64, countServerNames int) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("invalid 'serverId'")
|
||||
}
|
||||
if countServerNames <= 0 {
|
||||
return nil
|
||||
}
|
||||
userPlanId, err := this.FindServerUserPlanId(tx, serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userPlanId <= 0 {
|
||||
return nil
|
||||
}
|
||||
userPlan, err := SharedUserPlanDAO.FindEnabledUserPlan(tx, userPlanId, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userPlan == nil {
|
||||
return fmt.Errorf("invalid user plan with id %q", types.String(userPlanId))
|
||||
}
|
||||
if userPlan.IsExpired() {
|
||||
return errors.New("the user plan has been expired")
|
||||
}
|
||||
if userPlan.UserId == 0 {
|
||||
return nil
|
||||
}
|
||||
plan, err := SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if plan == nil {
|
||||
return fmt.Errorf("invalid plan with id %q", types.String(userPlan.PlanId))
|
||||
}
|
||||
if plan.TotalServerNames > 0 {
|
||||
totalServerNames, err := this.CountAllServerNamesWithUserId(tx, int64(userPlan.UserId), userPlanId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if totalServerNames+int64(countServerNames) > int64(plan.TotalServerNames) {
|
||||
return errors.New("server names over plan quota")
|
||||
}
|
||||
}
|
||||
if plan.TotalServerNamesPerServer > 0 {
|
||||
if countServerNames > types.Int(plan.TotalServerNamesPerServer) {
|
||||
return errors.New("server names per server over plan quota")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 同步服务所在的集群
|
||||
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
|
||||
@@ -10,26 +10,26 @@ import (
|
||||
)
|
||||
|
||||
// CopyServerConfigToServers 拷贝服务配置到一组服务
|
||||
func (this *ServerDAO) CopyServerConfigToServers(tx *dbs.Tx, fromServerId int64, toServerIds []int64, configCode serverconfigs.ConfigCode) error {
|
||||
func (this *ServerDAO) CopyServerConfigToServers(tx *dbs.Tx, fromServerId int64, toServerIds []int64, configCode serverconfigs.ConfigCode, wafCopyRegions bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// CopyServerConfigToGroups 拷贝服务配置到分组
|
||||
func (this *ServerDAO) CopyServerConfigToGroups(tx *dbs.Tx, fromServerId int64, groupIds []int64, configCode string) error {
|
||||
func (this *ServerDAO) CopyServerConfigToGroups(tx *dbs.Tx, fromServerId int64, groupIds []int64, configCode string, wafCopyRegions bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// CopyServerConfigToCluster 拷贝服务配置到集群
|
||||
func (this *ServerDAO) CopyServerConfigToCluster(tx *dbs.Tx, fromServerId int64, clusterId int64, configCode string) error {
|
||||
func (this *ServerDAO) CopyServerConfigToCluster(tx *dbs.Tx, fromServerId int64, clusterId int64, configCode string, wafCopyRegions bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// CopyServerConfigToUser 拷贝服务配置到用户
|
||||
func (this *ServerDAO) CopyServerConfigToUser(tx *dbs.Tx, fromServerId int64, userId int64, configCode string) error {
|
||||
func (this *ServerDAO) CopyServerConfigToUser(tx *dbs.Tx, fromServerId int64, userId int64, configCode string, wafCopyRegions bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// CopyServerUAMConfigs 复制UAM设置
|
||||
func (this *ServerDAO) CopyServerUAMConfigs(tx *dbs.Tx, fromServerId int64, toServerIds []int64) error {
|
||||
func (this *ServerDAO) CopyServerUAMConfigs(tx *dbs.Tx, fromServerId int64, toServerIds []int64, wafCopyRegions bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ func TestServerDAO_FindEnabledServerWithDomain(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDAO_UpdateServerTrafficLimitStatus(t *testing.T) {
|
||||
func TestServerDAO_RenewServerTrafficLimitStatus(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
@@ -250,7 +250,7 @@ func TestServerDAO_UpdateServerTrafficLimitStatus(t *testing.T) {
|
||||
defer func() {
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}()
|
||||
err := models.NewServerDAO().UpdateServerTrafficLimitStatus(tx, &serverconfigs.TrafficLimitConfig{
|
||||
err := models.NewServerDAO().RenewServerTrafficLimitStatus(tx, &serverconfigs.TrafficLimitConfig{
|
||||
IsOn: true,
|
||||
DailySize: &shared.SizeCapacity{Count: 1, Unit: "mb"},
|
||||
MonthlySize: &shared.SizeCapacity{Count: 10, Unit: "mb"},
|
||||
@@ -263,40 +263,15 @@ func TestServerDAO_UpdateServerTrafficLimitStatus(t *testing.T) {
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestServerDAO_CalculateServerTrafficLimitConfig(t *testing.T) {
|
||||
func TestServerDAO_UpdateServerTrafficLimitStatus(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = models.NewServerDAO()
|
||||
var tx *dbs.Tx
|
||||
before := time.Now()
|
||||
defer func() {
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}()
|
||||
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
config, err := models.SharedServerDAO.CalculateServerTrafficLimitConfig(tx, 23, cacheMap)
|
||||
err := dao.UpdateServerTrafficLimitStatus(tx, 23, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 20)), 14, "day", "traffic")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
logs.PrintAsJSON(config, t)
|
||||
}
|
||||
|
||||
func TestServerDAO_CalculateServerTrafficLimitConfig_Cache(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
before := time.Now()
|
||||
defer func() {
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}()
|
||||
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
for i := 0; i < 10; i++ {
|
||||
config, err := models.SharedServerDAO.CalculateServerTrafficLimitConfig(tx, 23, cacheMap)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = config
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDAO_FindBytes(t *testing.T) {
|
||||
|
||||
@@ -285,7 +285,7 @@ func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, ignoreData b
|
||||
}
|
||||
|
||||
// CountCerts 计算符合条件的证书数量
|
||||
func (this *SSLCertDAO) CountCerts(tx *dbs.Tx, isCA bool, isAvailable bool, isExpired bool, expiringDays int64, keyword string, userId int64, domains []string) (int64, error) {
|
||||
func (this *SSLCertDAO) CountCerts(tx *dbs.Tx, isCA bool, isAvailable bool, isExpired bool, expiringDays int64, keyword string, userId int64, domains []string, userOnly bool) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(SSLCertStateEnabled)
|
||||
if isCA {
|
||||
@@ -308,8 +308,12 @@ func (this *SSLCertDAO) CountCerts(tx *dbs.Tx, isCA bool, isAvailable bool, isEx
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
// 只查询管理员上传的
|
||||
query.Attr("userId", 0)
|
||||
if userOnly {
|
||||
query.Gt("userId", 0)
|
||||
} else {
|
||||
// 只查询管理员上传的
|
||||
query.Attr("userId", 0)
|
||||
}
|
||||
}
|
||||
|
||||
// 域名
|
||||
@@ -322,7 +326,7 @@ func (this *SSLCertDAO) CountCerts(tx *dbs.Tx, isCA bool, isAvailable bool, isEx
|
||||
}
|
||||
|
||||
// ListCertIds 列出符合条件的证书
|
||||
func (this *SSLCertDAO) ListCertIds(tx *dbs.Tx, isCA bool, isAvailable bool, isExpired bool, expiringDays int64, keyword string, userId int64, domains []string, offset int64, size int64) (certIds []int64, err error) {
|
||||
func (this *SSLCertDAO) ListCertIds(tx *dbs.Tx, isCA bool, isAvailable bool, isExpired bool, expiringDays int64, keyword string, userId int64, domains []string, userOnly bool, offset int64, size int64) (certIds []int64, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(SSLCertStateEnabled)
|
||||
if isCA {
|
||||
@@ -345,8 +349,12 @@ func (this *SSLCertDAO) ListCertIds(tx *dbs.Tx, isCA bool, isAvailable bool, isE
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
// 只查询管理员上传的
|
||||
query.Attr("userId", 0)
|
||||
if userOnly {
|
||||
query.Gt("userId", 0)
|
||||
} else {
|
||||
// 只查询管理员上传的
|
||||
query.Attr("userId", 0)
|
||||
}
|
||||
}
|
||||
|
||||
// 域名
|
||||
@@ -434,6 +442,14 @@ func (this *SSLCertDAO) CheckUserCert(tx *dbs.Tx, certId int64, userId int64) er
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindCertUserId 查找证书所属用户ID
|
||||
func (this *SSLCertDAO) FindCertUserId(tx *dbs.Tx, certId int64) (userId int64, err error) {
|
||||
return this.Query(tx).
|
||||
Pk(certId).
|
||||
Result("userId").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// UpdateCertUser 修改证书所属用户
|
||||
func (this *SSLCertDAO) UpdateCertUser(tx *dbs.Tx, certId int64, userId int64) error {
|
||||
if certId <= 0 || userId <= 0 {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/zero"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -126,23 +125,6 @@ func (this *SysSettingDAO) CompareInt64Setting(tx *dbs.Tx, code string, anotherV
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ReadGlobalConfig 读取全局配置
|
||||
func (this *SysSettingDAO) ReadGlobalConfig(tx *dbs.Tx) (*serverconfigs.GlobalConfig, error) {
|
||||
globalConfigData, err := this.ReadSetting(tx, systemconfigs.SettingCodeServerGlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(globalConfigData) == 0 {
|
||||
return &serverconfigs.GlobalConfig{}, nil
|
||||
}
|
||||
config := &serverconfigs.GlobalConfig{}
|
||||
err = json.Unmarshal(globalConfigData, 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"
|
||||
|
||||
239
internal/db/models/user_plan_bandwidth_stat_dao.go
Normal file
239
internal/db/models/user_plan_bandwidth_stat_dao.go
Normal file
@@ -0,0 +1,239 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserPlanBandwidthStatDAO dbs.DAO
|
||||
|
||||
const (
|
||||
UserPlanBandwidthStatTablePartitions = 20 // 分表数量
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedUserPlanBandwidthStatDAO.CleanDefaultDays(nil, 100)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedUserPlanBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewUserPlanBandwidthStatDAO() *UserPlanBandwidthStatDAO {
|
||||
return dbs.NewDAO(&UserPlanBandwidthStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserPlanBandwidthStats",
|
||||
Model: new(UserPlanBandwidthStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserPlanBandwidthStatDAO)
|
||||
}
|
||||
|
||||
var SharedUserPlanBandwidthStatDAO *UserPlanBandwidthStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserPlanBandwidthStatDAO = NewUserPlanBandwidthStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUserPlanBandwidth 写入数据
|
||||
// 暂时不使用region区分
|
||||
func (this *UserPlanBandwidthStatDAO) UpdateUserPlanBandwidth(tx *dbs.Tx, userId int64, userPlanId int64, regionId int64, day string, timeAt string, bandwidthBytes int64, totalBytes int64, cachedBytes int64, attackBytes int64, countRequests int64, countCachedRequests int64, countAttackRequests int64) error {
|
||||
if userId <= 0 || userPlanId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(userPlanId)).
|
||||
Param("bytes", bandwidthBytes).
|
||||
Param("totalBytes", totalBytes).
|
||||
Param("cachedBytes", cachedBytes).
|
||||
Param("attackBytes", attackBytes).
|
||||
Param("countRequests", countRequests).
|
||||
Param("countCachedRequests", countCachedRequests).
|
||||
Param("countAttackRequests", countAttackRequests).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"userPlanId": userPlanId,
|
||||
"regionId": regionId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bandwidthBytes,
|
||||
"totalBytes": totalBytes,
|
||||
"avgBytes": totalBytes / 300,
|
||||
"cachedBytes": cachedBytes,
|
||||
"attackBytes": attackBytes,
|
||||
"countRequests": countRequests,
|
||||
"countCachedRequests": countCachedRequests,
|
||||
"countAttackRequests": countAttackRequests,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
"avgBytes": dbs.SQL("(totalBytes+:totalBytes)/300"), // 因为生成SQL语句时会自动将avgBytes排在totalBytes之前,所以这里不用担心先后顺序的问题
|
||||
"totalBytes": dbs.SQL("totalBytes+:totalBytes"),
|
||||
"cachedBytes": dbs.SQL("cachedBytes+:cachedBytes"),
|
||||
"attackBytes": dbs.SQL("attackBytes+:attackBytes"),
|
||||
"countRequests": dbs.SQL("countRequests+:countRequests"),
|
||||
"countCachedRequests": dbs.SQL("countCachedRequests+:countCachedRequests"),
|
||||
"countAttackRequests": dbs.SQL("countAttackRequests+:countAttackRequests"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *UserPlanBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, userPlanId int64, month string, percentile int, useAvg bool) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
|
||||
// 如果是100%以上,则快速返回
|
||||
if percentile >= 100 {
|
||||
result, err = this.Query(tx).
|
||||
Table(this.partialTable(userPlanId)).
|
||||
Attr("userPlanId", userPlanId).
|
||||
Result(this.sumBytesField(useAvg)).
|
||||
Between("day", month+"01", month+"31").
|
||||
Group("day").
|
||||
Group("timeAt").
|
||||
Desc("bytes").
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
return
|
||||
}
|
||||
|
||||
// 总数量
|
||||
total, err := this.Query(tx).
|
||||
Table(this.partialTable(userPlanId)).
|
||||
Attr("userPlanId", userPlanId).
|
||||
Between("day", month+"01", month+"31").
|
||||
CountAttr("DISTINCT day, timeAt")
|
||||
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))
|
||||
}
|
||||
|
||||
// 查询 nth 位置
|
||||
result, err = this.Query(tx).
|
||||
Table(this.partialTable(userPlanId)).
|
||||
Attr("userPlanId", userPlanId).
|
||||
Result(this.sumBytesField(useAvg)).
|
||||
Between("day", month+"01", month+"31").
|
||||
Group("day").
|
||||
Group("timeAt").
|
||||
Desc("bytes").
|
||||
Offset(offset).
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SumMonthlyBytes 读取单月总流量
|
||||
func (this *UserPlanBandwidthStatDAO) SumMonthlyBytes(tx *dbs.Tx, userPlanId int64, month string) (int64, error) {
|
||||
if !regexputils.YYYYMM.MatchString(month) {
|
||||
return 0, errors.New("invalid ")
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(userPlanId)).
|
||||
Attr("userPlanId", userPlanId).
|
||||
Between("day", month+"01", month+"31").
|
||||
SumInt64("totalBytes", 0)
|
||||
}
|
||||
|
||||
// CleanDefaultDays 清理过期数据
|
||||
func (this *UserPlanBandwidthStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.UserPlanBandwidthStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.UserPlanBandwidthStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 100
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
// CleanDays 清理过期数据
|
||||
func (this *UserPlanBandwidthStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days)) // 保留大约3个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// 获取字节字段
|
||||
func (this *UserPlanBandwidthStatDAO) bytesField(useAvg bool) string {
|
||||
if useAvg {
|
||||
return "avgBytes AS bytes"
|
||||
}
|
||||
return "bytes"
|
||||
}
|
||||
|
||||
func (this *UserPlanBandwidthStatDAO) sumBytesField(useAvg bool) string {
|
||||
if useAvg {
|
||||
return "SUM(avgBytes) AS bytes"
|
||||
}
|
||||
return "SUM(bytes) AS bytes"
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *UserPlanBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(UserPlanBandwidthStatTablePartitions)
|
||||
var resultErr error
|
||||
for i := 0; i < UserPlanBandwidthStatTablePartitions; i++ {
|
||||
var table = this.partialTable(int64(i))
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
err := f(table, locker)
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// 获取分区表
|
||||
func (this *UserPlanBandwidthStatDAO) partialTable(userPlanId int64) string {
|
||||
return this.Table + "_" + types.String(userPlanId%int64(UserPlanBandwidthStatTablePartitions))
|
||||
}
|
||||
39
internal/db/models/user_plan_bandwidth_stat_dao_test.go
Normal file
39
internal/db/models/user_plan_bandwidth_stat_dao_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "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 TestUserPlanBandwidthStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var dao = models.NewUserPlanBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
|
||||
{
|
||||
resultBytes, err := dao.FindMonthlyPercentile(tx, 20, timeutil.Format("Ym"), 100, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("result bytes0:", resultBytes)
|
||||
}
|
||||
|
||||
{
|
||||
resultBytes, err := dao.FindMonthlyPercentile(tx, 20, timeutil.Format("Ym"), 95, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("result bytes1:", resultBytes)
|
||||
}
|
||||
|
||||
{
|
||||
resultBytes, err := dao.FindMonthlyPercentile(tx, 20, timeutil.Format("Ym"), 95, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("result bytes2:", resultBytes)
|
||||
}
|
||||
}
|
||||
59
internal/db/models/user_plan_bandwidth_stat_model.go
Normal file
59
internal/db/models/user_plan_bandwidth_stat_model.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
UserPlanBandwidthStatField_Id dbs.FieldName = "id" // ID
|
||||
UserPlanBandwidthStatField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
UserPlanBandwidthStatField_UserPlanId dbs.FieldName = "userPlanId" // 用户套餐ID
|
||||
UserPlanBandwidthStatField_Day dbs.FieldName = "day" // 日期YYYYMMDD
|
||||
UserPlanBandwidthStatField_TimeAt dbs.FieldName = "timeAt" // 时间点HHII
|
||||
UserPlanBandwidthStatField_Bytes dbs.FieldName = "bytes" // 带宽
|
||||
UserPlanBandwidthStatField_RegionId dbs.FieldName = "regionId" // 区域ID
|
||||
UserPlanBandwidthStatField_TotalBytes dbs.FieldName = "totalBytes" // 总流量
|
||||
UserPlanBandwidthStatField_AvgBytes dbs.FieldName = "avgBytes" // 平均流量
|
||||
UserPlanBandwidthStatField_CachedBytes dbs.FieldName = "cachedBytes" // 缓存的流量
|
||||
UserPlanBandwidthStatField_AttackBytes dbs.FieldName = "attackBytes" // 攻击流量
|
||||
UserPlanBandwidthStatField_CountRequests dbs.FieldName = "countRequests" // 请求数
|
||||
UserPlanBandwidthStatField_CountCachedRequests dbs.FieldName = "countCachedRequests" // 缓存的请求数
|
||||
UserPlanBandwidthStatField_CountAttackRequests dbs.FieldName = "countAttackRequests" // 攻击请求数
|
||||
)
|
||||
|
||||
// UserPlanBandwidthStat 用户套餐带宽峰值
|
||||
type UserPlanBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
UserPlanId uint64 `field:"userPlanId"` // 用户套餐ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHII
|
||||
Bytes uint64 `field:"bytes"` // 带宽
|
||||
RegionId uint32 `field:"regionId"` // 区域ID
|
||||
TotalBytes uint64 `field:"totalBytes"` // 总流量
|
||||
AvgBytes uint64 `field:"avgBytes"` // 平均流量
|
||||
CachedBytes uint64 `field:"cachedBytes"` // 缓存的流量
|
||||
AttackBytes uint64 `field:"attackBytes"` // 攻击流量
|
||||
CountRequests uint64 `field:"countRequests"` // 请求数
|
||||
CountCachedRequests uint64 `field:"countCachedRequests"` // 缓存的请求数
|
||||
CountAttackRequests uint64 `field:"countAttackRequests"` // 攻击请求数
|
||||
}
|
||||
|
||||
type UserPlanBandwidthStatOperator struct {
|
||||
Id any // ID
|
||||
UserId any // 用户ID
|
||||
UserPlanId any // 用户套餐ID
|
||||
Day any // 日期YYYYMMDD
|
||||
TimeAt any // 时间点HHII
|
||||
Bytes any // 带宽
|
||||
RegionId any // 区域ID
|
||||
TotalBytes any // 总流量
|
||||
AvgBytes any // 平均流量
|
||||
CachedBytes any // 缓存的流量
|
||||
AttackBytes any // 攻击流量
|
||||
CountRequests any // 请求数
|
||||
CountCachedRequests any // 缓存的请求数
|
||||
CountAttackRequests any // 攻击请求数
|
||||
}
|
||||
|
||||
func NewUserPlanBandwidthStatOperator() *UserPlanBandwidthStatOperator {
|
||||
return &UserPlanBandwidthStatOperator{}
|
||||
}
|
||||
@@ -1 +1,8 @@
|
||||
package models
|
||||
|
||||
import timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
|
||||
// IsExpired 判断套餐是否过期
|
||||
func (this *UserPlan) IsExpired() bool {
|
||||
return len(this.DayTo) == 0 || this.DayTo < timeutil.Format("Y-m-d")
|
||||
}
|
||||
|
||||
28
internal/db/models/user_plan_stat_dao.go
Normal file
28
internal/db/models/user_plan_stat_dao.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
type UserPlanStatDAO dbs.DAO
|
||||
|
||||
func NewUserPlanStatDAO() *UserPlanStatDAO {
|
||||
return dbs.NewDAO(&UserPlanStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserPlanStats",
|
||||
Model: new(UserPlanStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserPlanStatDAO)
|
||||
}
|
||||
|
||||
var SharedUserPlanStatDAO *UserPlanStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserPlanStatDAO = NewUserPlanStatDAO()
|
||||
})
|
||||
}
|
||||
10
internal/db/models/user_plan_stat_dao_community.go
Normal file
10
internal/db/models/user_plan_stat_dao_community.go
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
func (this *UserPlanStatDAO) IncreaseUserPlanStat(tx *dbs.Tx, userPlanId int64, trafficBytes int64, countRequests int64) error {
|
||||
return nil
|
||||
}
|
||||
6
internal/db/models/user_plan_stat_dao_test.go
Normal file
6
internal/db/models/user_plan_stat_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
38
internal/db/models/user_plan_stat_model.go
Normal file
38
internal/db/models/user_plan_stat_model.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
UserPlanStatField_Id dbs.FieldName = "id" // ID
|
||||
UserPlanStatField_UserPlanId dbs.FieldName = "userPlanId" // 用户套餐ID
|
||||
UserPlanStatField_Date dbs.FieldName = "date" // 日期:YYYYMMDD或YYYYMM
|
||||
UserPlanStatField_DateType dbs.FieldName = "dateType" // 日期类型:day|month
|
||||
UserPlanStatField_TrafficBytes dbs.FieldName = "trafficBytes" // 流量
|
||||
UserPlanStatField_CountRequests dbs.FieldName = "countRequests" // 总请求数
|
||||
UserPlanStatField_IsProcessed dbs.FieldName = "isProcessed" // 是否已处理
|
||||
)
|
||||
|
||||
// UserPlanStat 用户套餐统计
|
||||
type UserPlanStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserPlanId uint64 `field:"userPlanId"` // 用户套餐ID
|
||||
Date string `field:"date"` // 日期:YYYYMMDD或YYYYMM
|
||||
DateType string `field:"dateType"` // 日期类型:day|month
|
||||
TrafficBytes uint64 `field:"trafficBytes"` // 流量
|
||||
CountRequests uint64 `field:"countRequests"` // 总请求数
|
||||
IsProcessed bool `field:"isProcessed"` // 是否已处理
|
||||
}
|
||||
|
||||
type UserPlanStatOperator struct {
|
||||
Id any // ID
|
||||
UserPlanId any // 用户套餐ID
|
||||
Date any // 日期:YYYYMMDD或YYYYMM
|
||||
DateType any // 日期类型:day|month
|
||||
TrafficBytes any // 流量
|
||||
CountRequests any // 总请求数
|
||||
IsProcessed any // 是否已处理
|
||||
}
|
||||
|
||||
func NewUserPlanStatOperator() *UserPlanStatOperator {
|
||||
return &UserPlanStatOperator{}
|
||||
}
|
||||
1
internal/db/models/user_plan_stat_model_ext.go
Normal file
1
internal/db/models/user_plan_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -55,7 +55,9 @@ func (this *CustomHTTPProvider) Auth(params maps.Map) error {
|
||||
|
||||
// GetDomains 获取所有域名列表
|
||||
func (this *CustomHTTPProvider) GetDomains() (domains []string, err error) {
|
||||
resp, err := this.post(maps.Map{})
|
||||
resp, err := this.post(maps.Map{
|
||||
"action": "GetDomains",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -189,36 +189,6 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterMessageServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MessageRecipientService{}).(*services.MessageRecipientService)
|
||||
pb.RegisterMessageRecipientServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MessageReceiverService{}).(*services.MessageReceiverService)
|
||||
pb.RegisterMessageReceiverServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MessageRecipientGroupService{}).(*services.MessageRecipientGroupService)
|
||||
pb.RegisterMessageRecipientGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MessageMediaInstanceService{}).(*services.MessageMediaInstanceService)
|
||||
pb.RegisterMessageMediaInstanceServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MessageTaskService{}).(*services.MessageTaskService)
|
||||
pb.RegisterMessageTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MessageTaskLogService{}).(*services.MessageTaskLogService)
|
||||
pb.RegisterMessageTaskLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.NodeGroupService{}).(*services.NodeGroupService)
|
||||
pb.RegisterNodeGroupServiceServer(server, instance)
|
||||
@@ -454,11 +424,6 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterNodeClusterFirewallActionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.MonitorNodeService{}).(*services.MonitorNodeService)
|
||||
pb.RegisterMonitorNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.AuthorityNodeService{}).(*services.AuthorityNodeService)
|
||||
pb.RegisterAuthorityNodeServiceServer(server, instance)
|
||||
|
||||
@@ -137,8 +137,8 @@ func (this *NodeStatusExecutor) updateDisk(status *nodeconfigs.NodeStatus) {
|
||||
})
|
||||
|
||||
// 当前TeaWeb所在的fs
|
||||
rootFS := ""
|
||||
rootTotal := uint64(0)
|
||||
var rootFS = ""
|
||||
var rootTotal = uint64(0)
|
||||
if lists.ContainsString([]string{"darwin", "linux", "freebsd"}, runtime.GOOS) {
|
||||
for _, p := range partitions {
|
||||
if p.Mountpoint == "/" {
|
||||
@@ -152,9 +152,9 @@ func (this *NodeStatusExecutor) updateDisk(status *nodeconfigs.NodeStatus) {
|
||||
}
|
||||
}
|
||||
|
||||
total := rootTotal
|
||||
totalUsage := uint64(0)
|
||||
maxUsage := float64(0)
|
||||
var total = rootTotal
|
||||
var totalUsage = uint64(0)
|
||||
var maxUsage = float64(0)
|
||||
for _, partition := range partitions {
|
||||
if runtime.GOOS != "windows" && !strings.Contains(partition.Device, "/") && !strings.Contains(partition.Device, "\\") {
|
||||
continue
|
||||
@@ -180,6 +180,8 @@ func (this *NodeStatusExecutor) updateDisk(status *nodeconfigs.NodeStatus) {
|
||||
}
|
||||
}
|
||||
status.DiskTotal = total
|
||||
status.DiskUsage = float64(totalUsage) / float64(total)
|
||||
if total > 0 {
|
||||
status.DiskUsage = float64(totalUsage) / float64(total)
|
||||
}
|
||||
status.DiskMaxUsage = maxUsage / 100
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (this *ACMETaskService) CountAllEnabledACMETasks(ctx context.Context, req *
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
count, err := acmemodels.SharedACMETaskDAO.CountAllEnabledACMETasks(tx, req.UserId, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword)
|
||||
count, err := acmemodels.SharedACMETaskDAO.CountAllEnabledACMETasks(tx, req.UserId, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, req.UserOnly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (this *ACMETaskService) ListEnabledACMETasks(ctx context.Context, req *pb.L
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
tasks, err := acmemodels.SharedACMETaskDAO.ListEnabledACMETasks(tx, req.UserId, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, req.Offset, req.Size)
|
||||
tasks, err := acmemodels.SharedACMETaskDAO.ListEnabledACMETasks(tx, req.UserId, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, req.UserOnly, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -255,7 +255,7 @@ func (this *ACMETaskService) UpdateACMETask(ctx context.Context, req *pb.UpdateA
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckACMETask(tx, userId, req.AcmeTaskId)
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckUserACMETask(tx, userId, req.AcmeTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -279,7 +279,7 @@ func (this *ACMETaskService) DeleteACMETask(ctx context.Context, req *pb.DeleteA
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckACMETask(tx, userId, req.AcmeTaskId)
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckUserACMETask(tx, userId, req.AcmeTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -303,7 +303,7 @@ func (this *ACMETaskService) RunACMETask(ctx context.Context, req *pb.RunACMETas
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckACMETask(tx, userId, req.AcmeTaskId)
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckUserACMETask(tx, userId, req.AcmeTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -329,7 +329,7 @@ func (this *ACMETaskService) FindEnabledACMETask(ctx context.Context, req *pb.Fi
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckACMETask(tx, userId, req.AcmeTaskId)
|
||||
canAccess, err := acmemodels.SharedACMETaskDAO.CheckUserACMETask(tx, userId, req.AcmeTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -440,3 +440,40 @@ func (this *ACMETaskService) FindEnabledACMETask(ctx context.Context, req *pb.Fi
|
||||
SslCert: pbCert,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// FindACMETaskUser 查找任务所属用户
|
||||
func (this *ACMETaskService) FindACMETaskUser(ctx context.Context, req *pb.FindACMETaskUserRequest) (*pb.FindACMETaskUserResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
userId, err := acmemodels.SharedACMETaskDAO.FindACMETaskUserId(tx, req.AcmeTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userId <= 0 {
|
||||
return &pb.FindACMETaskUserResponse{User: nil}, nil
|
||||
}
|
||||
|
||||
user, err := models.SharedUserDAO.FindEnabledBasicUser(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return &pb.FindACMETaskUserResponse{
|
||||
User: &pb.User{
|
||||
Id: userId,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindACMETaskUserResponse{
|
||||
User: &pb.User{
|
||||
Id: userId,
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
||||
result.CountServers = countServers
|
||||
|
||||
this.BeginTag(ctx, "SharedServerDAO.CountAllEnabledServersMatch")
|
||||
countAuditingServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", 0, 0, configutils.BoolStateYes, nil)
|
||||
countAuditingServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", 0, 0, configutils.BoolStateYes, nil, 0)
|
||||
this.EndTag(ctx, "SharedServerDAO.CountAllEnabledServersMatch")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -78,7 +78,7 @@ func (this *APINodeService) DeleteAPINode(ctx context.Context, req *pb.DeleteAPI
|
||||
|
||||
// FindAllEnabledAPINodes 列出所有可用API节点
|
||||
func (this *APINodeService) FindAllEnabledAPINodes(ctx context.Context, req *pb.FindAllEnabledAPINodesRequest) (*pb.FindAllEnabledAPINodesResponse, error) {
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser, rpcutils.UserTypeNode, rpcutils.UserTypeMonitor, rpcutils.UserTypeDNS, rpcutils.UserTypeAuthority)
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser, rpcutils.UserTypeNode, rpcutils.UserTypeDNS, rpcutils.UserTypeAuthority)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -95,12 +95,6 @@ func (this *BaseService) ValidateUserNode(ctx context.Context, canRest bool) (us
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateMonitorNode 校验监控节点
|
||||
func (this *BaseService) ValidateMonitorNode(ctx context.Context) (nodeId int64, err error) {
|
||||
_, _, nodeId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeMonitor)
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateAuthorityNode 校验认证节点
|
||||
func (this *BaseService) ValidateAuthorityNode(ctx context.Context) (nodeId int64, err error) {
|
||||
_, _, nodeId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAuthority)
|
||||
@@ -111,7 +105,7 @@ func (this *BaseService) ValidateAuthorityNode(ctx context.Context) (nodeId int6
|
||||
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, rpcutils.UserTypeAPI}
|
||||
roles = []rpcutils.UserType{rpcutils.UserTypeNode, rpcutils.UserTypeCluster, rpcutils.UserTypeAdmin, rpcutils.UserTypeUser, rpcutils.UserTypeDNS, rpcutils.UserTypeReport, rpcutils.UserTypeLog, rpcutils.UserTypeAPI}
|
||||
}
|
||||
|
||||
if ctx == nil {
|
||||
@@ -195,8 +189,6 @@ func (this *BaseService) ValidateNodeId(ctx context.Context, roles ...rpcutils.U
|
||||
nodeIntId, err = models.SharedUserNodeDAO.FindEnabledUserNodeIdWithUniqueId(nil, nodeId)
|
||||
case rpcutils.UserTypeAdmin:
|
||||
nodeIntId = 0
|
||||
case rpcutils.UserTypeMonitor:
|
||||
nodeIntId, err = models.SharedMonitorNodeDAO.FindEnabledMonitorNodeIdWithUniqueId(nil, nodeId)
|
||||
case rpcutils.UserTypeDNS:
|
||||
nodeIntId, err = models.SharedNSNodeDAO.FindEnabledNodeIdWithUniqueId(nil, nodeId)
|
||||
case rpcutils.UserTypeReport:
|
||||
|
||||
@@ -86,7 +86,7 @@ func (this *HTTPFirewallRuleSetService) FindEnabledHTTPFirewallRuleSetConfig(ctx
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
config, err := models.SharedHTTPFirewallRuleSetDAO.ComposeFirewallRuleSet(tx, req.FirewallRuleSetId)
|
||||
config, err := models.SharedHTTPFirewallRuleSetDAO.ComposeFirewallRuleSet(tx, req.FirewallRuleSetId, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// MessageMediaInstanceService 消息媒介实例服务
|
||||
type MessageMediaInstanceService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateMessageMediaInstance 创建消息媒介实例
|
||||
func (this *MessageMediaInstanceService) CreateMessageMediaInstance(ctx context.Context, req *pb.CreateMessageMediaInstanceRequest) (*pb.CreateMessageMediaInstanceResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
params := maps.Map{}
|
||||
if len(req.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ParamsJSON, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
instanceId, err := models.SharedMessageMediaInstanceDAO.CreateMediaInstance(tx, req.Name, req.MediaType, params, req.Description, req.RateJSON, req.HashLife)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateMessageMediaInstanceResponse{MessageMediaInstanceId: instanceId}, nil
|
||||
}
|
||||
|
||||
// UpdateMessageMediaInstance 修改消息实例
|
||||
func (this *MessageMediaInstanceService) UpdateMessageMediaInstance(ctx context.Context, req *pb.UpdateMessageMediaInstanceRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := maps.Map{}
|
||||
if len(req.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ParamsJSON, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageMediaInstanceDAO.UpdateMediaInstance(tx, req.MessageMediaInstanceId, req.Name, req.MediaType, params, req.Description, req.RateJSON, req.HashLife, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteMessageMediaInstance 删除媒介实例
|
||||
func (this *MessageMediaInstanceService) DeleteMessageMediaInstance(ctx context.Context, req *pb.DeleteMessageMediaInstanceRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageMediaInstanceDAO.DisableMessageMediaInstance(tx, req.MessageMediaInstanceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountAllEnabledMessageMediaInstances 计算媒介实例数量
|
||||
func (this *MessageMediaInstanceService) CountAllEnabledMessageMediaInstances(ctx context.Context, req *pb.CountAllEnabledMessageMediaInstancesRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedMessageMediaInstanceDAO.CountAllEnabledMediaInstances(tx, req.MediaType, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListEnabledMessageMediaInstances 列出单页媒介实例
|
||||
func (this *MessageMediaInstanceService) ListEnabledMessageMediaInstances(ctx context.Context, req *pb.ListEnabledMessageMediaInstancesRequest) (*pb.ListEnabledMessageMediaInstancesResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
instances, err := models.SharedMessageMediaInstanceDAO.ListAllEnabledMediaInstances(tx, req.MediaType, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbInstances := []*pb.MessageMediaInstance{}
|
||||
for _, instance := range instances {
|
||||
// 媒介
|
||||
media, err := models.SharedMessageMediaDAO.FindEnabledMediaWithType(tx, instance.MediaType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if media == nil {
|
||||
continue
|
||||
}
|
||||
pbMedia := &pb.MessageMedia{
|
||||
Id: int64(media.Id),
|
||||
Type: media.Type,
|
||||
Name: media.Name,
|
||||
Description: media.Description,
|
||||
UserDescription: media.UserDescription,
|
||||
IsOn: media.IsOn,
|
||||
}
|
||||
|
||||
pbInstances = append(pbInstances, &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
Name: instance.Name,
|
||||
IsOn: instance.IsOn,
|
||||
MessageMedia: pbMedia,
|
||||
ParamsJSON: instance.Params,
|
||||
Description: instance.Description,
|
||||
RateJSON: instance.Rate,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListEnabledMessageMediaInstancesResponse{MessageMediaInstances: pbInstances}, nil
|
||||
}
|
||||
|
||||
// FindEnabledMessageMediaInstance 查找单个媒介实例信息
|
||||
func (this *MessageMediaInstanceService) FindEnabledMessageMediaInstance(ctx context.Context, req *pb.FindEnabledMessageMediaInstanceRequest) (*pb.FindEnabledMessageMediaInstanceResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, req.MessageMediaInstanceId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil {
|
||||
return &pb.FindEnabledMessageMediaInstanceResponse{MessageMediaInstance: nil}, nil
|
||||
}
|
||||
|
||||
// 媒介
|
||||
media, err := models.SharedMessageMediaDAO.FindEnabledMediaWithType(tx, instance.MediaType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if media == nil {
|
||||
return &pb.FindEnabledMessageMediaInstanceResponse{MessageMediaInstance: nil}, nil
|
||||
}
|
||||
pbMedia := &pb.MessageMedia{
|
||||
Id: int64(media.Id),
|
||||
Type: media.Type,
|
||||
Name: media.Name,
|
||||
Description: media.Description,
|
||||
UserDescription: media.UserDescription,
|
||||
IsOn: media.IsOn,
|
||||
}
|
||||
|
||||
return &pb.FindEnabledMessageMediaInstanceResponse{MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
Name: instance.Name,
|
||||
IsOn: instance.IsOn,
|
||||
MessageMedia: pbMedia,
|
||||
ParamsJSON: instance.Params,
|
||||
Description: instance.Description,
|
||||
RateJSON: instance.Rate,
|
||||
HashLife: types.Int32(instance.HashLife),
|
||||
}}, nil
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// MessageReceiverService 消息对象接收人
|
||||
type MessageReceiverService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// UpdateMessageReceivers 创建接收者
|
||||
func (this *MessageReceiverService) UpdateMessageReceivers(ctx context.Context, req *pb.UpdateMessageReceiversRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(req.Role) == 0 {
|
||||
req.Role = nodeconfigs.NodeRoleNode
|
||||
}
|
||||
|
||||
params := maps.Map{}
|
||||
if len(req.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ParamsJSON, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = this.RunTx(func(tx *dbs.Tx) error {
|
||||
err = models.SharedMessageReceiverDAO.DisableReceivers(tx, req.NodeClusterId, req.NodeId, req.ServerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for messageType, options := range req.RecipientOptions {
|
||||
for _, option := range options.RecipientOptions {
|
||||
_, err := models.SharedMessageReceiverDAO.CreateReceiver(tx, req.Role, req.NodeClusterId, req.NodeId, req.ServerId, messageType, params, option.MessageRecipientId, option.MessageRecipientGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindAllEnabledMessageReceivers 查找接收者
|
||||
func (this *MessageReceiverService) FindAllEnabledMessageReceivers(ctx context.Context, req *pb.FindAllEnabledMessageReceiversRequest) (*pb.FindAllEnabledMessageReceiversResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(req.Role) == 0 {
|
||||
req.Role = nodeconfigs.NodeRoleNode
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
receivers, err := models.SharedMessageReceiverDAO.FindAllEnabledReceivers(tx, req.Role, req.NodeClusterId, req.NodeId, req.ServerId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbReceivers := []*pb.MessageReceiver{}
|
||||
for _, receiver := range receivers {
|
||||
var pbRecipient *pb.MessageRecipient = nil
|
||||
|
||||
// 接收人
|
||||
if receiver.RecipientId > 0 {
|
||||
recipient, err := models.SharedMessageRecipientDAO.FindEnabledMessageRecipient(tx, int64(receiver.RecipientId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recipient == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 管理员
|
||||
admin, err := models.SharedAdminDAO.FindEnabledAdmin(tx, int64(recipient.AdminId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if admin == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 接收人
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(recipient.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: int64(recipient.Id),
|
||||
Admin: &pb.Admin{
|
||||
Id: int64(admin.Id),
|
||||
Fullname: admin.Fullname,
|
||||
Username: admin.Username,
|
||||
IsOn: admin.IsOn,
|
||||
},
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
Name: instance.Name,
|
||||
IsOn: instance.IsOn,
|
||||
},
|
||||
IsOn: recipient.IsOn,
|
||||
MessageRecipientGroups: nil,
|
||||
Description: "",
|
||||
User: "",
|
||||
}
|
||||
}
|
||||
|
||||
// 接收人分组
|
||||
var pbRecipientGroup *pb.MessageRecipientGroup = nil
|
||||
if receiver.RecipientGroupId > 0 {
|
||||
group, err := models.SharedMessageRecipientGroupDAO.FindEnabledMessageRecipientGroup(tx, int64(receiver.RecipientGroupId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group == nil {
|
||||
continue
|
||||
}
|
||||
pbRecipientGroup = &pb.MessageRecipientGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
}
|
||||
}
|
||||
|
||||
pbReceivers = append(pbReceivers, &pb.MessageReceiver{
|
||||
Id: int64(receiver.Id),
|
||||
ClusterId: int64(receiver.ClusterId),
|
||||
NodeId: int64(receiver.NodeId),
|
||||
ServerId: int64(receiver.ServerId),
|
||||
Type: receiver.Type,
|
||||
ParamsJSON: receiver.Params,
|
||||
MessageRecipient: pbRecipient,
|
||||
MessageRecipientGroup: pbRecipientGroup,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledMessageReceiversResponse{MessageReceivers: pbReceivers}, nil
|
||||
}
|
||||
|
||||
// DeleteMessageReceiver 删除接收者
|
||||
func (this *MessageReceiverService) DeleteMessageReceiver(ctx context.Context, req *pb.DeleteMessageReceiverRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageReceiverDAO.DisableMessageReceiver(tx, req.MessageReceiverId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountAllEnabledMessageReceivers 计算接收者数量
|
||||
func (this *MessageReceiverService) CountAllEnabledMessageReceivers(ctx context.Context, req *pb.CountAllEnabledMessageReceiversRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(req.Role) == 0 {
|
||||
req.Role = nodeconfigs.NodeRoleNode
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedMessageReceiverDAO.CountAllEnabledReceivers(tx, req.Role, req.NodeClusterId, req.NodeId, req.ServerId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// MessageRecipientService 消息接收人服务
|
||||
type MessageRecipientService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateMessageRecipient 创建接收人
|
||||
func (this *MessageRecipientService) CreateMessageRecipient(ctx context.Context, req *pb.CreateMessageRecipientRequest) (*pb.CreateMessageRecipientResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
recipientId, err := models.SharedMessageRecipientDAO.CreateRecipient(tx, req.AdminId, req.MessageMediaInstanceId, req.User, req.MessageRecipientGroupIds, req.Description, req.TimeFrom, req.TimeTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateMessageRecipientResponse{MessageRecipientId: recipientId}, nil
|
||||
}
|
||||
|
||||
// UpdateMessageRecipient 修改接收人
|
||||
func (this *MessageRecipientService) UpdateMessageRecipient(ctx context.Context, req *pb.UpdateMessageRecipientRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageRecipientDAO.UpdateRecipient(tx, req.MessageRecipientId, req.AdminId, req.MessageMediaInstanceId, req.User, req.MessageRecipientGroupIds, req.Description, req.TimeFrom, req.TimeTo, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteMessageRecipient 删除接收人
|
||||
func (this *MessageRecipientService) DeleteMessageRecipient(ctx context.Context, req *pb.DeleteMessageRecipientRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageRecipientDAO.DisableMessageRecipient(tx, req.MessageRecipientId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountAllEnabledMessageRecipients 计算接收人数量
|
||||
func (this *MessageRecipientService) CountAllEnabledMessageRecipients(ctx context.Context, req *pb.CountAllEnabledMessageRecipientsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedMessageRecipientDAO.CountAllEnabledRecipients(tx, req.AdminId, req.MessageRecipientGroupId, req.MediaType, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListEnabledMessageRecipients 列出单页接收人
|
||||
func (this *MessageRecipientService) ListEnabledMessageRecipients(ctx context.Context, req *pb.ListEnabledMessageRecipientsRequest) (*pb.ListEnabledMessageRecipientsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
recipients, err := models.SharedMessageRecipientDAO.ListAllEnabledRecipients(tx, req.AdminId, req.MessageRecipientGroupId, req.MediaType, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbRecipients := []*pb.MessageRecipient{}
|
||||
for _, recipient := range recipients {
|
||||
// admin
|
||||
admin, err := models.SharedAdminDAO.FindEnabledAdmin(tx, int64(recipient.AdminId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if admin == nil {
|
||||
continue
|
||||
}
|
||||
pbAdmin := &pb.Admin{
|
||||
Id: int64(admin.Id),
|
||||
Fullname: admin.Fullname,
|
||||
Username: admin.Username,
|
||||
IsOn: admin.IsOn,
|
||||
}
|
||||
|
||||
// 媒介实例
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(recipient.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil {
|
||||
continue
|
||||
}
|
||||
pbInstance := &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
IsOn: instance.IsOn,
|
||||
Name: instance.Name,
|
||||
Description: instance.Description,
|
||||
}
|
||||
|
||||
// 分组
|
||||
pbGroups := []*pb.MessageRecipientGroup{}
|
||||
groupIds := recipient.DecodeGroupIds()
|
||||
if len(groupIds) > 0 {
|
||||
for _, groupId := range groupIds {
|
||||
group, err := models.SharedMessageRecipientGroupDAO.FindEnabledMessageRecipientGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group != nil {
|
||||
pbGroups = append(pbGroups, &pb.MessageRecipientGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbRecipients = append(pbRecipients, &pb.MessageRecipient{
|
||||
Id: int64(recipient.Id),
|
||||
Admin: pbAdmin,
|
||||
User: recipient.User,
|
||||
MessageMediaInstance: pbInstance,
|
||||
IsOn: recipient.IsOn,
|
||||
MessageRecipientGroups: pbGroups,
|
||||
Description: recipient.Description,
|
||||
TimeFrom: recipient.TimeFrom,
|
||||
TimeTo: recipient.TimeTo,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListEnabledMessageRecipientsResponse{MessageRecipients: pbRecipients}, nil
|
||||
}
|
||||
|
||||
// FindEnabledMessageRecipient 查找单个接收人信息
|
||||
func (this *MessageRecipientService) FindEnabledMessageRecipient(ctx context.Context, req *pb.FindEnabledMessageRecipientRequest) (*pb.FindEnabledMessageRecipientResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
recipient, err := models.SharedMessageRecipientDAO.FindEnabledMessageRecipient(tx, req.MessageRecipientId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recipient == nil {
|
||||
return &pb.FindEnabledMessageRecipientResponse{MessageRecipient: nil}, nil
|
||||
}
|
||||
|
||||
// admin
|
||||
admin, err := models.SharedAdminDAO.FindEnabledAdmin(tx, int64(recipient.AdminId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if admin == nil {
|
||||
return &pb.FindEnabledMessageRecipientResponse{MessageRecipient: nil}, nil
|
||||
}
|
||||
pbAdmin := &pb.Admin{
|
||||
Id: int64(admin.Id),
|
||||
Fullname: admin.Fullname,
|
||||
Username: admin.Username,
|
||||
IsOn: admin.IsOn,
|
||||
}
|
||||
|
||||
// 媒介实例
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(recipient.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil {
|
||||
return &pb.FindEnabledMessageRecipientResponse{MessageRecipient: nil}, nil
|
||||
}
|
||||
pbInstance := &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
IsOn: instance.IsOn,
|
||||
Name: instance.Name,
|
||||
Description: instance.Description,
|
||||
}
|
||||
|
||||
// 分组
|
||||
pbGroups := []*pb.MessageRecipientGroup{}
|
||||
groupIds := recipient.DecodeGroupIds()
|
||||
if len(groupIds) > 0 {
|
||||
for _, groupId := range groupIds {
|
||||
group, err := models.SharedMessageRecipientGroupDAO.FindEnabledMessageRecipientGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group != nil {
|
||||
pbGroups = append(pbGroups, &pb.MessageRecipientGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.FindEnabledMessageRecipientResponse{MessageRecipient: &pb.MessageRecipient{
|
||||
Id: int64(recipient.Id),
|
||||
User: recipient.User,
|
||||
Admin: pbAdmin,
|
||||
MessageMediaInstance: pbInstance,
|
||||
IsOn: recipient.IsOn,
|
||||
MessageRecipientGroups: pbGroups,
|
||||
Description: recipient.Description,
|
||||
TimeFrom: recipient.TimeFrom,
|
||||
TimeTo: recipient.TimeTo,
|
||||
}}, nil
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// 消息接收人分组
|
||||
type MessageRecipientGroupService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// 创建分组
|
||||
func (this *MessageRecipientGroupService) CreateMessageRecipientGroup(ctx context.Context, req *pb.CreateMessageRecipientGroupRequest) (*pb.CreateMessageRecipientGroupResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
groupId, err := models.SharedMessageRecipientGroupDAO.CreateGroup(tx, req.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateMessageRecipientGroupResponse{MessageRecipientGroupId: groupId}, nil
|
||||
}
|
||||
|
||||
// 修改分组
|
||||
func (this *MessageRecipientGroupService) UpdateMessageRecipientGroup(ctx context.Context, req *pb.UpdateMessageRecipientGroupRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageRecipientGroupDAO.UpdateGroup(tx, req.MessageRecipientGroupId, req.Name, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// 查找所有可用的分组
|
||||
func (this *MessageRecipientGroupService) FindAllEnabledMessageRecipientGroups(ctx context.Context, req *pb.FindAllEnabledMessageRecipientGroupsRequest) (*pb.FindAllEnabledMessageRecipientGroupsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
groups, err := models.SharedMessageRecipientGroupDAO.FindAllEnabledGroups(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbGroups := []*pb.MessageRecipientGroup{}
|
||||
for _, group := range groups {
|
||||
pbGroups = append(pbGroups, &pb.MessageRecipientGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
IsOn: group.IsOn,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledMessageRecipientGroupsResponse{MessageRecipientGroups: pbGroups}, nil
|
||||
}
|
||||
|
||||
// 删除分组
|
||||
func (this *MessageRecipientGroupService) DeleteMessageRecipientGroup(ctx context.Context, req *pb.DeleteMessageRecipientGroupRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageRecipientGroupDAO.DisableMessageRecipientGroup(tx, req.MessageRecipientGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// 查找单个分组信息
|
||||
func (this *MessageRecipientGroupService) FindEnabledMessageRecipientGroup(ctx context.Context, req *pb.FindEnabledMessageRecipientGroupRequest) (*pb.FindEnabledMessageRecipientGroupResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
group, err := models.SharedMessageRecipientGroupDAO.FindEnabledMessageRecipientGroup(tx, req.MessageRecipientGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if group == nil {
|
||||
return &pb.FindEnabledMessageRecipientGroupResponse{MessageRecipientGroup: nil}, nil
|
||||
}
|
||||
pbGroup := &pb.MessageRecipientGroup{
|
||||
Id: int64(group.Id),
|
||||
IsOn: group.IsOn,
|
||||
Name: group.Name,
|
||||
}
|
||||
return &pb.FindEnabledMessageRecipientGroupResponse{MessageRecipientGroup: pbGroup}, nil
|
||||
}
|
||||
@@ -1,409 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// MessageTaskService 消息发送任务服务
|
||||
type MessageTaskService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateMessageTask 创建任务
|
||||
func (this *MessageTaskService) CreateMessageTask(ctx context.Context, req *pb.CreateMessageTaskRequest) (*pb.CreateMessageTaskResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
taskId, err := models.SharedMessageTaskDAO.CreateMessageTask(tx, req.RecipientId, req.InstanceId, req.User, req.Subject, req.Body, req.IsPrimary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.CreateMessageTaskResponse{MessageTaskId: taskId}, nil
|
||||
}
|
||||
|
||||
// FindSendingMessageTasks 查找要发送的任务
|
||||
func (this *MessageTaskService) FindSendingMessageTasks(ctx context.Context, req *pb.FindSendingMessageTasksRequest) (*pb.FindSendingMessageTasksResponse, error) {
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
tasks, err := models.SharedMessageTaskDAO.FindSendingMessageTasks(tx, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbTasks := []*pb.MessageTask{}
|
||||
for _, task := range tasks {
|
||||
var pbRecipient *pb.MessageRecipient
|
||||
if task.RecipientId > 0 {
|
||||
recipient, err := models.SharedMessageRecipientDAO.FindEnabledMessageRecipient(tx, int64(task.RecipientId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recipient == nil || !recipient.IsOn {
|
||||
// 如果发送人已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// 媒介
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(recipient.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil || !instance.IsOn {
|
||||
// 如果媒介实例已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: int64(recipient.Id),
|
||||
User: recipient.User,
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
MessageMedia: &pb.MessageMedia{
|
||||
Type: instance.MediaType,
|
||||
},
|
||||
ParamsJSON: instance.Params,
|
||||
RateJSON: instance.Rate,
|
||||
},
|
||||
}
|
||||
} else { // 没有指定既定的接收人
|
||||
// 媒介
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(task.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil || !instance.IsOn {
|
||||
// 如果媒介实例已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: 0,
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
MessageMedia: &pb.MessageMedia{
|
||||
Type: instance.MediaType,
|
||||
},
|
||||
ParamsJSON: instance.Params,
|
||||
RateJSON: instance.Rate,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pbTasks = append(pbTasks, &pb.MessageTask{
|
||||
Id: int64(task.Id),
|
||||
MessageRecipient: pbRecipient,
|
||||
User: task.User,
|
||||
Subject: task.Subject,
|
||||
Body: task.Body,
|
||||
CreatedAt: int64(task.CreatedAt),
|
||||
Status: types.Int32(task.Status),
|
||||
SentAt: int64(task.SentAt),
|
||||
})
|
||||
}
|
||||
return &pb.FindSendingMessageTasksResponse{MessageTasks: pbTasks}, nil
|
||||
}
|
||||
|
||||
// UpdateMessageTaskStatus 修改任务状态
|
||||
func (this *MessageTaskService) UpdateMessageTaskStatus(ctx context.Context, req *pb.UpdateMessageTaskStatusRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
resultJSON := []byte{}
|
||||
if req.Result != nil {
|
||||
resultJSON, err = json.Marshal(maps.Map{
|
||||
"isOk": req.Result.IsOk,
|
||||
"error": req.Result.Error,
|
||||
"response": req.Result.Response,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedMessageTaskDAO.UpdateMessageTaskStatus(tx, req.MessageTaskId, int(req.Status), resultJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建发送记录
|
||||
if (int(req.Status) == models.MessageTaskStatusSuccess || int(req.Status) == models.MessageTaskStatusFailed) && req.Result != nil {
|
||||
err = models.SharedMessageTaskLogDAO.CreateLog(tx, req.MessageTaskId, req.Result.IsOk, req.Result.Error, req.Result.Response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteMessageTask 删除消息任务
|
||||
func (this *MessageTaskService) DeleteMessageTask(ctx context.Context, req *pb.DeleteMessageTaskRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, req.MessageTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledMessageTask 读取消息任务状态
|
||||
func (this *MessageTaskService) FindEnabledMessageTask(ctx context.Context, req *pb.FindEnabledMessageTaskRequest) (*pb.FindEnabledMessageTaskResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
task, err := models.SharedMessageTaskDAO.FindEnabledMessageTask(tx, req.MessageTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if task == nil {
|
||||
return &pb.FindEnabledMessageTaskResponse{MessageTask: nil}, nil
|
||||
}
|
||||
|
||||
var pbRecipient *pb.MessageRecipient
|
||||
if task.RecipientId > 0 {
|
||||
recipient, err := models.SharedMessageRecipientDAO.FindEnabledMessageRecipient(tx, int64(task.RecipientId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recipient == nil || !recipient.IsOn {
|
||||
// 如果发送人已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindEnabledMessageTaskResponse{MessageTask: nil}, nil
|
||||
}
|
||||
|
||||
// 媒介
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(recipient.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil || !instance.IsOn {
|
||||
// 如果媒介实例已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindEnabledMessageTaskResponse{MessageTask: nil}, nil
|
||||
}
|
||||
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
MessageMedia: &pb.MessageMedia{
|
||||
Type: instance.MediaType,
|
||||
},
|
||||
ParamsJSON: instance.Params,
|
||||
},
|
||||
}
|
||||
} else { // 没有指定既定的接收人
|
||||
// 媒介
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(task.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil || !instance.IsOn {
|
||||
// 如果媒介实例已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindEnabledMessageTaskResponse{MessageTask: nil}, nil
|
||||
}
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: 0,
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
MessageMedia: &pb.MessageMedia{
|
||||
Type: instance.MediaType,
|
||||
},
|
||||
ParamsJSON: instance.Params,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var result = &pb.MessageTaskResult{}
|
||||
if len(task.Result) > 0 {
|
||||
err = json.Unmarshal(task.Result, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.FindEnabledMessageTaskResponse{MessageTask: &pb.MessageTask{
|
||||
Id: int64(task.Id),
|
||||
MessageRecipient: pbRecipient,
|
||||
User: task.User,
|
||||
Subject: task.Subject,
|
||||
Body: task.Body,
|
||||
CreatedAt: int64(task.CreatedAt),
|
||||
Status: int32(task.Status),
|
||||
SentAt: int64(task.SentAt),
|
||||
Result: result,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// CountMessageTasksWithStatus 计算某个状态的消息任务数量
|
||||
func (this *MessageTaskService) CountMessageTasksWithStatus(ctx context.Context, req *pb.CountMessageTasksWithStatusRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedMessageTaskDAO.CountMessageTasksWithStatus(tx, types.Int(req.Status))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListMessageTasksWithStatus 根据状态列出某页任务
|
||||
func (this *MessageTaskService) ListMessageTasksWithStatus(ctx context.Context, req *pb.ListMessageTasksWithStatusRequest) (*pb.ListMessageTasksWithStatusResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
tasks, err := models.SharedMessageTaskDAO.ListMessageTasksWithStatus(tx, types.Int(req.Status), req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbTasks = []*pb.MessageTask{}
|
||||
for _, task := range tasks {
|
||||
var pbRecipient *pb.MessageRecipient
|
||||
if task.RecipientId > 0 {
|
||||
recipient, err := models.SharedMessageRecipientDAO.FindEnabledMessageRecipient(tx, int64(task.RecipientId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recipient == nil || !recipient.IsOn {
|
||||
// 如果发送人已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// 媒介
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(recipient.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil || !instance.IsOn {
|
||||
// 如果媒介实例已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: int64(recipient.Id),
|
||||
User: recipient.User,
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
Name: instance.Name,
|
||||
MessageMedia: &pb.MessageMedia{
|
||||
Type: instance.MediaType,
|
||||
},
|
||||
ParamsJSON: instance.Params,
|
||||
RateJSON: instance.Rate,
|
||||
},
|
||||
}
|
||||
} else { // 没有指定既定的接收人
|
||||
// 媒介
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(task.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil || !instance.IsOn {
|
||||
// 如果媒介实例已经删除或者禁用,则删除此消息
|
||||
err = models.SharedMessageTaskDAO.DisableMessageTask(tx, int64(task.Id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: 0,
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
Name: instance.Name,
|
||||
MessageMedia: &pb.MessageMedia{
|
||||
Type: instance.MediaType,
|
||||
},
|
||||
ParamsJSON: instance.Params,
|
||||
RateJSON: instance.Rate,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var result = &pb.MessageTaskResult{}
|
||||
if len(task.Result) > 0 {
|
||||
err = json.Unmarshal(task.Result, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
pbTasks = append(pbTasks, &pb.MessageTask{
|
||||
Id: int64(task.Id),
|
||||
MessageRecipient: pbRecipient,
|
||||
User: task.User,
|
||||
Subject: task.Subject,
|
||||
Body: task.Body,
|
||||
CreatedAt: int64(task.CreatedAt),
|
||||
Status: types.Int32(task.Status),
|
||||
SentAt: int64(task.SentAt),
|
||||
Result: result,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListMessageTasksWithStatusResponse{MessageTasks: pbTasks}, nil
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// MessageTaskLogService 消息发送日志相关服务
|
||||
type MessageTaskLogService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CountMessageTaskLogs 计算日志数量
|
||||
func (this *MessageTaskLogService) CountMessageTaskLogs(ctx context.Context, req *pb.CountMessageTaskLogsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedMessageTaskLogDAO.CountLogs(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListMessageTaskLogs 列出当页日志
|
||||
func (this *MessageTaskLogService) ListMessageTaskLogs(ctx context.Context, req *pb.ListMessageTaskLogsRequest) (*pb.ListMessageTaskLogsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
logs, err := models.SharedMessageTaskLogDAO.ListLogs(tx, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pbLogs := []*pb.MessageTaskLog{}
|
||||
for _, log := range logs {
|
||||
task, err := models.SharedMessageTaskDAO.FindEnabledMessageTask(tx, int64(log.TaskId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if task == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var pbRecipient *pb.MessageRecipient
|
||||
if task.RecipientId > 0 {
|
||||
recipient, err := models.SharedMessageRecipientDAO.FindEnabledMessageRecipient(tx, int64(task.RecipientId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recipient != nil {
|
||||
pbRecipient = &pb.MessageRecipient{
|
||||
Id: int64(recipient.Id),
|
||||
User: recipient.User,
|
||||
}
|
||||
task.InstanceId = recipient.InstanceId
|
||||
}
|
||||
}
|
||||
|
||||
instance, err := models.SharedMessageMediaInstanceDAO.FindEnabledMessageMediaInstance(tx, int64(task.InstanceId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if instance == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pbLogs = append(pbLogs, &pb.MessageTaskLog{
|
||||
Id: int64(log.Id),
|
||||
CreatedAt: int64(log.CreatedAt),
|
||||
IsOk: log.IsOk,
|
||||
Error: log.Error,
|
||||
Response: log.Response,
|
||||
MessageTask: &pb.MessageTask{
|
||||
Id: int64(task.Id),
|
||||
MessageRecipient: pbRecipient,
|
||||
MessageMediaInstance: &pb.MessageMediaInstance{
|
||||
Id: int64(instance.Id),
|
||||
Name: instance.Name,
|
||||
},
|
||||
User: task.User,
|
||||
Subject: task.Subject,
|
||||
Body: task.Body,
|
||||
CreatedAt: int64(task.CreatedAt),
|
||||
Status: int32(task.Status),
|
||||
SentAt: int64(task.SentAt),
|
||||
Result: nil,
|
||||
},
|
||||
})
|
||||
}
|
||||
return &pb.ListMessageTaskLogsResponse{MessageTaskLogs: pbLogs}, nil
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
type MonitorNodeService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateMonitorNode 创建监控节点
|
||||
func (this *MonitorNodeService) CreateMonitorNode(ctx context.Context, req *pb.CreateMonitorNodeRequest) (*pb.CreateMonitorNodeResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
nodeId, err := models.SharedMonitorNodeDAO.CreateMonitorNode(tx, req.Name, req.Description, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateMonitorNodeResponse{MonitorNodeId: nodeId}, nil
|
||||
}
|
||||
|
||||
// UpdateMonitorNode 修改监控节点
|
||||
func (this *MonitorNodeService) UpdateMonitorNode(ctx context.Context, req *pb.UpdateMonitorNodeRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedMonitorNodeDAO.UpdateMonitorNode(tx, req.MonitorNodeId, req.Name, req.Description, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteMonitorNode 删除监控节点
|
||||
func (this *MonitorNodeService) DeleteMonitorNode(ctx context.Context, req *pb.DeleteMonitorNodeRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedMonitorNodeDAO.DisableMonitorNode(tx, req.MonitorNodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindAllEnabledMonitorNodes 列出所有可用监控节点
|
||||
func (this *MonitorNodeService) FindAllEnabledMonitorNodes(ctx context.Context, req *pb.FindAllEnabledMonitorNodesRequest) (*pb.FindAllEnabledMonitorNodesResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
nodes, err := models.SharedMonitorNodeDAO.FindAllEnabledMonitorNodes(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := []*pb.MonitorNode{}
|
||||
for _, node := range nodes {
|
||||
result = append(result, &pb.MonitorNode{
|
||||
Id: int64(node.Id),
|
||||
IsOn: node.IsOn,
|
||||
UniqueId: node.UniqueId,
|
||||
Secret: node.Secret,
|
||||
Name: node.Name,
|
||||
Description: node.Description,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledMonitorNodesResponse{MonitorNodes: result}, nil
|
||||
}
|
||||
|
||||
// CountAllEnabledMonitorNodes 计算监控节点数量
|
||||
func (this *MonitorNodeService) CountAllEnabledMonitorNodes(ctx context.Context, req *pb.CountAllEnabledMonitorNodesRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
count, err := models.SharedMonitorNodeDAO.CountAllEnabledMonitorNodes(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListEnabledMonitorNodes 列出单页的监控节点
|
||||
func (this *MonitorNodeService) ListEnabledMonitorNodes(ctx context.Context, req *pb.ListEnabledMonitorNodesRequest) (*pb.ListEnabledMonitorNodesResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
nodes, err := models.SharedMonitorNodeDAO.ListEnabledMonitorNodes(tx, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := []*pb.MonitorNode{}
|
||||
for _, node := range nodes {
|
||||
result = append(result, &pb.MonitorNode{
|
||||
Id: int64(node.Id),
|
||||
IsOn: node.IsOn,
|
||||
UniqueId: node.UniqueId,
|
||||
Secret: node.Secret,
|
||||
Name: node.Name,
|
||||
Description: node.Description,
|
||||
StatusJSON: node.Status,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.ListEnabledMonitorNodesResponse{MonitorNodes: result}, nil
|
||||
}
|
||||
|
||||
// FindEnabledMonitorNode 根据ID查找节点
|
||||
func (this *MonitorNodeService) FindEnabledMonitorNode(ctx context.Context, req *pb.FindEnabledMonitorNodeRequest) (*pb.FindEnabledMonitorNodeResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
node, err := models.SharedMonitorNodeDAO.FindEnabledMonitorNode(tx, req.MonitorNodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if node == nil {
|
||||
return &pb.FindEnabledMonitorNodeResponse{MonitorNode: nil}, nil
|
||||
}
|
||||
|
||||
result := &pb.MonitorNode{
|
||||
Id: int64(node.Id),
|
||||
IsOn: node.IsOn,
|
||||
UniqueId: node.UniqueId,
|
||||
Secret: node.Secret,
|
||||
Name: node.Name,
|
||||
Description: node.Description,
|
||||
}
|
||||
return &pb.FindEnabledMonitorNodeResponse{MonitorNode: result}, nil
|
||||
}
|
||||
|
||||
// FindCurrentMonitorNode 获取当前监控节点的版本
|
||||
func (this *MonitorNodeService) FindCurrentMonitorNode(ctx context.Context, req *pb.FindCurrentMonitorNodeRequest) (*pb.FindCurrentMonitorNodeResponse, error) {
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New("context: need 'nodeId'")
|
||||
}
|
||||
nodeIds := md.Get("nodeid")
|
||||
if len(nodeIds) == 0 {
|
||||
return nil, errors.New("invalid 'nodeId'")
|
||||
}
|
||||
nodeId := nodeIds[0]
|
||||
node, err := models.SharedMonitorNodeDAO.FindEnabledMonitorNodeWithUniqueId(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if node == nil {
|
||||
return &pb.FindCurrentMonitorNodeResponse{MonitorNode: nil}, nil
|
||||
}
|
||||
|
||||
result := &pb.MonitorNode{
|
||||
Id: int64(node.Id),
|
||||
IsOn: node.IsOn,
|
||||
UniqueId: node.UniqueId,
|
||||
Secret: node.Secret,
|
||||
Name: node.Name,
|
||||
Description: node.Description,
|
||||
}
|
||||
return &pb.FindCurrentMonitorNodeResponse{MonitorNode: result}, nil
|
||||
}
|
||||
|
||||
// UpdateMonitorNodeStatus 更新节点状态
|
||||
func (this *MonitorNodeService) UpdateMonitorNodeStatus(ctx context.Context, req *pb.UpdateMonitorNodeStatusRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验节点
|
||||
_, nodeId, err := this.ValidateNodeId(ctx, rpcutils.UserTypeMonitor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.MonitorNodeId > 0 {
|
||||
nodeId = req.MonitorNodeId
|
||||
}
|
||||
|
||||
if nodeId <= 0 {
|
||||
return nil, errors.New("'nodeId' should be greater than 0")
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedMonitorNodeDAO.UpdateNodeStatus(tx, nodeId, req.StatusJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func (this *NodeClusterService) CreateNodeCluster(ctx context.Context, req *pb.C
|
||||
req.DnsTTL = 0
|
||||
}
|
||||
|
||||
clusterId, err = models.SharedNodeClusterDAO.CreateCluster(tx, adminId, req.Name, req.NodeGrantId, req.InstallDir, req.DnsDomainId, req.DnsName, req.DnsTTL, req.HttpCachePolicyId, req.HttpFirewallPolicyId, systemServices, serverGlobalConfig, req.AutoInstallNftables)
|
||||
clusterId, err = models.SharedNodeClusterDAO.CreateCluster(tx, adminId, req.Name, req.NodeGrantId, req.InstallDir, req.DnsDomainId, req.DnsName, req.DnsTTL, req.HttpCachePolicyId, req.HttpFirewallPolicyId, systemServices, serverGlobalConfig, req.AutoInstallNftables, req.AutoSystemTuning)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func (this *NodeClusterService) UpdateNodeCluster(ctx context.Context, req *pb.U
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.AutoOpenPorts, clockConfig, req.AutoRemoteStart, req.AutoInstallNftables, sshParams)
|
||||
err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.AutoOpenPorts, clockConfig, req.AutoRemoteStart, req.AutoInstallNftables, sshParams, req.AutoSystemTuning)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -233,6 +233,7 @@ func (this *NodeClusterService) FindEnabledNodeCluster(ctx context.Context, req
|
||||
ClockJSON: cluster.Clock,
|
||||
AutoRemoteStart: cluster.AutoRemoteStart,
|
||||
AutoInstallNftables: cluster.AutoInstallNftables,
|
||||
AutoSystemTuning: cluster.AutoSystemTuning,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
@@ -963,15 +964,21 @@ func (this *NodeClusterService) FindFreePortInNodeCluster(ctx context.Context, r
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
globalConfig, err := models.SharedSysSettingDAO.ReadGlobalConfig(tx)
|
||||
|
||||
// 检查端口
|
||||
globalServerConfig, err := models.SharedNodeClusterDAO.FindClusterGlobalServerConfig(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查端口
|
||||
portMin := globalConfig.TCPAll.PortRangeMin
|
||||
portMax := globalConfig.TCPAll.PortRangeMax
|
||||
denyPorts := globalConfig.TCPAll.DenyPorts
|
||||
var portMin, portMax int
|
||||
var denyPorts []int
|
||||
|
||||
if globalServerConfig != nil {
|
||||
portMin = globalServerConfig.TCPAll.PortRangeMin
|
||||
portMax = globalServerConfig.TCPAll.PortRangeMax
|
||||
denyPorts = globalServerConfig.TCPAll.DenyPorts
|
||||
}
|
||||
|
||||
if portMin == 0 && portMax == 0 {
|
||||
portMin = 10_000
|
||||
|
||||
@@ -216,7 +216,7 @@ func (this *ReverseProxyService) UpdateReverseProxy(ctx context.Context, req *pb
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedReverseProxyDAO.UpdateReverseProxy(tx, req.ReverseProxyId, types.Int8(req.RequestHostType), req.RequestHost, req.RequestHostExcludingPort, req.RequestURI, req.StripPrefix, req.AutoFlush, req.AddHeaders, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.ProxyProtocolJSON, req.FollowRedirects)
|
||||
err = models.SharedReverseProxyDAO.UpdateReverseProxy(tx, req.ReverseProxyId, types.Int8(req.RequestHostType), req.RequestHost, req.RequestHostExcludingPort, req.RequestURI, req.StripPrefix, req.AutoFlush, req.AddHeaders, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.ProxyProtocolJSON, req.FollowRedirects, req.Retry50X)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
@@ -117,12 +118,12 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe
|
||||
var auditingServerNamesJSON = []byte("[]")
|
||||
if userId > 0 {
|
||||
// 如果域名不为空的时候需要审核
|
||||
if len(serverNamesJSON) > 0 && string(serverNamesJSON) != "[]" {
|
||||
globalConfig, err := models.SharedSysSettingDAO.ReadGlobalConfig(tx)
|
||||
if len(serverNamesJSON) > 0 && string(serverNamesJSON) != "[]" && req.NodeClusterId > 0 {
|
||||
globalServerConfig, err := models.SharedNodeClusterDAO.FindClusterGlobalServerConfig(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if globalConfig != nil && globalConfig.HTTPAll.DomainAuditingIsOn {
|
||||
if globalServerConfig != nil && globalServerConfig.HTTPAll.DomainAuditingIsOn {
|
||||
isAuditing = true
|
||||
serverNamesJSON = []byte("[]")
|
||||
auditingServerNamesJSON = req.ServerNamesJSON
|
||||
@@ -147,7 +148,7 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe
|
||||
}
|
||||
|
||||
// 套餐
|
||||
plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId))
|
||||
plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -258,11 +259,12 @@ func (this *ServerService) CreateBasicHTTPServer(ctx context.Context, req *pb.Cr
|
||||
if userId > 0 {
|
||||
// 如果域名不为空的时候需要审核
|
||||
if len(serverNamesJSON) > 0 && string(serverNamesJSON) != "[]" {
|
||||
globalConfig, err := models.SharedSysSettingDAO.ReadGlobalConfig(tx)
|
||||
globalServerConfig, err := models.SharedNodeClusterDAO.FindClusterGlobalServerConfig(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if globalConfig != nil && globalConfig.HTTPAll.DomainAuditingIsOn {
|
||||
|
||||
if globalServerConfig != nil && globalServerConfig.HTTPAll.DomainAuditingIsOn {
|
||||
isAuditing = true
|
||||
serverNamesJSON = []byte("[]")
|
||||
auditingServerNamesJSON = serverNamesJSON
|
||||
@@ -1076,6 +1078,12 @@ func (this *ServerService) UpdateServerNames(ctx context.Context, req *pb.Update
|
||||
}
|
||||
}
|
||||
|
||||
// 套餐额度限制
|
||||
err = models.SharedServerDAO.CheckServerPlanQuota(tx, req.ServerId, len(serverconfigs.PlainServerNames(serverNameConfigs)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查用户
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
@@ -1084,22 +1092,31 @@ func (this *ServerService) UpdateServerNames(ctx context.Context, req *pb.Update
|
||||
}
|
||||
|
||||
// 是否需要审核
|
||||
globalConfig, err := models.SharedSysSettingDAO.ReadGlobalConfig(tx)
|
||||
clusterId, err := models.SharedServerDAO.FindServerClusterId(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if globalConfig != nil && globalConfig.HTTPAll.DomainAuditingIsOn {
|
||||
err = models.SharedServerDAO.UpdateAuditingServerNames(tx, req.ServerId, true, req.ServerNamesJSON)
|
||||
if clusterId > 0 {
|
||||
globalServerConfig, err := models.SharedNodeClusterDAO.FindClusterGlobalServerConfig(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if globalServerConfig != nil && globalServerConfig.HTTPAll.DomainAuditingIsOn {
|
||||
err = models.SharedServerDAO.UpdateAuditingServerNames(tx, req.ServerId, true, req.ServerNamesJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 发送审核通知
|
||||
err = models.SharedMessageDAO.CreateMessage(tx, 0, 0, models.MessageTypeServerNamesRequireAuditing, models.MessageLevelWarning, "有新的网站域名需要审核", "有新的网站域名需要审核", maps.Map{
|
||||
"serverId": req.ServerId,
|
||||
}.AsJSON())
|
||||
// 发送审核通知
|
||||
err = models.SharedMessageDAO.CreateMessage(tx, 0, 0, models.MessageTypeServerNamesRequireAuditing, models.MessageLevelWarning, "有新的网站域名需要审核", "有新的网站域名需要审核", maps.Map{
|
||||
"serverId": req.ServerId,
|
||||
}.AsJSON())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
return this.Success()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1278,7 +1295,7 @@ func (this *ServerService) CountAllEnabledServersMatch(ctx context.Context, req
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
count, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, req.ServerGroupId, req.Keyword, req.UserId, req.NodeClusterId, types.Int8(req.AuditingFlag), utils.SplitStrings(req.ProtocolFamily, ","))
|
||||
count, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, req.ServerGroupId, req.Keyword, req.UserId, req.NodeClusterId, types.Int8(req.AuditingFlag), utils.SplitStrings(req.ProtocolFamily, ","), req.UserPlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2019,6 +2036,52 @@ func (this *ServerService) FindAllEnabledServerNamesWithUserId(ctx context.Conte
|
||||
return &pb.FindAllEnabledServerNamesWithUserIdResponse{ServerNames: serverNames}, nil
|
||||
}
|
||||
|
||||
// CountAllServerNamesWithUserId 计算一个用户下的所有域名数量
|
||||
func (this *ServerService) CountAllServerNamesWithUserId(ctx context.Context, req *pb.CountAllServerNamesWithUserIdRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedServerDAO.CountAllServerNamesWithUserId(tx, req.UserId, req.UserPlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// CountServerNames 计算某个网站下的域名数量
|
||||
func (this *ServerService) CountServerNames(ctx context.Context, req *pb.CountServerNamesRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.ServerId <= 0 {
|
||||
return nil, errors.New("invalid 'serverId'")
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
count, err := models.SharedServerDAO.CountServerNames(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// FindAllUserServers 查找一个用户下的所有服务
|
||||
func (this *ServerService) FindAllUserServers(ctx context.Context, req *pb.FindAllUserServersRequest) (*pb.FindAllUserServersResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
@@ -2051,6 +2114,26 @@ func (this *ServerService) FindAllUserServers(ctx context.Context, req *pb.FindA
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CountAllUserServers 计算一个用户下的所有网站数量
|
||||
func (this *ServerService) CountAllUserServers(ctx context.Context, req *pb.CountAllUserServersRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
countServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", req.UserId, 0, configutils.BoolStateAll, nil, req.UserPlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(countServers)
|
||||
}
|
||||
|
||||
// ComposeAllUserServersConfig 查找某个用户下的服务配置
|
||||
func (this *ServerService) ComposeAllUserServersConfig(ctx context.Context, req *pb.ComposeAllUserServersConfigRequest) (*pb.ComposeAllUserServersConfigResponse, error) {
|
||||
_, err := this.ValidateNode(ctx)
|
||||
@@ -2644,7 +2727,7 @@ func (this *ServerService) UpdateServerUserPlan(ctx context.Context, req *pb.Upd
|
||||
}
|
||||
|
||||
if req.UserPlanId > 0 {
|
||||
userId, err := models.SharedServerDAO.FindServerUserId(tx, req.ServerId)
|
||||
userId, err = models.SharedServerDAO.FindServerUserId(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2662,14 +2745,47 @@ func (this *ServerService) UpdateServerUserPlan(ctx context.Context, req *pb.Upd
|
||||
if int64(userPlan.UserId) != userId {
|
||||
return nil, errors.New("can not find user plan with id '" + types.String(req.UserPlanId) + "'")
|
||||
}
|
||||
if userPlan.IsExpired() {
|
||||
return nil, fmt.Errorf("the user plan %q has been expired", types.String(req.UserPlanId))
|
||||
}
|
||||
|
||||
// 检查是否已经被别的服务所使用
|
||||
serverId, err := models.SharedServerDAO.FindEnabledServerIdWithUserPlanId(tx, req.UserPlanId)
|
||||
// 检查限制
|
||||
plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if serverId > 0 && serverId != req.ServerId {
|
||||
return nil, errors.New("the user plan is used by other server")
|
||||
if plan == nil {
|
||||
return nil, errors.New("can not find plan with id '" + types.String(userPlan.PlanId) + "'")
|
||||
}
|
||||
|
||||
if plan.TotalServers > 0 {
|
||||
countServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", userId, 0, configutils.BoolStateAll, nil, req.UserPlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if countServers+1 > int64(plan.TotalServers) {
|
||||
return nil, errors.New("total servers over quota")
|
||||
}
|
||||
}
|
||||
|
||||
countServerNames, err := models.SharedServerDAO.CountServerNames(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if plan.TotalServerNamesPerServer > 0 {
|
||||
if countServerNames > int64(plan.TotalServerNamesPerServer) {
|
||||
return nil, errors.New("total server names per server over quota")
|
||||
}
|
||||
}
|
||||
|
||||
totalServerNames, err := models.SharedServerDAO.CountAllServerNamesWithUserId(tx, userId, req.UserPlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if plan.TotalServerNames > 0 {
|
||||
if totalServerNames+countServerNames > int64(plan.TotalServerNames) {
|
||||
return nil, errors.New("total server names over quota")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2714,7 +2830,7 @@ func (this *ServerService) FindServerUserPlan(ctx context.Context, req *pb.FindS
|
||||
return &pb.FindServerUserPlanResponse{UserPlan: nil}, nil
|
||||
}
|
||||
|
||||
plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId))
|
||||
plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2732,11 +2848,14 @@ func (this *ServerService) FindServerUserPlan(ctx context.Context, req *pb.FindS
|
||||
DayTo: userPlan.DayTo,
|
||||
User: nil,
|
||||
Plan: &pb.Plan{
|
||||
Id: int64(plan.Id),
|
||||
Name: plan.Name,
|
||||
PriceType: plan.PriceType,
|
||||
TrafficPriceJSON: plan.TrafficPrice,
|
||||
TrafficLimitJSON: plan.TrafficLimit,
|
||||
Id: int64(plan.Id),
|
||||
Name: plan.Name,
|
||||
PriceType: plan.PriceType,
|
||||
TrafficPriceJSON: plan.TrafficPrice,
|
||||
TrafficLimitJSON: plan.TrafficLimit,
|
||||
TotalServers: types.Int32(plan.TotalServers),
|
||||
TotalServerNames: types.Int32(plan.TotalServerNames),
|
||||
TotalServerNamesPerServer: types.Int32(plan.TotalServerNamesPerServer),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
@@ -2878,7 +2997,7 @@ func (this *ServerService) CopyServerConfig(ctx context.Context, req *pb.CopySer
|
||||
}
|
||||
}
|
||||
}
|
||||
err = models.SharedServerDAO.CopyServerConfigToServers(tx, req.ServerId, req.TargetServerIds, req.ConfigCode)
|
||||
err = models.SharedServerDAO.CopyServerConfigToServers(tx, req.ServerId, req.TargetServerIds, req.ConfigCode, req.WafCopyRegions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2895,7 +3014,7 @@ func (this *ServerService) CopyServerConfig(ctx context.Context, req *pb.CopySer
|
||||
}
|
||||
}
|
||||
}
|
||||
err = models.SharedServerDAO.CopyServerConfigToGroups(tx, req.ServerId, req.TargetServerGroupIds, req.ConfigCode)
|
||||
err = models.SharedServerDAO.CopyServerConfigToGroups(tx, req.ServerId, req.TargetServerGroupIds, req.ConfigCode, req.WafCopyRegions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2907,7 +3026,7 @@ func (this *ServerService) CopyServerConfig(ctx context.Context, req *pb.CopySer
|
||||
if req.TargetClusterId <= 0 {
|
||||
return this.Success()
|
||||
}
|
||||
err = models.SharedServerDAO.CopyServerConfigToCluster(tx, req.ServerId, req.TargetClusterId, req.ConfigCode)
|
||||
err = models.SharedServerDAO.CopyServerConfigToCluster(tx, req.ServerId, req.TargetClusterId, req.ConfigCode, req.WafCopyRegions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2926,7 +3045,7 @@ func (this *ServerService) CopyServerConfig(ctx context.Context, req *pb.CopySer
|
||||
// 只能同步到自己的网站
|
||||
req.TargetUserId = userId
|
||||
}
|
||||
err = models.SharedServerDAO.CopyServerConfigToUser(tx, req.ServerId, req.TargetUserId, req.ConfigCode)
|
||||
err = models.SharedServerDAO.CopyServerConfigToUser(tx, req.ServerId, req.TargetUserId, req.ConfigCode, req.WafCopyRegions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2934,3 +3053,43 @@ func (this *ServerService) CopyServerConfig(ctx context.Context, req *pb.CopySer
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindServerAuditingPrompt 获取域名审核时的提示文字
|
||||
func (this *ServerService) FindServerAuditingPrompt(ctx context.Context, req *pb.FindServerAuditingPromptRequest) (*pb.FindServerAuditingPromptResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
clusterId, err := models.SharedServerDAO.FindServerClusterId(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if clusterId <= 0 {
|
||||
return &pb.FindServerAuditingPromptResponse{
|
||||
PromptText: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
globalServerConfig, err := models.SharedNodeClusterDAO.FindClusterGlobalServerConfig(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if globalServerConfig != nil {
|
||||
return &pb.FindServerAuditingPromptResponse{
|
||||
PromptText: globalServerConfig.HTTPAll.DomainAuditingPrompt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindServerAuditingPromptResponse{
|
||||
PromptText: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -63,17 +63,31 @@ func init() {
|
||||
}
|
||||
|
||||
for _, stat := range m {
|
||||
// 更新服务的带宽峰值
|
||||
// 更新网站的带宽峰值
|
||||
if stat.ServerId > 0 {
|
||||
err = models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.NodeRegionId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
|
||||
// 更新带宽统计
|
||||
err = models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.NodeRegionId, stat.UserPlanId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerBandwidthStatService", "dump bandwidth stats failed: "+err.Error())
|
||||
}
|
||||
|
||||
// 更新网站的bandwidth字段,方便快速排序
|
||||
err = models.SharedServerDAO.UpdateServerBandwidth(tx, stat.ServerId, stat.Day+stat.TimeAt, stat.Bytes, stat.CountRequests, stat.CountAttackRequests)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerBandwidthStatService", "update server bandwidth failed: "+err.Error())
|
||||
}
|
||||
|
||||
// 套餐统计
|
||||
if stat.UserPlanId > 0 {
|
||||
// 总体统计
|
||||
err = models.SharedUserPlanStatDAO.IncreaseUserPlanStat(tx, stat.UserPlanId, stat.TotalBytes, stat.CountRequests)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerBandwidthStatService", "IncreaseUserPlanStat: "+err.Error())
|
||||
}
|
||||
|
||||
// 分时统计
|
||||
err = models.SharedUserPlanBandwidthStatDAO.UpdateUserPlanBandwidth(tx, stat.UserId, stat.UserPlanId, stat.NodeRegionId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新用户的带宽峰值
|
||||
@@ -147,6 +161,7 @@ func (this *ServerBandwidthStatService) UploadServerBandwidthStats(ctx context.C
|
||||
CountRequests: stat.CountRequests,
|
||||
CountCachedRequests: stat.CountCachedRequests,
|
||||
CountAttackRequests: stat.CountAttackRequests,
|
||||
UserPlanId: stat.UserPlanId,
|
||||
}
|
||||
}
|
||||
serverBandwidthStatsLocker.Unlock()
|
||||
|
||||
@@ -191,7 +191,7 @@ func (this *SSLCertService) CountSSLCerts(ctx context.Context, req *pb.CountSSLC
|
||||
return nil, errors.New("invalid user")
|
||||
}
|
||||
|
||||
count, err := models.SharedSSLCertDAO.CountCerts(tx, req.IsCA, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, userId, req.Domains)
|
||||
count, err := models.SharedSSLCertDAO.CountCerts(tx, req.IsCA, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, userId, req.Domains, req.UserOnly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func (this *SSLCertService) ListSSLCerts(ctx context.Context, req *pb.ListSSLCer
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
certIds, err := models.SharedSSLCertDAO.ListCertIds(tx, req.IsCA, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, userId, req.Domains, req.Offset, req.Size)
|
||||
certIds, err := models.SharedSSLCertDAO.ListCertIds(tx, req.IsCA, req.IsAvailable, req.IsExpired, int64(req.ExpiringDays), req.Keyword, userId, req.Domains, req.UserOnly, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -368,3 +368,40 @@ func (this *SSLCertService) ListUpdatedSSLCertOCSP(ctx context.Context, req *pb.
|
||||
SslCertOCSP: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindSSLCertUser 查找证书所属用户
|
||||
func (this *SSLCertService) FindSSLCertUser(ctx context.Context, req *pb.FindSSLCertUserRequest) (*pb.FindSSLCertUserResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
userId, err := models.SharedSSLCertDAO.FindCertUserId(tx, req.SslCertId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userId <= 0 {
|
||||
return &pb.FindSSLCertUserResponse{User: nil}, nil
|
||||
}
|
||||
|
||||
user, err := models.SharedUserDAO.FindEnabledBasicUser(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return &pb.FindSSLCertUserResponse{
|
||||
User: &pb.User{
|
||||
Id: userId,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindSSLCertUserResponse{
|
||||
User: &pb.User{
|
||||
Id: userId,
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -14,12 +14,6 @@ type SysLockerService struct {
|
||||
// SysLockerLock 获得锁
|
||||
func (this *SysLockerService) SysLockerLock(ctx context.Context, req *pb.SysLockerLockRequest) (*pb.SysLockerLockResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, false)
|
||||
if err != nil {
|
||||
_, err = this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
key := req.Key
|
||||
if userId > 0 {
|
||||
@@ -44,12 +38,6 @@ func (this *SysLockerService) SysLockerLock(ctx context.Context, req *pb.SysLock
|
||||
// SysLockerUnlock 释放锁
|
||||
func (this *SysLockerService) SysLockerUnlock(ctx context.Context, req *pb.SysLockerUnlockRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, false)
|
||||
if err != nil {
|
||||
_, err = this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
key := req.Key
|
||||
if userId > 0 {
|
||||
|
||||
@@ -412,7 +412,7 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
|
||||
}
|
||||
|
||||
// 网站数量
|
||||
countServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", req.UserId, 0, configutils.BoolStateAll, []string{})
|
||||
countServers, err := models.SharedServerDAO.CountAllEnabledServersMatch(tx, 0, "", req.UserId, 0, configutils.BoolStateAll, []string{}, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ const (
|
||||
UserTypeProvider = "provider"
|
||||
UserTypeNode = "node"
|
||||
UserTypeCluster = "cluster"
|
||||
UserTypeMonitor = "monitor"
|
||||
UserTypeStat = "stat"
|
||||
UserTypeDNS = "dns"
|
||||
UserTypeLog = "log"
|
||||
|
||||
13008
internal/setup/sql.json
13008
internal/setup/sql.json
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,11 @@ var recordsTables = []*SQLRecordsTable{
|
||||
UniqueFields: []string{"agentId", "ip"},
|
||||
IgnoreId: true,
|
||||
},
|
||||
{
|
||||
TableName: "edgeMessageMedias",
|
||||
UniqueFields: []string{"type"},
|
||||
IgnoreId: true,
|
||||
},
|
||||
}
|
||||
|
||||
type sqlItem struct {
|
||||
|
||||
@@ -95,6 +95,12 @@ var upgradeFuncs = []*upgradeVersion{
|
||||
{
|
||||
"1.2.1", upgradeV1_2_1,
|
||||
},
|
||||
{
|
||||
"1.2.9", upgradeV1_2_9,
|
||||
},
|
||||
{
|
||||
"1.2.10", upgradeV1_2_10,
|
||||
},
|
||||
}
|
||||
|
||||
// UpgradeSQLData 升级SQL数据
|
||||
@@ -746,3 +752,67 @@ func upgradeV1_2_1(db *dbs.DB) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 1.2.10
|
||||
func upgradeV1_2_10(db *dbs.DB) error {
|
||||
{
|
||||
type OldGlobalConfig struct {
|
||||
// HTTP & HTTPS相关配置
|
||||
HTTPAll struct {
|
||||
DomainAuditingIsOn bool `yaml:"domainAuditingIsOn" json:"domainAuditingIsOn"` // 域名是否需要审核
|
||||
DomainAuditingPrompt string `yaml:"domainAuditingPrompt" json:"domainAuditingPrompt"` // 域名审核的提示
|
||||
} `yaml:"httpAll" json:"httpAll"`
|
||||
|
||||
TCPAll struct {
|
||||
PortRangeMin int `yaml:"portRangeMin" json:"portRangeMin"` // 最小端口
|
||||
PortRangeMax int `yaml:"portRangeMax" json:"portRangeMax"` // 最大端口
|
||||
DenyPorts []int `yaml:"denyPorts" json:"denyPorts"` // 禁止使用的端口
|
||||
} `yaml:"tcpAll" json:"tcpAll"`
|
||||
}
|
||||
|
||||
globalConfigValue, err := db.FindCol(0, "SELECT value FROM edgeSysSettings WHERE code='serverGlobalConfig'")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var globalConfigString = types.String(globalConfigValue)
|
||||
if len(globalConfigString) > 0 {
|
||||
var oldGlobalConfig = &OldGlobalConfig{}
|
||||
err = json.Unmarshal([]byte(globalConfigString), oldGlobalConfig)
|
||||
if err == nil { // we ignore error
|
||||
ones, _, err := db.FindOnes("SELECT id,globalServerConfig FROM edgeNodeClusters")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var id = one.GetInt64("id")
|
||||
var globalServerConfigData = []byte(one.GetString("globalServerConfig"))
|
||||
if len(globalServerConfigData) > 32 {
|
||||
var globalServerConfig = &serverconfigs.GlobalServerConfig{}
|
||||
err = json.Unmarshal(globalServerConfigData, globalServerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
globalServerConfig.HTTPAll.DomainAuditingIsOn = oldGlobalConfig.HTTPAll.DomainAuditingIsOn
|
||||
globalServerConfig.HTTPAll.DomainAuditingPrompt = oldGlobalConfig.HTTPAll.DomainAuditingPrompt
|
||||
|
||||
globalServerConfig.TCPAll.DenyPorts = oldGlobalConfig.TCPAll.DenyPorts
|
||||
globalServerConfig.TCPAll.PortRangeMin = oldGlobalConfig.TCPAll.PortRangeMin
|
||||
globalServerConfig.TCPAll.PortRangeMax = oldGlobalConfig.TCPAll.PortRangeMax
|
||||
|
||||
globalServerConfigJSON, err := json.Marshal(globalServerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = db.Exec("UPDATE edgeNodeClusters SET globalServerConfig=? WHERE id=?", globalServerConfigJSON, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -213,3 +213,16 @@ func upgradeV0_5_8(db *dbs.DB) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// v1.2.9
|
||||
func upgradeV1_2_9(db *dbs.DB) error {
|
||||
// 升级WAF规则
|
||||
{
|
||||
_, err := db.Exec("UPDATE edgeHTTPFirewallRules SET value=? WHERE value=? AND param='${userAgent}'", "python|pycurl|http-client|httpclient|apachebench|nethttp|http_request|java|perl|ruby|scrapy|php\\b|rust", "python|pycurl|http-client|httpclient|apachebench|nethttp|http_request|java|perl|ruby|scrapy|php|rust")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -271,4 +271,21 @@ func TestUpgradeSQLData_v1_2_1(t *testing.T) {
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
|
||||
func TestUpgradeSQLData_v1_2_10(t *testing.T) {
|
||||
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
err = upgradeV1_2_10(db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ func (this *NodeMonitorTask) MonitorCluster(cluster *models.NodeCluster) error {
|
||||
this.notifiedMap[nodeId] = time.Now().Unix()
|
||||
|
||||
var subject = "节点\"" + node.Name + "\"已处于离线状态"
|
||||
var msg = "集群'" + cluster.Name + "'节点\"" + node.Name + "\"已处于离线状态,请检查节点是否异常"
|
||||
var msg = "集群 \"" + cluster.Name + "\" 节点 \"" + node.Name + "\" 已处于离线状态,请检查节点是否异常"
|
||||
err = models.SharedMessageDAO.CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, clusterId, int64(node.Id), models.MessageTypeNodeInactive, models.LevelError, subject, msg, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user