merge: 合并代码20240706
This commit is contained in:
@@ -279,11 +279,7 @@ func PostCDREventFromSMF(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 推送到ws订阅组
|
||||
// if v, ok := cdrEvent.CDR["recordType"]; ok {
|
||||
// if v == "MOC" || v == "MTSM" {
|
||||
// wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_IMS_CDR, cdrEvent)
|
||||
// }
|
||||
// }
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_SMF_CDR, cdrEvent)
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
|
||||
@@ -3,7 +3,7 @@ package cm
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
|
||||
@@ -2,26 +2,35 @@ package event
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
wsService "be.ems/src/modules/ws/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
UriUEEvent = "/upload-ue/v1/:eventType"
|
||||
// 走Gin
|
||||
UriUEEventAMF = "/upload-ue/v1/:eventType"
|
||||
// 走Mux
|
||||
UriUEEvent = config.DefaultUriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
|
||||
CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
|
||||
)
|
||||
|
||||
type UEEvent struct {
|
||||
NeType string `json:"neType" xorm:"ne_type"`
|
||||
NeName string `json:"neName" xorm:"ne_name"`
|
||||
RmUID string `json:"rmUID" xorm:"rm_uid"`
|
||||
Timestamp int `json:"timestamp" xorm:"timestamp"`
|
||||
Timestamp int64 `json:"timestamp" xorm:"timestamp"`
|
||||
EventType string `json:"eventType" xorm:"event_type"`
|
||||
EventJson map[string]any `json:"eventJSON" xorm:"event_json"`
|
||||
}
|
||||
@@ -51,13 +60,13 @@ func PostUEEventFromAMF(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
ueEvent.NeType = "AMF"
|
||||
ueEvent.Timestamp = int(time.Now().Unix())
|
||||
ueEvent.Timestamp = time.Now().Unix()
|
||||
ueEvent.EventType = eventType
|
||||
log.Trace("ueEvent:", ueEvent)
|
||||
log.Trace("ueEvent AMF:", ueEvent)
|
||||
|
||||
affected, err := dborm.XormInsertTableOne("ue_event", ueEvent)
|
||||
affected, err := dborm.XormInsertTableOne("ue_event_amf", ueEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert ue_event:", err)
|
||||
log.Error("Failed to insert ue_event_amf:", err)
|
||||
services.ResponseInternalServerError500ProcessError(c.Writer, err)
|
||||
return
|
||||
}
|
||||
@@ -67,3 +76,30 @@ func PostUEEventFromAMF(c *gin.Context) {
|
||||
|
||||
services.ResponseStatusOK204NoContent(c.Writer)
|
||||
}
|
||||
|
||||
func PostUEEvent(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("PostUEEvent processing... ")
|
||||
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
var ueEvent UEEvent
|
||||
if err := ctx.ShouldBindJSON(r, &ueEvent); err != nil {
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
ueEvent.NeType = strings.ToUpper(neType)
|
||||
tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType))
|
||||
affected, err := dborm.XormInsertTableOne(tableName, ueEvent)
|
||||
if err != nil && affected <= 0 {
|
||||
log.Error("Failed to insert "+tableName, err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 推送到ws订阅组
|
||||
if ueEvent.NeType == "MME" {
|
||||
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_MME_UE, ueEvent)
|
||||
}
|
||||
|
||||
services.ResponseStatusOK204NoContent(w)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/file"
|
||||
"be.ems/lib/log"
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package fm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"be.ems/restagent/config"
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/go-gsm/ucp"
|
||||
)
|
||||
|
||||
func AlarmForwardBySMSC(alarmData *Alarm) error {
|
||||
opt := &ucp.Options{
|
||||
Addr: config.GetYamlConfig().Alarm.SMSC.Addr,
|
||||
User: config.GetYamlConfig().Alarm.SMSC.SystemID,
|
||||
Password: config.GetYamlConfig().Alarm.SMSC.Password,
|
||||
AccessCode: config.GetYamlConfig().Alarm.SMSC.SystemType,
|
||||
}
|
||||
|
||||
client := ucp.New(opt)
|
||||
if err := client.Connect(); err != nil {
|
||||
log.Error("Failed to connect:", err)
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
reader, _ := readline.New(">>> ")
|
||||
defer reader.Close()
|
||||
|
||||
for {
|
||||
fmt.Print(">>> ")
|
||||
lines, _ := reader.Readline()
|
||||
fields := strings.Fields(lines)
|
||||
|
||||
if len(fields) == 1 {
|
||||
// exit CLI
|
||||
if fields[0] == "exit" {
|
||||
return nil
|
||||
}
|
||||
// display help message
|
||||
if fields[0] == "help" {
|
||||
log.Trace("\n\tSend a 'message' to 'receiver' with a 'sender' mask\n\t>>> sender receiver message\n\n\tExit the cli\n\t>>> exit\n")
|
||||
}
|
||||
}
|
||||
|
||||
// sender receiver message...
|
||||
if len(fields) >= 3 {
|
||||
sender := fields[0]
|
||||
receiver := fields[1]
|
||||
message := strings.Join(fields[2:], " ")
|
||||
ids, err := client.Send(sender, receiver, message)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
log.Debug("%v", ids)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,8 @@ var (
|
||||
var (
|
||||
TIME_DELAY_AFTER_WRITE time.Duration = 200
|
||||
TIME_DEAD_LINE time.Duration = 10
|
||||
WIN_ROW_SIZE byte = 100
|
||||
WIN_COL_SIZE byte = 100
|
||||
WIN_ROW_SIZE int16 = 200
|
||||
WIN_COL_SIZE int16 = 120
|
||||
BUFFER_SIZE int = 65535
|
||||
)
|
||||
|
||||
@@ -118,9 +118,15 @@ func PostMML2ToNF(w http.ResponseWriter, r *http.Request) {
|
||||
// services.ResponseWithJson(w, http.StatusOK, response)
|
||||
// return
|
||||
// }
|
||||
|
||||
// 发送窗口大小设置命令
|
||||
conn.Write([]byte{255, 251, 31}) // 发送WILL WINDOW SIZE
|
||||
conn.Write([]byte{255, 250, 31, 0, WIN_ROW_SIZE, 0, WIN_COL_SIZE, 255, 240}) // 发送设置 WINDOW SIZE
|
||||
conn.Write([]byte{255, 251, 31}) // 发送WILL WINDOW SIZE
|
||||
conn.Write([]byte{
|
||||
255, 250, 31,
|
||||
byte(WIN_COL_SIZE >> 8), byte(WIN_COL_SIZE & 0xFF),
|
||||
byte(WIN_ROW_SIZE >> 8), byte(WIN_ROW_SIZE & 0xFF),
|
||||
255, 240,
|
||||
}) // 发送设置 WINDOW SIZE
|
||||
|
||||
conn.SetDeadline(time.Now().Add(TIME_DEAD_LINE * time.Second))
|
||||
loginStr := fmt.Sprintf("%s\n%s\n", config.GetYamlConfig().MML.User, config.GetYamlConfig().MML.Password)
|
||||
|
||||
@@ -8,12 +8,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/global"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/lib/services"
|
||||
"be.ems/restagent/config"
|
||||
tokenConst "be.ems/src/framework/constants/token"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
@@ -241,66 +243,38 @@ func GetSubscriptionsFromNSSF(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Get UEInfo from NF/NFs
|
||||
func GetUEInfoFromNF(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("GetUEInfoFromNF processing... ")
|
||||
log.Debug("GetUEInfoFromNF processing... ")
|
||||
|
||||
vars := mux.Vars(r)
|
||||
neType := vars["elementTypeValue"]
|
||||
if neType == "" {
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
//neTypeLower := strings.ToLower(neType)
|
||||
var neId string
|
||||
neIds := services.GetParamsArrByName("neId", r)
|
||||
if len(neIds) == 1 {
|
||||
neId = neIds[0]
|
||||
} else {
|
||||
neId := ctx.GetQuery(r, "neId")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
if neType == "" || neId == "" {
|
||||
log.Error("elementTypeValue/neId is empty")
|
||||
services.ResponseNotFound404UriNotExist(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// token, err := services.CheckFrontValidRequest(w, r)
|
||||
// if err != nil {
|
||||
// log.Error("Request error:", err)
|
||||
// return
|
||||
// }
|
||||
// log.Debug("token:", token)
|
||||
neInfo := neService.NewNeInfoImpl.SelectNeInfoByNeTypeAndNeID(neType, neId)
|
||||
|
||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
||||
if err != nil {
|
||||
log.Error("Failed to XormGetNeInfo:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else if neInfo == nil {
|
||||
err := global.ErrCMNotFoundTargetNE
|
||||
log.Error(global.ErrCMNotFoundTargetNE)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
var response services.MapResponse
|
||||
if neInfo.NeId == neId && neInfo.NeId != "" {
|
||||
requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.Port, r.RequestURI)
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Failed to Get from NF:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
}
|
||||
log.Debug("response:", response)
|
||||
}
|
||||
log.Trace("neInfo:", neInfo)
|
||||
|
||||
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
|
||||
requestURI2NF := fmt.Sprintf("%s%s", hostUri, r.RequestURI)
|
||||
|
||||
log.Debug("requestURI2NF:", requestURI2NF)
|
||||
|
||||
resp, err := client.R().
|
||||
EnableTrace().
|
||||
SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
|
||||
// SetHeaders(map[string]string{"accessToken": token}).
|
||||
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
|
||||
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
|
||||
Get(requestURI2NF)
|
||||
if err != nil {
|
||||
log.Error("Get system state from NF is failed:", err)
|
||||
services.ResponseInternalServerError500ProcessError(w, err)
|
||||
return
|
||||
} else {
|
||||
var response services.MapResponse
|
||||
_ = json.Unmarshal(resp.Body(), &response)
|
||||
services.ResponseWithJson(w, resp.StatusCode(), response)
|
||||
return
|
||||
}
|
||||
services.ResponseWithJson(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// POST User Info from NF/NFs
|
||||
|
||||
15
go.mod
15
go.mod
@@ -5,12 +5,10 @@ go 1.21
|
||||
toolchain go1.21.0
|
||||
|
||||
require (
|
||||
github.com/chzyer/readline v1.5.1
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/dlclark/regexp2 v1.10.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-admin-team/go-admin-core/sdk v1.5.1
|
||||
github.com/go-gsm/ucp v0.0.1
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
||||
@@ -46,11 +44,14 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/creack/pty v1.1.9 // indirect
|
||||
github.com/go-admin-team/go-admin-core v1.3.12-0.20221121065133-27b7dbe27a8f // indirect
|
||||
github.com/go-gsm/charset v1.0.0 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/time v0.1.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -62,6 +63,7 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect
|
||||
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd // indirect
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
@@ -112,7 +114,9 @@ require (
|
||||
github.com/nyaruka/phonenumbers v1.0.55 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.6
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/reiver/go-oi v1.0.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.3 // indirect
|
||||
@@ -139,10 +143,9 @@ require (
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/tools v0.16.1 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
45
go.sum
45
go.sum
@@ -65,6 +65,7 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
|
||||
@@ -92,18 +93,14 @@ github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973/go.mod h1:9+sJ9zv
|
||||
github.com/chanxuehong/util v0.0.0-20200304121633-ca8141845b13/go.mod h1:XEYt99iTxMqkv+gW85JX/DdUINHUe43Sbe5AtqSaDAQ=
|
||||
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd h1:TM3wjEWel4U31J72dlhnwCBqPC0+FA0Ejm2NCbn5a5U=
|
||||
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd/go.mod h1:/dvhOIRCjjiZu6NV0QTTiMcc5XwoORbxfDSsRY2IfaM=
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a h1:yTfhjWYoPomJkHVArtNHpo36FuOa6Kc2ZjTLvyyQ5Lg=
|
||||
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a/go.mod h1:lINNCb1ZH3c0uL/9ApaQ8muR4QILsi0STj8Ojt8ZmwU=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
@@ -179,10 +176,6 @@ github.com/go-forks/fsnotify v1.4.7/go.mod h1:AU8mot+GznW5+B4jRJHxKg/2EeO+jMORGR
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gsm/charset v1.0.0 h1:6k6LOKHtxgCPXE15X0unRewjOksyhmHBIp6x7qLQ6Ls=
|
||||
github.com/go-gsm/charset v1.0.0/go.mod h1:sC8+2VpAM2sZDlxv11MxWIZiuf8MipOgM/hCYsRQRps=
|
||||
github.com/go-gsm/ucp v0.0.1 h1:vM5ly5iRNGMGGiVx4K3+puF9AhpwkC76BkiV9LFv0bw=
|
||||
github.com/go-gsm/ucp v0.0.1/go.mod h1:58/PrXWFcmaQyZ5p/Dp2YiCnhlVx0HdKXFGmqiVO/mI=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
@@ -278,8 +271,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -435,10 +429,10 @@ github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZX
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -585,6 +579,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
@@ -596,18 +592,26 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
|
||||
github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
|
||||
@@ -626,8 +630,8 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
@@ -780,6 +784,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
@@ -827,7 +832,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -868,6 +872,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
@@ -959,11 +964,11 @@ golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -974,6 +979,7 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
@@ -986,6 +992,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
@@ -994,8 +1001,6 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -1162,8 +1167,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.5 h1:QoEEmn/d5BbuPIL2qvXwzJdttFFhRQFkaq+tEKb7SMI=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.5/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package cachekey
|
||||
|
||||
// 缓存的key常量
|
||||
|
||||
// 登录用户
|
||||
const LOGIN_TOKEN_KEY = "login_tokens:"
|
||||
|
||||
// 验证码
|
||||
const CAPTCHA_CODE_KEY = "captcha_codes:"
|
||||
|
||||
// 参数管理
|
||||
const SYS_CONFIG_KEY = "sys_config:"
|
||||
|
||||
// 字典管理
|
||||
const SYS_DICT_KEY = "sys_dict:"
|
||||
|
||||
// 防重提交
|
||||
const REPEAT_SUBMIT_KEY = "repeat_submit:"
|
||||
|
||||
// 限流
|
||||
const RATE_LIMIT_KEY = "rate_limit:"
|
||||
|
||||
// 登录账户密码错误次数
|
||||
const PWD_ERR_CNT_KEY = "pwd_err_cnt:"
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Param 地址栏参数{id}
|
||||
func Param(r *http.Request, key string) string {
|
||||
// GetParam 地址栏参数{id}
|
||||
func GetParam(r *http.Request, key string) string {
|
||||
vars := mux.Vars(r)
|
||||
v, ok := vars[key]
|
||||
if ok {
|
||||
@@ -47,7 +47,7 @@ func QueryMap(r *http.Request) map[string]any {
|
||||
return queryParams
|
||||
}
|
||||
|
||||
// ShouldBindQuery 查询参数读取json请求结构团体
|
||||
// ShouldBindQuery 查询参数读取json请求结构团体 &xxx
|
||||
func ShouldBindQuery(r *http.Request, args any) error {
|
||||
queryParams := QueryMap(r)
|
||||
body, err := json.Marshal(queryParams)
|
||||
@@ -57,7 +57,7 @@ func ShouldBindQuery(r *http.Request, args any) error {
|
||||
return json.Unmarshal(body, args)
|
||||
}
|
||||
|
||||
// 读取json请求结构团体
|
||||
// ShouldBindJSON 读取json请求结构团体 &xxx
|
||||
func ShouldBindJSON(r *http.Request, args any) error {
|
||||
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) // 设置较大的长度,例如 1<<20 (1MB)
|
||||
if err != nil {
|
||||
@@ -1,49 +0,0 @@
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"regexp"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// 获取默认数据源
|
||||
func DefaultDB() *xorm.Engine {
|
||||
return dborm.DbClient.XEngine
|
||||
}
|
||||
|
||||
// RawDB 原生查询语句
|
||||
func RawDB(source string, sql string, parameters []any) ([]map[string]any, error) {
|
||||
// 数据源
|
||||
db := DefaultDB()
|
||||
|
||||
// 使用正则表达式替换连续的空白字符为单个空格
|
||||
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
||||
|
||||
// log.Infof("sql=> %v", fmtSql)
|
||||
// log.Infof("parameters=> %v", parameters)
|
||||
|
||||
// 查询结果
|
||||
var rows []map[string]any
|
||||
err := db.SQL(fmtSql, parameters...).Find(&rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// ExecDB 原生执行语句
|
||||
func ExecDB(source string, sql string, parameters []any) (sql.Result, error) {
|
||||
// 数据源
|
||||
db := DefaultDB()
|
||||
|
||||
// 使用正则表达式替换连续的空白字符为单个空格
|
||||
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
||||
// 执行结果
|
||||
res, err := db.Exec(append([]any{fmtSql}, parameters...)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package datasource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PageNumSize 分页页码记录数
|
||||
func PageNumSize(pageNum, pageSize any) (int, int) {
|
||||
// 记录起始索引
|
||||
pageNumStr := fmt.Sprintf("%v", pageNum)
|
||||
num := 1
|
||||
if v, err := strconv.Atoi(pageNumStr); err == nil && v > 0 {
|
||||
num = v
|
||||
}
|
||||
|
||||
// 显示记录数
|
||||
pageSizeStr := fmt.Sprintf("%v", pageSize)
|
||||
size := 10
|
||||
if v, err := strconv.Atoi(pageSizeStr); err == nil && v > 0 {
|
||||
size = v
|
||||
}
|
||||
return num - 1, size
|
||||
}
|
||||
|
||||
// SetFieldValue 判断结构体内是否存在指定字段并设置值
|
||||
func SetFieldValue(obj any, fieldName string, value any) {
|
||||
// 获取结构体的反射值
|
||||
userValue := reflect.ValueOf(obj)
|
||||
|
||||
// 获取字段的反射值
|
||||
fieldValue := userValue.Elem().FieldByName(fieldName)
|
||||
|
||||
// 检查字段是否存在
|
||||
if fieldValue.IsValid() && fieldValue.CanSet() {
|
||||
// 获取字段的类型
|
||||
fieldType := fieldValue.Type()
|
||||
|
||||
// 转换传入的值类型为字段类型
|
||||
switch fieldType.Kind() {
|
||||
case reflect.String:
|
||||
if value == nil {
|
||||
fieldValue.SetString("")
|
||||
} else {
|
||||
fieldValue.SetString(fmt.Sprintf("%v", value))
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
intValue, err := strconv.ParseInt(fmt.Sprintf("%v", value), 10, 64)
|
||||
if err != nil {
|
||||
intValue = 0
|
||||
}
|
||||
fieldValue.SetInt(intValue)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
uintValue, err := strconv.ParseUint(fmt.Sprintf("%v", value), 10, 64)
|
||||
if err != nil {
|
||||
uintValue = 0
|
||||
}
|
||||
fieldValue.SetUint(uintValue)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
floatValue, err := strconv.ParseFloat(fmt.Sprintf("%v", value), 64)
|
||||
if err != nil {
|
||||
floatValue = 0
|
||||
}
|
||||
fieldValue.SetFloat(floatValue)
|
||||
default:
|
||||
// 设置字段的值
|
||||
fieldValue.Set(reflect.ValueOf(value).Convert(fieldValue.Type()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertIdsSlice 将 []string 转换为 []any
|
||||
func ConvertIdsSlice(ids []string) []any {
|
||||
// 将 []string 转换为 []any
|
||||
arr := make([]any, len(ids))
|
||||
for i, v := range ids {
|
||||
arr[i] = v
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// 查询-参数值的占位符
|
||||
func KeyPlaceholderByQuery(sum int) string {
|
||||
placeholders := make([]string, sum)
|
||||
for i := 0; i < sum; i++ {
|
||||
placeholders[i] = "?"
|
||||
}
|
||||
return strings.Join(placeholders, ",")
|
||||
}
|
||||
|
||||
// 插入-参数映射键值占位符 keys, placeholder, values
|
||||
func KeyPlaceholderValueByInsert(params map[string]any) ([]string, string, []any) {
|
||||
// 参数映射的键
|
||||
keys := make([]string, len(params))
|
||||
// 参数映射的值
|
||||
values := make([]any, len(params))
|
||||
sum := 0
|
||||
for k, v := range params {
|
||||
keys[sum] = k
|
||||
values[sum] = v
|
||||
sum++
|
||||
}
|
||||
// 参数值的占位符
|
||||
placeholders := make([]string, sum)
|
||||
for i := 0; i < sum; i++ {
|
||||
placeholders[i] = "?"
|
||||
}
|
||||
return keys, strings.Join(placeholders, ","), values
|
||||
}
|
||||
|
||||
// 更新-参数映射键值占位符 keys, values
|
||||
func KeyValueByUpdate(params map[string]any) ([]string, []any) {
|
||||
// 参数映射的键
|
||||
keys := make([]string, len(params))
|
||||
// 参数映射的值
|
||||
values := make([]any, len(params))
|
||||
sum := 0
|
||||
for k, v := range params {
|
||||
keys[sum] = k + "=?"
|
||||
values[sum] = v
|
||||
sum++
|
||||
}
|
||||
return keys, values
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package mmlclient
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/conf"
|
||||
)
|
||||
|
||||
// 定义MMLClient结构体
|
||||
type MMLClient struct {
|
||||
awaitTime time.Duration // 等待时间
|
||||
conn net.Conn
|
||||
reader *bufio.Reader
|
||||
size int // 包含字符
|
||||
}
|
||||
|
||||
// 封装NewMMLClient函数,用于创建MMLClient实例
|
||||
// 网元UDM的IP地址 "198.51.100.1"
|
||||
func NewMMLClient(ip string) (*MMLClient, error) {
|
||||
// 创建TCP连接
|
||||
portMML := conf.Get("mml.port").(int)
|
||||
hostMML := fmt.Sprintf("%s:%d", ip, portMML)
|
||||
conn, err := net.Dial("tcp", hostMML)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 进行登录
|
||||
usernameMML := conf.Get("mml.user").(string)
|
||||
passwordMML := conf.Get("mml.password").(string)
|
||||
fmt.Fprintln(conn, usernameMML)
|
||||
fmt.Fprintln(conn, passwordMML)
|
||||
|
||||
// 发送后等待
|
||||
awaitTime := time.Duration(300) * time.Millisecond
|
||||
time.Sleep(awaitTime)
|
||||
|
||||
// 读取内容
|
||||
buf := make([]byte, 1024*1024*1)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建MMLClient实例
|
||||
client := &MMLClient{
|
||||
conn: conn,
|
||||
reader: bufio.NewReader(conn),
|
||||
awaitTime: awaitTime,
|
||||
size: n,
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// 封装Send函数,用于向TCP连接发送数据
|
||||
func (c *MMLClient) Send(msg string) error {
|
||||
_, err := fmt.Fprintln(c.conn, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(c.awaitTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 封装Receive函数,用于从TCP连接中接收数据
|
||||
func (c *MMLClient) Receive() (string, error) {
|
||||
buf := make([]byte, 1024*1024*1)
|
||||
n, err := c.reader.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return "", fmt.Errorf("server closed the connection")
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
c.size += n
|
||||
return string(buf[0:n]), nil
|
||||
}
|
||||
|
||||
// 封装Close函数,用于关闭TCP连接
|
||||
func (c *MMLClient) Close() error {
|
||||
return c.conn.Close()
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package mmlclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 发送MML原始消息
|
||||
// ip 网元IP地址
|
||||
// msg 指令
|
||||
func MMLSendMsg(ip, msg string) (string, error) {
|
||||
// 创建MMLClient实例
|
||||
client, err := NewMMLClient(ip)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create MMLClient instance: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 发送数据
|
||||
err = client.Send(msg)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("sending data failed: %v", err)
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
data, err := client.Receive()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to receive data: %v", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 发送MML
|
||||
// ip 网元IP地址
|
||||
// msg 指令
|
||||
func MMLSendMsgToString(ip, msg string) (string, error) {
|
||||
// 发送获取数据
|
||||
str, err := MMLSendMsg(ip, msg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
str = strings.ToLower(str)
|
||||
|
||||
// 截断
|
||||
index := strings.Index(str, "\n")
|
||||
if index != -1 {
|
||||
str = str[:index]
|
||||
}
|
||||
|
||||
// 命令成功
|
||||
if strings.Contains(str, "ok") || strings.Contains(str, "success") {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf(str)
|
||||
}
|
||||
|
||||
// 发送MML
|
||||
// ip 网元IP地址
|
||||
// msg 指令
|
||||
func MMLSendMsgToMap(ip, msg string) (map[string]string, error) {
|
||||
// 发送获取数据
|
||||
str, err := MMLSendMsg(ip, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 无数据
|
||||
if strings.HasPrefix(str, "No Auth Data") {
|
||||
return nil, fmt.Errorf("no auth data")
|
||||
}
|
||||
|
||||
// 初始化一个map用于存储拆分后的键值对
|
||||
m := make(map[string]string)
|
||||
|
||||
var items []string
|
||||
if strings.Contains(str, "\r\n") {
|
||||
// 按照分隔符"\r\n"进行拆分
|
||||
items = strings.Split(str, "\r\n")
|
||||
} else if strings.Contains(str, "\n") {
|
||||
// 按照分隔符"\n"进行拆分
|
||||
items = strings.Split(str, "\n")
|
||||
}
|
||||
|
||||
// 遍历拆分后的结果
|
||||
for _, item := range items {
|
||||
var pair []string
|
||||
|
||||
if strings.Contains(item, "=") {
|
||||
// 按照分隔符"="进行拆分键值对
|
||||
pair = strings.SplitN(item, "=", 2)
|
||||
} else if strings.Contains(item, ":") {
|
||||
// 按照分隔符":"进行拆分键值对
|
||||
pair = strings.SplitN(item, ":", 2)
|
||||
}
|
||||
|
||||
if len(pair) == 2 {
|
||||
// 将键值对存入map中
|
||||
m[pair[0]] = pair[1]
|
||||
}
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package date
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/log"
|
||||
)
|
||||
|
||||
const (
|
||||
// 年 列如:2022
|
||||
YYYY = "2006"
|
||||
// 年-月 列如:2022-12
|
||||
YYYY_MM = "2006-01"
|
||||
// 年-月-日 列如:2022-12-30
|
||||
YYYY_MM_DD = "2006-01-02"
|
||||
// 年月日时分秒 列如:20221230010159
|
||||
YYYYMMDDHHMMSS = "20060102150405"
|
||||
// 年-月-日 时:分:秒 列如:2022-12-30 01:01:59
|
||||
YYYY_MM_DD_HH_MM_SS = "2006-01-02 15:04:05"
|
||||
)
|
||||
|
||||
// 格式时间字符串
|
||||
//
|
||||
// dateStr 时间字符串
|
||||
//
|
||||
// formatStr 时间格式 默认YYYY-MM-DD HH:mm:ss
|
||||
func ParseStrToDate(dateStr, formatStr string) time.Time {
|
||||
t, err := time.Parse(formatStr, dateStr)
|
||||
if err != nil {
|
||||
log.Infof("utils ParseStrToDate err %v", err)
|
||||
return time.Time{}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// 格式时间
|
||||
//
|
||||
// date 可转的Date对象
|
||||
//
|
||||
// formatStr 时间格式 默认YYYY-MM-DD HH:mm:ss
|
||||
func ParseDateToStr(date any, formatStr string) string {
|
||||
t, ok := date.(time.Time)
|
||||
if !ok {
|
||||
switch v := date.(type) {
|
||||
case int64:
|
||||
if v == 0 {
|
||||
return ""
|
||||
}
|
||||
t = time.UnixMilli(v)
|
||||
case string:
|
||||
parsedTime, err := time.Parse(formatStr, v)
|
||||
if err != nil {
|
||||
fmt.Printf("utils ParseDateToStr err %v \n", err)
|
||||
return ""
|
||||
}
|
||||
t = parsedTime
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return t.Format(formatStr)
|
||||
}
|
||||
|
||||
// 格式时间成日期路径
|
||||
//
|
||||
// 年/月 列如:2022/12
|
||||
func ParseDatePath(date time.Time) string {
|
||||
return date.Format("2006/01")
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
// Number 解析数值型
|
||||
func Number(str any) int64 {
|
||||
switch str := str.(type) {
|
||||
case string:
|
||||
if str == "" {
|
||||
return 0
|
||||
}
|
||||
num, err := strconv.ParseInt(str, 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return num
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||
return reflect.ValueOf(str).Int()
|
||||
case float32, float64:
|
||||
return int64(reflect.ValueOf(str).Float())
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// Boolean 解析布尔型
|
||||
func Boolean(str any) bool {
|
||||
switch str := str.(type) {
|
||||
case string:
|
||||
if str == "" || str == "false" || str == "0" {
|
||||
return false
|
||||
}
|
||||
// 尝试将字符串解析为数字
|
||||
if num, err := strconv.ParseFloat(str, 64); err == nil {
|
||||
return num != 0
|
||||
}
|
||||
return true
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||
num := reflect.ValueOf(str).Int()
|
||||
return num != 0
|
||||
case float32, float64:
|
||||
num := reflect.ValueOf(str).Float()
|
||||
return num != 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// FirstUpper 首字母转大写
|
||||
//
|
||||
// 字符串 abc_123!@# 结果 Abc_123
|
||||
func FirstUpper(str string) string {
|
||||
if len(str) == 0 {
|
||||
return str
|
||||
}
|
||||
reg := regexp.MustCompile(`[^_\w]+`)
|
||||
str = reg.ReplaceAllString(str, "")
|
||||
return strings.ToUpper(str[:1]) + str[1:]
|
||||
}
|
||||
|
||||
// Bit 比特位为单位
|
||||
func Bit(bit float64) string {
|
||||
var GB, MB, KB string
|
||||
|
||||
if bit > float64(1<<30) {
|
||||
GB = fmt.Sprintf("%0.2f", bit/(1<<30))
|
||||
}
|
||||
|
||||
if bit > float64(1<<20) && bit < (1<<30) {
|
||||
MB = fmt.Sprintf("%.2f", bit/(1<<20))
|
||||
}
|
||||
|
||||
if bit > float64(1<<10) && bit < (1<<20) {
|
||||
KB = fmt.Sprintf("%.2f", bit/(1<<10))
|
||||
}
|
||||
|
||||
if GB != "" {
|
||||
return GB + "GB"
|
||||
} else if MB != "" {
|
||||
return MB + "MB"
|
||||
} else if KB != "" {
|
||||
return KB + "KB"
|
||||
} else {
|
||||
return fmt.Sprintf("%vB", bit)
|
||||
}
|
||||
}
|
||||
|
||||
// CronExpression 解析 Cron 表达式,返回下一次执行的时间戳(毫秒)
|
||||
//
|
||||
// 【*/5 * * * * ?】 6个参数
|
||||
func CronExpression(expression string) int64 {
|
||||
specParser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
|
||||
schedule, err := specParser.Parse(expression)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 0
|
||||
}
|
||||
return schedule.Next(time.Now()).UnixMilli()
|
||||
}
|
||||
|
||||
// SafeContent 内容值进行安全掩码
|
||||
func SafeContent(value string) string {
|
||||
if len(value) < 3 {
|
||||
return strings.Repeat("*", len(value))
|
||||
} else if len(value) < 6 {
|
||||
return string(value[0]) + strings.Repeat("*", len(value)-1)
|
||||
} else if len(value) < 10 {
|
||||
return string(value[0]) + strings.Repeat("*", len(value)-2) + string(value[len(value)-1])
|
||||
} else if len(value) < 15 {
|
||||
return value[:2] + strings.Repeat("*", len(value)-4) + value[len(value)-2:]
|
||||
} else {
|
||||
return value[:3] + strings.Repeat("*", len(value)-6) + value[len(value)-3:]
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveDuplicates 数组内字符串去重
|
||||
func RemoveDuplicates(ids []string) []string {
|
||||
uniqueIDs := make(map[string]bool)
|
||||
uniqueIDSlice := make([]string, 0)
|
||||
|
||||
for _, id := range ids {
|
||||
_, ok := uniqueIDs[id]
|
||||
if !ok && id != "" {
|
||||
uniqueIDs[id] = true
|
||||
uniqueIDSlice = append(uniqueIDSlice, id)
|
||||
}
|
||||
}
|
||||
|
||||
return uniqueIDSlice
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package regular
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Replace 正则替换
|
||||
func Replace(originStr, pattern, repStr string) string {
|
||||
regex := regexp.MustCompile(pattern)
|
||||
return regex.ReplaceAllString(originStr, repStr)
|
||||
}
|
||||
|
||||
// 判断是否为有效用户名格式
|
||||
//
|
||||
// 用户名不能以数字开头,可包含大写小写字母,数字,且不少于5位
|
||||
func ValidUsername(username string) bool {
|
||||
if username == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^[a-zA-Z][a-z0-9A-Z]{5,}`
|
||||
match, err := regexp.MatchString(pattern, username)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
// 判断是否为有效手机号格式,1开头的11位手机号
|
||||
func ValidMobile(mobile string) bool {
|
||||
if mobile == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^1[3|4|5|6|7|8|9][0-9]\d{8}$`
|
||||
match, err := regexp.MatchString(pattern, mobile)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
// 判断是否为http(s)://开头
|
||||
//
|
||||
// link 网络链接
|
||||
func ValidHttp(link string) bool {
|
||||
if link == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^http(s)?:\/\/+`
|
||||
match, err := regexp.MatchString(pattern, link)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ScanPort(port int) bool {
|
||||
ln, err := net.Listen("tcp", ":"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
defer ln.Close()
|
||||
return false
|
||||
}
|
||||
|
||||
func ScanUDPPort(port int) bool {
|
||||
ln, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: port})
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
defer ln.Close()
|
||||
return false
|
||||
}
|
||||
|
||||
func ScanPortWithProto(port int, proto string) bool {
|
||||
if proto == "udp" {
|
||||
return ScanUDPPort(port)
|
||||
}
|
||||
return ScanPort(port)
|
||||
}
|
||||
@@ -23,6 +23,4 @@ type LoginUser struct {
|
||||
|
||||
// User 用户信息
|
||||
User dborm.User `json:"user"`
|
||||
|
||||
Session dborm.Session `json:"-"`
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package vo
|
||||
|
||||
// Router 路由信息对象
|
||||
type Router struct {
|
||||
// 路由名字 英文首字母大写
|
||||
Name string `json:"name"`
|
||||
// 路由地址
|
||||
Path string `json:"path"`
|
||||
// 其他元素
|
||||
Meta RouterMeta `json:"meta"`
|
||||
// 组件地址
|
||||
Component string `json:"component"`
|
||||
// 重定向地址
|
||||
Redirect string `json:"redirect"`
|
||||
// 子路由
|
||||
Children []Router `json:"children,omitempty"`
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package vo
|
||||
|
||||
// RouterMeta 路由元信息对象
|
||||
type RouterMeta struct {
|
||||
// 设置该菜单在侧边栏和面包屑中展示的名字
|
||||
Title string `json:"title"`
|
||||
// 设置该菜单的图标
|
||||
Icon string `json:"icon"`
|
||||
// 设置为true,则不会被 <keep-alive>缓存
|
||||
Cache bool `json:"cache"`
|
||||
// 内链地址(http(s)://开头), 打开目标位置 '_blank' | '_self' | ''
|
||||
Target string `json:"target"`
|
||||
// 在菜单中隐藏子节点
|
||||
HideChildInMenu bool `json:"hideChildInMenu"`
|
||||
// 在菜单中隐藏自己和子节点
|
||||
HideInMenu bool `json:"hideInMenu"`
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package vo
|
||||
|
||||
// import sysmenu "be.ems/features/sys_menu"
|
||||
|
||||
// TreeSelect 树结构实体类
|
||||
type TreeSelect struct {
|
||||
// ID 节点ID
|
||||
ID string `json:"id"`
|
||||
|
||||
// Label 节点名称
|
||||
Label string `json:"label"`
|
||||
|
||||
// Title 节点名称旧版本layui
|
||||
Title string `json:"title"`
|
||||
|
||||
// Children 子节点
|
||||
Children []TreeSelect `json:"children"`
|
||||
}
|
||||
|
||||
// // SysMenuTreeSelect 使用给定的 SysMenu 对象解析为 TreeSelect 对象
|
||||
// func SysMenuTreeSelect(sysMenu sysmenu.SysMenu) TreeSelect {
|
||||
// t := TreeSelect{}
|
||||
// t.ID = sysMenu.MenuID
|
||||
// t.Label = sysMenu.MenuName
|
||||
|
||||
// if len(sysMenu.Children) > 0 {
|
||||
// for _, menu := range sysMenu.Children {
|
||||
// child := SysMenuTreeSelect(menu)
|
||||
// t.Children = append(t.Children, child)
|
||||
// }
|
||||
// } else {
|
||||
// t.Children = []TreeSelect{}
|
||||
// }
|
||||
|
||||
// return t
|
||||
// }
|
||||
@@ -1,78 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/services"
|
||||
)
|
||||
|
||||
// 已禁用
|
||||
// 登录策略限制登录时间和访问ip范围
|
||||
func ArrowIPAddr(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
|
||||
// 读取配置信息 登录策略设置
|
||||
result, err := dborm.XormGetConfig("Security", "loginSecurity")
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
data := make(map[string]any)
|
||||
err = json.Unmarshal([]byte(result["value_json"].(string)), &data)
|
||||
if err != nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 开关
|
||||
switchStr := data["switch"].(string)
|
||||
if switchStr == "0" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ipRange := data["ipRange"].(string)
|
||||
logintimeRange := data["logintime_range"].(string)
|
||||
|
||||
// 检查ip
|
||||
ips := strings.Split(ipRange, "/")
|
||||
hasIP := false
|
||||
for _, ip := range ips {
|
||||
if ipAddr == ip {
|
||||
hasIP = true
|
||||
}
|
||||
}
|
||||
if !hasIP {
|
||||
services.ResponseErrorWithJson(w, 502, "网关登录策略-IP限制: "+ipAddr)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查开放时间
|
||||
logintimeRangeArr := strings.Split(logintimeRange, " - ")
|
||||
|
||||
// 加载中国时区
|
||||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
// 获取当前时间
|
||||
currentTime := time.Now().In(loc)
|
||||
|
||||
// 获取当前日期
|
||||
currentDate := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, currentTime.Location())
|
||||
ymd := currentDate.Format("2006-01-02")
|
||||
|
||||
// 定义开始时间和结束时间
|
||||
startTime, _ := time.ParseInLocation("2006-01-02 15:04:05", ymd+" "+logintimeRangeArr[0], loc)
|
||||
endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", ymd+" "+logintimeRangeArr[1], loc)
|
||||
|
||||
// 判断当前时间是否在范围内
|
||||
if currentTime.After(startTime) && currentTime.Before(endTime) {
|
||||
next.ServeHTTP(w, r)
|
||||
} else {
|
||||
services.ResponseErrorWithJson(w, 502, "网关登录策略-不在开放时间范围内")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"be.ems/lib/core/cache"
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/vo"
|
||||
"be.ems/lib/core/vo/result"
|
||||
"be.ems/lib/dborm"
|
||||
commonConstants "be.ems/src/framework/constants/common"
|
||||
tokenUtils "be.ems/src/framework/utils/token"
|
||||
)
|
||||
|
||||
// 已禁用由Gin部分接管
|
||||
// Authorize 用户身份授权认证校验
|
||||
//
|
||||
// 只需含有其中角色 "hasRoles": {"xxx"},
|
||||
//
|
||||
// 只需含有其中权限 "hasPerms": {"xxx"},
|
||||
//
|
||||
// 同时匹配其中角色 "matchRoles": {"xxx"},
|
||||
//
|
||||
// 同时匹配其中权限 "matchPerms": {"xxx"},
|
||||
func Authorize(options map[string][]string) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取请求头标识信息
|
||||
tokenStr := ctx.Authorization(r)
|
||||
// 获取请求头标识信息-旧头
|
||||
accessToken := r.Header.Get("AccessToken")
|
||||
if tokenStr == "" && accessToken != "" {
|
||||
// 验证令牌 == 这里直接查数据库session
|
||||
if !dborm.XormExistValidToken(accessToken, 0) {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization valid error"))
|
||||
return
|
||||
}
|
||||
se, err := dborm.XormUpdateSessionShakeTime(accessToken)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization shake error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
data, ok := cache.GetLocalTTL(se.AccountId)
|
||||
if data == nil || !ok {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization info error"))
|
||||
return
|
||||
}
|
||||
loginUser := data.(vo.LoginUser)
|
||||
|
||||
// 登录用户角色权限校验
|
||||
if options != nil {
|
||||
var roles []string
|
||||
for _, item := range loginUser.User.Roles {
|
||||
roles = append(roles, item.RoleKey)
|
||||
}
|
||||
perms := loginUser.Permissions
|
||||
verifyOk := verifyRolePermission(roles, perms, options)
|
||||
if !verifyOk {
|
||||
msg := fmt.Sprintf("Unauthorized access %s %s", r.Method, r.RequestURI)
|
||||
ctx.JSON(w, 403, result.CodeMsg(403, msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 在请求的 Context 中存储数据
|
||||
rContext := r.Context()
|
||||
rContext = context.WithValue(rContext, ctx.ContextKey(commonConstants.CTX_LOGIN_USER), loginUser)
|
||||
// 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(rContext))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求头标识信息
|
||||
if tokenStr == "" {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization token error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证令牌
|
||||
claims, err := tokenUtils.Verify(tokenStr)
|
||||
if err != nil {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization valid error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 获取缓存的用户信息
|
||||
loginUser := tokenUtils.LoginUser(claims)
|
||||
if loginUser.UserID == "" {
|
||||
ctx.JSON(w, 401, result.CodeMsg(401, "Invalid identity authorization shake error"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查刷新有效期后存入上下文
|
||||
tokenUtils.RefreshIn(&loginUser)
|
||||
|
||||
// 登录用户角色权限校验
|
||||
if options != nil {
|
||||
var roles []string
|
||||
for _, item := range loginUser.User.Roles {
|
||||
roles = append(roles, item.RoleKey)
|
||||
}
|
||||
perms := loginUser.Permissions
|
||||
verifyOk := verifyRolePermission(roles, perms, options)
|
||||
if !verifyOk {
|
||||
msg := fmt.Sprintf("Unauthorized access %s %s", r.Method, r.RequestURI)
|
||||
ctx.JSON(w, 403, result.CodeMsg(403, msg))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 在请求的 Context 中存储数据
|
||||
rContext := r.Context()
|
||||
rContext = context.WithValue(rContext, ctx.ContextKey(commonConstants.CTX_LOGIN_USER), loginUser)
|
||||
// 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(rContext))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// verifyRolePermission 校验角色权限是否满足
|
||||
//
|
||||
// roles 角色字符数组
|
||||
//
|
||||
// perms 权限字符数组
|
||||
//
|
||||
// options 参数
|
||||
func verifyRolePermission(roles, perms []string, options map[string][]string) bool {
|
||||
// 直接放行 管理员角色或任意权限
|
||||
if contains(roles, "admin") || contains(perms, "*:*:*") {
|
||||
return true
|
||||
}
|
||||
opts := make([]bool, 4)
|
||||
|
||||
// 只需含有其中角色
|
||||
hasRole := false
|
||||
if arr, ok := options["hasRoles"]; ok && len(arr) > 0 {
|
||||
hasRole = some(roles, arr)
|
||||
opts[0] = true
|
||||
}
|
||||
|
||||
// 只需含有其中权限
|
||||
hasPerms := false
|
||||
if arr, ok := options["hasPerms"]; ok && len(arr) > 0 {
|
||||
hasPerms = some(perms, arr)
|
||||
opts[1] = true
|
||||
}
|
||||
|
||||
// 同时匹配其中角色
|
||||
matchRoles := false
|
||||
if arr, ok := options["matchRoles"]; ok && len(arr) > 0 {
|
||||
matchRoles = every(roles, arr)
|
||||
opts[2] = true
|
||||
}
|
||||
|
||||
// 同时匹配其中权限
|
||||
matchPerms := false
|
||||
if arr, ok := options["matchPerms"]; ok && len(arr) > 0 {
|
||||
matchPerms = every(perms, arr)
|
||||
opts[3] = true
|
||||
}
|
||||
|
||||
// 同时判断 含有其中
|
||||
if opts[0] && opts[1] {
|
||||
return hasRole || hasPerms
|
||||
}
|
||||
// 同时判断 匹配其中
|
||||
if opts[2] && opts[3] {
|
||||
return matchRoles && matchPerms
|
||||
}
|
||||
// 同时判断 含有其中且匹配其中
|
||||
if opts[0] && opts[3] {
|
||||
return hasRole && matchPerms
|
||||
}
|
||||
if opts[1] && opts[2] {
|
||||
return hasPerms && matchRoles
|
||||
}
|
||||
|
||||
return hasRole || hasPerms || matchRoles || matchPerms
|
||||
}
|
||||
|
||||
// contains 检查字符串数组中是否包含指定的字符串
|
||||
func contains(arr []string, target string) bool {
|
||||
for _, str := range arr {
|
||||
if str == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// some 检查字符串数组中含有其中一项
|
||||
func some(origin []string, target []string) bool {
|
||||
has := false
|
||||
for _, t := range target {
|
||||
for _, o := range origin {
|
||||
if t == o {
|
||||
has = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if has {
|
||||
break
|
||||
}
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
// every 检查字符串数组中同时包含所有项
|
||||
func every(origin []string, target []string) bool {
|
||||
match := true
|
||||
for _, t := range target {
|
||||
found := false
|
||||
for _, o := range origin {
|
||||
if t == o {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return match
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package midware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 已禁用由Gin部分接管
|
||||
// Cors 跨域
|
||||
func Cors(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// 设置Vary头部
|
||||
w.Header().Set("Vary", "Origin")
|
||||
w.Header().Set("Keep-Alive", "timeout=5")
|
||||
|
||||
requestOrigin := r.Header.Get("Origin")
|
||||
if requestOrigin == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
// OPTIONS
|
||||
if r.Method == "OPTIONS" {
|
||||
requestMethod := r.Header.Get("Access-Control-Request-Method")
|
||||
if requestMethod == "" {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// 响应最大时间值
|
||||
w.Header().Set("Access-Control-Max-Age", "31536000")
|
||||
|
||||
// 允许方法
|
||||
allowMethods := []string{
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"PATCH",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Methods", strings.Join(allowMethods, ","))
|
||||
|
||||
// 允许请求头
|
||||
allowHeaders := []string{
|
||||
"Accesstoken",
|
||||
"Content-Type",
|
||||
"operationtype",
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Headers", strings.Join(allowHeaders, ","))
|
||||
|
||||
w.WriteHeader(204)
|
||||
return
|
||||
}
|
||||
|
||||
// 暴露请求头
|
||||
exposeHeaders := []string{"X-RepeatSubmit-Rest", "AccessToken"}
|
||||
w.Header().Set("Access-Control-Expose-Headers", strings.Join(exposeHeaders, ","))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/datasource"
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/utils/date"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/lib/log"
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/utils/date"
|
||||
)
|
||||
|
||||
// LogMML mml操作日志搜集
|
||||
@@ -36,7 +36,7 @@ func LogMML(next http.Handler) http.Handler {
|
||||
// 收尾存入数据库的参数
|
||||
mmlCmd := bodyArgs["mml"].([]any)[0]
|
||||
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
|
||||
neType := ctx.Param(r, "elementTypeValue")
|
||||
neType := ctx.GetParam(r, "elementTypeValue")
|
||||
neId := ctx.GetQuery(r, "ne_id")
|
||||
timeStr := date.ParseDateToStr(time.Now(), date.YYYY_MM_DD_HH_MM_SS)
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/core/utils/ctx"
|
||||
"be.ems/lib/core/utils/parse"
|
||||
"be.ems/lib/core/ctx"
|
||||
"be.ems/src/framework/constants/common"
|
||||
"be.ems/src/framework/middleware/collectlogs"
|
||||
"be.ems/src/framework/utils/ip2region"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/modules/system/model"
|
||||
"be.ems/src/modules/system/service"
|
||||
)
|
||||
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"be.ems/features/cdr"
|
||||
"be.ems/features/cm"
|
||||
"be.ems/features/dbrest"
|
||||
"be.ems/features/event"
|
||||
"be.ems/features/file"
|
||||
"be.ems/features/fm"
|
||||
"be.ems/features/lm"
|
||||
"be.ems/features/mml"
|
||||
"be.ems/features/nbi"
|
||||
"be.ems/features/pm"
|
||||
"be.ems/features/security"
|
||||
"be.ems/features/sm"
|
||||
@@ -172,9 +172,9 @@ func init() {
|
||||
Register("POST", mml.CustomUriMML2, mml.PostMML2ToNF, nil)
|
||||
|
||||
// Northbound Get NRM
|
||||
Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
// Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
|
||||
Register("GET", nbi.CustomGetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
// Register("GET", nbi.CustomGetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||
|
||||
// Import/Export NF CM
|
||||
Register("GET", cm.NeCmUri, cm.ExportCmFromNF, nil)
|
||||
@@ -261,9 +261,7 @@ func init() {
|
||||
Register("DELETE", ue.CustomUriPCFUserM, ue.DeletePCFUserInfo, nil)
|
||||
//PCF User file
|
||||
Register("GET", ue.UriPCFUserFileExport, ue.GetUEInfoFileExportNF, nil)
|
||||
Register("GET", ue.CustomUriPCFUserFileExport, ue.GetUEInfoFromNF, nil)
|
||||
Register("PUT", ue.UriPCFUserFileImport, ue.PutPCFUserInfo, nil)
|
||||
Register("PUT", ue.CustomUriPCFUserFileImport, ue.PutPCFUserInfo, nil)
|
||||
|
||||
// UE Number
|
||||
Register("GET", ue.UriUENum, ue.GetUENumFromNF, nil)
|
||||
@@ -289,6 +287,9 @@ func init() {
|
||||
Register("POST", cdr.UriSMFCDREvent, cdr.PostCDREventFromSMF, nil)
|
||||
Register("POST", cdr.CustomUriSMFCDREvent, cdr.PostCDREventFromSMF, nil)
|
||||
|
||||
// UE event 上报的UE事件
|
||||
Register("POST", event.UriUEEvent, event.PostUEEvent, nil)
|
||||
|
||||
// UE event AMF上报的UE事件, 无前缀给到Gin处理
|
||||
//Register("POST", event.UriUEEvent, event.PostUEEventFromAMF, nil)
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package wsinfo
|
||||
|
||||
import (
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
ID string
|
||||
Socket *websocket.Conn
|
||||
Msg chan []byte
|
||||
}
|
||||
|
||||
func NewWsClient(ID string, socket *websocket.Conn) *Client {
|
||||
return &Client{
|
||||
ID: ID,
|
||||
Socket: socket,
|
||||
Msg: make(chan []byte, 100),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Read() {
|
||||
defer func() {
|
||||
close(c.Msg)
|
||||
}()
|
||||
for {
|
||||
_, message, err := c.Socket.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ProcessData(c, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Write() {
|
||||
defer func() {
|
||||
c.Socket.Close()
|
||||
}()
|
||||
for {
|
||||
message, ok := <-c.Msg
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_ = c.Socket.WriteMessage(websocket.TextMessage, message)
|
||||
}
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
package wsinfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/log"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
||||
type WsInput struct {
|
||||
Type string `json:"type"`
|
||||
DownloadProgress
|
||||
PsProcessConfig
|
||||
SSHSessionConfig
|
||||
NetConfig
|
||||
}
|
||||
|
||||
type DownloadProgress struct {
|
||||
Keys []string `json:"keys"`
|
||||
}
|
||||
|
||||
type PsProcessConfig struct {
|
||||
Pid int32 `json:"pid"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type SSHSessionConfig struct {
|
||||
LoginUser string `json:"loginUser"`
|
||||
LoginIP string `json:"loginIP"`
|
||||
}
|
||||
|
||||
type NetConfig struct {
|
||||
Port uint32 `json:"port"`
|
||||
ProcessName string `json:"processName"`
|
||||
ProcessID int32 `json:"processID"`
|
||||
}
|
||||
|
||||
type PsProcessData struct {
|
||||
PID int32 `json:"PID"`
|
||||
Name string `json:"name"`
|
||||
PPID int32 `json:"PPID"`
|
||||
Username string `json:"username"`
|
||||
Status string `json:"status"`
|
||||
StartTime string `json:"startTime"`
|
||||
NumThreads int32 `json:"numThreads"`
|
||||
NumConnections int `json:"numConnections"`
|
||||
CpuPercent string `json:"cpuPercent"`
|
||||
|
||||
DiskRead string `json:"diskRead"`
|
||||
DiskWrite string `json:"diskWrite"`
|
||||
CmdLine string `json:"cmdLine"`
|
||||
|
||||
Rss string `json:"rss"`
|
||||
VMS string `json:"vms"`
|
||||
HWM string `json:"hwm"`
|
||||
Data string `json:"data"`
|
||||
Stack string `json:"stack"`
|
||||
Locked string `json:"locked"`
|
||||
Swap string `json:"swap"`
|
||||
|
||||
CpuValue float64 `json:"cpuValue"`
|
||||
RssValue uint64 `json:"rssValue"`
|
||||
|
||||
Envs []string `json:"envs"`
|
||||
|
||||
OpenFiles []process.OpenFilesStat `json:"openFiles"`
|
||||
Connects []processConnect `json:"connects"`
|
||||
}
|
||||
|
||||
type processConnect struct {
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
Laddr net.Addr `json:"localaddr"`
|
||||
Raddr net.Addr `json:"remoteaddr"`
|
||||
PID int32 `json:"PID"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ProcessConnects []processConnect
|
||||
|
||||
func (p ProcessConnects) Len() int {
|
||||
return len(p)
|
||||
}
|
||||
|
||||
func (p ProcessConnects) Less(i, j int) bool {
|
||||
return p[i].PID < p[j].PID
|
||||
}
|
||||
|
||||
func (p ProcessConnects) Swap(i, j int) {
|
||||
p[i], p[j] = p[j], p[i]
|
||||
}
|
||||
|
||||
type sshSession struct {
|
||||
Username string `json:"username"`
|
||||
PID int32 `json:"PID"`
|
||||
Terminal string `json:"terminal"`
|
||||
Host string `json:"host"`
|
||||
LoginTime string `json:"loginTime"`
|
||||
}
|
||||
|
||||
func ProcessData(c *Client, inputMsg []byte) {
|
||||
wsInput := &WsInput{}
|
||||
err := json.Unmarshal(inputMsg, wsInput)
|
||||
if err != nil {
|
||||
log.Errorf("unmarshal wsInput error,err %s", err.Error())
|
||||
return
|
||||
}
|
||||
switch wsInput.Type {
|
||||
case "ps":
|
||||
res, err := getProcessData(wsInput.PsProcessConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "ssh":
|
||||
res, err := getSSHSessions(wsInput.SSHSessionConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
case "net":
|
||||
res, err := getNetConnections(wsInput.NetConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Msg <- res
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type Process struct {
|
||||
Total uint64 `json:"total"`
|
||||
Written uint64 `json:"written"`
|
||||
Percent float64 `json:"percent"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
const (
|
||||
b = uint64(1)
|
||||
kb = 1024 * b
|
||||
mb = 1024 * kb
|
||||
gb = 1024 * mb
|
||||
)
|
||||
|
||||
func formatBytes(bytes uint64) string {
|
||||
switch {
|
||||
case bytes < kb:
|
||||
return fmt.Sprintf("%dB", bytes)
|
||||
case bytes < mb:
|
||||
return fmt.Sprintf("%.2fKB", float64(bytes)/float64(kb))
|
||||
case bytes < gb:
|
||||
return fmt.Sprintf("%.2fMB", float64(bytes)/float64(mb))
|
||||
default:
|
||||
return fmt.Sprintf("%.2fGB", float64(bytes)/float64(gb))
|
||||
}
|
||||
}
|
||||
|
||||
func getProcessData(processConfig PsProcessConfig) (res []byte, err error) {
|
||||
var processes []*process.Process
|
||||
processes, err = process.Processes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
result []PsProcessData
|
||||
resultMutex sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
numWorkers = 4
|
||||
)
|
||||
|
||||
handleData := func(proc *process.Process) {
|
||||
procData := PsProcessData{
|
||||
PID: proc.Pid,
|
||||
}
|
||||
if processConfig.Pid > 0 && processConfig.Pid != proc.Pid {
|
||||
return
|
||||
}
|
||||
if procName, err := proc.Name(); err == nil {
|
||||
procData.Name = procName
|
||||
} else {
|
||||
procData.Name = "<UNKNOWN>"
|
||||
}
|
||||
if processConfig.Name != "" && !strings.Contains(procData.Name, processConfig.Name) {
|
||||
return
|
||||
}
|
||||
if username, err := proc.Username(); err == nil {
|
||||
procData.Username = username
|
||||
}
|
||||
if processConfig.Username != "" && !strings.Contains(procData.Username, processConfig.Username) {
|
||||
return
|
||||
}
|
||||
procData.PPID, _ = proc.Ppid()
|
||||
statusArray, _ := proc.Status()
|
||||
if len(statusArray) > 0 {
|
||||
procData.Status = strings.Join(statusArray, ",")
|
||||
}
|
||||
createTime, procErr := proc.CreateTime()
|
||||
if procErr == nil {
|
||||
t := time.Unix(createTime/1000, 0)
|
||||
procData.StartTime = t.Format("2006-1-2 15:04:05")
|
||||
}
|
||||
procData.NumThreads, _ = proc.NumThreads()
|
||||
connections, procErr := proc.Connections()
|
||||
if procErr == nil {
|
||||
procData.NumConnections = len(connections)
|
||||
for _, conn := range connections {
|
||||
if conn.Laddr.IP != "" || conn.Raddr.IP != "" {
|
||||
procData.Connects = append(procData.Connects, processConnect{
|
||||
Status: conn.Status,
|
||||
Laddr: conn.Laddr,
|
||||
Raddr: conn.Raddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
procData.CpuValue, _ = proc.CPUPercent()
|
||||
procData.CpuPercent = fmt.Sprintf("%.2f", procData.CpuValue) + "%"
|
||||
menInfo, procErr := proc.MemoryInfo()
|
||||
if procErr == nil {
|
||||
procData.Rss = formatBytes(menInfo.RSS)
|
||||
procData.RssValue = menInfo.RSS
|
||||
procData.Data = formatBytes(menInfo.Data)
|
||||
procData.VMS = formatBytes(menInfo.VMS)
|
||||
procData.HWM = formatBytes(menInfo.HWM)
|
||||
procData.Stack = formatBytes(menInfo.Stack)
|
||||
procData.Locked = formatBytes(menInfo.Locked)
|
||||
procData.Swap = formatBytes(menInfo.Swap)
|
||||
} else {
|
||||
procData.Rss = "--"
|
||||
procData.Data = "--"
|
||||
procData.VMS = "--"
|
||||
procData.HWM = "--"
|
||||
procData.Stack = "--"
|
||||
procData.Locked = "--"
|
||||
procData.Swap = "--"
|
||||
|
||||
procData.RssValue = 0
|
||||
}
|
||||
ioStat, procErr := proc.IOCounters()
|
||||
if procErr == nil {
|
||||
procData.DiskWrite = formatBytes(ioStat.WriteBytes)
|
||||
procData.DiskRead = formatBytes(ioStat.ReadBytes)
|
||||
} else {
|
||||
procData.DiskWrite = "--"
|
||||
procData.DiskRead = "--"
|
||||
}
|
||||
procData.CmdLine, _ = proc.Cmdline()
|
||||
procData.OpenFiles, _ = proc.OpenFiles()
|
||||
procData.Envs, _ = proc.Environ()
|
||||
|
||||
resultMutex.Lock()
|
||||
result = append(result, procData)
|
||||
resultMutex.Unlock()
|
||||
}
|
||||
|
||||
chunkSize := (len(processes) + numWorkers - 1) / numWorkers
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
start := i * chunkSize
|
||||
end := (i + 1) * chunkSize
|
||||
if end > len(processes) {
|
||||
end = len(processes)
|
||||
}
|
||||
|
||||
go func(start, end int) {
|
||||
defer wg.Done()
|
||||
for j := start; j < end; j++ {
|
||||
handleData(processes[j])
|
||||
}
|
||||
}(start, end)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].PID < result[j].PID
|
||||
})
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
|
||||
var (
|
||||
result []sshSession
|
||||
users []host.UserStat
|
||||
processes []*process.Process
|
||||
)
|
||||
processes, err = process.Processes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
users, err = host.Users()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, proc := range processes {
|
||||
name, _ := proc.Name()
|
||||
if name != "sshd" || proc.Pid == 0 {
|
||||
continue
|
||||
}
|
||||
connections, _ := proc.Connections()
|
||||
for _, conn := range connections {
|
||||
for _, user := range users {
|
||||
if user.Host == "" {
|
||||
continue
|
||||
}
|
||||
if conn.Raddr.IP == user.Host {
|
||||
if config.LoginUser != "" && !strings.Contains(user.User, config.LoginUser) {
|
||||
continue
|
||||
}
|
||||
if config.LoginIP != "" && !strings.Contains(user.Host, config.LoginIP) {
|
||||
continue
|
||||
}
|
||||
if terminal, err := proc.Cmdline(); err == nil {
|
||||
if strings.Contains(terminal, user.Terminal) {
|
||||
session := sshSession{
|
||||
Username: user.User,
|
||||
Host: user.Host,
|
||||
Terminal: user.Terminal,
|
||||
PID: proc.Pid,
|
||||
}
|
||||
t := time.Unix(int64(user.Started), 0)
|
||||
session.LoginTime = t.Format("2006-1-2 15:04:05")
|
||||
result = append(result, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
|
||||
var netTypes = [...]string{"tcp", "udp"}
|
||||
|
||||
func getNetConnections(config NetConfig) (res []byte, err error) {
|
||||
var (
|
||||
result []processConnect
|
||||
proc *process.Process
|
||||
)
|
||||
for _, netType := range netTypes {
|
||||
connections, _ := net.Connections(netType)
|
||||
if err == nil {
|
||||
for _, conn := range connections {
|
||||
if config.ProcessID > 0 && config.ProcessID != conn.Pid {
|
||||
continue
|
||||
}
|
||||
proc, err = process.NewProcess(conn.Pid)
|
||||
if err == nil {
|
||||
name, _ := proc.Name()
|
||||
if name != "" && config.ProcessName != "" && !strings.Contains(name, config.ProcessName) {
|
||||
continue
|
||||
}
|
||||
if config.Port > 0 && config.Port != conn.Laddr.Port && config.Port != conn.Raddr.Port {
|
||||
continue
|
||||
}
|
||||
result = append(result, processConnect{
|
||||
Type: netType,
|
||||
Status: conn.Status,
|
||||
Laddr: conn.Laddr,
|
||||
Raddr: conn.Raddr,
|
||||
PID: conn.Pid,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err = json.Marshal(result)
|
||||
return
|
||||
}
|
||||
@@ -177,8 +177,8 @@ type MMLParam struct {
|
||||
Port2 int `yaml:"port2"`
|
||||
Sleep int64 `yaml:"sleep"`
|
||||
DeadLine int64 `yaml:"deadLine"`
|
||||
SizeRow byte `yaml:"sizeRow"`
|
||||
SizeCol byte `yaml:"sizeCol"`
|
||||
SizeRow int16 `yaml:"sizeRow"`
|
||||
SizeCol int16 `yaml:"sizeCol"`
|
||||
BufferSize int `yaml:"bufferSize"`
|
||||
User string `yaml:"user"`
|
||||
Password string `ymal:"password"`
|
||||
@@ -226,8 +226,8 @@ func NewYamlConfig() YamlConfig {
|
||||
ConnParam: "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True",
|
||||
},
|
||||
MML: MMLParam{
|
||||
SizeRow: 100,
|
||||
SizeCol: 128,
|
||||
SizeRow: 200,
|
||||
SizeCol: 120,
|
||||
BufferSize: 65535,
|
||||
},
|
||||
Alarm: AlarmConfig{
|
||||
|
||||
@@ -54,14 +54,14 @@ redis:
|
||||
# OMC系统使用库
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.2.219" # Redis host
|
||||
password: "123456"
|
||||
host: "127.0.0.1" # Redis host
|
||||
password: "helloearth"
|
||||
db: 10 # Redis db_num
|
||||
# UDM网元用户库
|
||||
udmuser:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.2.219"
|
||||
password: "123456"
|
||||
host: "127.0.0.1"
|
||||
password: "helloearth"
|
||||
db: 0 # Redis db_num
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
defaultDataSourceName: "default"
|
||||
@@ -73,13 +73,12 @@ mml:
|
||||
port2: 5002
|
||||
sleep: 200
|
||||
deadLine: 10
|
||||
sizeRow: 100
|
||||
sizeRow: 600
|
||||
sizeCol: 128
|
||||
bufferSize: 65535
|
||||
user: admin
|
||||
password: admin
|
||||
mmlHome: ./mmlhome
|
||||
upload: /home/manager
|
||||
|
||||
# NE config
|
||||
ne:
|
||||
|
||||
@@ -21,17 +21,9 @@ rest:
|
||||
- ipv4: 0.0.0.0
|
||||
ipv6:
|
||||
port: 33040
|
||||
- ipv4: 0.0.0.0
|
||||
ipv6:
|
||||
port: 34443
|
||||
scheme: https
|
||||
clientAuthType: 0
|
||||
caFile: ./etc/certs/omc-ca.crt
|
||||
certFile: ./etc/certs/omc-server.crt
|
||||
keyFile: ./etc/certs/omc-server.key
|
||||
|
||||
webServer:
|
||||
enabled: true
|
||||
enabled: false
|
||||
rootDir: d:/local.git/fe.ems.vue3/dist
|
||||
listen:
|
||||
- addr: :80
|
||||
@@ -46,10 +38,10 @@ webServer:
|
||||
database:
|
||||
type: mysql
|
||||
user: root
|
||||
password: 1000omc@kp!
|
||||
host: 127.0.0.1
|
||||
port: 33066
|
||||
name: omc_db
|
||||
password: "root@1234"
|
||||
host: "192.168.5.59"
|
||||
port: 3306
|
||||
name: "omc_db"
|
||||
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
|
||||
backup: d:/local.git/be.ems/restagent/database
|
||||
|
||||
@@ -59,14 +51,14 @@ redis:
|
||||
# OMC系统使用库
|
||||
default:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.2.219" # Redis host
|
||||
password: "123456"
|
||||
host: "192.168.5.59" # Redis host
|
||||
password: "redis@1234"
|
||||
db: 10 # Redis db_num
|
||||
# UDM网元用户库
|
||||
udmuser:
|
||||
port: 6379 # Redis port
|
||||
host: "192.168.2.219"
|
||||
password: "123456"
|
||||
host: "192.168.5.60"
|
||||
password: "helloearth"
|
||||
db: 0 # Redis db_num
|
||||
# 多个数据源时可以用这个指定默认的数据源
|
||||
defaultDataSourceName: "default"
|
||||
@@ -78,7 +70,7 @@ mml:
|
||||
port2: 5002
|
||||
sleep: 200
|
||||
deadLine: 10
|
||||
sizeRow: 100
|
||||
sizeRow: 600
|
||||
sizeCol: 128
|
||||
bufferSize: 65535
|
||||
user: admin
|
||||
@@ -87,7 +79,7 @@ mml:
|
||||
|
||||
# NE config
|
||||
ne:
|
||||
user: root
|
||||
user: omcuser
|
||||
etcdir: /usr/local/etc
|
||||
bindir: /usr/local/bin
|
||||
omcdir: /usr/local/omc
|
||||
@@ -116,12 +108,12 @@ omc:
|
||||
checksign: false
|
||||
rootDir: ./
|
||||
binDir: ./bin
|
||||
backup: ./backup
|
||||
upload: ./upload
|
||||
frontUpload: d:/local.git/fe.ems/upload
|
||||
frontTraceDir: d:/local.git/fe.ems/trace
|
||||
software: ./software
|
||||
license: ./license
|
||||
backup: C:/usr/local/omc/backup
|
||||
upload: C:/usr/local/omc/upload
|
||||
frontUpload: C:/usr/local/omc/upload
|
||||
frontTraceDir: C:/usr/local/omc/trace
|
||||
software: C:/usr/local/omc/software
|
||||
license: C:/usr/local/omc/license
|
||||
gtpUri: gtp:192.168.2.219:2152
|
||||
checkContentType: false
|
||||
testMode: false
|
||||
@@ -134,7 +126,7 @@ omc:
|
||||
# email/sms
|
||||
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
|
||||
alarm:
|
||||
forwardAlarm: true
|
||||
forwardAlarm: false
|
||||
email:
|
||||
smtp: mail.agrandtech.com
|
||||
port: 25
|
||||
@@ -189,12 +181,12 @@ testConfig:
|
||||
file: ./etc/testconfig.yaml
|
||||
|
||||
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||
staticFile:
|
||||
# 默认资源,dir目录需要预先创建
|
||||
default:
|
||||
prefix: "/static"
|
||||
dir: "./static"
|
||||
# 文件上传资源目录映射,与项目目录同级
|
||||
upload:
|
||||
prefix: "/upload"
|
||||
dir: "./upload"
|
||||
# staticFile:
|
||||
# # 默认资源,dir目录需要预先创建
|
||||
# default:
|
||||
# prefix: "/static"
|
||||
# dir: "./static"
|
||||
# # 文件上传资源目录映射,与项目目录同级
|
||||
# upload:
|
||||
# prefix: "/upload"
|
||||
# dir: "./upload"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile for rest agent project
|
||||
|
||||
PROJECT = OMC
|
||||
VERSION = 2.2405.4
|
||||
VERSION = 2.2407.1
|
||||
PLATFORM = amd64
|
||||
ARMPLATFORM = aarch64
|
||||
BUILDDIR = ../../build
|
||||
@@ -14,7 +14,7 @@ BINNAME = restagent
|
||||
|
||||
.PHONY: build $(BINNAME)
|
||||
build $(BINNAME):
|
||||
go build -o $(BINNAME) -v -ldflags "-X '$(LIBDIR)/global.Version=$(VERSION)' \
|
||||
go build -o $(BINNAME) -v -ldflags "-s -w -X '$(LIBDIR)/global.Version=$(VERSION)' \
|
||||
-X '$(LIBDIR)/global.BuildTime=`date`' \
|
||||
-X '$(LIBDIR)/global.GoVer=`go version`'"
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ func main() {
|
||||
uriGroup := app.Group(config.UriPrefix)
|
||||
uriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
|
||||
// AMF上报的UE事件, 无前缀,暂时特殊处理
|
||||
app.POST(event.UriUEEvent, event.PostUEEventFromAMF)
|
||||
app.POST(event.UriUEEventAMF, event.PostUEEventFromAMF)
|
||||
|
||||
var listenLocalhost bool = false
|
||||
for _, rest := range conf.Rest {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 项目信息
|
||||
framework:
|
||||
name: "CN EMS"
|
||||
version: "2.2405.4"
|
||||
version: "2.2407.1"
|
||||
|
||||
# 应用服务配置
|
||||
server:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package admin
|
||||
|
||||
// 管理员常量信息
|
||||
// 系统管理员常量信息
|
||||
|
||||
// 管理员-系统指定角色ID
|
||||
// 系统管理员-系统指定角色ID
|
||||
const ROLE_ID = "1"
|
||||
|
||||
// 管理员-系统指定角色KEY
|
||||
const ROLE_KEY = "admin"
|
||||
// 系统管理员-系统指定角色KEY
|
||||
const ROLE_KEY = "system"
|
||||
|
||||
// 管理员-系统指定权限
|
||||
// 系统管理员-系统指定权限
|
||||
const PERMISSION = "*:*:*"
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/constants/common"
|
||||
tokenConstants "be.ems/src/framework/constants/token"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
@@ -178,6 +179,8 @@ var maskProperties []string = []string{
|
||||
"oldPassword",
|
||||
"newPassword",
|
||||
"confirmPassword",
|
||||
tokenConstants.RESPONSE_FIELD,
|
||||
tokenConstants.ACCESS_TOKEN,
|
||||
}
|
||||
|
||||
// processSensitiveFields 处理敏感属性字段
|
||||
|
||||
@@ -20,6 +20,7 @@ var URL_WHITE_LIST = []string{
|
||||
"/systemState",
|
||||
"/omcNeConfig",
|
||||
"/cdrEvent",
|
||||
"/ueEvent",
|
||||
"/upload-ue",
|
||||
"/oauth/token",
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ func Authorization(c *gin.Context) string {
|
||||
return ""
|
||||
}
|
||||
// 拆分 Authorization 请求头,提取 JWT 令牌部分
|
||||
arr := strings.Split(authHeader, token.HEADER_PREFIX)
|
||||
if len(arr) == 2 && arr[1] == "" {
|
||||
arr := strings.SplitN(authHeader, token.HEADER_PREFIX, 2)
|
||||
if len(arr) < 2 {
|
||||
return ""
|
||||
}
|
||||
return arr[1]
|
||||
@@ -212,6 +212,11 @@ func LoginUserToDataScopeSQL(c *gin.Context, deptAlias string, userAlias string)
|
||||
conditions = append(conditions, sql)
|
||||
}
|
||||
|
||||
if roledatascope.DEPT == dataScope {
|
||||
sql := fmt.Sprintf(`%s.dept_id = '%s'`, deptAlias, userInfo.DeptID)
|
||||
conditions = append(conditions, sql)
|
||||
}
|
||||
|
||||
if roledatascope.DEPT_AND_CHILD == dataScope {
|
||||
sql := fmt.Sprintf(`%s.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = '%s' or find_in_set('%s' , ancestors ) )`, deptAlias, userInfo.DeptID, userInfo.DeptID)
|
||||
conditions = append(conditions, sql)
|
||||
@@ -220,7 +225,7 @@ func LoginUserToDataScopeSQL(c *gin.Context, deptAlias string, userAlias string)
|
||||
if roledatascope.SELF == dataScope {
|
||||
// 数据权限为仅本人且没有userAlias别名不查询任何数据
|
||||
if userAlias == "" {
|
||||
sql := fmt.Sprintf(`%s.dept_id = '0'`, deptAlias)
|
||||
sql := fmt.Sprintf(`%s.parent_id = '0'`, deptAlias)
|
||||
conditions = append(conditions, sql)
|
||||
} else {
|
||||
sql := fmt.Sprintf(`%s.user_id = '%s'`, userAlias, userInfo.UserID)
|
||||
|
||||
@@ -48,7 +48,14 @@ func ParseDateToStr(date any, formatStr string) string {
|
||||
if v == 0 {
|
||||
return ""
|
||||
}
|
||||
t = time.UnixMilli(v)
|
||||
if v > 9999999999 {
|
||||
t = time.UnixMilli(v)
|
||||
} else if v > 999999999 {
|
||||
t = time.Unix(v, 0)
|
||||
} else {
|
||||
logger.Infof("utils ParseDateToStr err %v", "Invalid timestamp")
|
||||
return ""
|
||||
}
|
||||
case string:
|
||||
parsedTime, err := time.Parse(formatStr, v)
|
||||
if err != nil {
|
||||
|
||||
@@ -172,10 +172,10 @@ func Color(colorStr string) *color.RGBA {
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertIPMask 转换IP网络地址掩码 24 -> 255.255.255.0
|
||||
// ConvertIPMask 转换IP网络地址掩码 24->"255.255.255.0" 20->"255.255.240.0"
|
||||
func ConvertIPMask(bits int64) string {
|
||||
if bits < 0 || bits > 32 {
|
||||
return "Invalid Mask Bits"
|
||||
return "255.255.255.255"
|
||||
}
|
||||
|
||||
// 构建一个32位的uint32类型掩码,指定前bits位为1,其余为0
|
||||
|
||||
@@ -66,12 +66,12 @@ func SetFieldValue(obj any, fieldName string, value any) {
|
||||
}
|
||||
fieldValue.SetFloat(floatValue)
|
||||
case reflect.Struct:
|
||||
fmt.Printf("%s 时间解析 %s %v \n", fieldName, fieldValue.Type(), value)
|
||||
fmt.Printf("%s time resolution %s %v \n", fieldName, fieldValue.Type(), value)
|
||||
if fieldValue.Type() == reflect.TypeOf(time.Time{}) && value != nil {
|
||||
// 解析 value 并转换为 time.Time 类型
|
||||
parsedTime, err := time.Parse("2006-01-02 15:04:05 +0800 CST", fmt.Sprintf("%v", value))
|
||||
if err != nil {
|
||||
fmt.Println("时间解析出错:", err)
|
||||
fmt.Println("Time resolution error:", err)
|
||||
} else {
|
||||
// 设置字段的值
|
||||
fieldValue.Set(reflect.ValueOf(parsedTime))
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/cmd"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
@@ -23,35 +22,31 @@ type FileListRow struct {
|
||||
}
|
||||
|
||||
// 文件列表
|
||||
// neIp 网元IP空字符串为本地
|
||||
// search 文件名后模糊*
|
||||
//
|
||||
// return 目录大小,行记录,异常
|
||||
func FileList(path, neIp, search string) (string, []FileListRow, error) {
|
||||
func FileList(sshClient *ConnSSH, path, search string) (string, []FileListRow, error) {
|
||||
totalSize := ""
|
||||
var rows []FileListRow
|
||||
rowStr := ""
|
||||
|
||||
// 发送命令
|
||||
searchStr := ""
|
||||
searchStr := "*"
|
||||
if search != "" {
|
||||
searchStr = search + "*"
|
||||
searchStr = search + searchStr
|
||||
}
|
||||
pathStr := fmt.Sprintf("cd %s \n", path)
|
||||
cmdStr := fmt.Sprintf("ls -lht --time-style=+%%s %s \n", searchStr)
|
||||
cmdStr := fmt.Sprintf("cd %s && ls -lthd --time-style=+%%s %s", path, searchStr)
|
||||
|
||||
// 是否远程读取
|
||||
if neIp != "" {
|
||||
usernameNe := config.Get("ne.user").(string) // 网元统一用户
|
||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neIp)
|
||||
resultStr, err := cmd.ExecWithCheck("ssh", sshHost, pathStr, cmdStr)
|
||||
// 是否远程客户端读取
|
||||
if sshClient == nil {
|
||||
resultStr, err := cmd.Execf(cmdStr)
|
||||
if err != nil {
|
||||
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
||||
return totalSize, rows, err
|
||||
}
|
||||
rowStr = resultStr
|
||||
} else {
|
||||
resultStr, err := cmd.Execf(pathStr, cmdStr)
|
||||
resultStr, err := sshClient.RunCMD(cmdStr)
|
||||
if err != nil {
|
||||
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
||||
return totalSize, rows, err
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/config"
|
||||
"be.ems/src/framework/logger"
|
||||
)
|
||||
|
||||
// 网元NE 文件复制到远程文件
|
||||
func FileSCPLocalToNe(neIp, localPath, nePath string) error {
|
||||
usernameNe := config.Get("ne.user").(string)
|
||||
// scp /path/to/local/file.txt user@remote-server:/path/to/remote/directory/
|
||||
neDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, nePath)
|
||||
cmd := exec.Command("scp", "-r", localPath, neDir)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Errorf("FileSCPLocalToNe %s => %s", output, err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 网元NE 远程文件复制到本地文件
|
||||
func FileSCPNeToLocal(neIp, nePath, localPath string) error {
|
||||
// 确保文件夹路径存在
|
||||
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
||||
logger.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
|
||||
return err
|
||||
}
|
||||
// 如果目标文件已经存在,先将目标文件重命名
|
||||
if info, err := os.Stat(localPath); err == nil && !info.IsDir() {
|
||||
ext := filepath.Ext(localPath)
|
||||
name := localPath[0 : len(localPath)-len(ext)]
|
||||
newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
||||
err := os.Rename(localPath, newName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
usernameNe := config.Get("ne.user").(string)
|
||||
// scp user@remote-server:/path/to/remote/directory/ /path/to/local/file.txt
|
||||
neDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, nePath)
|
||||
cmd := exec.Command("scp", "-r", neDir, localPath)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Errorf("FileSCPNeToLocal %s => %s", output, err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
202
src/framework/utils/ssh/sftp.go
Normal file
202
src/framework/utils/ssh/sftp.go
Normal file
@@ -0,0 +1,202 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"be.ems/src/framework/logger"
|
||||
gosftp "github.com/pkg/sftp"
|
||||
)
|
||||
|
||||
// SSHClientSFTP SSH客户端SFTP对象
|
||||
type SSHClientSFTP struct {
|
||||
Client *gosftp.Client
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *SSHClientSFTP) Close() {
|
||||
if s.Client != nil {
|
||||
s.Client.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制目录-远程到本地
|
||||
func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error {
|
||||
// 列出远程目录中的文件和子目录
|
||||
remoteFiles, err := s.Client.ReadDir(remoteDir)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to reading remote directory %s: => %s", remoteDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建本地目录
|
||||
err = os.MkdirAll(localDir, 0775)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local directory %s: => %s", localDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 遍历远程文件和子目录并复制到本地
|
||||
for _, remoteFile := range remoteFiles {
|
||||
remotePath := filepath.Join(remoteDir, remoteFile.Name())
|
||||
localPath := filepath.Join(localDir, remoteFile.Name())
|
||||
|
||||
if remoteFile.IsDir() {
|
||||
// 如果是子目录,则递归复制子目录
|
||||
err = s.CopyDirRemoteToLocal(remotePath, localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to copying remote directory %s: => %s", remotePath, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// 如果是文件,则复制文件内容
|
||||
remoteFile, err := s.Client.Open(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to opening remote file %s: => %s", remotePath, err.Error())
|
||||
continue
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
localFile, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local file %s: => %s", localPath, err.Error())
|
||||
continue
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
_, err = io.Copy(localFile, remoteFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to copying file contents from %s to %s: => %s", remotePath, localPath, err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制目录-本地到远程
|
||||
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
||||
// 创建远程目录
|
||||
err := s.Client.MkdirAll(remoteDir)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remoteDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 遍历本地目录中的文件和子目录并复制到远程
|
||||
err = filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成远程路径
|
||||
remotePath := filepath.Join(remoteDir, localPath[len(localDir):])
|
||||
|
||||
if info.IsDir() {
|
||||
// 如果是子目录,则创建远程目录
|
||||
err := s.Client.MkdirAll(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
// 如果是文件,则复制文件内容
|
||||
localFile, err := os.Open(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to opening local file %s: => %s", localPath, err.Error())
|
||||
return nil
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
remoteFile, err := s.Client.Create(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote file %s: => %s", remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
_, err = io.Copy(remoteFile, localFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to copying file contents from %s to %s: => %s", localPath, remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to walking local directory: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制文件-远程到本地
|
||||
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
||||
// 打开远程文件
|
||||
remoteFile, err := s.Client.Open(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to opening remote file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果目标文件已经存在,先将目标文件重命名
|
||||
// if info, err := os.Stat(localPath); err == nil && !info.IsDir() {
|
||||
// ext := filepath.Ext(localPath)
|
||||
// name := localPath[0 : len(localPath)-len(ext)]
|
||||
// newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
||||
// err := os.Rename(localPath, newName)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// 创建本地文件
|
||||
localFile, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to creating local file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
// 复制文件内容
|
||||
_, err = io.Copy(localFile, remoteFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to copying contents: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制文件-本地到远程
|
||||
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
||||
// 打开本地文件
|
||||
localFile, err := os.Open(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to opening local file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
// 创建远程文件
|
||||
remoteFile, err := s.Client.Create(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to creating remote file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
// 复制文件内容
|
||||
_, err = io.Copy(remoteFile, localFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to copying contents: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,14 +1,10 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/logger"
|
||||
@@ -89,24 +85,6 @@ func (c *ConnSSH) Close() {
|
||||
}
|
||||
}
|
||||
|
||||
// NewClientByLocalPrivate 创建SSH客户端-本地私钥(~/.ssh/id_rsa)直连
|
||||
//
|
||||
// ssh.ConnSSH{
|
||||
// User: "user",
|
||||
// Addr: "192.168.x.x",
|
||||
// Port: body.Port,
|
||||
// }
|
||||
func (c *ConnSSH) NewClientByLocalPrivate() (*ConnSSH, error) {
|
||||
c.Port = 22
|
||||
c.AuthMode = "1"
|
||||
privateKey, err := c.CurrentUserRsaKey(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.PrivateKey = privateKey
|
||||
return c.NewClient()
|
||||
}
|
||||
|
||||
// RunCMD 执行单次命令
|
||||
func (c *ConnSSH) RunCMD(cmd string) (string, error) {
|
||||
if c.Client == nil {
|
||||
@@ -128,57 +106,6 @@ func (c *ConnSSH) RunCMD(cmd string) (string, error) {
|
||||
return c.LastResult, err
|
||||
}
|
||||
|
||||
// SendToAuthorizedKeys 发送当前用户私钥到远程服务器进行授权密钥
|
||||
func (c *ConnSSH) SendToAuthorizedKeys() error {
|
||||
publicKey, err := c.CurrentUserRsaKey(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
||||
cmdStrArr := []string{
|
||||
fmt.Sprintf("sudo mkdir -p /home/%s/.ssh && sudo chown %s:%s /home/%s/.ssh && sudo chmod 700 /home/%s/.ssh", c.User, c.User, c.User, c.User, c.User),
|
||||
fmt.Sprintf("sudo touch /home/%s/.ssh/authorized_keys && sudo chown %s:%s /home/%s/.ssh/authorized_keys && sudo chmod 600 /home/%s/.ssh/authorized_keys", c.User, c.User, c.User, c.User, c.User),
|
||||
fmt.Sprintf("echo '%s' | sudo tee -a /home/%s/.ssh/authorized_keys", authorizedKeysEntry, c.User),
|
||||
}
|
||||
_, err = c.RunCMD(strings.Join(cmdStrArr, " && "))
|
||||
if err != nil {
|
||||
logger.Errorf("SendAuthorizedKeys echo err %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CurrentUserRsaKey 当前用户OMC使用的RSA私钥
|
||||
// 默认读取私钥
|
||||
// ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
|
||||
// ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
|
||||
func (c *ConnSSH) CurrentUserRsaKey(publicKey bool) (string, error) {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
logger.Errorf("CurrentUserRsaKey get => %s", err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 是否存在私钥并创建
|
||||
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
|
||||
if _, err := os.Stat(keyPath); err != nil {
|
||||
if _, err := cmd.ExecWithCheck("ssh-keygen", "-t", "rsa", "-P", "", "-f", keyPath); err != nil {
|
||||
logger.Errorf("CurrentUserPrivateKey ssh-keygen [%s] rsa => %s", usr.Username, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 读取用户默认的文件
|
||||
if publicKey {
|
||||
keyPath = keyPath + ".pub"
|
||||
}
|
||||
key, err := os.ReadFile(keyPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CurrentUserRsaKey [%s] read => %s", usr.Username, err.Error())
|
||||
return "", fmt.Errorf("read file %s fail", keyPath)
|
||||
}
|
||||
return string(key), nil
|
||||
}
|
||||
|
||||
// NewClientSession 创建SSH客户端会话对象
|
||||
func (c *ConnSSH) NewClientSession(cols, rows int) (*SSHClientSession, error) {
|
||||
sshSession, err := c.Client.NewSession()
|
||||
@@ -216,69 +143,6 @@ func (c *ConnSSH) NewClientSession(cols, rows int) (*SSHClientSession, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SSHClientSession SSH客户端会话对象
|
||||
type SSHClientSession struct {
|
||||
Stdin io.WriteCloser
|
||||
Stdout *singleWriter
|
||||
Session *gossh.Session
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *SSHClientSession) Close() {
|
||||
if s.Stdin != nil {
|
||||
s.Stdin.Close()
|
||||
}
|
||||
if s.Stdout != nil {
|
||||
s.Stdout = nil
|
||||
}
|
||||
if s.Session != nil {
|
||||
s.Session.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Write 写入命令 回车(\n)才会执行
|
||||
func (s *SSHClientSession) Write(cmd string) (int, error) {
|
||||
if s.Stdin == nil {
|
||||
return 0, fmt.Errorf("ssh client session is nil to content write failed")
|
||||
}
|
||||
return s.Stdin.Write([]byte(cmd))
|
||||
}
|
||||
|
||||
// Read 读取结果
|
||||
func (s *SSHClientSession) Read() []byte {
|
||||
if s.Stdout == nil {
|
||||
return []byte{}
|
||||
}
|
||||
bs := s.Stdout.Bytes()
|
||||
if len(bs) > 0 {
|
||||
s.Stdout.Reset()
|
||||
return bs
|
||||
}
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// singleWriter SSH客户端会话消息
|
||||
type singleWriter struct {
|
||||
b bytes.Buffer
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (w *singleWriter) Write(p []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
return w.b.Write(p)
|
||||
}
|
||||
func (w *singleWriter) Bytes() []byte {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
return w.b.Bytes()
|
||||
}
|
||||
func (w *singleWriter) Reset() {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
w.b.Reset()
|
||||
}
|
||||
|
||||
// NewClientSFTP 创建SSH客户端SFTP对象
|
||||
func (c *ConnSSH) NewClientSFTP() (*SSHClientSFTP, error) {
|
||||
sftpClient, err := gosftp.NewClient(c.Client)
|
||||
@@ -292,193 +156,70 @@ func (c *ConnSSH) NewClientSFTP() (*SSHClientSFTP, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SSHClientSFTP SSH客户端SFTP对象
|
||||
type SSHClientSFTP struct {
|
||||
Client *gosftp.Client
|
||||
// NewClientByLocalPrivate 创建SSH客户端-本地私钥(~/.ssh/id_rsa)直连
|
||||
//
|
||||
// ssh.ConnSSH{
|
||||
// User: "user",
|
||||
// Addr: "192.168.x.x",
|
||||
// Port: body.Port,
|
||||
// }
|
||||
func (c *ConnSSH) NewClientByLocalPrivate() (*ConnSSH, error) {
|
||||
c.Port = 22
|
||||
c.AuthMode = "1"
|
||||
privateKey, err := c.CurrentUserRsaKey(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.PrivateKey = privateKey
|
||||
return c.NewClient()
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *SSHClientSFTP) Close() {
|
||||
if s.Client != nil {
|
||||
s.Client.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制目录-远程到本地
|
||||
func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error {
|
||||
// 列出远程目录中的文件和子目录
|
||||
remoteFiles, err := s.Client.ReadDir(remoteDir)
|
||||
// CurrentUserRsaKey 当前用户OMC使用的RSA私钥
|
||||
// 默认读取私钥
|
||||
// ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
|
||||
// ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
|
||||
func (c *ConnSSH) CurrentUserRsaKey(publicKey bool) (string, error) {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to reading remote directory %s: => %s", remoteDir, err.Error())
|
||||
return err
|
||||
logger.Errorf("CurrentUserRsaKey get => %s", err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 创建本地目录
|
||||
err = os.MkdirAll(localDir, 0775)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local directory %s: => %s", localDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 遍历远程文件和子目录并复制到本地
|
||||
for _, remoteFile := range remoteFiles {
|
||||
remotePath := filepath.Join(remoteDir, remoteFile.Name())
|
||||
localPath := filepath.Join(localDir, remoteFile.Name())
|
||||
|
||||
if remoteFile.IsDir() {
|
||||
// 如果是子目录,则递归复制子目录
|
||||
err = s.CopyDirRemoteToLocal(remotePath, localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to copying remote directory %s: => %s", remotePath, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// 如果是文件,则复制文件内容
|
||||
remoteFile, err := s.Client.Open(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to opening remote file %s: => %s", remotePath, err.Error())
|
||||
continue
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
localFile, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local file %s: => %s", localPath, err.Error())
|
||||
continue
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
_, err = io.Copy(localFile, remoteFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to copying file contents from %s to %s: => %s", remotePath, localPath, err.Error())
|
||||
continue
|
||||
}
|
||||
// 是否存在私钥并创建
|
||||
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
|
||||
if _, err := os.Stat(keyPath); err != nil {
|
||||
if _, err := cmd.ExecWithCheck("ssh-keygen", "-t", "rsa", "-P", "", "-f", keyPath); err != nil {
|
||||
logger.Errorf("CurrentUserPrivateKey ssh-keygen [%s] rsa => %s", usr.Username, err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
// 读取用户默认的文件
|
||||
if publicKey {
|
||||
keyPath = keyPath + ".pub"
|
||||
}
|
||||
key, err := os.ReadFile(keyPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CurrentUserRsaKey [%s] read => %s", usr.Username, err.Error())
|
||||
return "", fmt.Errorf("read file %s fail", keyPath)
|
||||
}
|
||||
return string(key), nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制目录-本地到远程
|
||||
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
||||
// 创建远程目录
|
||||
err := s.Client.MkdirAll(remoteDir)
|
||||
// SendToAuthorizedKeys 发送当前用户私钥到远程服务器进行授权密钥
|
||||
func (c *ConnSSH) SendToAuthorizedKeys() error {
|
||||
publicKey, err := c.CurrentUserRsaKey(true)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remoteDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 遍历本地目录中的文件和子目录并复制到远程
|
||||
err = filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成远程路径
|
||||
remotePath := filepath.Join(remoteDir, localPath[len(localDir):])
|
||||
|
||||
if info.IsDir() {
|
||||
// 如果是子目录,则创建远程目录
|
||||
err := s.Client.MkdirAll(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
// 如果是文件,则复制文件内容
|
||||
localFile, err := os.Open(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to opening local file %s: => %s", localPath, err.Error())
|
||||
return nil
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
remoteFile, err := s.Client.Create(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote file %s: => %s", remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
_, err = io.Copy(remoteFile, localFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to copying file contents from %s to %s: => %s", localPath, remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
||||
cmdStrArr := []string{
|
||||
fmt.Sprintf("sudo mkdir -p /home/%s/.ssh && sudo chown %s:%s /home/%s/.ssh && sudo chmod 700 /home/%s/.ssh", c.User, c.User, c.User, c.User, c.User),
|
||||
fmt.Sprintf("sudo touch /home/%s/.ssh/authorized_keys && sudo chown %s:%s /home/%s/.ssh/authorized_keys && sudo chmod 600 /home/%s/.ssh/authorized_keys", c.User, c.User, c.User, c.User, c.User),
|
||||
fmt.Sprintf("echo '%s' | sudo tee -a /home/%s/.ssh/authorized_keys", authorizedKeysEntry, c.User),
|
||||
}
|
||||
_, err = c.RunCMD(strings.Join(cmdStrArr, " && "))
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to walking local directory: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制文件-远程到本地
|
||||
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
||||
// 打开远程文件
|
||||
remoteFile, err := s.Client.Open(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to opening remote file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果目标文件已经存在,先将目标文件重命名
|
||||
// if info, err := os.Stat(localPath); err == nil && !info.IsDir() {
|
||||
// ext := filepath.Ext(localPath)
|
||||
// name := localPath[0 : len(localPath)-len(ext)]
|
||||
// newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
||||
// err := os.Rename(localPath, newName)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// 创建本地文件
|
||||
localFile, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to creating local file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
// 复制文件内容
|
||||
_, err = io.Copy(localFile, remoteFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to copying contents: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制文件-本地到远程
|
||||
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
||||
// 打开本地文件
|
||||
localFile, err := os.Open(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to opening local file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
// 创建远程文件
|
||||
remoteFile, err := s.Client.Create(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to creating remote file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
// 复制文件内容
|
||||
_, err = io.Copy(remoteFile, localFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to copying contents: => %s", err.Error())
|
||||
logger.Errorf("SendAuthorizedKeys echo err %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
73
src/framework/utils/ssh/ssh_session.go
Normal file
73
src/framework/utils/ssh/ssh_session.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// SSHClientSession SSH客户端会话对象
|
||||
type SSHClientSession struct {
|
||||
Stdin io.WriteCloser
|
||||
Stdout *singleWriter
|
||||
Session *gossh.Session
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *SSHClientSession) Close() {
|
||||
if s.Stdin != nil {
|
||||
s.Stdin.Close()
|
||||
}
|
||||
if s.Stdout != nil {
|
||||
s.Stdout = nil
|
||||
}
|
||||
if s.Session != nil {
|
||||
s.Session.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Write 写入命令 回车(\n)才会执行
|
||||
func (s *SSHClientSession) Write(cmd string) (int, error) {
|
||||
if s.Stdin == nil {
|
||||
return 0, fmt.Errorf("ssh client session is nil to content write failed")
|
||||
}
|
||||
return s.Stdin.Write([]byte(cmd))
|
||||
}
|
||||
|
||||
// Read 读取结果
|
||||
func (s *SSHClientSession) Read() []byte {
|
||||
if s.Stdout == nil {
|
||||
return []byte{}
|
||||
}
|
||||
bs := s.Stdout.Bytes()
|
||||
if len(bs) > 0 {
|
||||
s.Stdout.Reset()
|
||||
return bs
|
||||
}
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// singleWriter SSH客户端会话消息
|
||||
type singleWriter struct {
|
||||
b bytes.Buffer
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (w *singleWriter) Write(p []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
return w.b.Write(p)
|
||||
}
|
||||
func (w *singleWriter) Bytes() []byte {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
return w.b.Bytes()
|
||||
}
|
||||
func (w *singleWriter) Reset() {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
w.b.Reset()
|
||||
}
|
||||
77
src/framework/utils/telnet/parse.go
Normal file
77
src/framework/utils/telnet/parse.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package telnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ConvertToStr 转换为string
|
||||
func ConvertToStr(telnetClient *ConnTelnet, cmd string) (string, error) {
|
||||
output, err := telnetClient.RunCMD(cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
str := strings.ToLower(output)
|
||||
|
||||
// 截断
|
||||
index := strings.Index(str, "\n")
|
||||
if index != -1 {
|
||||
str = str[:index]
|
||||
}
|
||||
|
||||
// 命令成功
|
||||
if strings.Contains(str, "ok") || strings.Contains(str, "success") {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf(str)
|
||||
}
|
||||
|
||||
// ConvertToMap 转换为map
|
||||
func ConvertToMap(telnetClient *ConnTelnet, cmd string) (map[string]string, error) {
|
||||
output, err := telnetClient.RunCMD(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 无数据
|
||||
if strings.HasPrefix(output, "No ") {
|
||||
// 截断
|
||||
index := strings.Index(output, "\n")
|
||||
if index != -1 {
|
||||
output = output[:index]
|
||||
}
|
||||
return nil, fmt.Errorf(output)
|
||||
}
|
||||
|
||||
// 初始化一个map用于存储拆分后的键值对
|
||||
m := make(map[string]string)
|
||||
|
||||
var items []string
|
||||
if strings.Contains(output, "\r\n") {
|
||||
// 按照分隔符"\r\n"进行拆分
|
||||
items = strings.Split(output, "\r\n")
|
||||
} else if strings.Contains(output, "\n") {
|
||||
// 按照分隔符"\n"进行拆分
|
||||
items = strings.Split(output, "\n")
|
||||
}
|
||||
|
||||
// 遍历拆分后的结果
|
||||
for _, item := range items {
|
||||
var pair []string
|
||||
|
||||
if strings.Contains(item, "=") {
|
||||
// 按照分隔符"="进行拆分键值对
|
||||
pair = strings.SplitN(item, "=", 2)
|
||||
} else if strings.Contains(item, ":") {
|
||||
// 按照分隔符":"进行拆分键值对
|
||||
pair = strings.SplitN(item, ":", 2)
|
||||
}
|
||||
|
||||
if len(pair) == 2 {
|
||||
// 将键值对存入map中
|
||||
m[pair[0]] = pair[1]
|
||||
}
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
@@ -50,11 +50,11 @@ func (c *ConnTelnet) NewClient() (*ConnTelnet, error) {
|
||||
// fmt.Fprintln(client, c.User)
|
||||
// fmt.Fprintln(client, c.Password)
|
||||
|
||||
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
||||
client.Write([]byte{255, 251, 31}) // 发送窗口大小选项
|
||||
client.Write([]byte{255, 250, 31, 0, 128, 0, 120, 255, 240}) // 发送窗口行和列的大小
|
||||
c.Client = &client
|
||||
|
||||
// 调整窗口大小 (120 列 x 128 行)
|
||||
requestPty(c.Client, 120, 128)
|
||||
|
||||
// 排空连接登录的信息
|
||||
c.RunCMD("")
|
||||
return c, nil
|
||||
@@ -73,8 +73,6 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
||||
return "", fmt.Errorf("telnet client not connected")
|
||||
}
|
||||
conn := *c.Client
|
||||
var buf bytes.Buffer
|
||||
tmp := make([]byte, 1024)
|
||||
|
||||
// 写入命令
|
||||
if cmd != "" {
|
||||
@@ -83,22 +81,24 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 读取命令消息
|
||||
var buf bytes.Buffer
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
// 设置读取超时时间为1000毫秒
|
||||
conn.SetReadDeadline(time.Now().Add(1000 * time.Millisecond))
|
||||
// 读取命令消息
|
||||
n, err := conn.Read(tmp)
|
||||
if err != nil {
|
||||
// 判断是否是超时错误
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
break
|
||||
}
|
||||
if n == 0 || err != nil {
|
||||
tmp = nil
|
||||
break
|
||||
}
|
||||
if n == 0 {
|
||||
|
||||
tmpStr := string(tmp[:n])
|
||||
buf.WriteString(tmpStr)
|
||||
|
||||
// 是否有终止符
|
||||
if strings.HasSuffix(tmpStr, ">") || strings.HasSuffix(tmpStr, "> ") || strings.HasSuffix(tmpStr, "# ") {
|
||||
tmp = nil
|
||||
break
|
||||
}
|
||||
buf.Write(tmp[:n])
|
||||
}
|
||||
defer buf.Reset()
|
||||
|
||||
@@ -107,77 +107,24 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
||||
}
|
||||
|
||||
// NewClient 创建Telnet客户端会话对象
|
||||
func (c *ConnTelnet) NewClientSession(cols, rows uint8) (*TelnetClientSession, error) {
|
||||
func (c *ConnTelnet) NewClientSession(cols, rows int) (*TelnetClientSession, error) {
|
||||
if c.Client == nil {
|
||||
return nil, fmt.Errorf("telnet client not connected")
|
||||
}
|
||||
requestPty(c.Client, cols, rows)
|
||||
return &TelnetClientSession{
|
||||
Client: *c.Client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TelnetClientSession Telnet客户端会话对象
|
||||
type TelnetClientSession struct {
|
||||
Client net.Conn
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *TelnetClientSession) Close() {
|
||||
if s.Client != nil {
|
||||
s.Client.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Write 写入命令 不带回车(\n)也会执行根据客户端情况
|
||||
func (s *TelnetClientSession) Write(cmd string) (int, error) {
|
||||
if s.Client == nil {
|
||||
return 0, fmt.Errorf("client is nil to content write failed")
|
||||
}
|
||||
return s.Client.Write([]byte(cmd))
|
||||
}
|
||||
|
||||
// Read 读取结果 等待一会才有结果
|
||||
func (s *TelnetClientSession) Read() []byte {
|
||||
if s.Client == nil {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
// 设置读取超时时间为100毫秒
|
||||
s.Client.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
_, err := s.Client.Read(buf)
|
||||
if err != nil {
|
||||
return []byte{}
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
// CombinedOutput 发送命令带结果返回
|
||||
func (s *TelnetClientSession) CombinedOutput(cmd string) (string, error) {
|
||||
n, err := s.Write(cmd)
|
||||
if n == 0 || err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
// 设置读取超时时间为1000毫秒
|
||||
s.Client.SetReadDeadline(time.Now().Add(1000 * time.Millisecond))
|
||||
n, err := s.Client.Read(tmp)
|
||||
if err != nil {
|
||||
// 判断是否是超时错误
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
buf.Write(tmp[:n])
|
||||
}
|
||||
defer buf.Reset()
|
||||
|
||||
return buf.String(), nil
|
||||
// requestPty 调整终端窗口大小
|
||||
func requestPty(client *net.Conn, cols, rows int) error {
|
||||
if client == nil {
|
||||
return fmt.Errorf("telnet client not connected")
|
||||
}
|
||||
conn := *client
|
||||
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
||||
conn.Write([]byte{255, 251, 31})
|
||||
conn.Write([]byte{255, 250, 31, byte(cols >> 8), byte(cols & 0xFF), byte(rows >> 8), byte(rows & 0xFF), 255, 240})
|
||||
return nil
|
||||
}
|
||||
|
||||
74
src/framework/utils/telnet/telnet_session.go
Normal file
74
src/framework/utils/telnet/telnet_session.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package telnet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TelnetClientSession Telnet客户端会话对象
|
||||
type TelnetClientSession struct {
|
||||
Client net.Conn
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *TelnetClientSession) Close() {
|
||||
if s.Client != nil {
|
||||
s.Client.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Write 写入命令 不带回车(\n)也会执行根据客户端情况
|
||||
func (s *TelnetClientSession) Write(cmd string) (int, error) {
|
||||
if s.Client == nil {
|
||||
return 0, fmt.Errorf("client is nil to content write failed")
|
||||
}
|
||||
return s.Client.Write([]byte(cmd))
|
||||
}
|
||||
|
||||
// Read 读取结果 等待一会才有结果
|
||||
func (s *TelnetClientSession) Read() []byte {
|
||||
if s.Client == nil {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
// 设置读取超时时间为100毫秒
|
||||
s.Client.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
_, err := s.Client.Read(buf)
|
||||
if err != nil {
|
||||
return []byte{}
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
// CombinedOutput 发送命令带结果返回
|
||||
func (s *TelnetClientSession) CombinedOutput(cmd string) (string, error) {
|
||||
n, err := s.Write(cmd)
|
||||
if n == 0 || err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
// 设置读取超时时间为1000毫秒
|
||||
s.Client.SetReadDeadline(time.Now().Add(1000 * time.Millisecond))
|
||||
n, err := s.Client.Read(tmp)
|
||||
if err != nil {
|
||||
// 判断是否是超时错误
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
buf.Write(tmp[:n])
|
||||
}
|
||||
defer buf.Reset()
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"be.ems/lib/core/utils/date"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
@@ -1,22 +1,30 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
sysService "be.ems/src/modules/system/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 AMFController 结构体
|
||||
var NewAMFController = &AMFController{
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
ueEventService: neDataService.NewUEEventImpl,
|
||||
ueEventService: neDataService.NewUEEventAMFImpl,
|
||||
}
|
||||
|
||||
// 网元AMF
|
||||
@@ -25,8 +33,8 @@ var NewAMFController = &AMFController{
|
||||
type AMFController struct {
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
// CDR会话事件服务
|
||||
ueEventService neDataService.IUEEvent
|
||||
// UE会话事件服务
|
||||
ueEventService neDataService.IUEEventAMF
|
||||
}
|
||||
|
||||
// UE会话列表
|
||||
@@ -34,19 +42,19 @@ type AMFController struct {
|
||||
// GET /ue/list
|
||||
func (s *AMFController) UEList(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys model.UEEventQuery
|
||||
var querys model.UEEventAMFQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
// return
|
||||
// }
|
||||
// querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
data := s.ueEventService.SelectPage(querys)
|
||||
@@ -78,3 +86,125 @@ func (s *AMFController) UERemove(c *gin.Context) {
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// UE会话列表导出
|
||||
//
|
||||
// POST /ue/export
|
||||
func (s *AMFController) UEExport(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.UEEventAMFQuery
|
||||
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
}
|
||||
data := s.ueEventService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]model.UEEventAMF)
|
||||
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("amf_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 第一行表头标题
|
||||
headerCells := map[string]string{
|
||||
"A1": "ID",
|
||||
"B1": "IMSI",
|
||||
"C1": "Event Type",
|
||||
"D1": "Result",
|
||||
"E1": "Time",
|
||||
}
|
||||
// 读取字典数据 UE 事件类型
|
||||
dictUEEventType := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_type")
|
||||
// 读取字典数据 UE 事件认证代码类型
|
||||
dictUEAauthCode := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_auth_code")
|
||||
// 读取字典数据 UE 事件CM状态
|
||||
dictUEEventCmState := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_cm_state")
|
||||
// 从第二行开始的数据
|
||||
dataCells := make([]map[string]any, 0)
|
||||
for i, row := range rows {
|
||||
idx := strconv.Itoa(i + 2)
|
||||
// 解析 JSON 字符串为 map
|
||||
var eventJSON map[string]interface{}
|
||||
err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON)
|
||||
if err != nil {
|
||||
logger.Warnf("UEExport Error parsing JSON: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// 取IMSI
|
||||
imsi := ""
|
||||
if v, ok := eventJSON["imsi"]; ok && v != nil {
|
||||
imsi = v.(string)
|
||||
}
|
||||
// 取类型
|
||||
eventType := ""
|
||||
for _, v := range dictUEEventType {
|
||||
if row.EventType == v.DictValue {
|
||||
eventType = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
// 取结果
|
||||
eventResult := ""
|
||||
// 取时间
|
||||
timeStr := ""
|
||||
if row.EventType == "auth-result" {
|
||||
if v, ok := eventJSON["authTime"]; ok && v != nil {
|
||||
timeStr = v.(string)
|
||||
}
|
||||
if v, ok := eventJSON["authCode"]; ok && v != nil {
|
||||
eventResult = v.(string)
|
||||
for _, v := range dictUEAauthCode {
|
||||
if eventResult == v.DictValue {
|
||||
eventResult = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if row.EventType == "detach" {
|
||||
if v, ok := eventJSON["detachTime"]; ok && v != nil {
|
||||
timeStr = v.(string)
|
||||
}
|
||||
eventResult = "Success"
|
||||
}
|
||||
if row.EventType == "cm-state" {
|
||||
if v, ok := eventJSON["changeTime"]; ok && v != nil {
|
||||
timeStr = v.(string)
|
||||
}
|
||||
if v, ok := eventJSON["status"]; ok && v != nil {
|
||||
eventResult = v.(string)
|
||||
for _, v := range dictUEEventCmState {
|
||||
if eventResult == v.DictValue {
|
||||
eventResult = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataCells = append(dataCells, map[string]any{
|
||||
"A" + idx: row.ID,
|
||||
"B" + idx: imsi,
|
||||
"C" + idx: eventType,
|
||||
"D" + idx: eventResult,
|
||||
"E" + idx: timeStr,
|
||||
})
|
||||
}
|
||||
|
||||
// 导出数据表格
|
||||
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.FileAttachment(saveFilePath, fileName)
|
||||
}
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
sysService "be.ems/src/modules/system/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 IMSController 结构体
|
||||
var NewIMSController = &IMSController{
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
cdrEventService: neDataService.NewCDREventImpl,
|
||||
cdrEventService: neDataService.NewCDREventIMSImpl,
|
||||
}
|
||||
|
||||
// 网元IMS
|
||||
@@ -26,7 +35,7 @@ type IMSController struct {
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
// CDR会话事件服务
|
||||
cdrEventService neDataService.ICDREvent
|
||||
cdrEventService neDataService.ICDREventIMS
|
||||
}
|
||||
|
||||
// CDR会话列表
|
||||
@@ -34,19 +43,19 @@ type IMSController struct {
|
||||
// GET /cdr/list
|
||||
func (s *IMSController) CDRList(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys model.CDREventQuery
|
||||
var querys model.CDREventIMSQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
// return
|
||||
// }
|
||||
// querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
data := s.cdrEventService.SelectPage(querys)
|
||||
@@ -78,3 +87,126 @@ func (s *IMSController) CDRRemove(c *gin.Context) {
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// CDR会话列表导出
|
||||
//
|
||||
// POST /cdr/export
|
||||
func (s *IMSController) CDRExport(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.CDREventIMSQuery
|
||||
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
}
|
||||
data := s.cdrEventService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]model.CDREventIMS)
|
||||
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("ims_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 第一行表头标题
|
||||
headerCells := map[string]string{
|
||||
"A1": "ID",
|
||||
"B1": "Record Behavior",
|
||||
"C1": "Type",
|
||||
"D1": "Called",
|
||||
"E1": "Caller",
|
||||
"F1": "Duration",
|
||||
"G1": "Result",
|
||||
"H1": "Time",
|
||||
}
|
||||
// 读取字典数据 CDR SIP响应代码类别类型
|
||||
dictCDRSipCode := sysService.NewSysDictDataImpl.SelectDictDataByType("cdr_sip_code")
|
||||
// 读取字典数据 CDR 呼叫类型
|
||||
dictCDRCallType := sysService.NewSysDictDataImpl.SelectDictDataByType("cdr_call_type")
|
||||
// 从第二行开始的数据
|
||||
dataCells := make([]map[string]any, 0)
|
||||
for i, row := range rows {
|
||||
idx := strconv.Itoa(i + 2)
|
||||
// 解析 JSON 字符串为 map
|
||||
var cdrJSON map[string]interface{}
|
||||
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
|
||||
if err != nil {
|
||||
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
// 记录类型
|
||||
recordType := ""
|
||||
if v, ok := cdrJSON["recordType"]; ok && v != nil {
|
||||
recordType = v.(string)
|
||||
}
|
||||
// 被叫
|
||||
called := ""
|
||||
if v, ok := cdrJSON["calledParty"]; ok && v != nil {
|
||||
called = v.(string)
|
||||
}
|
||||
// 主叫
|
||||
caller := ""
|
||||
if v, ok := cdrJSON["callerParty"]; ok && v != nil {
|
||||
caller = v.(string)
|
||||
}
|
||||
// 呼叫类型
|
||||
callType := "sms"
|
||||
callTypeLable := "SMS"
|
||||
if v, ok := cdrJSON["callType"]; ok && v != nil {
|
||||
callType = v.(string)
|
||||
for _, v := range dictCDRCallType {
|
||||
if callType == v.DictValue {
|
||||
callTypeLable = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 时长
|
||||
duration := "-"
|
||||
if v, ok := cdrJSON["callDuration"]; ok && v != nil && callType != "sms" {
|
||||
duration = fmt.Sprint(parse.Number(v))
|
||||
}
|
||||
// 呼叫结果 非短信都有code作为结果 sms短信都ok
|
||||
callResult := "Success"
|
||||
if v, ok := cdrJSON["cause"]; ok && v != nil && callType != "sms" {
|
||||
cause := fmt.Sprint(v)
|
||||
for _, v := range dictCDRSipCode {
|
||||
if cause == v.DictValue {
|
||||
callResult = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 取时间
|
||||
timeStr := ""
|
||||
if v, ok := cdrJSON["releaseTime"]; ok && v != nil {
|
||||
releaseTime := parse.Number(v)
|
||||
timeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DDTHH_MM_SSZ)
|
||||
}
|
||||
|
||||
dataCells = append(dataCells, map[string]any{
|
||||
"A" + idx: row.ID,
|
||||
"B" + idx: recordType,
|
||||
"C" + idx: callTypeLable,
|
||||
"D" + idx: called,
|
||||
"E" + idx: caller,
|
||||
"F" + idx: duration,
|
||||
"G" + idx: callResult,
|
||||
"H" + idx: timeStr,
|
||||
})
|
||||
}
|
||||
|
||||
// 导出数据表格
|
||||
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.FileAttachment(saveFilePath, fileName)
|
||||
}
|
||||
|
||||
200
src/modules/network_data/controller/mme.go
Normal file
200
src/modules/network_data/controller/mme.go
Normal file
@@ -0,0 +1,200 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
sysService "be.ems/src/modules/system/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 MMEController 结构体
|
||||
var NewMMEController = &MMEController{
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
ueEventService: neDataService.NewUEEventMMEImpl,
|
||||
}
|
||||
|
||||
// 网元MME
|
||||
//
|
||||
// PATH /mme
|
||||
type MMEController struct {
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
// UE会话事件服务
|
||||
ueEventService neDataService.IUEEventMME
|
||||
}
|
||||
|
||||
// UE会话列表
|
||||
//
|
||||
// GET /ue/list
|
||||
func (s *MMEController) UEList(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys model.UEEventMMEQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
// return
|
||||
// }
|
||||
// querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
data := s.ueEventService.SelectPage(querys)
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
// UE会话删除
|
||||
//
|
||||
// DELETE /ue/:ueIds
|
||||
func (s *MMEController) UERemove(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
ueIds := c.Param("ueIds")
|
||||
if ueIds == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
ids := strings.Split(ueIds, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
c.JSON(200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
rows, err := s.ueEventService.DeleteByIds(uniqueIDs)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// UE会话列表导出
|
||||
//
|
||||
// POST /ue/export
|
||||
func (s *MMEController) UEExport(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.UEEventMMEQuery
|
||||
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
}
|
||||
data := s.ueEventService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]model.UEEventMME)
|
||||
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("mme_ue_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 第一行表头标题
|
||||
headerCells := map[string]string{
|
||||
"A1": "ID",
|
||||
"B1": "IMSI",
|
||||
"C1": "Event Type",
|
||||
"D1": "Result",
|
||||
"E1": "Time",
|
||||
}
|
||||
// 读取字典数据 UE 事件类型
|
||||
dictUEEventType := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_type")
|
||||
// 读取字典数据 UE 事件认证代码类型
|
||||
dictUEAauthCode := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_auth_code")
|
||||
// 读取字典数据 UE 事件CM状态
|
||||
dictUEEventCmState := sysService.NewSysDictDataImpl.SelectDictDataByType("ue_event_cm_state")
|
||||
// 从第二行开始的数据
|
||||
dataCells := make([]map[string]any, 0)
|
||||
for i, row := range rows {
|
||||
idx := strconv.Itoa(i + 2)
|
||||
// 解析 JSON 字符串为 map
|
||||
var eventJSON map[string]interface{}
|
||||
err := json.Unmarshal([]byte(row.EventJSONStr), &eventJSON)
|
||||
if err != nil {
|
||||
logger.Warnf("UEExport Error parsing JSON: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// 取IMSI
|
||||
imsi := ""
|
||||
if v, ok := eventJSON["imsi"]; ok && v != nil {
|
||||
imsi = v.(string)
|
||||
}
|
||||
// 取类型
|
||||
eventType := row.EventType
|
||||
for _, v := range dictUEEventType {
|
||||
if row.EventType == v.DictValue {
|
||||
eventType = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
// 取结果
|
||||
eventResult := ""
|
||||
if v, ok := eventJSON["result"]; ok && v != nil {
|
||||
eventResult = v.(string)
|
||||
if row.EventType == "auth-result" {
|
||||
for _, v := range dictUEAauthCode {
|
||||
if eventResult == v.DictValue {
|
||||
eventResult = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if row.EventType == "cm-state" {
|
||||
for _, v := range dictUEEventCmState {
|
||||
if eventResult == v.DictValue {
|
||||
eventResult = i18n.TKey(language, v.DictLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 取时间
|
||||
timeStr := ""
|
||||
if v, ok := eventJSON["timestamp"]; ok && v != nil {
|
||||
rowTime := parse.Number(v)
|
||||
timeStr = date.ParseDateToStr(rowTime, date.YYYY_MM_DDTHH_MM_SSZ)
|
||||
}
|
||||
|
||||
dataCells = append(dataCells, map[string]any{
|
||||
"A" + idx: row.ID,
|
||||
"B" + idx: imsi,
|
||||
"C" + idx: eventType,
|
||||
"D" + idx: eventResult,
|
||||
"E" + idx: timeStr,
|
||||
})
|
||||
}
|
||||
|
||||
// 导出数据表格
|
||||
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.FileAttachment(saveFilePath, fileName)
|
||||
}
|
||||
@@ -1,32 +1,39 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// 实例化控制层 IMSController 结构体
|
||||
// 实例化控制层 SMFController 结构体
|
||||
var NewSMFController = &SMFController{
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
cdrEventService: neDataService.NewSMFCDREventImpl,
|
||||
cdrEventService: neDataService.NewCDREventSMFImpl,
|
||||
}
|
||||
|
||||
// 网元IMS
|
||||
// 网元SMF
|
||||
//
|
||||
// PATH /ims
|
||||
// PATH /smf
|
||||
type SMFController struct {
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
// SMF CDR会话事件服务
|
||||
cdrEventService neDataService.SMFCDREvent
|
||||
// CDR会话事件服务
|
||||
cdrEventService neDataService.ICDREventSMF
|
||||
}
|
||||
|
||||
// CDR会话列表
|
||||
@@ -34,19 +41,19 @@ type SMFController struct {
|
||||
// GET /cdr/list
|
||||
func (s *SMFController) CDRList(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys model.SMFCDREventQuery
|
||||
var querys model.CDREventSMFQuery
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
querys.RmUID = neInfo.RmUID
|
||||
// neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||
// if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||
// c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
// return
|
||||
// }
|
||||
// querys.RmUID = neInfo.RmUID
|
||||
|
||||
// 查询数据
|
||||
data := s.cdrEventService.SelectPage(querys)
|
||||
@@ -78,3 +85,174 @@ func (s *SMFController) CDRRemove(c *gin.Context) {
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// CDR会话列表导出
|
||||
//
|
||||
// POST /cdr/export
|
||||
func (s *SMFController) CDRExport(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
// 查询结果,根据查询条件结果,单页最大值限制
|
||||
var querys model.CDREventSMFQuery
|
||||
if err := c.ShouldBindBodyWith(&querys, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 限制导出数据集
|
||||
if querys.PageSize > 10000 {
|
||||
querys.PageSize = 10000
|
||||
}
|
||||
data := s.cdrEventService.SelectPage(querys)
|
||||
if parse.Number(data["total"]) == 0 {
|
||||
// 导出数据记录为空
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||||
return
|
||||
}
|
||||
rows := data["rows"].([]model.CDREventSMF)
|
||||
|
||||
// 导出文件名称
|
||||
fileName := fmt.Sprintf("smf_cdr_event_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||||
// 第一行表头标题
|
||||
headerCells := map[string]string{
|
||||
"A1": "ID",
|
||||
"B1": "Charging ID",
|
||||
"C1": "Subscriber ID Data",
|
||||
"D1": "Subscriber ID Type",
|
||||
"E1": "Data Volume Uplink",
|
||||
"F1": "Data Volume Downlink",
|
||||
"G1": "Data Total Volume",
|
||||
"H1": "Duration",
|
||||
"I1": "Invocation Time",
|
||||
"J1": "PDU Session Charging Information",
|
||||
}
|
||||
// 从第二行开始的数据
|
||||
dataCells := make([]map[string]any, 0)
|
||||
for i, row := range rows {
|
||||
idx := strconv.Itoa(i + 2)
|
||||
// 解析 JSON 字符串为 map
|
||||
var cdrJSON map[string]interface{}
|
||||
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
|
||||
if err != nil {
|
||||
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
// 计费ID
|
||||
chargingID := ""
|
||||
if v, ok := cdrJSON["chargingID"]; ok && v != nil {
|
||||
chargingID = fmt.Sprint(parse.Number(v))
|
||||
}
|
||||
// 订阅 ID 类型
|
||||
subscriptionIDType := "-"
|
||||
// 订阅 ID 数据
|
||||
subscriptionIDData := "-"
|
||||
if v, ok := cdrJSON["subscriberIdentifier"]; ok && v != nil {
|
||||
if sub, subOk := v.(map[string]any); subOk && sub != nil {
|
||||
subscriptionIDType = sub["subscriptionIDType"].(string)
|
||||
subscriptionIDData = sub["subscriptionIDData"].(string)
|
||||
}
|
||||
}
|
||||
// 数据量上行链路
|
||||
dataVolumeUplink := []string{}
|
||||
// 数据量下行链路
|
||||
dataVolumeDownlink := []string{}
|
||||
// 数据总量
|
||||
dataTotalVolume := []string{}
|
||||
if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil {
|
||||
usageList := v.([]any)
|
||||
if len(usageList) > 0 {
|
||||
for _, used := range usageList {
|
||||
usedUnit := used.(map[string]any)
|
||||
usedUnitList := usedUnit["usedUnitContainer"].([]any)
|
||||
if len(usedUnitList) > 0 {
|
||||
for _, data := range usedUnitList {
|
||||
udata := data.(map[string]any)
|
||||
if dup, dupOk := udata["dataVolumeUplink"]; dupOk {
|
||||
dataVolumeUplink = append(dataVolumeUplink, fmt.Sprint(parse.Number(dup)))
|
||||
}
|
||||
if ddown, ddownOk := udata["dataVolumeDownlink"]; ddownOk {
|
||||
dataVolumeDownlink = append(dataVolumeDownlink, fmt.Sprint(parse.Number(ddown)))
|
||||
}
|
||||
if dt, dtOk := udata["dataTotalVolume"]; dtOk {
|
||||
dataTotalVolume = append(dataTotalVolume, fmt.Sprint(parse.Number(dt)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 时长
|
||||
duration := "-"
|
||||
if v, ok := cdrJSON["duration"]; ok && v != nil {
|
||||
duration = fmt.Sprint(parse.Number(v))
|
||||
}
|
||||
// 调用时间
|
||||
invocationTimestamp := ""
|
||||
if v, ok := cdrJSON["invocationTimestamp"]; ok && v != nil {
|
||||
invocationTimestamp = v.(string)
|
||||
}
|
||||
// 记录打开时间
|
||||
pduSessionChargingInformation := ""
|
||||
if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil {
|
||||
pduInfo := v.(map[string]any)
|
||||
|
||||
User_Identifier := ""
|
||||
if v, ok := pduInfo["userIdentifier"]; ok && v != nil {
|
||||
User_Identifier = v.(string)
|
||||
}
|
||||
SSC_Mode := ""
|
||||
if v, ok := pduInfo["sSCMode"]; ok && v != nil {
|
||||
SSC_Mode = v.(string)
|
||||
}
|
||||
RAT_Type := ""
|
||||
if v, ok := pduInfo["rATType"]; ok && v != nil {
|
||||
RAT_Type = v.(string)
|
||||
}
|
||||
DNN_ID := ""
|
||||
if v, ok := pduInfo["dNNID"]; ok && v != nil {
|
||||
DNN_ID = v.(string)
|
||||
}
|
||||
PDU_Type := ""
|
||||
if v, ok := pduInfo["pDUType"]; ok && v != nil {
|
||||
PDU_Type = v.(string)
|
||||
}
|
||||
PDU_IPv4 := ""
|
||||
PDU_IPv6 := ""
|
||||
if v, ok := pduInfo["pDUAddress"]; ok && v != nil {
|
||||
pDUAddress := v.(map[string]any)
|
||||
if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil {
|
||||
PDU_IPv4 = addr.(string)
|
||||
}
|
||||
if addr, ok := pDUAddress["pDUIPv6AddresswithPrefix"]; ok && addr != nil {
|
||||
PDU_IPv6 = addr.(string)
|
||||
}
|
||||
}
|
||||
|
||||
pduSessionChargingInformation = fmt.Sprintf(`User Identifier: %s
|
||||
SSC Mode: %s RAT Type: %s DNN ID: %s
|
||||
PDU Type: %s
|
||||
PDU IPv4 Address: %s
|
||||
PDU IPv6 Addres Swith Prefix: %s`, User_Identifier, SSC_Mode, RAT_Type, DNN_ID, PDU_Type, PDU_IPv4, PDU_IPv6)
|
||||
}
|
||||
|
||||
dataCells = append(dataCells, map[string]any{
|
||||
"A" + idx: row.ID,
|
||||
"B" + idx: chargingID,
|
||||
"C" + idx: subscriptionIDData,
|
||||
"D" + idx: subscriptionIDType,
|
||||
"E" + idx: strings.Join(dataVolumeUplink, ","),
|
||||
"F" + idx: strings.Join(dataVolumeDownlink, ","),
|
||||
"G" + idx: strings.Join(dataTotalVolume, ","),
|
||||
"H" + idx: duration,
|
||||
"I" + idx: invocationTimestamp,
|
||||
"J" + idx: pduSessionChargingInformation,
|
||||
})
|
||||
}
|
||||
|
||||
// 导出数据表格
|
||||
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.FileAttachment(saveFilePath, fileName)
|
||||
}
|
||||
|
||||
@@ -2,18 +2,19 @@ package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mmlclient "be.ems/lib/core/mml_client"
|
||||
"be.ems/src/framework/constants/uploadsubpath"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/ssh"
|
||||
"be.ems/src/framework/utils/telnet"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_element/model"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
@@ -21,21 +22,21 @@ import (
|
||||
|
||||
// 实例化控制层 UDMAuthController 结构体
|
||||
var NewUDMAuth = &UDMAuthController{
|
||||
udmAuthService: neService.NewUDMAuthImpl,
|
||||
udmAuthService: neDataService.NewUDMAuthImpl,
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
}
|
||||
|
||||
// UDM鉴权用户请求
|
||||
// UDM鉴权用户
|
||||
//
|
||||
// PATH /udm/auth
|
||||
type UDMAuthController struct {
|
||||
// UDM鉴权信息服务
|
||||
udmAuthService neService.IUDMAuth
|
||||
udmAuthService neDataService.IUDMAuth
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
}
|
||||
|
||||
// UDM鉴权用户-获取全部保存数据库
|
||||
// UDM鉴权用户重载数据
|
||||
//
|
||||
// POST /resetData/:neId
|
||||
func (s *UDMAuthController) ResetData(c *gin.Context) {
|
||||
@@ -47,21 +48,21 @@ func (s *UDMAuthController) ResetData(c *gin.Context) {
|
||||
}
|
||||
|
||||
neId = ""
|
||||
data := s.udmAuthService.Save(neId)
|
||||
data := s.udmAuthService.ResetData(neId)
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM鉴权用户
|
||||
// UDM鉴权用户列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *UDMAuthController) List(c *gin.Context) {
|
||||
querys := ctx.QueryMap(c)
|
||||
querys["neId"] = ""
|
||||
data := s.udmAuthService.Page(querys)
|
||||
data := s.udmAuthService.SelectPage(querys)
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-信息
|
||||
// UDM鉴权用户信息
|
||||
//
|
||||
// GET /:neId/:imsi
|
||||
func (s *UDMAuthController) Info(c *gin.Context) {
|
||||
@@ -80,10 +81,16 @@ func (s *UDMAuthController) Info(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("dsp authdat:imsi=%s", imsi)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToMap(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("dsp authdat:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToMap(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -94,31 +101,31 @@ func (s *UDMAuthController) Info(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 查询数据库是否存在并存入
|
||||
neId = ""
|
||||
var userInfo model.UDMAuth
|
||||
list := s.udmAuthService.List(model.UDMAuth{NeID: neId, Imsi: imsi})
|
||||
if len(list) > 0 {
|
||||
userInfo = list[0]
|
||||
// 返回查询的用户信息
|
||||
userInfo.Amf = data["amf"]
|
||||
userInfo.AlgoIndex = data["algo"]
|
||||
userInfo.Opc = data["opc"]
|
||||
userInfo.Ki = data["ki"]
|
||||
} else {
|
||||
userInfo := model.UDMAuth{
|
||||
Imsi: imsi,
|
||||
Amf: data["amf"],
|
||||
AlgoIndex: data["algo"],
|
||||
Opc: data["opc"],
|
||||
Ki: data["ki"],
|
||||
}
|
||||
s.udmAuthService.Insert(neId, userInfo)
|
||||
u := model.UDMAuth{
|
||||
IMSI: imsi,
|
||||
Amf: data["amf"],
|
||||
Status: "1",
|
||||
Ki: data["ki"],
|
||||
AlgoIndex: data["algo"],
|
||||
Opc: data["opc"],
|
||||
NeId: neId,
|
||||
}
|
||||
c.JSON(200, result.OkData(userInfo))
|
||||
|
||||
// 查询imsi存在赋予id用于更新
|
||||
list := s.udmAuthService.SelectList(u)
|
||||
if len(list) > 0 {
|
||||
item := list[0]
|
||||
if item.ID != "" {
|
||||
u.ID = item.ID
|
||||
}
|
||||
}
|
||||
go s.udmAuthService.Insert(neId, u)
|
||||
|
||||
c.JSON(200, result.OkData(u))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-增加
|
||||
// UDM鉴权用户新增
|
||||
//
|
||||
// POST /:neId
|
||||
func (s *UDMAuthController) Add(c *gin.Context) {
|
||||
@@ -131,7 +138,7 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
||||
|
||||
var body model.UDMAuth
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.Imsi == "" {
|
||||
if err != nil || body.IMSI == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
@@ -143,10 +150,16 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("add authdat:imsi=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.Imsi, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("add authdat:imsi=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.IMSI, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -155,12 +168,12 @@ func (s *UDMAuthController) Add(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmAuthService.Insert(neId, body)
|
||||
go s.udmAuthService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-批量添加
|
||||
// UDM鉴权用户批量新增
|
||||
//
|
||||
// POST /:neId/:num
|
||||
func (s *UDMAuthController) Adds(c *gin.Context) {
|
||||
@@ -174,7 +187,7 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
||||
|
||||
var body model.UDMAuth
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.Imsi == "" {
|
||||
if err != nil || body.IMSI == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
@@ -186,10 +199,16 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("baa authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.Imsi, num, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("baa authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s,opc=%s", body.IMSI, num, body.Ki, body.Amf, body.AlgoIndex, body.Opc)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -198,12 +217,12 @@ func (s *UDMAuthController) Adds(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmAuthService.Inserts(neId, body, num)
|
||||
go s.udmAuthService.LoadData(neId, body.IMSI, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-修改
|
||||
// UDM鉴权用户修改
|
||||
//
|
||||
// PUT /:neId
|
||||
func (s *UDMAuthController) Edit(c *gin.Context) {
|
||||
@@ -216,7 +235,7 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
||||
|
||||
var body model.UDMAuth
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.Imsi == "" {
|
||||
if err != nil || body.IMSI == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
@@ -228,23 +247,29 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("mod authdata:imsi=%s", body.Imsi)
|
||||
// 修改的参数名称
|
||||
if body.Ki != "" {
|
||||
msg += fmt.Sprintf(",ki=%s", body.Ki)
|
||||
}
|
||||
if body.Amf != "" {
|
||||
msg += fmt.Sprintf(",amf=%s", body.Amf)
|
||||
}
|
||||
if body.AlgoIndex != "" {
|
||||
msg += fmt.Sprintf(",algo=%s", body.AlgoIndex)
|
||||
}
|
||||
if body.Opc != "" {
|
||||
msg += fmt.Sprintf(",opc=%s", body.Opc)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("mod authdata:imsi=%s", body.IMSI)
|
||||
// 修改的参数名称
|
||||
if body.Ki != "" {
|
||||
cmd += fmt.Sprintf(",ki=%s", body.Ki)
|
||||
}
|
||||
if body.Amf != "" {
|
||||
cmd += fmt.Sprintf(",amf=%s", body.Amf)
|
||||
}
|
||||
if body.AlgoIndex != "" {
|
||||
cmd += fmt.Sprintf(",algo=%s", body.AlgoIndex)
|
||||
}
|
||||
if body.Opc != "" {
|
||||
cmd += fmt.Sprintf(",opc=%s", body.Opc)
|
||||
}
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -253,12 +278,12 @@ func (s *UDMAuthController) Edit(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmAuthService.Update(neId, body)
|
||||
go s.udmAuthService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-删除
|
||||
// UDM鉴权用户删除
|
||||
//
|
||||
// DELETE /:neId/:imsi
|
||||
func (s *UDMAuthController) Remove(c *gin.Context) {
|
||||
@@ -285,27 +310,34 @@ func (s *UDMAuthController) Remove(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
resultData := map[string]string{}
|
||||
for _, imsi := range uniqueIDs {
|
||||
msg := fmt.Sprintf("del authdat:imsi=%s", imsi)
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("del authdat:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
resultData[imsi] = err.Error()
|
||||
continue
|
||||
}
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmAuthService.Delete(neId, imsi)
|
||||
resultData[imsi] = data
|
||||
go s.udmAuthService.Delete(neId, imsi)
|
||||
}
|
||||
resultData[imsi] = data
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(resultData))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-批量删除
|
||||
// UDM鉴权用户批量删除
|
||||
//
|
||||
// DELETE /:neId/:imsi/:num
|
||||
func (s *UDMAuthController) Removes(c *gin.Context) {
|
||||
@@ -325,10 +357,16 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("bde authdat:start_imsi=%s,sub_num=%s", imsi, num)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("bde authdat:start_imsi=%s,sub_num=%s", imsi, num)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -337,12 +375,12 @@ func (s *UDMAuthController) Removes(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmAuthService.Deletes(neId, imsi, num)
|
||||
go s.udmAuthService.LoadData(neId, imsi, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM鉴权用户-导出
|
||||
// UDM鉴权用户导出
|
||||
//
|
||||
// POST /export
|
||||
func (s *UDMAuthController) Export(c *gin.Context) {
|
||||
@@ -358,14 +396,14 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
||||
}
|
||||
|
||||
if !(body.Type == "csv" || body.Type == "txt") {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errExportType")))
|
||||
return
|
||||
}
|
||||
|
||||
neId := ""
|
||||
list := s.udmAuthService.List(model.UDMAuth{NeID: neId})
|
||||
list := s.udmAuthService.SelectList(model.UDMAuth{NeId: neId})
|
||||
// 文件名
|
||||
fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
|
||||
fileName := fmt.Sprintf("udm_auth_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
|
||||
filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||
|
||||
if body.Type == "csv" {
|
||||
@@ -373,7 +411,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
||||
data := [][]string{}
|
||||
data = append(data, []string{"imsi", "ki", "algo", "amf", "opc"})
|
||||
for _, v := range list {
|
||||
data = append(data, []string{v.Imsi, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
|
||||
data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
|
||||
}
|
||||
// 输出到文件
|
||||
err := file.WriterFileCSV(data, filePath)
|
||||
@@ -387,7 +425,7 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
||||
// 转换数据
|
||||
data := [][]string{}
|
||||
for _, v := range list {
|
||||
data = append(data, []string{v.Imsi, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
|
||||
data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, v.Opc})
|
||||
}
|
||||
// 输出到文件
|
||||
err = file.WriterFileTXT(data, ",", filePath)
|
||||
@@ -400,55 +438,68 @@ func (s *UDMAuthController) Export(c *gin.Context) {
|
||||
c.FileAttachment(filePath, fileName)
|
||||
}
|
||||
|
||||
// UDM鉴权用户-导入
|
||||
// UDM鉴权用户导入
|
||||
//
|
||||
// POST /import
|
||||
func (s *UDMAuthController) Import(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.PostForm("neId")
|
||||
if neId == "" {
|
||||
var body struct {
|
||||
NeId string `json:"neId" binding:"required"`
|
||||
UploadPath string `json:"uploadPath" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
formFile, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 获取文件名
|
||||
if !(strings.HasSuffix(formFile.Filename, ".csv") || strings.HasSuffix(formFile.Filename, ".txt")) {
|
||||
|
||||
// 判断文件名
|
||||
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserAuthFileFormat")))
|
||||
return
|
||||
}
|
||||
// 上传文件转存
|
||||
upFilePath, err := file.TransferUploadFile(formFile, uploadsubpath.IMPORT, nil)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
|
||||
if neInfo.NeId != body.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 本地文件
|
||||
localPath := file.ParseUploadFilePath(upFilePath)
|
||||
nePath := "/tmp" //config.Get("mml.upload").(string)
|
||||
// 复制到远程
|
||||
err = ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
fileName := localPath[strings.LastIndex(localPath, "/")+1:]
|
||||
msg := fmt.Sprintf("import authdat:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))
|
||||
// 本地文件
|
||||
localFilePath := file.ParseUploadFilePath(body.UploadPath)
|
||||
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
|
||||
// 复制到远程
|
||||
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg("error uploading file"))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("import authdat:path=%s", neFilePath)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -456,15 +507,15 @@ func (s *UDMAuthController) Import(c *gin.Context) {
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
if strings.HasSuffix(fileName, ".csv") {
|
||||
data := file.ReadFileCSV(localPath)
|
||||
neId = ""
|
||||
go s.udmAuthService.InsertCSV(neId, data)
|
||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||
data := file.ReadFileCSV(localFilePath)
|
||||
neId := ""
|
||||
go s.udmAuthService.InsertData(neId, "csv", data)
|
||||
}
|
||||
if strings.HasSuffix(fileName, ".txt") {
|
||||
data := file.ReadFileTXT(",", localPath)
|
||||
neId = ""
|
||||
go s.udmAuthService.InsertTxt(neId, data)
|
||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||
data := file.ReadFileTXT(",", localFilePath)
|
||||
neId := ""
|
||||
go s.udmAuthService.InsertData(neId, "txt", data)
|
||||
}
|
||||
}
|
||||
c.JSON(200, result.OkMsg(data))
|
||||
@@ -2,19 +2,20 @@ package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mmlclient "be.ems/lib/core/mml_client"
|
||||
"be.ems/src/framework/constants/uploadsubpath"
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/file"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/ssh"
|
||||
"be.ems/src/framework/utils/telnet"
|
||||
"be.ems/src/framework/vo/result"
|
||||
"be.ems/src/modules/network_element/model"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
neDataService "be.ems/src/modules/network_data/service"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
@@ -22,21 +23,21 @@ import (
|
||||
|
||||
// 实例化控制层 UDMSubController 结构体
|
||||
var NewUDMSub = &UDMSubController{
|
||||
udmSubService: neService.NewUDMSubImpl,
|
||||
udmSubService: neDataService.NewUDMSubImpl,
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
}
|
||||
|
||||
// UDM签约用户请求
|
||||
// UDM签约用户
|
||||
//
|
||||
// PATH /udm/sub
|
||||
type UDMSubController struct {
|
||||
// UDM鉴权信息服务
|
||||
udmSubService neService.IUDMSub
|
||||
// UDM签约信息服务
|
||||
udmSubService neDataService.IUDMSub
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
}
|
||||
|
||||
// UDM签约用户-获取全部保存数据库
|
||||
// UDM签约用户重载数据
|
||||
//
|
||||
// POST /resetData/:neId
|
||||
func (s *UDMSubController) ResetData(c *gin.Context) {
|
||||
@@ -48,21 +49,21 @@ func (s *UDMSubController) ResetData(c *gin.Context) {
|
||||
}
|
||||
|
||||
neId = ""
|
||||
data := s.udmSubService.Save(neId)
|
||||
data := s.udmSubService.ResetData(neId)
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM签约用户
|
||||
// UDM签约用户列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *UDMSubController) List(c *gin.Context) {
|
||||
querys := ctx.QueryMap(c)
|
||||
querys["neId"] = ""
|
||||
data := s.udmSubService.Page(querys)
|
||||
data := s.udmSubService.SelectPage(querys)
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
// UDM签约用户-信息
|
||||
// UDM签约用户信息
|
||||
//
|
||||
// GET /:neId/:imsi
|
||||
func (s *UDMSubController) Info(c *gin.Context) {
|
||||
@@ -81,10 +82,16 @@ func (s *UDMSubController) Info(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("dsp udmuser:imsi=%s", imsi)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToMap(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("dsp udmuser:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToMap(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -103,8 +110,9 @@ func (s *UDMSubController) Info(c *gin.Context) {
|
||||
if imsMsisdnLen != -1 {
|
||||
msisdn = msisdn[:imsMsisdnLen]
|
||||
}
|
||||
userInfo := model.UDMSub{
|
||||
Imsi: imsi,
|
||||
neId = ""
|
||||
u := model.UDMSub{
|
||||
IMSI: imsi,
|
||||
Msisdn: msisdn,
|
||||
Ambr: data["AMBR"],
|
||||
Arfb: data["AreaForbidden"],
|
||||
@@ -114,35 +122,37 @@ func (s *UDMSubController) Info(c *gin.Context) {
|
||||
Nssai: data["NSSAI"],
|
||||
SmfSel: data["Smf-Selection"],
|
||||
Rat: fmt.Sprint(rat),
|
||||
NeId: neId,
|
||||
}
|
||||
// 1,64,24,65,def_eps,1,2,010200000000,-
|
||||
if v, ok := data["EPS-Data"]; ok {
|
||||
userInfo.EpsDat = v
|
||||
u.EpsDat = v
|
||||
arr := strings.Split(v, ",")
|
||||
userInfo.EpsFlag = arr[0]
|
||||
userInfo.EpsOdb = arr[1]
|
||||
userInfo.HplmnOdb = arr[2]
|
||||
userInfo.Ard = arr[3]
|
||||
userInfo.Epstpl = arr[4]
|
||||
userInfo.ContextId = arr[5]
|
||||
userInfo.ApnContext = arr[7]
|
||||
userInfo.StaticIp = arr[8]
|
||||
u.EpsFlag = arr[0]
|
||||
u.EpsOdb = arr[1]
|
||||
u.HplmnOdb = arr[2]
|
||||
u.Ard = arr[3]
|
||||
u.Epstpl = arr[4]
|
||||
u.ContextId = arr[5]
|
||||
u.ApnContext = arr[7]
|
||||
// [6] 是不要的,导入和导出不用
|
||||
u.StaticIp = arr[8]
|
||||
}
|
||||
|
||||
// 查询数据库是否存在并存入更新
|
||||
neId = ""
|
||||
list := s.udmSubService.List(model.UDMSub{NeID: neId, Imsi: imsi})
|
||||
// 查询imsi存在赋予id用于更新
|
||||
list := s.udmSubService.SelectList(u)
|
||||
if len(list) > 0 {
|
||||
listItme := list[0]
|
||||
userInfo.ID = listItme.ID
|
||||
s.udmSubService.Update(neId, userInfo)
|
||||
} else {
|
||||
s.udmSubService.Insert(neId, userInfo)
|
||||
item := list[0]
|
||||
if item.ID != "" {
|
||||
u.ID = item.ID
|
||||
}
|
||||
}
|
||||
c.JSON(200, result.OkData(userInfo))
|
||||
go s.udmSubService.Insert(neId, u)
|
||||
|
||||
c.JSON(200, result.OkData(u))
|
||||
}
|
||||
|
||||
// UDM签约用户-增加
|
||||
// UDM签约用户新增
|
||||
//
|
||||
// POST /:neId
|
||||
func (s *UDMSubController) Add(c *gin.Context) {
|
||||
@@ -155,7 +165,7 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
||||
|
||||
var body model.UDMSub
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.Imsi == "" {
|
||||
if err != nil || body.IMSI == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
@@ -167,15 +177,21 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("add udmuser:imsi=%s,msisdn=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
|
||||
body.Imsi, body.Msisdn, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
|
||||
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
||||
if body.StaticIp != "" {
|
||||
msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("add udmuser:imsi=%s,msisdn=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
|
||||
body.IMSI, body.Msisdn, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
|
||||
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
||||
if body.StaticIp != "" {
|
||||
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||
}
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -184,12 +200,12 @@ func (s *UDMSubController) Add(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmSubService.Insert(neId, body)
|
||||
go s.udmSubService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM签约用户-批量添加
|
||||
// UDM签约用户批量新增
|
||||
//
|
||||
// POST /:neId/:num
|
||||
func (s *UDMSubController) Adds(c *gin.Context) {
|
||||
@@ -203,7 +219,7 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
||||
|
||||
var body model.UDMSub
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.Imsi == "" {
|
||||
if err != nil || body.IMSI == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
@@ -215,15 +231,21 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("baa udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
|
||||
body.Imsi, body.Msisdn, num, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
|
||||
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
||||
if body.StaticIp != "" {
|
||||
msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("baa udmuser:start_imsi=%s,start_msisdn=%s,sub_num=%s,ambr=%s,nssai=%s,arfb=%s,sar=%s,rat=%s,cn=%s,smf_sel=%s,sm_data=%s,eps_flag=%s,eps_odb=%s,hplmn_odb=%s,ard=%s,epstpl=%s,context_id=%s,apn_context=%s",
|
||||
body.IMSI, body.Msisdn, num, body.Ambr, body.Nssai, body.Arfb, body.Sar, body.Rat, body.Cn, body.SmfSel, body.SmData, body.EpsFlag, body.EpsOdb, body.HplmnOdb, body.Ard, body.Epstpl, body.ContextId, body.ApnContext)
|
||||
// static_ip指给4G UE分配的静态IP,没有可不带此字段名,批量添加IP会自动递增
|
||||
if body.StaticIp != "" {
|
||||
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||
}
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -232,12 +254,12 @@ func (s *UDMSubController) Adds(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmSubService.Inserts(neId, body, num)
|
||||
go s.udmSubService.LoadData(neId, body.IMSI, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM签约用户-修改
|
||||
// UDM签约用户修改
|
||||
//
|
||||
// PUT /:neId
|
||||
func (s *UDMSubController) Edit(c *gin.Context) {
|
||||
@@ -250,7 +272,7 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
||||
|
||||
var body model.UDMSub
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.Imsi == "" {
|
||||
if err != nil || body.IMSI == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
@@ -262,65 +284,71 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("mod udmuser:imsi=%s", body.Imsi)
|
||||
// 修改的参数名称
|
||||
if body.Msisdn != "" {
|
||||
msg += fmt.Sprintf(",msisdn=%s", body.Msisdn)
|
||||
}
|
||||
if body.Ambr != "" {
|
||||
msg += fmt.Sprintf(",ambr=%s", body.Ambr)
|
||||
}
|
||||
if body.Nssai != "" {
|
||||
msg += fmt.Sprintf(",nssai=%s", body.Nssai)
|
||||
}
|
||||
if body.Arfb != "" {
|
||||
msg += fmt.Sprintf(",arfb=%s", body.Arfb)
|
||||
}
|
||||
if body.Sar != "" {
|
||||
msg += fmt.Sprintf(",sar=%s", body.Sar)
|
||||
}
|
||||
if body.Rat != "" {
|
||||
msg += fmt.Sprintf(",rat=%s", body.Rat)
|
||||
}
|
||||
if body.Cn != "" {
|
||||
msg += fmt.Sprintf(",cn=%s", body.Cn)
|
||||
}
|
||||
if body.SmfSel != "" {
|
||||
msg += fmt.Sprintf(",smf_sel=%s", body.SmfSel)
|
||||
}
|
||||
if body.SmData != "" {
|
||||
msg += fmt.Sprintf(",sm_data=%s", body.SmData)
|
||||
}
|
||||
if body.EpsDat != "" {
|
||||
msg += fmt.Sprintf(",eps_dat=%s", body.EpsDat)
|
||||
}
|
||||
if body.EpsFlag != "" {
|
||||
msg += fmt.Sprintf(",eps_flag=%s", body.EpsFlag)
|
||||
}
|
||||
if body.EpsOdb != "" {
|
||||
msg += fmt.Sprintf(",eps_odb=%s", body.EpsOdb)
|
||||
}
|
||||
if body.HplmnOdb != "" {
|
||||
msg += fmt.Sprintf(",hplmn_odb=%s", body.HplmnOdb)
|
||||
}
|
||||
if body.Epstpl != "" {
|
||||
msg += fmt.Sprintf(",epstpl=%s", body.Epstpl)
|
||||
}
|
||||
if body.Ard != "" {
|
||||
msg += fmt.Sprintf(",ard=%s", body.Ard)
|
||||
}
|
||||
if body.ContextId != "" {
|
||||
msg += fmt.Sprintf(",context_id=%s", body.ContextId)
|
||||
}
|
||||
if body.ApnContext != "" {
|
||||
msg += fmt.Sprintf(",apn_context=%s", body.ApnContext)
|
||||
}
|
||||
if body.StaticIp != "" {
|
||||
msg += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("mod udmuser:imsi=%s", body.IMSI)
|
||||
// 修改的参数名称
|
||||
if body.Msisdn != "" {
|
||||
cmd += fmt.Sprintf(",msisdn=%s", body.Msisdn)
|
||||
}
|
||||
if body.Ambr != "" {
|
||||
cmd += fmt.Sprintf(",ambr=%s", body.Ambr)
|
||||
}
|
||||
if body.Nssai != "" {
|
||||
cmd += fmt.Sprintf(",nssai=%s", body.Nssai)
|
||||
}
|
||||
if body.Arfb != "" {
|
||||
cmd += fmt.Sprintf(",arfb=%s", body.Arfb)
|
||||
}
|
||||
if body.Sar != "" {
|
||||
cmd += fmt.Sprintf(",sar=%s", body.Sar)
|
||||
}
|
||||
if body.Rat != "" {
|
||||
cmd += fmt.Sprintf(",rat=%s", body.Rat)
|
||||
}
|
||||
if body.Cn != "" {
|
||||
cmd += fmt.Sprintf(",cn=%s", body.Cn)
|
||||
}
|
||||
if body.SmfSel != "" {
|
||||
cmd += fmt.Sprintf(",smf_sel=%s", body.SmfSel)
|
||||
}
|
||||
if body.SmData != "" {
|
||||
cmd += fmt.Sprintf(",sm_data=%s", body.SmData)
|
||||
}
|
||||
if body.EpsDat != "" {
|
||||
cmd += fmt.Sprintf(",eps_dat=%s", body.EpsDat)
|
||||
}
|
||||
if body.EpsFlag != "" {
|
||||
cmd += fmt.Sprintf(",eps_flag=%s", body.EpsFlag)
|
||||
}
|
||||
if body.EpsOdb != "" {
|
||||
cmd += fmt.Sprintf(",eps_odb=%s", body.EpsOdb)
|
||||
}
|
||||
if body.HplmnOdb != "" {
|
||||
cmd += fmt.Sprintf(",hplmn_odb=%s", body.HplmnOdb)
|
||||
}
|
||||
if body.Epstpl != "" {
|
||||
cmd += fmt.Sprintf(",epstpl=%s", body.Epstpl)
|
||||
}
|
||||
if body.Ard != "" {
|
||||
cmd += fmt.Sprintf(",ard=%s", body.Ard)
|
||||
}
|
||||
if body.ContextId != "" {
|
||||
cmd += fmt.Sprintf(",context_id=%s", body.ContextId)
|
||||
}
|
||||
if body.ApnContext != "" {
|
||||
cmd += fmt.Sprintf(",apn_context=%s", body.ApnContext)
|
||||
}
|
||||
if body.StaticIp != "" {
|
||||
cmd += fmt.Sprintf(",static_ip=%s", body.StaticIp)
|
||||
}
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -329,12 +357,12 @@ func (s *UDMSubController) Edit(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmSubService.Update(neId, body)
|
||||
go s.udmSubService.Insert(neId, body)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM签约用户-删除
|
||||
// UDM签约用户删除
|
||||
//
|
||||
// DELETE /:neId/:imsi
|
||||
func (s *UDMSubController) Remove(c *gin.Context) {
|
||||
@@ -361,27 +389,34 @@ func (s *UDMSubController) Remove(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
resultData := map[string]string{}
|
||||
for _, imsi := range uniqueIDs {
|
||||
msg := fmt.Sprintf("del udmuser:imsi=%s", imsi)
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("del udmuser:imsi=%s", imsi)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
resultData[imsi] = err.Error()
|
||||
continue
|
||||
}
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmSubService.Delete(neId, imsi)
|
||||
resultData[imsi] = data
|
||||
go s.udmSubService.Delete(neId, imsi)
|
||||
}
|
||||
resultData[imsi] = data
|
||||
}
|
||||
|
||||
c.JSON(200, result.OkData(resultData))
|
||||
}
|
||||
|
||||
// UDM签约用户-批量删除
|
||||
// UDM签约用户批量删除
|
||||
//
|
||||
// DELETE /:neId/:imsi/:num
|
||||
func (s *UDMSubController) Removes(c *gin.Context) {
|
||||
@@ -401,10 +436,16 @@ func (s *UDMSubController) Removes(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("bde udmuser:start_imsi=%s,sub_num=%s", imsi, num)
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient("UDM", neId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("bde udmuser:start_imsi=%s,sub_num=%s", imsi, num)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -413,12 +454,12 @@ func (s *UDMSubController) Removes(c *gin.Context) {
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
neId = ""
|
||||
s.udmSubService.Deletes(neId, imsi, num)
|
||||
go s.udmSubService.LoadData(neId, imsi, num)
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// UDM签约用户-导出
|
||||
// UDM签约用户导出
|
||||
//
|
||||
// POST /export
|
||||
func (s *UDMSubController) Export(c *gin.Context) {
|
||||
@@ -439,9 +480,9 @@ func (s *UDMSubController) Export(c *gin.Context) {
|
||||
}
|
||||
|
||||
neId := ""
|
||||
list := s.udmSubService.List(model.UDMSub{NeID: neId})
|
||||
list := s.udmSubService.SelectList(model.UDMSub{NeId: neId})
|
||||
// 文件名
|
||||
fileName := fmt.Sprintf("OMC_SUB_USER_EXPORT_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
|
||||
fileName := fmt.Sprintf("udm_sub_user_export_%s_%d.%s", neId, time.Now().UnixMilli(), body.Type)
|
||||
filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
|
||||
|
||||
if body.Type == "csv" {
|
||||
@@ -450,7 +491,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
|
||||
data = append(data, []string{"imsi", "msisdn", "ambr", "nssai", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"})
|
||||
for _, v := range list {
|
||||
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
|
||||
data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
|
||||
data = append(data, []string{v.IMSI, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
|
||||
}
|
||||
// 输出到文件
|
||||
err = file.WriterFileCSV(data, filePath)
|
||||
@@ -465,7 +506,7 @@ func (s *UDMSubController) Export(c *gin.Context) {
|
||||
data := [][]string{}
|
||||
for _, v := range list {
|
||||
epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
|
||||
data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
|
||||
data = append(data, []string{v.IMSI, v.Msisdn, v.Ambr, v.Nssai, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, epsDat})
|
||||
}
|
||||
// 输出到文件
|
||||
err = file.WriterFileTXT(data, ",", filePath)
|
||||
@@ -478,55 +519,68 @@ func (s *UDMSubController) Export(c *gin.Context) {
|
||||
c.FileAttachment(filePath, fileName)
|
||||
}
|
||||
|
||||
// UDM签约用户-导入
|
||||
// UDM签约用户导入
|
||||
//
|
||||
// POST /import
|
||||
func (s *UDMSubController) Import(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neId := c.PostForm("neId")
|
||||
if neId == "" {
|
||||
var body struct {
|
||||
NeId string `json:"neId" binding:"required"`
|
||||
UploadPath string `json:"uploadPath" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
formFile, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 获取文件名
|
||||
if !(strings.HasSuffix(formFile.Filename, ".csv") || strings.HasSuffix(formFile.Filename, ".txt")) {
|
||||
|
||||
// 判断文件名
|
||||
if !(strings.HasSuffix(body.UploadPath, ".csv") || strings.HasSuffix(body.UploadPath, ".txt")) {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "ne.udm.errImportUserSubFileFormat")))
|
||||
return
|
||||
}
|
||||
// 上传文件转存
|
||||
upFilePath, err := file.TransferUploadFile(formFile, uploadsubpath.IMPORT, nil)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询网元获取IP
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", neId)
|
||||
if neInfo.NeId != neId || neInfo.IP == "" {
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("UDM", body.NeId)
|
||||
if neInfo.NeId != body.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 本地文件
|
||||
localPath := file.ParseUploadFilePath(upFilePath)
|
||||
nePath := "/tmp" //config.Get("mml.upload").(string)
|
||||
// 复制到远程
|
||||
err = ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
fileName := localPath[strings.LastIndex(localPath, "/")+1:]
|
||||
msg := fmt.Sprintf("import udmuser:path=%s", fmt.Sprintf("%s/%s", nePath, fileName))
|
||||
// 本地文件
|
||||
localFilePath := file.ParseUploadFilePath(body.UploadPath)
|
||||
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
|
||||
// 复制到远程
|
||||
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg("error uploading file"))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元主机的Telnet客户端
|
||||
telnetClient, err := s.neInfoService.NeRunTelnetClient(neInfo.NeType, neInfo.NeId, 1)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer telnetClient.Close()
|
||||
|
||||
// 发送MML
|
||||
data, err := mmlclient.MMLSendMsgToString(neInfo.IP, msg)
|
||||
cmd := fmt.Sprintf("import udmuser:path=%s", neFilePath)
|
||||
data, err := telnet.ConvertToStr(telnetClient, cmd)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
@@ -534,15 +588,15 @@ func (s *UDMSubController) Import(c *gin.Context) {
|
||||
|
||||
// 命令ok时
|
||||
if strings.Contains(data, "ok") {
|
||||
if strings.HasSuffix(fileName, ".csv") {
|
||||
data := file.ReadFileCSV(localPath)
|
||||
neId = ""
|
||||
go s.udmSubService.InsertCSV(neId, data)
|
||||
if strings.HasSuffix(body.UploadPath, ".csv") {
|
||||
data := file.ReadFileCSV(localFilePath)
|
||||
neId := ""
|
||||
go s.udmSubService.InsertData(neId, "csv", data)
|
||||
}
|
||||
if strings.HasSuffix(fileName, ".txt") {
|
||||
data := file.ReadFileTXT(",", localPath)
|
||||
neId = ""
|
||||
go s.udmSubService.InsertTxt(neId, data)
|
||||
if strings.HasSuffix(body.UploadPath, ".txt") {
|
||||
data := file.ReadFileTXT(",", localFilePath)
|
||||
neId := ""
|
||||
go s.udmSubService.InsertData(neId, "txt", data)
|
||||
}
|
||||
}
|
||||
c.JSON(200, result.OkMsg(data))
|
||||
@@ -2,20 +2,20 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
// CDREvent CDR会话对象 cdr_event_ims/cdr_event_smf
|
||||
type CDREvent struct {
|
||||
// CDREventIMS CDR会话对象IMS cdr_event_ims
|
||||
type CDREventIMS struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
|
||||
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
|
||||
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
// CDREventQuery CDR会话对象查询参数结构体
|
||||
type CDREventQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型
|
||||
// CDREventIMSQuery CDR会话对象IMS查询参数结构体
|
||||
type CDREventIMSQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型IMS
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
|
||||
@@ -2,29 +2,34 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
// CDREvent CDR会话对象 cdr_event_smf
|
||||
// CDREventSMF CDR会话对象SMF cdr_event_smf
|
||||
type CDREventSMF struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
|
||||
RecordType string `json:"recordType" gorm:"column:record_type"`
|
||||
ChargingID string `json:"chargingID" gorm:"column:charging_id"`
|
||||
SubscriberID string `json:"subscriberID" gorm:"column:subscriber_id"`
|
||||
Duration string `json:"duration" gorm:"column:duration"`
|
||||
DataVolumeUplink string `json:"dataVolumeUplink" gorm:"column:data_volume_uplink"`
|
||||
DataVolumeDownlink string `json:"dataVolumeDownlink" gorm:"column:data_volume_downlink"`
|
||||
DataTotalVolume string `json:"dataTotalVolume" gorm:"column:data_total_volume"`
|
||||
PDUAddress string `json:"pduAddress" gorm:"column:pdu_address"`
|
||||
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
|
||||
CDRJSONStr string `json:"cdrJSON" gorm:"column:cdr_json"`
|
||||
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||
|
||||
// ====== 非数据库字段属性 ======
|
||||
|
||||
// RecordType string `json:"recordType" gorm:"column:record_type"`
|
||||
// ChargingID string `json:"chargingID" gorm:"column:charging_id"`
|
||||
// SubscriberID string `json:"subscriberID" gorm:"column:subscriber_id"`
|
||||
// Duration string `json:"duration" gorm:"column:duration"`
|
||||
// DataVolumeUplink string `json:"dataVolumeUplink" gorm:"column:data_volume_uplink"`
|
||||
// DataVolumeDownlink string `json:"dataVolumeDownlink" gorm:"column:data_volume_downlink"`
|
||||
// DataTotalVolume string `json:"dataTotalVolume" gorm:"column:data_total_volume"`
|
||||
// PDUAddress string `json:"pduAddress" gorm:"column:pdu_address"`
|
||||
}
|
||||
|
||||
type SMFCDREventQuery struct {
|
||||
// CDREventSMFQuery CDR会话对象SMF查询参数结构体
|
||||
type CDREventSMFQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required"` // SMF
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
RecordType string `json:"recordType" form:"recordType"`
|
||||
RecordType string `json:"recordType" form:"recordType"` // 暂时没用到
|
||||
SubscriberID string `json:"subscriberID" form:"subscriberID"`
|
||||
StartTime string `json:"startTime" form:"startTime"`
|
||||
EndTime string `json:"endTime" form:"endTime"`
|
||||
|
||||
@@ -3,13 +3,13 @@ package model
|
||||
// UDMAuth UDM鉴权用户对象 u_auth_user
|
||||
type UDMAuth struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 默认ID
|
||||
Imsi string `json:"imsi" gorm:"column:imsi"` // SIM卡号
|
||||
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡号
|
||||
Amf string `json:"amf" gorm:"column:amf"` // ANF
|
||||
Status string `json:"status" gorm:"column:status"` // 状态
|
||||
Status string `json:"status" gorm:"column:status"` // 状态 默认给1
|
||||
Ki string `json:"ki" gorm:"column:ki"` // ki
|
||||
AlgoIndex string `json:"algoIndex" gorm:"column:algo_index"` // AlgoIndex
|
||||
Opc string `json:"opc" gorm:"column:opc"` // opc
|
||||
NeID string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
||||
}
|
||||
|
||||
func (UDMAuth) TableName() string {
|
||||
@@ -4,7 +4,7 @@ package model
|
||||
type UDMSub struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
Msisdn string `json:"msisdn" gorm:"column:msisdn"` // 相当手机号
|
||||
Imsi string `json:"imsi" gorm:"column:imsi"` // SIM卡号
|
||||
IMSI string `json:"imsi" gorm:"column:imsi"` // SIM卡号
|
||||
Ambr string `json:"ambr" gorm:"column:ambr"`
|
||||
Nssai string `json:"nssai" gorm:"column:nssai"`
|
||||
Rat string `json:"rat" gorm:"column:rat"`
|
||||
@@ -14,7 +14,7 @@ type UDMSub struct {
|
||||
SmData string `json:"smData" gorm:"column:sm_data"`
|
||||
SmfSel string `json:"smfSel" gorm:"column:smf_sel"`
|
||||
EpsDat string `json:"epsDat" gorm:"column:eps_dat"`
|
||||
NeID string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
||||
NeId string `json:"neId" gorm:"column:ne_id"` // UDM网元标识-子系统
|
||||
|
||||
EpsFlag string `json:"epsFlag" gorm:"column:eps_flag"`
|
||||
EpsOdb string `json:"epsOdb" gorm:"column:eps_odb"`
|
||||
@@ -27,7 +27,6 @@ type UDMSub struct {
|
||||
|
||||
// ====== 非数据库字段属性 ======
|
||||
|
||||
SubNum string `json:"subNum,omitempty" gorm:"-"` // 批量数
|
||||
}
|
||||
|
||||
func (UDMSub) TableName() string {
|
||||
@@ -2,20 +2,20 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
// UEEvent UE会话对象 ue_event
|
||||
type UEEvent struct {
|
||||
// UEEventAMF UE会话对象AMF ue_event_amf
|
||||
type UEEventAMF struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
|
||||
EventType string `json:"eventType" gorm:"column:event_type"`
|
||||
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
|
||||
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"`
|
||||
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
// UEEventQuery UE会话对象查询参数结构体
|
||||
type UEEventQuery struct {
|
||||
// UEEventAMFQuery UE会话对象AMF查询参数结构体
|
||||
type UEEventAMFQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持AMF
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
30
src/modules/network_data/model/ue_event_mme.go
Normal file
30
src/modules/network_data/model/ue_event_mme.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// UEEventMME UE会话对象MME ue_event_mme
|
||||
type UEEventMME struct {
|
||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
|
||||
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
|
||||
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
|
||||
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"`
|
||||
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||
}
|
||||
|
||||
// UEEventMMEQuery UE会话对象MME查询参数结构体
|
||||
type UEEventMMEQuery struct {
|
||||
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持MME
|
||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||
RmUID string `json:"rmUID" form:"rmUID"`
|
||||
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
|
||||
IMSI string `json:"imsi" form:"imsi"` // imsi
|
||||
StartTime string `json:"startTime" form:"startTime"`
|
||||
EndTime string `json:"endTime" form:"endTime"`
|
||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/middleware"
|
||||
"be.ems/src/framework/middleware/collectlogs"
|
||||
"be.ems/src/framework/middleware/repeat"
|
||||
"be.ems/src/modules/network_data/controller"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -44,49 +45,58 @@ func Setup(router *gin.Engine) {
|
||||
// 网元IMS
|
||||
imsGroup := neDataGroup.Group("/ims")
|
||||
{
|
||||
// CDR会话事件列表
|
||||
imsGroup.GET("/cdr/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewIMSController.CDRList,
|
||||
)
|
||||
// CDR会话删除
|
||||
imsGroup.DELETE("/cdr/:cdrIds",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewIMSController.CDRRemove,
|
||||
)
|
||||
imsGroup.POST("/cdr/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewIMSController.CDRExport,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元SMF
|
||||
smfGroup := neDataGroup.Group("/smf")
|
||||
{
|
||||
// CDR会话事件列表
|
||||
smfGroup.GET("/cdr/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewSMFController.CDRList,
|
||||
)
|
||||
// CDR会话删除
|
||||
smfGroup.DELETE("/cdr/:cdrIds",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewSMFController.CDRRemove,
|
||||
)
|
||||
smfGroup.POST("/cdr/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewSMFController.CDRExport,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元AMF
|
||||
amfGroup := neDataGroup.Group("/amf")
|
||||
{
|
||||
// UE会话事件
|
||||
amfGroup.GET("/ue/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewAMFController.UEList,
|
||||
)
|
||||
// UE会话删除
|
||||
amfGroup.DELETE("/ue/:ueIds",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewAMFController.UERemove,
|
||||
)
|
||||
amfGroup.POST("/ue/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewAMFController.UEExport,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元UPF
|
||||
@@ -98,4 +108,130 @@ func Setup(router *gin.Engine) {
|
||||
)
|
||||
}
|
||||
|
||||
// 网元UDM 鉴权用户信息
|
||||
udmAuthGroup := neDataGroup.Group("/udm/auth")
|
||||
{
|
||||
udmAuthGroup.PUT("/resetData/:neId",
|
||||
repeat.RepeatSubmit(5),
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_CLEAN)),
|
||||
controller.NewUDMAuth.ResetData,
|
||||
)
|
||||
udmAuthGroup.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewUDMAuth.List,
|
||||
)
|
||||
udmAuthGroup.GET("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewUDMAuth.Info,
|
||||
)
|
||||
udmAuthGroup.POST("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewUDMAuth.Add,
|
||||
)
|
||||
udmAuthGroup.POST("/:neId/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewUDMAuth.Adds,
|
||||
)
|
||||
udmAuthGroup.PUT("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewUDMAuth.Edit,
|
||||
)
|
||||
udmAuthGroup.DELETE("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewUDMAuth.Remove,
|
||||
)
|
||||
udmAuthGroup.DELETE("/:neId/:imsi/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewUDMAuth.Removes,
|
||||
)
|
||||
udmAuthGroup.POST("/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewUDMAuth.Export,
|
||||
)
|
||||
udmAuthGroup.POST("/import",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmAuth", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
controller.NewUDMAuth.Import,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元UDM 签约用户信息
|
||||
udmSubGroup := neDataGroup.Group("/udm/sub")
|
||||
{
|
||||
udmSubGroup.PUT("/resetData/:neId",
|
||||
repeat.RepeatSubmit(5),
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_CLEAN)),
|
||||
controller.NewUDMSub.ResetData,
|
||||
)
|
||||
udmSubGroup.GET("/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewUDMSub.List,
|
||||
)
|
||||
udmSubGroup.GET("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewUDMSub.Info,
|
||||
)
|
||||
udmSubGroup.POST("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewUDMSub.Add,
|
||||
)
|
||||
udmSubGroup.POST("/:neId/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_INSERT)),
|
||||
controller.NewUDMSub.Adds,
|
||||
)
|
||||
udmSubGroup.PUT("/:neId",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_UPDATE)),
|
||||
controller.NewUDMSub.Edit,
|
||||
)
|
||||
udmSubGroup.DELETE("/:neId/:imsi",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewUDMSub.Remove,
|
||||
)
|
||||
udmSubGroup.DELETE("/:neId/:imsi/:num",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewUDMSub.Removes,
|
||||
)
|
||||
udmSubGroup.POST("/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewUDMSub.Export,
|
||||
)
|
||||
udmSubGroup.POST("/import",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.udmSub", collectlogs.BUSINESS_TYPE_IMPORT)),
|
||||
controller.NewUDMSub.Import,
|
||||
)
|
||||
}
|
||||
|
||||
// 网元MME
|
||||
mmeGroup := neDataGroup.Group("/mme")
|
||||
{
|
||||
mmeGroup.GET("/ue/list",
|
||||
middleware.PreAuthorize(nil),
|
||||
controller.NewMMEController.UEList,
|
||||
)
|
||||
mmeGroup.DELETE("/ue/:ueIds",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||
controller.NewMMEController.UERemove,
|
||||
)
|
||||
mmeGroup.POST("/ue/export",
|
||||
middleware.PreAuthorize(nil),
|
||||
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)),
|
||||
controller.NewMMEController.UEExport,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package repository
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// CDR会话事件 数据层接口
|
||||
type ICDREvent interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.CDREventQuery) map[string]any
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectByIds(cdrIds []string) []model.CDREvent
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) int64
|
||||
}
|
||||
|
||||
// SMF CDR Event
|
||||
type SMFCDREvent interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.SMFCDREventQuery) map[string]any
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectByIds(cdrIds []string) []model.CDREventSMF
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) int64
|
||||
}
|
||||
@@ -1,344 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventImpl 结构体
|
||||
var NewCDREventImpl = &CDREventImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_ims`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_type": "NeType",
|
||||
"ne_name": "NeName",
|
||||
"rm_uid": "RmUID",
|
||||
"timestamp": "Timestamp",
|
||||
"cdr_json": "CDRJSONStr",
|
||||
"created_at": "CreatedAt",
|
||||
},
|
||||
}
|
||||
|
||||
// CDREventImpl CDR会话事件 数据层处理
|
||||
type CDREventImpl struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// Instance of SMF CDREventImpl
|
||||
var NewSMFCDREventImpl = &SMFCDREventImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, JSON_EXTRACT(cdr_json, '$.recordType') AS record_type, JSON_EXTRACT(cdr_json, '$.chargingID') AS charging_id, JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') AS subscriber_id, JSON_EXTRACT(cdr_json, '$.duration') AS duration, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink') AS data_volume_uplink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink') AS data_volume_downlink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume') AS data_total_volume, JSON_EXTRACT(cdr_json, '$.pDUSessionChargingInformation.pDUAddress') AS pdu_address, created_at from cdr_event_smf`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_type": "NeType",
|
||||
"ne_name": "NeName",
|
||||
"rm_uid": "RmUID",
|
||||
"timestamp": "Timestamp",
|
||||
"record_type": "RecordType",
|
||||
"charging_id": "ChargingID",
|
||||
"subscriber_id": "SubscriberID",
|
||||
"duration": "Duration",
|
||||
"data_volume_uplink": "DataVolumeUplink",
|
||||
"data_volume_downlink": "DataVolumeDownlink",
|
||||
"data_total_volume": "DataTotalVolume",
|
||||
"pdu_address": "PDUAddress",
|
||||
"created_at": "CreatedAt",
|
||||
},
|
||||
}
|
||||
|
||||
// CDREventImpl CDR会话事件 数据层处理
|
||||
type SMFCDREventImpl struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *CDREventImpl) convertResultRows(rows []map[string]any) []model.CDREvent {
|
||||
arr := make([]model.CDREvent, 0)
|
||||
for _, row := range rows {
|
||||
item := model.CDREvent{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, querys.NeType)
|
||||
}
|
||||
if querys.RmUID != "" {
|
||||
conditions = append(conditions, "rm_uid = ?")
|
||||
params = append(params, querys.RmUID)
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "timestamp >= ?")
|
||||
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||
params = append(params, beginDate.Unix())
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "timestamp <= ?")
|
||||
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||
params = append(params, endDate.Unix())
|
||||
}
|
||||
if querys.CallerParty != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.callerParty') = ?")
|
||||
params = append(params, querys.CallerParty)
|
||||
}
|
||||
if querys.CalledParty != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.calledParty') = ?")
|
||||
params = append(params, querys.CalledParty)
|
||||
}
|
||||
if querys.RecordType != "" {
|
||||
recordTypes := strings.Split(querys.RecordType, ",")
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
||||
conditions = append(conditions, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') in (%s)", placeholder))
|
||||
for _, recordType := range recordTypes {
|
||||
params = append(params, recordType)
|
||||
}
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.CDREvent{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from cdr_event_ims"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if querys.SortField != "" {
|
||||
sortSql := querys.SortField
|
||||
if querys.SortOrder != "" {
|
||||
if querys.SortOrder == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventImpl) SelectByIds(cdrIds []string) []model.CDREvent {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return []model.CDREvent{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventImpl) DeleteByIds(cdrIds []string) int64 {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
sql := "delete from cdr_event_ims where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *SMFCDREventImpl) convertResultRows(rows []map[string]any) []model.CDREventSMF {
|
||||
arr := make([]model.CDREventSMF, 0)
|
||||
for _, row := range rows {
|
||||
item := model.CDREventSMF{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *SMFCDREventImpl) SelectPage(querys model.SMFCDREventQuery) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, querys.NeType)
|
||||
}
|
||||
if querys.RmUID != "" {
|
||||
conditions = append(conditions, "rm_uid = ?")
|
||||
params = append(params, querys.RmUID)
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "timestamp >= ?")
|
||||
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||
params = append(params, beginDate.Unix())
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "timestamp <= ?")
|
||||
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||
params = append(params, endDate.Unix())
|
||||
}
|
||||
if querys.RecordType != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.recordType') = ?")
|
||||
params = append(params, querys.RecordType)
|
||||
}
|
||||
if querys.SubscriberID != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') = ?")
|
||||
params = append(params, querys.SubscriberID)
|
||||
}
|
||||
// if querys.RecordType != "" {
|
||||
// recordTypes := strings.Split(querys.RecordType, ",")
|
||||
// placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
||||
// conditions = append(conditions, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') in (%s)", placeholder))
|
||||
// for _, recordType := range recordTypes {
|
||||
// params = append(params, recordType)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.CDREventSMF{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from cdr_event_smf"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if querys.SortField != "" {
|
||||
sortSql := querys.SortField
|
||||
if querys.SortOrder != "" {
|
||||
if querys.SortOrder == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *SMFCDREventImpl) SelectByIds(cdrIds []string) []model.CDREventSMF {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return []model.CDREventSMF{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *SMFCDREventImpl) DeleteByIds(cdrIds []string) int64 {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
sql := "delete from cdr_event_smf where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
15
src/modules/network_data/repository/cdr_event_ims.go
Normal file
15
src/modules/network_data/repository/cdr_event_ims.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package repository
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// CDR会话事件IMS 数据层接口
|
||||
type ICDREventIMS interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.CDREventIMSQuery) map[string]any
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectByIds(cdrIds []string) []model.CDREventIMS
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) int64
|
||||
}
|
||||
178
src/modules/network_data/repository/cdr_event_ims.impl.go
Normal file
178
src/modules/network_data/repository/cdr_event_ims.impl.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventImpl 结构体
|
||||
var NewCDREventIMSImpl = &CDREventIMSImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_ims`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_type": "NeType",
|
||||
"ne_name": "NeName",
|
||||
"rm_uid": "RmUID",
|
||||
"timestamp": "Timestamp",
|
||||
"cdr_json": "CDRJSONStr",
|
||||
"created_at": "CreatedAt",
|
||||
},
|
||||
}
|
||||
|
||||
// CDREventIMSImpl CDR会话事件IMS 数据层处理
|
||||
type CDREventIMSImpl struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *CDREventIMSImpl) convertResultRows(rows []map[string]any) []model.CDREventIMS {
|
||||
arr := make([]model.CDREventIMS, 0)
|
||||
for _, row := range rows {
|
||||
item := model.CDREventIMS{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *CDREventIMSImpl) SelectPage(querys model.CDREventIMSQuery) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, querys.NeType)
|
||||
}
|
||||
if querys.RmUID != "" {
|
||||
conditions = append(conditions, "rm_uid = ?")
|
||||
params = append(params, querys.RmUID)
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "timestamp >= ?")
|
||||
if len(querys.StartTime) == 13 {
|
||||
querys.StartTime = querys.StartTime[:10]
|
||||
}
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "timestamp <= ?")
|
||||
if len(querys.EndTime) == 13 {
|
||||
querys.EndTime = querys.EndTime[:10]
|
||||
}
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
if querys.CallerParty != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.callerParty') = ?")
|
||||
params = append(params, querys.CallerParty)
|
||||
}
|
||||
if querys.CalledParty != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.calledParty') = ?")
|
||||
params = append(params, querys.CalledParty)
|
||||
}
|
||||
if querys.RecordType != "" {
|
||||
recordTypes := strings.Split(querys.RecordType, ",")
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
||||
conditions = append(conditions, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') in (%s)", placeholder))
|
||||
for _, recordType := range recordTypes {
|
||||
params = append(params, recordType)
|
||||
}
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.CDREventIMS{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from cdr_event_ims"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if querys.SortField != "" {
|
||||
sortSql := querys.SortField
|
||||
if querys.SortOrder != "" {
|
||||
if querys.SortOrder == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventIMSImpl) SelectByIds(cdrIds []string) []model.CDREventIMS {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return []model.CDREventIMS{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventIMSImpl) DeleteByIds(cdrIds []string) int64 {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
sql := "delete from cdr_event_ims where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
15
src/modules/network_data/repository/cdr_event_smf.go
Normal file
15
src/modules/network_data/repository/cdr_event_smf.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package repository
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// CDR会话事件SMF 数据层接口
|
||||
type ICDREventSMF interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.CDREventSMFQuery) map[string]any
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectByIds(cdrIds []string) []model.CDREventSMF
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) int64
|
||||
}
|
||||
185
src/modules/network_data/repository/cdr_event_smf.impl.go
Normal file
185
src/modules/network_data/repository/cdr_event_smf.impl.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventSMFImpl 结构体
|
||||
var NewCDREventSMFImpl = &CDREventSMFImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_smf`,
|
||||
// selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, JSON_EXTRACT(cdr_json, '$.recordType') AS record_type, JSON_EXTRACT(cdr_json, '$.chargingID') AS charging_id, JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') AS subscriber_id, JSON_EXTRACT(cdr_json, '$.duration') AS duration, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink') AS data_volume_uplink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink') AS data_volume_downlink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume') AS data_total_volume, JSON_EXTRACT(cdr_json, '$.pDUSessionChargingInformation.pDUAddress') AS pdu_address, created_at from cdr_event_smf`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_type": "NeType",
|
||||
"ne_name": "NeName",
|
||||
"rm_uid": "RmUID",
|
||||
"timestamp": "Timestamp",
|
||||
"cdr_json": "CDRJSONStr",
|
||||
"created_at": "CreatedAt",
|
||||
// "id": "ID",
|
||||
// "ne_type": "NeType",
|
||||
// "ne_name": "NeName",
|
||||
// "rm_uid": "RmUID",
|
||||
// "timestamp": "Timestamp",
|
||||
// "record_type": "RecordType",
|
||||
// "charging_id": "ChargingID",
|
||||
// "subscriber_id": "SubscriberID",
|
||||
// "duration": "Duration",
|
||||
// "data_volume_uplink": "DataVolumeUplink",
|
||||
// "data_volume_downlink": "DataVolumeDownlink",
|
||||
// "data_total_volume": "DataTotalVolume",
|
||||
// "pdu_address": "PDUAddress",
|
||||
// "created_at": "CreatedAt",
|
||||
},
|
||||
}
|
||||
|
||||
// CDREventSMFImpl CDR会话事件 数据层处理
|
||||
type CDREventSMFImpl struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *CDREventSMFImpl) convertResultRows(rows []map[string]any) []model.CDREventSMF {
|
||||
arr := make([]model.CDREventSMF, 0)
|
||||
for _, row := range rows {
|
||||
item := model.CDREventSMF{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *CDREventSMFImpl) SelectPage(querys model.CDREventSMFQuery) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, querys.NeType)
|
||||
}
|
||||
if querys.RmUID != "" {
|
||||
conditions = append(conditions, "rm_uid = ?")
|
||||
params = append(params, querys.RmUID)
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "timestamp >= ?")
|
||||
if len(querys.StartTime) == 13 {
|
||||
querys.StartTime = querys.StartTime[:10]
|
||||
}
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "timestamp <= ?")
|
||||
if len(querys.EndTime) == 13 {
|
||||
querys.EndTime = querys.EndTime[:10]
|
||||
}
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
if querys.RecordType != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.recordType') = ?")
|
||||
params = append(params, querys.RecordType)
|
||||
}
|
||||
if querys.SubscriberID != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') = ?")
|
||||
params = append(params, querys.SubscriberID)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.CDREventSMF{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from cdr_event_smf"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if querys.SortField != "" {
|
||||
sortSql := querys.SortField
|
||||
if querys.SortOrder != "" {
|
||||
if querys.SortOrder == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *CDREventSMFImpl) SelectByIds(cdrIds []string) []model.CDREventSMF {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return []model.CDREventSMF{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventSMFImpl) DeleteByIds(cdrIds []string) int64 {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||
sql := "delete from cdr_event_smf where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -96,19 +96,47 @@ func (r *PerfKPIImpl) SelectKpiReport(query model.GoldKPIQuery, kpiIds []string)
|
||||
params = append(params, query.RmUID)
|
||||
}
|
||||
if query.NeType != "" {
|
||||
conditions = append(conditions, "gk.ne_type = ?")
|
||||
params = append(params, query.NeType)
|
||||
//conditions = append(conditions, "gk.ne_type = ?")
|
||||
// params = append(params, query.NeType)
|
||||
tableName += strings.ToLower(query.NeType)
|
||||
}
|
||||
var dateTimeStr string = "CONCAT(gk.`date`, \" \", gk.start_time)"
|
||||
|
||||
var dateStr1, dateStr2, timeStr1, timeStr2 string
|
||||
if query.StartTime != "" {
|
||||
conditions = append(conditions, dateTimeStr+" >= ?")
|
||||
params = append(params, query.StartTime)
|
||||
dateStr1 = query.StartTime[:10]
|
||||
timeStr1 = query.StartTime[11:]
|
||||
}
|
||||
if query.EndTime != "" {
|
||||
conditions = append(conditions, dateTimeStr+" <= ?")
|
||||
params = append(params, query.EndTime)
|
||||
dateStr2 = query.EndTime[:10]
|
||||
timeStr2 = query.EndTime[11:]
|
||||
}
|
||||
if dateStr1 == dateStr2 && dateStr1 != "" {
|
||||
conditions = append(conditions, "gk.`date` = ?")
|
||||
params = append(params, dateStr1)
|
||||
conditions = append(conditions, "gk.`start_time` >= ?")
|
||||
params = append(params, timeStr1)
|
||||
conditions = append(conditions, "gk.`start_time` <= ?")
|
||||
params = append(params, timeStr2)
|
||||
} else {
|
||||
if dateStr1 != "" {
|
||||
conditions = append(conditions, "(gk.`date` > ? OR (gk.`date` = ? AND gk.`start_time` >= ?))")
|
||||
params = append(params, dateStr1, dateStr1, timeStr1)
|
||||
}
|
||||
if dateStr2 != "" {
|
||||
conditions = append(conditions, "(gk.`date` < ? OR (gk.`date` = ? AND gk.`start_time` <= ?))")
|
||||
params = append(params, dateStr2, dateStr2, timeStr2)
|
||||
}
|
||||
}
|
||||
|
||||
// var dateTimeStr string = "CONCAT(gk.`date`, \" \", gk.start_time)"
|
||||
// if query.StartTime != "" {
|
||||
// conditions = append(conditions, dateTimeStr+" >= ?")
|
||||
// params = append(params, query.StartTime)
|
||||
// }
|
||||
// if query.EndTime != "" {
|
||||
// conditions = append(conditions, dateTimeStr+" <= ?")
|
||||
// params = append(params, query.EndTime)
|
||||
// }
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
@@ -116,6 +144,7 @@ func (r *PerfKPIImpl) SelectKpiReport(query model.GoldKPIQuery, kpiIds []string)
|
||||
}
|
||||
|
||||
// 查询字段列
|
||||
var dateTimeStr string = "CONCAT(gk.`date`, \" \", gk.start_time)"
|
||||
timeFormat := "DATE_FORMAT(" + dateTimeStr + ", '%Y-%m-%d %H:%i:')"
|
||||
secondGroup := fmt.Sprintf("LPAD(FLOOR(SECOND(gk.start_time) / %d) * %d, 2, '0')", query.Interval, query.Interval)
|
||||
groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, secondGroup)
|
||||
|
||||
26
src/modules/network_data/repository/udm_auth.go
Normal file
26
src/modules/network_data/repository/udm_auth.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// UDM鉴权信息 数据层接口
|
||||
type IUDMAuth interface {
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
ClearAndInsert(neId string, uArr []model.UDMAuth) int64
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(query map[string]any) map[string]any
|
||||
|
||||
// SelectList 根据实体查询
|
||||
SelectList(u model.UDMAuth) []model.UDMAuth
|
||||
|
||||
// Insert 批量添加
|
||||
Inserts(uArr []model.UDMAuth) int64
|
||||
|
||||
// Delete 删除实体
|
||||
Delete(neId, imsi string) int64
|
||||
|
||||
// DeletePrefixByIMSI 删除前缀匹配的实体
|
||||
DeletePrefixByIMSI(neId, imsi string) int64
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_element/model"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 UDMAuthImpl 结构体
|
||||
@@ -16,13 +17,13 @@ var NewUDMAuthImpl = &UDMAuthImpl{
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"imsi": "Imsi",
|
||||
"imsi": "IMSI",
|
||||
"amf": "Amf",
|
||||
"status": "Status",
|
||||
"ki": "Ki",
|
||||
"algo_index": "AlgoIndex",
|
||||
"opc": "Opc",
|
||||
"ne_id": "NeID",
|
||||
"ne_id": "NeId",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -50,14 +51,13 @@ func (r *UDMAuthImpl) convertResultRows(rows []map[string]any) []model.UDMAuth {
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *UDMAuthImpl) ClearAndInsert(neID string, authArr []model.UDMAuth) int64 {
|
||||
// 清空指定ne_id
|
||||
func (r *UDMAuthImpl) ClearAndInsert(neId string, uArr []model.UDMAuth) int64 {
|
||||
// 不指定neID时,用 TRUNCATE 清空表快
|
||||
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_auth_user", nil)
|
||||
if err != nil {
|
||||
logger.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
return r.Inserts(authArr)
|
||||
return r.Inserts(uArr)
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
@@ -106,11 +106,9 @@ func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
sortSql := ""
|
||||
orderSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
if v == "imsi" {
|
||||
sortSql += " order by imsi "
|
||||
}
|
||||
sortSql := v.(string)
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
@@ -118,10 +116,11 @@ func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + sortSql + pageSql
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
@@ -133,17 +132,17 @@ func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *UDMAuthImpl) SelectList(auth model.UDMAuth) []model.UDMAuth {
|
||||
func (r *UDMAuthImpl) SelectList(u model.UDMAuth) []model.UDMAuth {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if auth.Imsi != "" {
|
||||
if u.IMSI != "" {
|
||||
conditions = append(conditions, "imsi = ?")
|
||||
params = append(params, auth.Imsi)
|
||||
params = append(params, u.IMSI)
|
||||
}
|
||||
if auth.NeID != "" {
|
||||
if u.NeId != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, auth.NeID)
|
||||
params = append(params, u.NeId)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
@@ -164,8 +163,8 @@ func (r *UDMAuthImpl) SelectList(auth model.UDMAuth) []model.UDMAuth {
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *UDMAuthImpl) Inserts(authUsers []model.UDMAuth) int64 {
|
||||
tx := datasource.DefaultDB().CreateInBatches(authUsers, 3000)
|
||||
func (r *UDMAuthImpl) Inserts(uArr []model.UDMAuth) int64 {
|
||||
tx := datasource.DefaultDB().CreateInBatches(uArr, 3000)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("CreateInBatches err => %v", err)
|
||||
}
|
||||
@@ -173,19 +172,19 @@ func (r *UDMAuthImpl) Inserts(authUsers []model.UDMAuth) int64 {
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *UDMAuthImpl) Delete(neID, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neID).Delete(&model.UDMAuth{})
|
||||
func (r *UDMAuthImpl) Delete(neId, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&model.UDMAuth{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Delete err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// DeletePrefixImsi 删除前缀匹配的实体
|
||||
func (r *UDMAuthImpl) DeletePrefixImsi(neID, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neID).Delete(&model.UDMAuth{})
|
||||
// DeletePrefixByIMSI 删除前缀匹配的实体
|
||||
func (r *UDMAuthImpl) DeletePrefixByIMSI(neId, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neId).Delete(&model.UDMAuth{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("DeletePrefixImsi err => %v", err)
|
||||
logger.Errorf("DeletePrefixByIMSI err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
26
src/modules/network_data/repository/udm_sub.go
Normal file
26
src/modules/network_data/repository/udm_sub.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// UDM签约信息 数据层接口
|
||||
type IUDMSub interface {
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
ClearAndInsert(neId string, uArr []model.UDMSub) int64
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(query map[string]any) map[string]any
|
||||
|
||||
// SelectList 根据实体查询
|
||||
SelectList(u model.UDMSub) []model.UDMSub
|
||||
|
||||
// Insert 批量添加
|
||||
Inserts(uArr []model.UDMSub) int64
|
||||
|
||||
// Delete 删除实体
|
||||
Delete(neId, imsi string) int64
|
||||
|
||||
// DeletePrefixByIMSI 删除前缀匹配的实体
|
||||
DeletePrefixByIMSI(neId, imsi string) int64
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_element/model"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 UDMSubImpl 结构体
|
||||
@@ -20,7 +20,7 @@ var NewUDMSubImpl = &UDMSubImpl{
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"msisdn": "Msisdn",
|
||||
"imsi": "Imsi",
|
||||
"imsi": "IMSI",
|
||||
"ambr": "Ambr",
|
||||
"nssai": "Nssai",
|
||||
"rat": "Rat",
|
||||
@@ -30,7 +30,7 @@ var NewUDMSubImpl = &UDMSubImpl{
|
||||
"sm_data": "SmData",
|
||||
"smf_sel": "SmfSel",
|
||||
"eps_dat": "EpsDat",
|
||||
"ne_id": "NeID",
|
||||
"ne_id": "NeId",
|
||||
"eps_flag": "EpsFlag",
|
||||
"eps_odb": "EpsOdb",
|
||||
"hplmn_odb": "HplmnOdb",
|
||||
@@ -66,14 +66,14 @@ func (r *UDMSubImpl) convertResultRows(rows []map[string]any) []model.UDMSub {
|
||||
}
|
||||
|
||||
// ClearAndInsert 清空ne_id后新增实体
|
||||
func (r *UDMSubImpl) ClearAndInsert(neID string, subArr []model.UDMSub) int64 {
|
||||
// 清空指定ne_id
|
||||
func (r *UDMSubImpl) ClearAndInsert(neID string, u []model.UDMSub) int64 {
|
||||
// 不指定neID时,用 TRUNCATE 清空表快
|
||||
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_sub_user", nil)
|
||||
if err != nil {
|
||||
logger.Errorf("TRUNCATE err => %v", err)
|
||||
}
|
||||
|
||||
return r.Inserts(subArr)
|
||||
return r.Inserts(u)
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询字典类型
|
||||
@@ -126,14 +126,9 @@ func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
sortSql := ""
|
||||
orderSql := ""
|
||||
if v, ok := query["sortField"]; ok && v != "" {
|
||||
if v == "imsi" {
|
||||
sortSql += " order by imsi "
|
||||
}
|
||||
if v == "msisdn" {
|
||||
sortSql += " order by msisdn "
|
||||
}
|
||||
sortSql := v.(string)
|
||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
||||
if o == "desc" {
|
||||
sortSql += " desc "
|
||||
@@ -141,10 +136,11 @@ func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + sortSql + pageSql
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
@@ -157,17 +153,17 @@ func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
|
||||
}
|
||||
|
||||
// SelectList 根据实体查询
|
||||
func (r *UDMSubImpl) SelectList(subUser model.UDMSub) []model.UDMSub {
|
||||
func (r *UDMSubImpl) SelectList(u model.UDMSub) []model.UDMSub {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if subUser.Imsi != "" {
|
||||
if u.IMSI != "" {
|
||||
conditions = append(conditions, "imsi = ?")
|
||||
params = append(params, subUser.Imsi)
|
||||
params = append(params, u.IMSI)
|
||||
}
|
||||
if subUser.NeID != "" {
|
||||
if u.NeId != "" {
|
||||
conditions = append(conditions, "ne_id = ?")
|
||||
params = append(params, subUser.NeID)
|
||||
params = append(params, u.NeId)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
@@ -187,126 +183,29 @@ func (r *UDMSubImpl) SelectList(subUser model.UDMSub) []model.UDMSub {
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// Insert 新增实体
|
||||
func (r *UDMSubImpl) Insert(subUser model.UDMSub) string {
|
||||
err := datasource.DefaultDB().Create(&subUser).Error
|
||||
if err != nil {
|
||||
logger.Errorf("Create err => %v", err)
|
||||
}
|
||||
return subUser.ID
|
||||
}
|
||||
|
||||
// Insert 批量添加
|
||||
func (r *UDMSubImpl) Inserts(subUser []model.UDMSub) int64 {
|
||||
tx := datasource.DefaultDB().CreateInBatches(subUser, 2000)
|
||||
func (r *UDMSubImpl) Inserts(uArr []model.UDMSub) int64 {
|
||||
tx := datasource.DefaultDB().CreateInBatches(uArr, 2000)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("CreateInBatches err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Update 修改更新
|
||||
func (r *UDMSubImpl) Update(neID string, subUser model.UDMSub) int64 {
|
||||
// 查询先
|
||||
var user model.UDMSub
|
||||
err := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", subUser.Imsi, neID).First(&user).Error
|
||||
if err != nil {
|
||||
logger.Errorf("Update First err => %v", err)
|
||||
}
|
||||
|
||||
if user.Msisdn != subUser.Msisdn {
|
||||
user.Msisdn = subUser.Msisdn
|
||||
}
|
||||
if user.Ambr != subUser.Ambr {
|
||||
user.Ambr = subUser.Ambr
|
||||
}
|
||||
if user.Arfb != subUser.Arfb {
|
||||
user.Arfb = subUser.Arfb
|
||||
}
|
||||
if user.Sar != subUser.Sar {
|
||||
user.Sar = subUser.Sar
|
||||
}
|
||||
if user.Rat != subUser.Rat {
|
||||
user.Rat = subUser.Rat
|
||||
}
|
||||
if user.Cn != subUser.Cn {
|
||||
user.Cn = subUser.Cn
|
||||
}
|
||||
if user.SmfSel != subUser.SmfSel {
|
||||
user.SmfSel = subUser.SmfSel
|
||||
}
|
||||
if user.SmData != subUser.SmData {
|
||||
user.SmData = subUser.SmData
|
||||
}
|
||||
if user.EpsDat != subUser.EpsDat {
|
||||
user.EpsDat = subUser.EpsDat
|
||||
}
|
||||
if user.EpsFlag != subUser.EpsFlag {
|
||||
user.EpsFlag = subUser.EpsFlag
|
||||
}
|
||||
if user.EpsDat != subUser.EpsDat {
|
||||
user.EpsOdb = subUser.EpsOdb
|
||||
}
|
||||
if user.HplmnOdb != subUser.HplmnOdb {
|
||||
user.HplmnOdb = subUser.HplmnOdb
|
||||
}
|
||||
if user.Epstpl != subUser.Epstpl {
|
||||
user.Epstpl = subUser.Epstpl
|
||||
}
|
||||
if user.Ard != subUser.Ard {
|
||||
user.Ard = subUser.Ard
|
||||
}
|
||||
if user.ContextId != subUser.ContextId {
|
||||
user.ContextId = subUser.ContextId
|
||||
}
|
||||
if user.ApnContext != subUser.ApnContext {
|
||||
user.ApnContext = subUser.ApnContext
|
||||
}
|
||||
if user.StaticIp != subUser.StaticIp {
|
||||
user.StaticIp = subUser.StaticIp
|
||||
}
|
||||
|
||||
tx := datasource.DefaultDB().Save(user)
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Update Save err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Delete 删除实体
|
||||
func (r *UDMSubImpl) Delete(neID, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neID).Delete(&model.UDMSub{})
|
||||
func (r *UDMSubImpl) Delete(neId, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi = ? and ne_id = ?", imsi, neId).Delete(&model.UDMSub{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Delete err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// DeletePrefixImsi 删除前缀匹配的实体
|
||||
func (r *UDMSubImpl) DeletePrefixImsi(neID, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neID).Delete(&model.UDMSub{})
|
||||
// DeletePrefixByIMSI 删除前缀匹配的实体
|
||||
func (r *UDMSubImpl) DeletePrefixByIMSI(neId, imsi string) int64 {
|
||||
tx := datasource.DefaultDB().Where("imsi like concat(?, '%') and ne_id = ?", imsi, neId).Delete(&model.UDMSub{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("DeletePrefixImsi err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
|
||||
// Delete 删除范围实体
|
||||
func (r *UDMSubImpl) Deletes(neID, imsi, num string) int64 {
|
||||
imsiV, err := strconv.Atoi(imsi)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
numV, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
tx := datasource.DefaultDB().Where("imsi >= ? and imsi < ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete(&model.UDMSub{})
|
||||
if err := tx.Error; err != nil {
|
||||
logger.Errorf("Deletes err => %v", err)
|
||||
logger.Errorf("DeletePrefixByIMSI err => %v", err)
|
||||
}
|
||||
return tx.RowsAffected
|
||||
}
|
||||
@@ -2,13 +2,13 @@ package repository
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// UE会话事件 数据层接口
|
||||
type IUEEvent interface {
|
||||
// UE会话事件AMF 数据层接口
|
||||
type IUEEventAMF interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.UEEventQuery) map[string]any
|
||||
SelectPage(querys model.UEEventAMFQuery) map[string]any
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectByIds(ueIds []string) []model.UEEvent
|
||||
SelectByIds(ueIds []string) []model.UEEventAMF
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(ueIds []string) int64
|
||||
@@ -6,15 +6,14 @@ import (
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/date"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 UEEventImpl 结构体
|
||||
var NewUEEventImpl = &UEEventImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event`,
|
||||
// 实例化数据层 UEEventAMFImpl 结构体
|
||||
var NewUEEventAMFImpl = &UEEventAMFImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event_amf`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
@@ -28,8 +27,8 @@ var NewUEEventImpl = &UEEventImpl{
|
||||
},
|
||||
}
|
||||
|
||||
// UEEventImpl UE会话事件 数据层处理
|
||||
type UEEventImpl struct {
|
||||
// UEEventAMFImpl UE会话事件 数据层处理
|
||||
type UEEventAMFImpl struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
@@ -37,10 +36,10 @@ type UEEventImpl struct {
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *UEEventImpl) convertResultRows(rows []map[string]any) []model.UEEvent {
|
||||
arr := make([]model.UEEvent, 0)
|
||||
func (r *UEEventAMFImpl) convertResultRows(rows []map[string]any) []model.UEEventAMF {
|
||||
arr := make([]model.UEEventAMF, 0)
|
||||
for _, row := range rows {
|
||||
item := model.UEEvent{}
|
||||
item := model.UEEventAMF{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
@@ -52,7 +51,7 @@ func (r *UEEventImpl) convertResultRows(rows []map[string]any) []model.UEEvent {
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
||||
func (r *UEEventAMFImpl) SelectPage(querys model.UEEventAMFQuery) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
@@ -66,17 +65,17 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "timestamp >= ?")
|
||||
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||
params = append(params, beginDate.Unix())
|
||||
if len(querys.StartTime) == 13 {
|
||||
querys.StartTime = querys.StartTime[:10]
|
||||
}
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "timestamp <= ?")
|
||||
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||
params = append(params, endDate.Unix())
|
||||
}
|
||||
if querys.IMSI != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(event_json, '$.imsi') = ?")
|
||||
params = append(params, querys.IMSI)
|
||||
if len(querys.EndTime) == 13 {
|
||||
querys.EndTime = querys.EndTime[:10]
|
||||
}
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
if querys.EventType != "" {
|
||||
eventTypes := strings.Split(querys.EventType, ",")
|
||||
@@ -86,6 +85,10 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
||||
params = append(params, eventType)
|
||||
}
|
||||
}
|
||||
if querys.IMSI != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(event_json, '$.imsi') = ?")
|
||||
params = append(params, querys.IMSI)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
@@ -95,11 +98,11 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.CDREvent{},
|
||||
"rows": []model.UEEventAMF{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from ue_event"
|
||||
totalSql := "select count(1) as 'total' from ue_event_amf"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
@@ -145,23 +148,23 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *UEEventImpl) SelectByIds(ueIds []string) []model.UEEvent {
|
||||
func (r *UEEventAMFImpl) SelectByIds(ueIds []string) []model.UEEventAMF {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
|
||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(ueIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return []model.UEEvent{}
|
||||
return []model.UEEventAMF{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *UEEventImpl) DeleteByIds(ueIds []string) int64 {
|
||||
func (r *UEEventAMFImpl) DeleteByIds(ueIds []string) int64 {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
|
||||
sql := "delete from ue_event where id in (" + placeholder + ")"
|
||||
sql := "delete from ue_event_amf where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(ueIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
15
src/modules/network_data/repository/ue_event_mme.go
Normal file
15
src/modules/network_data/repository/ue_event_mme.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package repository
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// UE会话事件MME 数据层接口
|
||||
type IUEEventMME interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.UEEventMMEQuery) map[string]any
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
SelectByIds(ueIds []string) []model.UEEventMME
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(ueIds []string) int64
|
||||
}
|
||||
175
src/modules/network_data/repository/ue_event_mme.impl.go
Normal file
175
src/modules/network_data/repository/ue_event_mme.impl.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/datasource"
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/utils/repo"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
)
|
||||
|
||||
// 实例化数据层 UEEventMMEImpl 结构体
|
||||
var NewUEEventMMEImpl = &UEEventMMEImpl{
|
||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, event_type, event_json, created_at from ue_event_mme`,
|
||||
|
||||
resultMap: map[string]string{
|
||||
"id": "ID",
|
||||
"ne_type": "NeType",
|
||||
"ne_name": "NeName",
|
||||
"rm_uid": "RmUID",
|
||||
"timestamp": "Timestamp",
|
||||
"event_type": "EventType",
|
||||
"event_json": "EventJSONStr",
|
||||
"created_at": "CreatedAt",
|
||||
},
|
||||
}
|
||||
|
||||
// UEEventMMEImpl UE会话事件 数据层处理
|
||||
type UEEventMMEImpl struct {
|
||||
// 查询视图对象SQL
|
||||
selectSql string
|
||||
// 结果字段与实体映射
|
||||
resultMap map[string]string
|
||||
}
|
||||
|
||||
// convertResultRows 将结果记录转实体结果组
|
||||
func (r *UEEventMMEImpl) convertResultRows(rows []map[string]any) []model.UEEventMME {
|
||||
arr := make([]model.UEEventMME, 0)
|
||||
for _, row := range rows {
|
||||
item := model.UEEventMME{}
|
||||
for key, value := range row {
|
||||
if keyMapper, ok := r.resultMap[key]; ok {
|
||||
repo.SetFieldValue(&item, keyMapper, value)
|
||||
}
|
||||
}
|
||||
arr = append(arr, item)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *UEEventMMEImpl) SelectPage(querys model.UEEventMMEQuery) map[string]any {
|
||||
// 查询条件拼接
|
||||
var conditions []string
|
||||
var params []any
|
||||
if querys.NeType != "" {
|
||||
conditions = append(conditions, "ne_type = ?")
|
||||
params = append(params, querys.NeType)
|
||||
}
|
||||
if querys.RmUID != "" {
|
||||
conditions = append(conditions, "rm_uid = ?")
|
||||
params = append(params, querys.RmUID)
|
||||
}
|
||||
if querys.StartTime != "" {
|
||||
conditions = append(conditions, "timestamp >= ?")
|
||||
if len(querys.StartTime) == 13 {
|
||||
querys.StartTime = querys.StartTime[:10]
|
||||
}
|
||||
params = append(params, querys.StartTime)
|
||||
}
|
||||
if querys.EndTime != "" {
|
||||
conditions = append(conditions, "timestamp <= ?")
|
||||
if len(querys.EndTime) == 13 {
|
||||
querys.EndTime = querys.EndTime[:10]
|
||||
}
|
||||
params = append(params, querys.EndTime)
|
||||
}
|
||||
if querys.EventType != "" {
|
||||
eventTypes := strings.Split(querys.EventType, ",")
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
|
||||
conditions = append(conditions, fmt.Sprintf("event_type in (%s)", placeholder))
|
||||
for _, eventType := range eventTypes {
|
||||
params = append(params, eventType)
|
||||
}
|
||||
}
|
||||
if querys.IMSI != "" {
|
||||
conditions = append(conditions, "JSON_EXTRACT(event_json, '$.imsi') = ?")
|
||||
params = append(params, querys.IMSI)
|
||||
}
|
||||
|
||||
// 构建查询条件语句
|
||||
whereSql := ""
|
||||
if len(conditions) > 0 {
|
||||
whereSql += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"total": 0,
|
||||
"rows": []model.UEEventMME{},
|
||||
}
|
||||
|
||||
// 查询数量 长度为0直接返回
|
||||
totalSql := "select count(1) as 'total' from ue_event_mme"
|
||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("total err => %v", err)
|
||||
return result
|
||||
}
|
||||
total := parse.Number(totalRows[0]["total"])
|
||||
if total == 0 {
|
||||
return result
|
||||
} else {
|
||||
result["total"] = total
|
||||
}
|
||||
|
||||
// 分页
|
||||
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||
pageSql := " limit ?,? "
|
||||
params = append(params, pageNum*pageSize)
|
||||
params = append(params, pageSize)
|
||||
|
||||
// 排序
|
||||
orderSql := ""
|
||||
if querys.SortField != "" {
|
||||
sortSql := querys.SortField
|
||||
if querys.SortOrder != "" {
|
||||
if querys.SortOrder == "desc" {
|
||||
sortSql += " desc "
|
||||
} else {
|
||||
sortSql += " asc "
|
||||
}
|
||||
}
|
||||
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||
results, err := datasource.RawDB("", querySql, params)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
}
|
||||
|
||||
// 转换实体
|
||||
result["rows"] = r.convertResultRows(results)
|
||||
return result
|
||||
}
|
||||
|
||||
// SelectByIds 通过ID查询
|
||||
func (r *UEEventMMEImpl) SelectByIds(ueIds []string) []model.UEEventMME {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
|
||||
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(ueIds)
|
||||
results, err := datasource.RawDB("", querySql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("query err => %v", err)
|
||||
return []model.UEEventMME{}
|
||||
}
|
||||
// 转换实体
|
||||
return r.convertResultRows(results)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *UEEventMMEImpl) DeleteByIds(ueIds []string) int64 {
|
||||
placeholder := repo.KeyPlaceholderByQuery(len(ueIds))
|
||||
sql := "delete from ue_event_mme where id in (" + placeholder + ")"
|
||||
parameters := repo.ConvertIdsSlice(ueIds)
|
||||
results, err := datasource.ExecDB("", sql, parameters)
|
||||
if err != nil {
|
||||
logger.Errorf("delete err => %v", err)
|
||||
return 0
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// CDR会话事件 服务层接口
|
||||
type ICDREvent interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.CDREventQuery) map[string]any
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) (int64, error)
|
||||
}
|
||||
|
||||
// CDR会话事件 服务层接口
|
||||
type SMFCDREvent interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.SMFCDREventQuery) map[string]any
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) (int64, error)
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
// 实例化数据层 CDREventImpl 结构体
|
||||
var NewCDREventImpl = &CDREventImpl{
|
||||
cdrEventRepository: repository.NewCDREventImpl,
|
||||
}
|
||||
|
||||
var NewSMFCDREventImpl = &SMFCDREventImpl{
|
||||
cdrEventRepository: repository.NewSMFCDREventImpl,
|
||||
}
|
||||
|
||||
// CDREventImpl CDR会话事件 服务层处理
|
||||
type CDREventImpl struct {
|
||||
// CDR会话事件数据信息
|
||||
cdrEventRepository repository.ICDREvent
|
||||
}
|
||||
|
||||
type SMFCDREventImpl struct {
|
||||
// CDR会话事件数据信息
|
||||
cdrEventRepository repository.SMFCDREvent
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
||||
return r.cdrEventRepository.SelectPage(querys)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventImpl) DeleteByIds(cdrIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
ids := r.cdrEventRepository.SelectByIds(cdrIds)
|
||||
if len(ids) <= 0 {
|
||||
return 0, fmt.Errorf("not data")
|
||||
}
|
||||
|
||||
if len(ids) == len(cdrIds) {
|
||||
rows := r.cdrEventRepository.DeleteByIds(cdrIds)
|
||||
return rows, nil
|
||||
}
|
||||
// 删除信息失败!
|
||||
return 0, fmt.Errorf("delete fail")
|
||||
}
|
||||
|
||||
func (r *SMFCDREventImpl) SelectPage(querys model.SMFCDREventQuery) map[string]any {
|
||||
return r.cdrEventRepository.SelectPage(querys)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *SMFCDREventImpl) DeleteByIds(cdrIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
ids := r.cdrEventRepository.SelectByIds(cdrIds)
|
||||
if len(ids) <= 0 {
|
||||
return 0, fmt.Errorf("not data")
|
||||
}
|
||||
|
||||
if len(ids) == len(cdrIds) {
|
||||
rows := r.cdrEventRepository.DeleteByIds(cdrIds)
|
||||
return rows, nil
|
||||
}
|
||||
// 删除信息失败!
|
||||
return 0, fmt.Errorf("delete fail")
|
||||
}
|
||||
12
src/modules/network_data/service/cdr_event_ims.go
Normal file
12
src/modules/network_data/service/cdr_event_ims.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// CDR会话事件IMS 服务层接口
|
||||
type ICDREventIMS interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.CDREventIMSQuery) map[string]any
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) (int64, error)
|
||||
}
|
||||
40
src/modules/network_data/service/cdr_event_ims.impl.go
Normal file
40
src/modules/network_data/service/cdr_event_ims.impl.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
// 实例化数据层 NewCDREventIMSImpl 结构体
|
||||
var NewCDREventIMSImpl = &CDREventIMSImpl{
|
||||
cdrEventIMSRepository: repository.NewCDREventIMSImpl,
|
||||
}
|
||||
|
||||
// CDREventImpl CDR会话事件IMS 服务层处理
|
||||
type CDREventIMSImpl struct {
|
||||
// CDR会话事件数据信息
|
||||
cdrEventIMSRepository repository.ICDREventIMS
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *CDREventIMSImpl) SelectPage(querys model.CDREventIMSQuery) map[string]any {
|
||||
return r.cdrEventIMSRepository.SelectPage(querys)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventIMSImpl) DeleteByIds(cdrIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
ids := r.cdrEventIMSRepository.SelectByIds(cdrIds)
|
||||
if len(ids) <= 0 {
|
||||
return 0, fmt.Errorf("not data")
|
||||
}
|
||||
|
||||
if len(ids) == len(cdrIds) {
|
||||
rows := r.cdrEventIMSRepository.DeleteByIds(cdrIds)
|
||||
return rows, nil
|
||||
}
|
||||
// 删除信息失败!
|
||||
return 0, fmt.Errorf("delete fail")
|
||||
}
|
||||
12
src/modules/network_data/service/cdr_event_smf.go
Normal file
12
src/modules/network_data/service/cdr_event_smf.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// CDR会话事件SMF 服务层接口
|
||||
type ICDREventSMF interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.CDREventSMFQuery) map[string]any
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(cdrIds []string) (int64, error)
|
||||
}
|
||||
37
src/modules/network_data/service/cdr_event_smf.impl.go
Normal file
37
src/modules/network_data/service/cdr_event_smf.impl.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
var NewCDREventSMFImpl = &CDREventSMFImpl{
|
||||
cdrEventRepository: repository.NewCDREventSMFImpl,
|
||||
}
|
||||
|
||||
type CDREventSMFImpl struct {
|
||||
// CDR会话事件数据信息
|
||||
cdrEventRepository repository.ICDREventSMF
|
||||
}
|
||||
|
||||
func (r *CDREventSMFImpl) SelectPage(querys model.CDREventSMFQuery) map[string]any {
|
||||
return r.cdrEventRepository.SelectPage(querys)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *CDREventSMFImpl) DeleteByIds(cdrIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
ids := r.cdrEventRepository.SelectByIds(cdrIds)
|
||||
if len(ids) <= 0 {
|
||||
return 0, fmt.Errorf("not data")
|
||||
}
|
||||
|
||||
if len(ids) == len(cdrIds) {
|
||||
rows := r.cdrEventRepository.DeleteByIds(cdrIds)
|
||||
return rows, nil
|
||||
}
|
||||
// 删除信息失败!
|
||||
return 0, fmt.Errorf("delete fail")
|
||||
}
|
||||
28
src/modules/network_data/service/udm_auth.go
Normal file
28
src/modules/network_data/service/udm_auth.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// UDM鉴权信息 服务层接口
|
||||
type IUDMAuth interface {
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
ResetData(neId string) int64
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
SelectPage(query map[string]any) map[string]any
|
||||
|
||||
// SelectList 查询数据库
|
||||
SelectList(u model.UDMAuth) []model.UDMAuth
|
||||
|
||||
// Insert 从数据中读取后删除imsi再存入数据库
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
Insert(neId string, u model.UDMAuth) int64
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
InsertData(neId, dataType string, data any) int64
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
Delete(neID, imsi string) int64
|
||||
|
||||
// LoadData 删除范围后重新加载 num表示imsi后几位
|
||||
LoadData(neID, imsi, num string) int64
|
||||
}
|
||||
146
src/modules/network_data/service/udm_auth.impl.go
Normal file
146
src/modules/network_data/service/udm_auth.impl.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/redis"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
// 实例化服务层 UDMAuthImpl 结构体
|
||||
var NewUDMAuthImpl = &UDMAuthImpl{
|
||||
udmAuthRepository: repository.NewUDMAuthImpl,
|
||||
}
|
||||
|
||||
// UDM鉴权信息 服务层处理
|
||||
type UDMAuthImpl struct {
|
||||
// UDM鉴权信息数据信息
|
||||
udmAuthRepository repository.IUDMAuth
|
||||
}
|
||||
|
||||
// dataByRedis UDM鉴权用户 db:0 中 ausf:*
|
||||
func (r *UDMAuthImpl) dataByRedis(imsi, neId string) []model.UDMAuth {
|
||||
arr := []model.UDMAuth{}
|
||||
key := fmt.Sprintf("ausf:%s", imsi)
|
||||
ausfArr, err := redis.GetKeys("udmuser", key)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
for _, key := range ausfArr {
|
||||
m, err := redis.GetHash("udmuser", key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 跳过-号数据
|
||||
imsi := key[5:]
|
||||
if strings.Contains(imsi, "-") {
|
||||
continue
|
||||
}
|
||||
|
||||
amf := ""
|
||||
if v, ok := m["amf"]; ok {
|
||||
amf = strings.Replace(v, "\r\n", "", 1)
|
||||
}
|
||||
a := model.UDMAuth{
|
||||
IMSI: imsi,
|
||||
Amf: amf,
|
||||
Status: "1", // 默认给1
|
||||
Ki: m["ki"],
|
||||
AlgoIndex: m["algo"],
|
||||
Opc: m["opc"],
|
||||
NeId: neId,
|
||||
}
|
||||
arr = append(arr, a)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
func (r *UDMAuthImpl) ResetData(neId string) int64 {
|
||||
authArr := r.dataByRedis("*", neId)
|
||||
// 数据清空后添加
|
||||
go r.udmAuthRepository.ClearAndInsert(neId, authArr)
|
||||
return int64(len(authArr))
|
||||
}
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
func (r *UDMAuthImpl) SelectPage(query map[string]any) map[string]any {
|
||||
return r.udmAuthRepository.SelectPage(query)
|
||||
}
|
||||
|
||||
// SelectList 查询数据库
|
||||
func (r *UDMAuthImpl) SelectList(u model.UDMAuth) []model.UDMAuth {
|
||||
return r.udmAuthRepository.SelectList(u)
|
||||
}
|
||||
|
||||
// Insert 从数据中读取后删除imsi再存入数据库
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
func (r *UDMAuthImpl) Insert(neId string, u model.UDMAuth) int64 {
|
||||
uArr := r.dataByRedis(u.IMSI, neId)
|
||||
if len(uArr) > 0 {
|
||||
r.udmAuthRepository.Delete(neId, u.IMSI)
|
||||
return r.udmAuthRepository.Inserts(uArr)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
func (r *UDMAuthImpl) InsertData(neId, dataType string, data any) int64 {
|
||||
// imsi截取前缀,重新获取部分数据
|
||||
prefixes := make(map[string]struct{})
|
||||
|
||||
if dataType == "csv" {
|
||||
for _, v := range data.([]map[string]string) {
|
||||
imsi := v["imsi"]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
if dataType == "txt" {
|
||||
for _, v := range data.([][]string) {
|
||||
imsi := v[0]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据前缀重新加载插入
|
||||
var num int64 = 0
|
||||
for prefix := range prefixes {
|
||||
// 直接删除前缀的记录
|
||||
r.udmAuthRepository.DeletePrefixByIMSI(neId, prefix)
|
||||
// keys ausf:4600001000004*
|
||||
authArr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(authArr) > 0 {
|
||||
num += r.udmAuthRepository.Inserts(authArr)
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
func (r *UDMAuthImpl) Delete(neId, imsi string) int64 {
|
||||
return r.udmAuthRepository.Delete(neId, imsi)
|
||||
}
|
||||
|
||||
// LoadData 删除范围后重新加载 num表示imsi后几位
|
||||
func (r *UDMAuthImpl) LoadData(neId, imsi, num string) int64 {
|
||||
prefix := imsi[:len(imsi)-len(num)-1]
|
||||
// 直接删除前缀的记录
|
||||
delNum := r.udmAuthRepository.DeletePrefixByIMSI(neId, prefix)
|
||||
// keys ausf:4600001000004*
|
||||
authArr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(authArr) > 0 {
|
||||
return r.udmAuthRepository.Inserts(authArr)
|
||||
}
|
||||
return delNum
|
||||
}
|
||||
28
src/modules/network_data/service/udm_sub.go
Normal file
28
src/modules/network_data/service/udm_sub.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// UDM签约用户信息 服务层接口
|
||||
type IUDMSub interface {
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
ResetData(neId string) int64
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
SelectPage(query map[string]any) map[string]any
|
||||
|
||||
// SelectList 查询数据库
|
||||
SelectList(u model.UDMSub) []model.UDMSub
|
||||
|
||||
// Insert 从数据中读取后删除imsi再存入数据库
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
Insert(neId string, u model.UDMSub) int64
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
InsertData(neId, dataType string, data any) int64
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
Delete(neId, imsi string) int64
|
||||
|
||||
// LoadData 删除范围后重新加载 num表示imsi后几位
|
||||
LoadData(neId, imsi, num string) int64
|
||||
}
|
||||
164
src/modules/network_data/service/udm_sub.impl.go
Normal file
164
src/modules/network_data/service/udm_sub.impl.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/redis"
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
// 实例化服务层 UDMSubImpl 结构体
|
||||
var NewUDMSubImpl = &UDMSubImpl{
|
||||
udmSubRepository: repository.NewUDMSubImpl,
|
||||
}
|
||||
|
||||
// UDM签约信息 服务层处理
|
||||
type UDMSubImpl struct {
|
||||
// UDM签约信息数据信息
|
||||
udmSubRepository repository.IUDMSub
|
||||
}
|
||||
|
||||
// dataByRedis UDM签约用户 db:0 中 udm-sd:*
|
||||
func (r *UDMSubImpl) dataByRedis(imsi, neId string) []model.UDMSub {
|
||||
arr := []model.UDMSub{}
|
||||
key := fmt.Sprintf("udm-sd:%s", imsi)
|
||||
udmsdArr, err := redis.GetKeys("udmuser", key)
|
||||
if err != nil {
|
||||
return arr
|
||||
}
|
||||
for _, key := range udmsdArr {
|
||||
m, err := redis.GetHash("udmuser", key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
a := model.UDMSub{
|
||||
IMSI: key[7:],
|
||||
Msisdn: m["gpsi"], // 46003550072
|
||||
SmfSel: m["smf-sel"],
|
||||
SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet
|
||||
NeId: neId,
|
||||
}
|
||||
|
||||
// def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,-
|
||||
if v, ok := m["am-dat"]; ok {
|
||||
arr := strings.Split(v, ",")
|
||||
a.Ambr = arr[0]
|
||||
a.Nssai = arr[1]
|
||||
a.Rat = arr[2]
|
||||
a.Arfb = arr[3]
|
||||
a.Sar = arr[4]
|
||||
a.Cn = arr[5]
|
||||
}
|
||||
// 1,64,24,65,def_eps,1,2,010200000000,-
|
||||
if v, ok := m["eps-dat"]; ok {
|
||||
arr := strings.Split(v, ",")
|
||||
// 跳过非常规数据
|
||||
if len(arr) > 9 {
|
||||
continue
|
||||
}
|
||||
a.EpsDat = v
|
||||
a.EpsFlag = arr[0]
|
||||
a.EpsOdb = arr[1]
|
||||
a.HplmnOdb = arr[2]
|
||||
a.Ard = arr[3]
|
||||
a.Epstpl = arr[4]
|
||||
a.ContextId = arr[5]
|
||||
a.ApnContext = arr[7]
|
||||
// [6] 是不要的,导入和导出不用
|
||||
a.StaticIp = arr[8]
|
||||
}
|
||||
|
||||
arr = append(arr, a)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据
|
||||
func (r *UDMSubImpl) ResetData(neId string) int64 {
|
||||
subArr := r.dataByRedis("*", neId)
|
||||
// 数据清空后添加
|
||||
go r.udmSubRepository.ClearAndInsert(neId, subArr)
|
||||
return int64(len(subArr))
|
||||
}
|
||||
|
||||
// SelectPage 分页查询数据库
|
||||
func (r *UDMSubImpl) SelectPage(query map[string]any) map[string]any {
|
||||
return r.udmSubRepository.SelectPage(query)
|
||||
}
|
||||
|
||||
// SelectList 查询数据库
|
||||
func (r *UDMSubImpl) SelectList(u model.UDMSub) []model.UDMSub {
|
||||
return r.udmSubRepository.SelectList(u)
|
||||
}
|
||||
|
||||
// Insert 从数据中读取后删除imsi再存入数据库
|
||||
// imsi长度15,ki长度32,opc长度0或者32
|
||||
func (r *UDMSubImpl) Insert(neId string, u model.UDMSub) int64 {
|
||||
uArr := r.dataByRedis(u.IMSI, neId)
|
||||
if len(uArr) > 0 {
|
||||
r.udmSubRepository.Delete(neId, u.IMSI)
|
||||
return r.udmSubRepository.Inserts(uArr)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InsertData 导入文件数据 dataType目前两种:txt/csv
|
||||
func (r *UDMSubImpl) InsertData(neId, dataType string, data any) int64 {
|
||||
// imsi截取前缀,重新获取部分数据
|
||||
prefixes := make(map[string]struct{})
|
||||
|
||||
if dataType == "csv" {
|
||||
for _, v := range data.([]map[string]string) {
|
||||
imsi := v["imsi"]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
if dataType == "txt" {
|
||||
for _, v := range data.([][]string) {
|
||||
imsi := v[0]
|
||||
if len(imsi) < 6 {
|
||||
continue
|
||||
}
|
||||
prefix := imsi[:len(imsi)-4]
|
||||
prefixes[prefix] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据前缀重新加载插入
|
||||
var num int64 = 0
|
||||
for prefix := range prefixes {
|
||||
// 直接删除前缀的记录
|
||||
r.udmSubRepository.DeletePrefixByIMSI(neId, prefix)
|
||||
// keys udm-sd:4600001000004*
|
||||
subArr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(subArr) > 0 {
|
||||
num += r.udmSubRepository.Inserts(subArr)
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// Delete 删除单个不重新加载
|
||||
func (r *UDMSubImpl) Delete(neId, imsi string) int64 {
|
||||
return r.udmSubRepository.Delete(neId, imsi)
|
||||
}
|
||||
|
||||
// LoadData 删除范围后重新加载 num表示imsi后几位
|
||||
func (r *UDMSubImpl) LoadData(neId, imsi, num string) int64 {
|
||||
prefix := imsi[:len(imsi)-len(num)-1]
|
||||
// 直接删除前缀的记录
|
||||
delNum := r.udmSubRepository.DeletePrefixByIMSI(neId, prefix)
|
||||
// keys udm-sd:4600001000004*
|
||||
authArr := r.dataByRedis(prefix+"*", neId)
|
||||
if len(authArr) > 0 {
|
||||
return r.udmSubRepository.Inserts(authArr)
|
||||
}
|
||||
return delNum
|
||||
}
|
||||
@@ -2,10 +2,10 @@ package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// UE会话事件 服务层接口
|
||||
type IUEEvent interface {
|
||||
// UE会话事件AMF 服务层接口
|
||||
type IUEEventAMF interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.UEEventQuery) map[string]any
|
||||
SelectPage(querys model.UEEventAMFQuery) map[string]any
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(ueIds []string) (int64, error)
|
||||
@@ -7,24 +7,24 @@ import (
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
// 实例化数据层 UEEventImpl 结构体
|
||||
var NewUEEventImpl = &UEEventImpl{
|
||||
ueEventRepository: repository.NewUEEventImpl,
|
||||
// 实例化数据层 UEEventMMEImpl 结构体
|
||||
var NewUEEventMMEImpl = &UEEventMMEImpl{
|
||||
ueEventRepository: repository.NewUEEventMMEImpl,
|
||||
}
|
||||
|
||||
// UEEventImpl UE会话事件 服务层处理
|
||||
type UEEventImpl struct {
|
||||
// UEEventMMEImpl UE会话事件MME 服务层处理
|
||||
type UEEventMMEImpl struct {
|
||||
// UE会话事件数据信息
|
||||
ueEventRepository repository.IUEEvent
|
||||
ueEventRepository repository.IUEEventMME
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
||||
func (r *UEEventMMEImpl) SelectPage(querys model.UEEventMMEQuery) map[string]any {
|
||||
return r.ueEventRepository.SelectPage(querys)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *UEEventImpl) DeleteByIds(ueIds []string) (int64, error) {
|
||||
func (r *UEEventMMEImpl) DeleteByIds(ueIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
ids := r.ueEventRepository.SelectByIds(ueIds)
|
||||
if len(ids) <= 0 {
|
||||
12
src/modules/network_data/service/ue_event_mme.go
Normal file
12
src/modules/network_data/service/ue_event_mme.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package service
|
||||
|
||||
import "be.ems/src/modules/network_data/model"
|
||||
|
||||
// UE会话事件MME 服务层接口
|
||||
type IUEEventMME interface {
|
||||
// SelectPage 根据条件分页查询
|
||||
SelectPage(querys model.UEEventMMEQuery) map[string]any
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
DeleteByIds(ueIds []string) (int64, error)
|
||||
}
|
||||
40
src/modules/network_data/service/ue_event_mme.impl.go
Normal file
40
src/modules/network_data/service/ue_event_mme.impl.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"be.ems/src/modules/network_data/model"
|
||||
"be.ems/src/modules/network_data/repository"
|
||||
)
|
||||
|
||||
// 实例化数据层 UEEventAMFImpl 结构体
|
||||
var NewUEEventAMFImpl = &UEEventAMFImpl{
|
||||
ueEventRepository: repository.NewUEEventAMFImpl,
|
||||
}
|
||||
|
||||
// UEEventAMFImpl UE会话事件AMF 服务层处理
|
||||
type UEEventAMFImpl struct {
|
||||
// UE会话事件数据信息
|
||||
ueEventRepository repository.IUEEventAMF
|
||||
}
|
||||
|
||||
// SelectPage 根据条件分页查询
|
||||
func (r *UEEventAMFImpl) SelectPage(querys model.UEEventAMFQuery) map[string]any {
|
||||
return r.ueEventRepository.SelectPage(querys)
|
||||
}
|
||||
|
||||
// DeleteByIds 批量删除信息
|
||||
func (r *UEEventAMFImpl) DeleteByIds(ueIds []string) (int64, error) {
|
||||
// 检查是否存在
|
||||
ids := r.ueEventRepository.SelectByIds(ueIds)
|
||||
if len(ids) <= 0 {
|
||||
return 0, fmt.Errorf("no data")
|
||||
}
|
||||
|
||||
if len(ids) == len(ueIds) {
|
||||
rows := r.ueEventRepository.DeleteByIds(ueIds)
|
||||
return rows, nil
|
||||
}
|
||||
// 删除信息失败!
|
||||
return 0, fmt.Errorf("delete fail")
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package controller
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
@@ -50,19 +51,30 @@ func (s *NeActionController) PushFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 本地文件
|
||||
localPath := file.ParseUploadFilePath(body.UploadPath)
|
||||
nePath := "/tmp" //config.Get("mml.upload").(string)
|
||||
// 复制到远程
|
||||
err := ssh.FileSCPLocalToNe(neInfo.IP, localPath, nePath)
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
// 本地文件
|
||||
localFilePath := file.ParseUploadFilePath(body.UploadPath)
|
||||
neFilePath := fmt.Sprintf("/tmp/%s", filepath.Base(localFilePath))
|
||||
// 复制到远程
|
||||
if err = sftpClient.CopyFileLocalToRemote(localFilePath, neFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(fmt.Sprintf("%s : please check if scp remote copy is allowed", neInfo.NeType)))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元端文件路径
|
||||
fileName := localPath[strings.LastIndex(localPath, "/")+1:]
|
||||
neFilePath := fmt.Sprintf("%s/%s", nePath, fileName)
|
||||
c.JSON(200, result.OkData(filepath.ToSlash(neFilePath)))
|
||||
}
|
||||
|
||||
@@ -89,14 +101,32 @@ func (s *NeActionController) PullFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
nePath := fmt.Sprintf("%s/%s", querys.Path, querys.FileName)
|
||||
localPath := fmt.Sprintf("/tmp/omc/pullFile/%s", querys.FileName)
|
||||
err := ssh.FileSCPNeToLocal(neInfo.IP, nePath, localPath)
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.FileAttachment(localPath, querys.FileName)
|
||||
defer sshClient.Close()
|
||||
// 网元主机的SSH客户端进行文件传输
|
||||
sftpClient, err := sshClient.NewClientSFTP()
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
nePath := fmt.Sprintf("%s/%s", querys.Path, querys.FileName)
|
||||
localFilePath := fmt.Sprintf("/tmp/omc/pullFile%s", nePath)
|
||||
if runtime.GOOS == "windows" {
|
||||
localFilePath = fmt.Sprintf("C:%s", localFilePath)
|
||||
}
|
||||
// 复制到本地
|
||||
if err = sftpClient.CopyFileRemoteToLocal(nePath, localFilePath); err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
c.FileAttachment(localFilePath, querys.FileName)
|
||||
}
|
||||
|
||||
// 网元端文件列表
|
||||
@@ -124,7 +154,16 @@ func (s *NeActionController) Files(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
totalSize, rows, err := ssh.FileList(querys.Path, neInfo.IP, querys.Search)
|
||||
// 网元主机的SSH客户端
|
||||
sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
defer sshClient.Close()
|
||||
|
||||
// 获取文件列表
|
||||
totalSize, rows, err := ssh.FileList(sshClient, querys.Path, querys.Search)
|
||||
if err != nil {
|
||||
c.JSON(200, result.Ok(map[string]any{
|
||||
"path": querys.Path,
|
||||
@@ -184,7 +223,7 @@ func (s *NeActionController) Service(c *gin.Context) {
|
||||
cmdStr = fmt.Sprintf("nohup sh -c \"sudo systemctl stop restagent && sleep 5s && sudo systemctl %s restagent\" > /dev/null 2>&1 &", body.Action)
|
||||
} else if neTypeLower == "ims" {
|
||||
if body.Action == "restart" {
|
||||
cmdStr = "sudo ims-stop || true && sudo ims-start"
|
||||
cmdStr = "ims-stop || true && ims-start"
|
||||
} else {
|
||||
cmdStr = fmt.Sprintf("sudo ims-%s", body.Action)
|
||||
}
|
||||
@@ -197,7 +236,7 @@ func (s *NeActionController) Service(c *gin.Context) {
|
||||
cmdStr = "sudo shutdown -h now"
|
||||
}
|
||||
|
||||
_, err := s.neInfoService.NeRunCMD(body.NeType, body.NeID, cmdStr)
|
||||
_, err := s.neInfoService.NeRunSSHCmd(body.NeType, body.NeID, cmdStr)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
202
src/modules/network_element/controller/ne_config.go
Normal file
202
src/modules/network_element/controller/ne_config.go
Normal file
@@ -0,0 +1,202 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/i18n"
|
||||
"be.ems/src/framework/utils/ctx"
|
||||
"be.ems/src/framework/utils/parse"
|
||||
"be.ems/src/framework/vo/result"
|
||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||
"be.ems/src/modules/network_element/model"
|
||||
neService "be.ems/src/modules/network_element/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// NewNeConfig 网元参数配置 实例化控制层
|
||||
var NewNeConfig = &NeConfigController{
|
||||
neConfigService: neService.NewNeConfigImpl,
|
||||
neInfoService: neService.NewNeInfoImpl,
|
||||
}
|
||||
|
||||
// 网元参数配置
|
||||
//
|
||||
// PATH /config
|
||||
type NeConfigController struct {
|
||||
// 网元参数配置可用属性值服务
|
||||
neConfigService neService.INeConfig
|
||||
// 网元信息服务
|
||||
neInfoService neService.INeInfo
|
||||
}
|
||||
|
||||
// 网元参数配置可用属性值列表
|
||||
//
|
||||
// GET /list
|
||||
func (s *NeConfigController) List(c *gin.Context) {
|
||||
querys := ctx.QueryMap(c)
|
||||
data := s.neConfigService.SelectPage(querys)
|
||||
|
||||
c.JSON(200, result.Ok(data))
|
||||
}
|
||||
|
||||
// 网元参数配置可用属性值信息
|
||||
//
|
||||
// GET /info/:id
|
||||
func (s *NeConfigController) Info(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
data := s.neConfigService.SelectById(id)
|
||||
if data.ID != id {
|
||||
// 没有可访问参数配置数据!
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neConfig.noData")))
|
||||
return
|
||||
}
|
||||
|
||||
// 将字符串转json数据
|
||||
if err := json.Unmarshal([]byte(data.ParamJSONStr), &data.ParamData); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, err.Error()))
|
||||
return
|
||||
}
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// 网元参数配置可用属性值新增
|
||||
//
|
||||
// POST /
|
||||
func (s *NeConfigController) Add(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var body model.NeConfig
|
||||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 将json数据转字符串存储
|
||||
paramDataByte, err := json.Marshal(body.ParamData)
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, err.Error()))
|
||||
return
|
||||
}
|
||||
body.ParamJSONStr = string(paramDataByte)
|
||||
|
||||
insertId := s.neConfigService.Insert(body)
|
||||
if insertId != "" {
|
||||
c.JSON(200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
c.JSON(200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 网元参数配置可用属性值修改
|
||||
//
|
||||
// PUT /
|
||||
func (s *NeConfigController) Edit(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var body model.NeConfig
|
||||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||||
if err != nil || body.ID == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否存在
|
||||
data := s.neConfigService.SelectById(body.ID)
|
||||
if data.ID != body.ID {
|
||||
// 没有可访问主机命令数据!
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "neConfig.noData")))
|
||||
return
|
||||
}
|
||||
|
||||
// 将json数据转字符串存储
|
||||
paramDataByte, err := json.Marshal(body.ParamData)
|
||||
if err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, err.Error()))
|
||||
return
|
||||
}
|
||||
body.ParamJSONStr = string(paramDataByte)
|
||||
|
||||
rows := s.neConfigService.Update(body)
|
||||
if rows > 0 {
|
||||
c.JSON(200, result.Ok(nil))
|
||||
return
|
||||
}
|
||||
c.JSON(200, result.Err(nil))
|
||||
}
|
||||
|
||||
// 网元参数配置可用属性值删除
|
||||
//
|
||||
// DELETE /:ids
|
||||
func (s *NeConfigController) Remove(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
ids := c.Param("ids")
|
||||
if ids == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
// 处理字符转id数组后去重
|
||||
idsArr := strings.Split(ids, ",")
|
||||
uniqueIDs := parse.RemoveDuplicates(idsArr)
|
||||
if len(uniqueIDs) <= 0 {
|
||||
c.JSON(200, result.Err(nil))
|
||||
return
|
||||
}
|
||||
rows, err := s.neConfigService.DeleteByIds(uniqueIDs)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
|
||||
return
|
||||
}
|
||||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||
c.JSON(200, result.OkMsg(msg))
|
||||
}
|
||||
|
||||
// 网元参数配置可用属性值列表指定网元类型全部无分页
|
||||
//
|
||||
// GET /list/:neType
|
||||
func (s *NeConfigController) ListByNeType(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
neType := c.Param("neType")
|
||||
if neType == "" {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
data := s.neConfigService.SelectNeConfigByNeType(neType)
|
||||
c.JSON(200, result.OkData(data))
|
||||
}
|
||||
|
||||
// 网元参数配置数据信息
|
||||
//
|
||||
// GET /data
|
||||
func (s *NeConfigController) Data(c *gin.Context) {
|
||||
language := ctx.AcceptLanguage(c)
|
||||
var querys struct {
|
||||
NeType string `form:"neType" binding:"required"` // 网元类型
|
||||
NeId string `form:"neId" binding:"required"` // 网元ID
|
||||
TopTag string `form:"topTag" binding:"required"` // 可用属性
|
||||
}
|
||||
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||
return
|
||||
}
|
||||
|
||||
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeId)
|
||||
if neInfo.NeId != querys.NeId || neInfo.IP == "" {
|
||||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||
return
|
||||
}
|
||||
|
||||
// 网元直连
|
||||
resData, err := neFetchlink.NeConfigInfo(neInfo, querys.TopTag)
|
||||
if err != nil {
|
||||
c.JSON(200, result.ErrMsg(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result.Ok(resData))
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user