sync: 同步 v1.0.4 并脱敏配置与镜像
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -83,7 +84,7 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
|
||||
batch.DeptID,
|
||||
batch.Category,
|
||||
batch.WarnStage,
|
||||
len(batch.Items),
|
||||
batchItemCount(batch),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
@@ -92,40 +93,61 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
deliveries := resolveTerminalPlatformDeliveries(ctx, batch)
|
||||
deliveries := resolveWechatDeliveries(ctx, batch)
|
||||
if len(deliveries) == 0 {
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no terminal recipients, tenantId:%s, count:%d", batch.TenantID, len(batch.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
var sendErrs []string
|
||||
for _, delivery := range deliveries {
|
||||
if len(delivery.Group.UserIDs) == 0 || len(delivery.Batch.Items) == 0 {
|
||||
if len(delivery.Group.UserIDs) == 0 || batchItemCount(delivery.Batch) == 0 {
|
||||
continue
|
||||
}
|
||||
userID := delivery.Group.UserIDs[0]
|
||||
if batch.Business == BusinessSimWarning {
|
||||
enabled, err := warningWechatEnabled(ctx, batch.TenantID, userID)
|
||||
if err != nil {
|
||||
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d query preference: %v", userID, err))
|
||||
continue
|
||||
}
|
||||
if !enabled {
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:user preference disabled, tenantId:%s, userId:%d, count:%d", batch.TenantID, userID, batchItemCount(delivery.Batch))
|
||||
continue
|
||||
}
|
||||
}
|
||||
bindings, err := queryWechatBindings(ctx, batch.TenantID, userID)
|
||||
if err != nil {
|
||||
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d query binding: %v", userID, err))
|
||||
continue
|
||||
}
|
||||
if len(bindings) == 0 {
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no openid, tenantId:%s, userId:%d, count:%d", batch.TenantID, userID, len(delivery.Batch.Items))
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no openid, tenantId:%s, userId:%d, count:%d", batch.TenantID, userID, batchItemCount(delivery.Batch))
|
||||
continue
|
||||
}
|
||||
|
||||
acquired, sentKey, err := acquireWechatSendDedupe(ctx, delivery.Batch, userID)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "WarningNotify wechat subscribe dedupe check failed, tenantId:%s, userId:%d, category:%s, stage:%d, count:%d, err:%+v",
|
||||
batch.TenantID, userID, delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items), err)
|
||||
batch.TenantID, userID, delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch), err)
|
||||
} else if !acquired {
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:duplicated, tenantId:%s, userId:%d, key:%s, category:%s, stage:%d, count:%d",
|
||||
batch.TenantID, userID, sentKey, delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items))
|
||||
batch.TenantID, userID, sentKey, delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch))
|
||||
continue
|
||||
}
|
||||
|
||||
successCount := 0
|
||||
for _, binding := range bindings {
|
||||
if batch.Business == BusinessSimWarning {
|
||||
enabled, err := warningWechatEnabled(ctx, batch.TenantID, userID)
|
||||
if err != nil {
|
||||
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d query preference: %v", userID, err))
|
||||
continue
|
||||
}
|
||||
if !enabled {
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:user preference disabled before send, tenantId:%s, userId:%d", batch.TenantID, userID)
|
||||
continue
|
||||
}
|
||||
}
|
||||
templateID := wechatTemplateID(delivery.Batch.Items, cfg.TemplateID)
|
||||
if templateID == "" {
|
||||
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d template id empty", userID))
|
||||
@@ -135,11 +157,11 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
|
||||
if err := sendWechatSubscription(ctx, cfg, payload); err != nil {
|
||||
sendErrs = append(sendErrs, fmt.Sprintf("userId=%d openid=%s: %v", userID, maskOpenID(binding.OpenID), err))
|
||||
g.Log().Errorf(ctx, "WarningNotify wechat subscribe failed, tenantId:%s, userId:%d, openid:%s, category:%s, stage:%d, count:%d, err:%+v",
|
||||
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items), err)
|
||||
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch), err)
|
||||
continue
|
||||
}
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe sent, tenantId:%s, userId:%d, openid:%s, category:%s, stage:%d, count:%d",
|
||||
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, len(delivery.Batch.Items))
|
||||
batch.TenantID, userID, maskOpenID(binding.OpenID), delivery.Batch.Category, delivery.Batch.WarnStage, batchItemCount(delivery.Batch))
|
||||
successCount++
|
||||
}
|
||||
if acquired && successCount == 0 {
|
||||
@@ -153,6 +175,107 @@ func sendWarningWechat(ctx context.Context, batch Batch) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveWechatDeliveries(ctx context.Context, batch Batch) []platformDelivery {
|
||||
if batch.prepared != nil {
|
||||
return []platformDelivery{{Group: *batch.prepared, Batch: batch}}
|
||||
}
|
||||
deliveries := resolveTerminalPlatformDeliveries(ctx, batch)
|
||||
appendEnterpriseWechatDeliveries(ctx, batch, &deliveries)
|
||||
if len(deliveries) == 0 {
|
||||
g.Log().Infof(ctx, "WarningNotify wechat subscribe skipped, reason:no eligible recipients, tenantId:%s, count:%d", batch.TenantID, batchItemCount(batch))
|
||||
}
|
||||
return deliveries
|
||||
}
|
||||
|
||||
func appendEnterpriseWechatDeliveries(ctx context.Context, batch Batch, deliveries *[]platformDelivery) {
|
||||
if batch.Business != BusinessSimWarning {
|
||||
return
|
||||
}
|
||||
itemsByUser := make(map[int64][]Event)
|
||||
seenByUser := make(map[int64]map[int]struct{})
|
||||
for index, item := range batch.Items {
|
||||
if item.ItemType != 1 {
|
||||
continue
|
||||
}
|
||||
createdBy := item.CreatedBy
|
||||
if createdBy <= 0 {
|
||||
createdBy = batch.CreatedBy
|
||||
}
|
||||
if createdBy <= 0 || item.ItemID <= 0 {
|
||||
continue
|
||||
}
|
||||
userID, ok, err := queryEnterpriseWarningUser(ctx, batch.TenantID, createdBy, item.ItemID)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "WarningNotify query enterprise user failed, tenantId:%s, userId:%d, cardId:%d, err:%+v", batch.TenantID, createdBy, item.ItemID, err)
|
||||
continue
|
||||
}
|
||||
if ok {
|
||||
appendTerminalEvent(itemsByUser, seenByUser, userID, index, item)
|
||||
}
|
||||
}
|
||||
userIDs := make([]int64, 0, len(itemsByUser))
|
||||
for userID := range itemsByUser {
|
||||
userIDs = append(userIDs, userID)
|
||||
}
|
||||
sort.Slice(userIDs, func(i, j int) bool { return userIDs[i] < userIDs[j] })
|
||||
for _, userID := range userIDs {
|
||||
items := itemsByUser[userID]
|
||||
enterpriseBatch := batch
|
||||
enterpriseBatch.Items = append([]Event(nil), items...)
|
||||
enterpriseBatch.WarnStage = highestStage(enterpriseBatch.Items)
|
||||
*deliveries = append(*deliveries, platformDelivery{
|
||||
Group: platformRecipientGroup{SendUserType: sendUserTypeAgent, UserIDs: []int64{userID}},
|
||||
Batch: enterpriseBatch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func enterpriseWarningRecipientEligible(userType string, userDeptID, cardDeptID int64, ancestors string) bool {
|
||||
if userType != consts.SysUserTypeSys || userDeptID <= 0 || cardDeptID <= 0 {
|
||||
return false
|
||||
}
|
||||
if userDeptID == cardDeptID {
|
||||
return true
|
||||
}
|
||||
target := strconv.FormatInt(userDeptID, 10)
|
||||
for _, ancestor := range strings.Split(ancestors, ",") {
|
||||
if strings.TrimSpace(ancestor) == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func queryEnterpriseWarningUser(ctx context.Context, tenantID string, userID, cardID int64) (int64, bool, error) {
|
||||
if strings.TrimSpace(tenantID) == "" || userID <= 0 || cardID <= 0 {
|
||||
return 0, false, nil
|
||||
}
|
||||
var result struct {
|
||||
UserID int64 `orm:"user_id"`
|
||||
UserType string `orm:"user_type"`
|
||||
DeptID int64 `orm:"dept_id"`
|
||||
CardDeptID int64 `orm:"card_dept_id"`
|
||||
Ancestors string `orm:"ancestors"`
|
||||
}
|
||||
err := g.DB().Model(dao.TSimCardInfo.Table()+" c").Ctx(ctx).Safe().
|
||||
LeftJoin(dao.SysUser.Table()+" u", "u.user_id = "+strconv.FormatInt(userID, 10)).
|
||||
InnerJoin(dao.SysDept.Table()+" d", "d.dept_id = c.dept_id AND d.tenant_id = c.tenant_id").
|
||||
InnerJoin(dao.SysDept.Table()+" ud", "ud.dept_id = u.dept_id AND ud.tenant_id = u.tenant_id").
|
||||
Fields("u.user_id, u.user_type, u.dept_id, c.dept_id AS card_dept_id, d.ancestors").
|
||||
Where("c.tenant_id", tenantID).
|
||||
Where("c.id", cardID).
|
||||
Where("u.tenant_id", tenantID).
|
||||
Where("u.user_type", consts.SysUserTypeSys).
|
||||
Where("u.status", consts.SysDeptStatusNormal).
|
||||
Where("u.deleted_at IS NULL").
|
||||
Where("d.deleted_at IS NULL").
|
||||
Where("ud.deleted_at IS NULL").
|
||||
Scan(&result)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
return result.UserID, result.UserID > 0 && enterpriseWarningRecipientEligible(result.UserType, result.DeptID, result.CardDeptID, result.Ancestors), nil
|
||||
}
|
||||
|
||||
func loadWarningWechatConfig(ctx context.Context) (warningWechatConfig, bool) {
|
||||
var cfg warningWechatConfig
|
||||
loaded := false
|
||||
@@ -358,6 +481,9 @@ func wechatBatchHasExpireKind(batch Batch) bool {
|
||||
|
||||
func wechatBatchTime(batch Batch) time.Time {
|
||||
latest := latestEvent(batch.Items)
|
||||
if !batch.LatestTime.IsZero() {
|
||||
latest.WarnTime = batch.LatestTime
|
||||
}
|
||||
if latest.WarnTime.IsZero() {
|
||||
return time.Now()
|
||||
}
|
||||
@@ -392,6 +518,9 @@ func wechatTemplateID(items []Event, fallback string) string {
|
||||
|
||||
func buildWechatPayload(batch Batch, openID string, templateID string, page string) warningWechatPayload {
|
||||
latest := latestEvent(batch.Items)
|
||||
if !batch.LatestTime.IsZero() {
|
||||
latest.WarnTime = batch.LatestTime
|
||||
}
|
||||
return warningWechatPayload{
|
||||
ToUser: strings.TrimSpace(openID),
|
||||
TemplateID: strings.TrimSpace(templateID),
|
||||
@@ -417,25 +546,25 @@ func latestEvent(items []Event) Event {
|
||||
}
|
||||
|
||||
func wechatDeviceText(batch Batch) string {
|
||||
if len(batch.Items) == 0 {
|
||||
if batchItemCount(batch) == 0 {
|
||||
return "--"
|
||||
}
|
||||
first := displayObjectCode(batch.Items[0])
|
||||
if len(batch.Items) == 1 {
|
||||
if batchItemCount(batch) == 1 {
|
||||
return first
|
||||
}
|
||||
return fmt.Sprintf("%s等%d张卡", first, len(batch.Items))
|
||||
return fmt.Sprintf("%s等%d张卡", first, batchItemCount(batch))
|
||||
}
|
||||
|
||||
func wechatDeviceCharacterText(batch Batch) string {
|
||||
if len(batch.Items) == 0 {
|
||||
if batchItemCount(batch) == 0 {
|
||||
return "NA"
|
||||
}
|
||||
first := displayObjectCode(batch.Items[0])
|
||||
if len(batch.Items) == 1 {
|
||||
if batchItemCount(batch) == 1 {
|
||||
return first
|
||||
}
|
||||
return fmt.Sprintf("%sx%d", first, len(batch.Items))
|
||||
return fmt.Sprintf("TOTAL-%d", batchItemCount(batch))
|
||||
}
|
||||
|
||||
func wechatTypeText(batch Batch) string {
|
||||
@@ -443,25 +572,28 @@ func wechatTypeText(batch Batch) string {
|
||||
if title == "" {
|
||||
title = "设备预警"
|
||||
}
|
||||
if len(batch.Items) > 1 {
|
||||
return fmt.Sprintf("%s,共%d张卡", title, len(batch.Items))
|
||||
if batchItemCount(batch) > 1 {
|
||||
return fmt.Sprintf("%s,共%d张卡", title, batchItemCount(batch))
|
||||
}
|
||||
return title
|
||||
}
|
||||
|
||||
func wechatReasonText(batch Batch) string {
|
||||
if len(batch.Items) == 1 {
|
||||
if batchItemCount(batch) == 1 {
|
||||
return emailWarningReason(batch.Items[0])
|
||||
}
|
||||
reason := fmt.Sprintf("共%d张卡触发预警,最高级别:%s", len(batch.Items), levelText(highestLevel(batch.Items)))
|
||||
if hasAffectOperation(batch.Items) {
|
||||
reason := fmt.Sprintf("%s\uff0c\u5171%d\u5f20\u5361", levelText(batchHighestLevel(batch)), batchItemCount(batch))
|
||||
if batchHasAffectOperation(batch) {
|
||||
reason += ",涉及停机或断网"
|
||||
}
|
||||
return reason
|
||||
}
|
||||
|
||||
func wechatValueText(batch Batch) string {
|
||||
if len(batch.Items) == 0 {
|
||||
if batchItemCount(batch) > 1 {
|
||||
return fmt.Sprintf("TOTAL-%d", batchItemCount(batch))
|
||||
}
|
||||
if batchItemCount(batch) == 0 {
|
||||
return "NA"
|
||||
}
|
||||
item := batch.Items[0]
|
||||
|
||||
Reference in New Issue
Block a user