All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m48s
236 lines
6.2 KiB
Go
236 lines
6.2 KiB
Go
package iot_card
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
assetAuditSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_audit"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
)
|
|
|
|
// AssetAuditService 资产审计服务接口。
|
|
type AssetAuditService interface {
|
|
LogOperation(ctx context.Context, log *model.AssetOperationLog)
|
|
}
|
|
|
|
func (s *Service) logCardAudit(ctx context.Context, p assetAuditSvc.BuildLogParams) {
|
|
if s == nil || s.assetAuditService == nil {
|
|
return
|
|
}
|
|
if p.Operator.Type == "" {
|
|
p.Operator = assetAuditSvc.OperatorFromContext(ctx)
|
|
}
|
|
if p.AssetType == "" {
|
|
p.AssetType = constants.AssetTypeIotCard
|
|
}
|
|
p.BeforeData, p.AfterData = normalizeCardAuditPayload(p.BeforeData, p.AfterData)
|
|
s.assetAuditService.LogOperation(ctx, assetAuditSvc.BuildLog(ctx, p))
|
|
}
|
|
|
|
func (s *StopResumeService) logCardAudit(ctx context.Context, p assetAuditSvc.BuildLogParams) {
|
|
if s == nil || s.assetAuditService == nil {
|
|
return
|
|
}
|
|
if p.Operator.Type == "" {
|
|
p.Operator = assetAuditSvc.OperatorFromContext(ctx)
|
|
}
|
|
if p.AssetType == "" {
|
|
p.AssetType = constants.AssetTypeIotCard
|
|
}
|
|
p.BeforeData, p.AfterData = normalizeCardAuditPayload(p.BeforeData, p.AfterData)
|
|
s.assetAuditService.LogOperation(ctx, assetAuditSvc.BuildLog(ctx, p))
|
|
}
|
|
|
|
func normalizeCardAuditPayload(beforeData, afterData map[string]any) (map[string]any, map[string]any) {
|
|
snapshot := map[string]any(nil)
|
|
if raw, ok := beforeData["card"]; ok {
|
|
if m, ok := raw.(map[string]any); ok {
|
|
snapshot = m
|
|
}
|
|
}
|
|
if snapshot == nil {
|
|
if raw, ok := afterData["card"]; ok {
|
|
if m, ok := raw.(map[string]any); ok {
|
|
snapshot = m
|
|
}
|
|
}
|
|
}
|
|
beforeContent := stripCardOperationMeta(beforeData)
|
|
afterContent := stripCardOperationMeta(afterData)
|
|
beforeContent = ensureCardOperationContentMap(beforeContent, beforeData)
|
|
afterContent = ensureCardOperationContentMap(afterContent, afterData)
|
|
enrichCardOperationContent(beforeContent, beforeData)
|
|
enrichCardOperationContent(afterContent, afterData)
|
|
return assetAuditSvc.WrapOperationContent(beforeContent, afterContent, snapshot)
|
|
}
|
|
|
|
func stripCardOperationMeta(data map[string]any) map[string]any {
|
|
if len(data) == 0 {
|
|
return nil
|
|
}
|
|
out := make(map[string]any, len(data))
|
|
for k, v := range data {
|
|
if k == "device" || k == "card" || k == "cards" || k == "asset_snapshot" || k == "operation_content" {
|
|
continue
|
|
}
|
|
out[k] = v
|
|
}
|
|
if len(out) == 0 {
|
|
return nil
|
|
}
|
|
return out
|
|
}
|
|
|
|
func ensureCardOperationContentMap(content map[string]any, raw map[string]any) map[string]any {
|
|
if content != nil || len(raw) == 0 {
|
|
return content
|
|
}
|
|
if _, ok := raw["card"].(map[string]any); ok {
|
|
return make(map[string]any)
|
|
}
|
|
if _, ok := raw["device"].(map[string]any); ok {
|
|
return make(map[string]any)
|
|
}
|
|
switch raw["cards"].(type) {
|
|
case []map[string]any, []any:
|
|
return make(map[string]any)
|
|
default:
|
|
return content
|
|
}
|
|
}
|
|
|
|
func enrichCardOperationContent(content map[string]any, raw map[string]any) {
|
|
if len(raw) == 0 {
|
|
return
|
|
}
|
|
|
|
if cardRaw, ok := raw["card"].(map[string]any); ok {
|
|
mergeReadableCardFields(content, cardRaw)
|
|
}
|
|
if deviceRaw, ok := raw["device"].(map[string]any); ok {
|
|
mergeReadableDeviceFields(content, deviceRaw)
|
|
}
|
|
|
|
switch cardsRaw := raw["cards"].(type) {
|
|
case []map[string]any:
|
|
cardIDs, iccids := collectCardReadableLists(cardsRaw)
|
|
if len(cardIDs) > 0 && content["card_ids"] == nil {
|
|
content["card_ids"] = cardIDs
|
|
}
|
|
if len(iccids) > 0 && content["iccids"] == nil {
|
|
content["iccids"] = iccids
|
|
}
|
|
case []any:
|
|
cards := make([]map[string]any, 0, len(cardsRaw))
|
|
for _, item := range cardsRaw {
|
|
cardMap, ok := item.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
cards = append(cards, cardMap)
|
|
}
|
|
cardIDs, iccids := collectCardReadableLists(cards)
|
|
if len(cardIDs) > 0 && content["card_ids"] == nil {
|
|
content["card_ids"] = cardIDs
|
|
}
|
|
if len(iccids) > 0 && content["iccids"] == nil {
|
|
content["iccids"] = iccids
|
|
}
|
|
}
|
|
}
|
|
|
|
func mergeReadableCardFields(content map[string]any, card map[string]any) {
|
|
if len(card) == 0 {
|
|
return
|
|
}
|
|
if _, ok := content["card_id"]; !ok {
|
|
if v, exists := card["id"]; exists {
|
|
content["card_id"] = v
|
|
}
|
|
}
|
|
if _, ok := content["iccid"]; !ok {
|
|
if v := stringifyCardAuditValue(card["iccid"]); v != "" {
|
|
content["iccid"] = v
|
|
}
|
|
}
|
|
if _, ok := content["device_virtual_no"]; !ok {
|
|
if v := stringifyCardAuditValue(card["device_virtual_no"]); v != "" {
|
|
content["device_virtual_no"] = v
|
|
}
|
|
}
|
|
}
|
|
|
|
func mergeReadableDeviceFields(content map[string]any, device map[string]any) {
|
|
if len(device) == 0 {
|
|
return
|
|
}
|
|
if _, ok := content["device_id"]; !ok {
|
|
if v, exists := device["id"]; exists {
|
|
content["device_id"] = v
|
|
}
|
|
}
|
|
if _, ok := content["device_virtual_no"]; !ok {
|
|
if v := stringifyCardAuditValue(device["virtual_no"]); v != "" {
|
|
content["device_virtual_no"] = v
|
|
}
|
|
}
|
|
if _, ok := content["device_imei"]; !ok {
|
|
if v := stringifyCardAuditValue(device["imei"]); v != "" {
|
|
content["device_imei"] = v
|
|
}
|
|
}
|
|
if _, ok := content["device_sn"]; !ok {
|
|
if v := stringifyCardAuditValue(device["sn"]); v != "" {
|
|
content["device_sn"] = v
|
|
}
|
|
}
|
|
}
|
|
|
|
func collectCardReadableLists(cards []map[string]any) ([]any, []string) {
|
|
cardIDs := make([]any, 0, len(cards))
|
|
iccids := make([]string, 0, len(cards))
|
|
for _, card := range cards {
|
|
if id, ok := card["id"]; ok {
|
|
cardIDs = append(cardIDs, id)
|
|
}
|
|
if iccid := stringifyCardAuditValue(card["iccid"]); iccid != "" {
|
|
iccids = append(iccids, iccid)
|
|
}
|
|
}
|
|
return cardIDs, iccids
|
|
}
|
|
|
|
func stringifyCardAuditValue(v any) string {
|
|
switch vv := v.(type) {
|
|
case string:
|
|
return vv
|
|
case fmt.Stringer:
|
|
return vv.String()
|
|
default:
|
|
if vv == nil {
|
|
return ""
|
|
}
|
|
return fmt.Sprint(vv)
|
|
}
|
|
}
|
|
|
|
func cardSnapshot(card *model.IotCard) map[string]any {
|
|
if card == nil {
|
|
return nil
|
|
}
|
|
return map[string]any{
|
|
"id": card.ID,
|
|
"iccid": card.ICCID,
|
|
"device_virtual_no": card.DeviceVirtualNo,
|
|
"shop_id": card.ShopID,
|
|
"status": card.Status,
|
|
"series_id": card.SeriesID,
|
|
"enable_polling": card.EnablePolling,
|
|
"realname_policy": card.RealnamePolicy,
|
|
"real_name_status": card.RealNameStatus,
|
|
"network_status": card.NetworkStatus,
|
|
"stop_reason": card.StopReason,
|
|
}
|
|
}
|