From b625536d9c7150af88b80f21a217e104c1388ec7 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 11 Sep 2023 21:01:32 +0800 Subject: [PATCH 1/5] =?UTF-8?q?UDM=E7=AD=BE=E7=BA=A6=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=AE=9E=E4=BD=93=E5=AD=97=E6=AE=B5=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/udm_user/model/udm_sub_user.go | 34 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/features/udm_user/model/udm_sub_user.go b/features/udm_user/model/udm_sub_user.go index c43c96de..d7daf90a 100644 --- a/features/udm_user/model/udm_sub_user.go +++ b/features/udm_user/model/udm_sub_user.go @@ -2,16 +2,26 @@ package model // UdmSubUser UDM签约用户 type UdmSubUser struct { - ID string `json:"id" xorm:"pk 'id' autoincr"` - Msisdn string `json:"msisdn" xorm:"msisdn"` // 相当手机号 - Imsi string `json:"imsi" xorm:"imsi"` // SIM卡号 - SubUeAMBRTemp string `json:"subUeAMBRTemp" xorm:"sub_ue_ambr_temp"` - SubSNSSAITemp string `json:"subSNSSAITemp" xorm:"sub_snssai_temp"` - Rai string `json:"rai" xorm:"rai"` - ForbiddenAreasTemp string `json:"forbiddenAreasTemp" xorm:"forbidden_areas_temp"` - ServiceAreaRestrictTemp string `json:"serviceAreaRestrictTemp" xorm:"service_area_restrict_temp"` - CnType string `json:"cnType" xorm:"cn_type"` - SubData string `json:"subData" xorm:"sub_data"` - Eps string `json:"eps" xorm:"eps"` - NeID string `json:"neId" xorm:"ne_id"` // UDM网元标识-子系统 + ID string `json:"id" xorm:"pk 'id' autoincr"` + Msisdn string `json:"msisdn" xorm:"msisdn"` // 相当手机号 + Imsi string `json:"imsi" xorm:"imsi"` // SIM卡号 + Ambr string `json:"ambr" xorm:"ambr"` + Nssai string `json:"nssai" xorm:"nssai"` + Rat string `json:"rat" xorm:"rat"` + Arfb string `json:"arfb" xorm:"arfb"` + Sar string `json:"sar" xorm:"sar"` + Cn string `json:"cn" xorm:"cn"` + SmData string `json:"smData" xorm:"sm_data"` + SmfSel string `json:"smfSel" xorm:"smf_sel"` + EpsDat string `json:"epsDat" xorm:"eps_dat"` + NeID string `json:"neId" xorm:"ne_id"` // UDM网元标识-子系统 + + EpsFlag string `json:"epsFlag" xorm:"eps_flag"` + EpsOdb string `json:"epsOdb" xorm:"eps_odb"` + HplmnOdb string `json:"hplmnOdb" xorm:"hplmn_odb"` + Ard string `json:"ard" xorm:"ard"` + Epstpl string `json:"epstpl" xorm:"epstpl"` + ContextId string `json:"contextId" xorm:"context_id"` + ApnContext string `json:"apnContext" xorm:"apn_context"` + StaticIp string `json:"staticIp" xorm:"static_ip"` } From 449d81c950f87a8a1d472575889d29625f76a200 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 11 Sep 2023 21:02:18 +0800 Subject: [PATCH 2/5] =?UTF-8?q?UDM=E7=AD=BE=E7=BA=A6=E7=94=A8=E6=88=B7redi?= =?UTF-8?q?s=E6=95=B0=E6=8D=AE=E5=AD=97=E6=AE=B5=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../udm_user/service/service_redis_data.go | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/features/udm_user/service/service_redis_data.go b/features/udm_user/service/service_redis_data.go index 0611b317..b0839842 100644 --- a/features/udm_user/service/service_redis_data.go +++ b/features/udm_user/service/service_redis_data.go @@ -54,27 +54,35 @@ func redisUdmSubUserList() []model.UdmSubUser { m := redis.GetHash(key) a := model.UdmSubUser{ - Imsi: imsi, - Msisdn: m["gpsi"], - SubData: m["sm-dat"], + Imsi: imsi, + Msisdn: m["gpsi"], + SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet } if a.Msisdn == "" { a.Msisdn = phone } + // 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.SubUeAMBRTemp = arr[0] - a.SubSNSSAITemp = arr[1] - a.Rai = arr[2] - a.ForbiddenAreasTemp = arr[3] - a.ServiceAreaRestrictTemp = arr[4] - a.CnType = arr[5] + 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, ",") - a.Eps = arr[0] + 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] } user = append(user, a) From 614e792670ca2a21746c2c67738dd54aeefb243b Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 11 Sep 2023 21:02:56 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A1=A5=E5=85=85UDM?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=95=B0=E6=8D=AE=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/udm_user/api_udm_user.go | 734 +++++++++++++++++- features/udm_user/repo/repo_udm_auth_user.go | 107 ++- features/udm_user/repo/repo_udm_sub_user.go | 156 +++- .../udm_user/service/service_udm_auth_user.go | 55 +- .../udm_user/service/service_udm_sub_user.go | 72 +- 5 files changed, 1087 insertions(+), 37 deletions(-) diff --git a/features/udm_user/api_udm_user.go b/features/udm_user/api_udm_user.go index 5511572a..3e6c253c 100644 --- a/features/udm_user/api_udm_user.go +++ b/features/udm_user/api_udm_user.go @@ -3,6 +3,9 @@ package udmuser import ( "fmt" "net/http" + "strconv" + "strings" + "time" "ems.agt/features/udm_user/model" "ems.agt/features/udm_user/service" @@ -34,7 +37,7 @@ func Routers() []services.RouterItem { }, { Method: "POST", - Pattern: "/auth/getSave", + Pattern: "/authSave/{neId}", Handler: apis.UdmAuthUserSave, Middleware: nil, //midware.Authorize(nil), }, @@ -46,10 +49,46 @@ func Routers() []services.RouterItem { }, { Method: "POST", - Pattern: "/auth/export", + Pattern: "/auth/{neId}", + Handler: apis.UdmAuthUserAdd, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "POST", + Pattern: "/auth/{neId}/{num}", + Handler: apis.UdmAuthUserAdds, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "PUT", + Pattern: "/auth/{neId}", + Handler: apis.UdmAuthUserEdit, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "DELETE", + Pattern: "/auth/{neId}/{imsi}", + Handler: apis.UdmAuthUserRemove, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "DELETE", + Pattern: "/auth/{neId}/{imsi}/{num}", + Handler: apis.UdmAuthUserRemoves, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "POST", + Pattern: "/authExport/{neId}", Handler: apis.UdmAuthUserExport, Middleware: nil, //midware.Authorize(nil), }, + { + Method: "POST", + Pattern: "/authImport/{neId}", + Handler: apis.UdmAuthUserImport, + Middleware: nil, //midware.Authorize(nil), + }, // UDM签约用户 { Method: "GET", @@ -59,16 +98,58 @@ func Routers() []services.RouterItem { }, { Method: "POST", - Pattern: "/sub/getSave", + Pattern: "/subSave/{neId}", Handler: apis.UdmSubUserSave, Middleware: nil, //midware.Authorize(nil), }, { Method: "GET", - Pattern: "/sub/{neId}/{imsi}", + Pattern: "/subInfo/{neId}/{imsi}", Handler: apis.UdmSubUserInfo, Middleware: nil, //midware.Authorize(nil), }, + { + Method: "POST", + Pattern: "/sub/{neId}", + Handler: apis.UdmSubUserAdd, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "POST", + Pattern: "/sub/{neId}/{num}", + Handler: apis.UdmSubUserAdds, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "PUT", + Pattern: "/sub/{neId}", + Handler: apis.UdmAuthUserEdit, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "DELETE", + Pattern: "/sub/{neId}/{imsi}", + Handler: apis.UdmSubUserRemove, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "DELETE", + Pattern: "/sub/{neId}/{imsi}/{num}", + Handler: apis.UdmSubUserRemoves, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "POST", + Pattern: "/subExport/{neId}", + Handler: apis.UdmSubUserExport, + Middleware: nil, //midware.Authorize(nil), + }, + { + Method: "POST", + Pattern: "/subImport/{neId}", + Handler: apis.UdmSubUserImport, + Middleware: nil, //midware.Authorize(nil), + }, // 添加更多的 Router 对象... } @@ -115,15 +196,21 @@ func (s *UdmUserApi) UdmAuthUserList(w http.ResponseWriter, r *http.Request) { // UDM鉴权用户-获取全部保存数据库 // -// POST /auth/getSave +// POST /authSave/{neId} func (s *UdmUserApi) UdmAuthUserSave(w http.ResponseWriter, r *http.Request) { - data := s.authUser.Save("") + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + data := s.authUser.Save(neId) ctx.JSON(w, 200, result.OkData(data)) } // UDM鉴权用户-信息 // -// GET /{neId}/{imsi} +// GET /authInfo/{neId}/{imsi} func (s *UdmUserApi) UdmAuthUserInfo(w http.ResponseWriter, r *http.Request) { neId := ctx.Param(r, "neId") imsi := ctx.Param(r, "imsi") @@ -146,22 +233,243 @@ func (s *UdmUserApi) UdmAuthUserInfo(w http.ResponseWriter, r *http.Request) { ctx.JSON(w, 200, result.ErrMsg(err.Error())) return } + + var userInfo model.UdmAuthUser + list := s.authUser.List(model.UdmAuthUser{NeID: neId, Imsi: imsi}) + if len(list) > 0 { + userInfo = list[0] + ctx.JSON(w, 200, result.OkData(list[0])) + } else { + userInfo = model.UdmAuthUser{ + Imsi: imsi, + Amf: data["amf"], + AlgoIndex: data["algo"], + Opc: data["opc"], + Ki: data["ki"], + } + + s.authUser.Insert(neId, userInfo) + } + ctx.JSON(w, 200, result.OkData(userInfo)) + +} + +// UDM鉴权用户-增加 +// +// POST /{neId} +func (s *UdmUserApi) UdmAuthUserAdd(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + var body model.UdmAuthUser + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + 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) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.authUser.Insert(neInfo.NeId, body) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM鉴权用户-批量添加 +// +// POST /{neId}/{num} +func (s *UdmUserApi) UdmAuthUserAdds(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + num := ctx.Param(r, "num") + if neId == "" || num == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + var body model.UdmAuthUser + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("bad authdat:start_imsi=%s,sub_num=%s,ki=%s,amf=%s,algo=%s", body.Imsi, num, body.Ki, body.Amf, body.AlgoIndex) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.authUser.Inserts(neInfo.NeId, body, num) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM鉴权用户-修改 +// +// PUT /{neId} +func (s *UdmUserApi) UdmAuthUserEdit(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + var body model.UdmAuthUser + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + 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) + } + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.authUser.Update(neInfo.NeId, body) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM鉴权用户-删除 +// +// DELETE /{neId}/{imsi} +func (s *UdmUserApi) UdmAuthUserRemove(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + imsi := ctx.Param(r, "imsi") + if neId == "" || imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("del authdat:imsi=%s", imsi) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.authUser.Delete(neId, imsi) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM鉴权用户-批量删除 +// +// DELETE /{neId}/{imsi}/{num} +func (s *UdmUserApi) UdmAuthUserRemoves(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + imsi := ctx.Param(r, "imsi") + num := ctx.Param(r, "num") + if neId == "" || imsi == "" || num == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("bde authdat:start_imsi=%s,sub_num=%s", imsi, num) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.authUser.Deletes(neId, imsi, num) + } ctx.JSON(w, 200, result.OkData(data)) } // UDM鉴权用户-导出 // -// POST /auth/export +// POST /authExport/{neId} func (s *UdmUserApi) UdmAuthUserExport(w http.ResponseWriter, r *http.Request) { - list := s.authUser.List(model.UdmAuthUser{}) + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + list := s.authUser.List(model.UdmAuthUser{NeID: neId}) // 文件名 - fileName := "OMC_AUTH_100.csv" - filePath := "C:/AMP/Probject/ems_backend/restagent/OMC_AUTH_100.csv" + fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.csv", neId, time.Now().UnixMilli()) + filePath := fmt.Sprintf("/usr/local/omc/upload/mml/%s", fileName) // 转换数据 data := [][]string{} - data = append(data, []string{"ID", "Msisdn", "Imsi", "Amf", "Status", "Ki", "AlgoIndex", "Opc"}) + data = append(data, []string{"imsi", "ki", "amf", "algo", "opc", "status"}) for _, v := range list { - data = append(data, []string{v.ID, v.Msisdn, v.Imsi, v.Amf, v.Status, v.Ki, v.AlgoIndex, v.Opc}) + data = append(data, []string{v.Imsi, v.Ki, v.Amf, v.AlgoIndex, v.Opc, v.Status}) } // 输出到文件 err := file.WriterCSVFile(data, filePath) @@ -172,6 +480,57 @@ func (s *UdmUserApi) UdmAuthUserExport(w http.ResponseWriter, r *http.Request) { ctx.FileAttachment(w, r, filePath, fileName) } +// UDM鉴权用户-导入 +// +// POST /authImport/{neId} +func (s *UdmUserApi) UdmAuthUserImport(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 文件名 + fileName := fmt.Sprintf("OMC_AUTH_USER_IMPORT_%s_%d.csv", neId, time.Now().UnixMilli()) + filePath := fmt.Sprintf("/usr/local/omc/upload/mml/%s", fileName) + dstPath := "/home/agtuser/" + // 输出保存文件 + err = ctx.SaveUploadedFile(r, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 复制到远程 + err = file.FileNeSCP(neInfo.Ip, filePath, dstPath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("import authdat:path=%s", fmt.Sprintf("%s%s", dstPath, fileName)) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + // 命令ok时 + if strings.Contains(data, "ok") { + data := file.ReadCSVFile(filePath) + s.authUser.InsertCSV(neId, data) + } + // ctx.JSON(w, 200, result.OkData(data)) + ctx.FileAttachment(w, r, filePath, fileName) +} + // UDM签约用户 // // GET /subs @@ -183,15 +542,21 @@ func (s *UdmUserApi) UdmSubUserList(w http.ResponseWriter, r *http.Request) { // UDM签约用户-获取全部保存数据库 // -// POST /sub/getSave +// POST /subSave/{neId} func (s *UdmUserApi) UdmSubUserSave(w http.ResponseWriter, r *http.Request) { - data := s.subUser.Save("") + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + data := s.subUser.Save(neId) ctx.JSON(w, 200, result.OkData(data)) } // UDM签约用户-信息 // -// GET /{neId}/{imsi} +// GET /subInfo/{neId}/{imsi} func (s *UdmUserApi) UdmSubUserInfo(w http.ResponseWriter, r *http.Request) { neId := ctx.Param(r, "neId") imsi := ctx.Param(r, "imsi") @@ -214,5 +579,342 @@ func (s *UdmUserApi) UdmSubUserInfo(w http.ResponseWriter, r *http.Request) { ctx.JSON(w, 200, result.ErrMsg(err.Error())) return } + + var userInfo model.UdmSubUser + list := s.subUser.List(model.UdmSubUser{NeID: neId, Imsi: imsi}) + if len(list) > 0 { + userInfo = list[0] + ctx.JSON(w, 200, result.OkData(list[0])) + } else { + cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64) + rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64) + userInfo = model.UdmSubUser{ + Imsi: imsi, + Msisdn: data["MSISDN"], + Ambr: data["AMBR"], + Arfb: data["AreaForbidden"], + Cn: fmt.Sprint(cnType), + SmData: data["SM-Data(snssai+dnn[1..n])"], + Sar: data["ServiceAreaRestriction"], + Nssai: data["NSSAI"], + SmfSel: data["Smf-Selection"], + Rat: fmt.Sprint(rat), + } + // 1,64,24,65,def_eps,1,2,010200000000,- + if v, ok := data["EPS-Data"]; ok { + 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] + } + + s.subUser.Insert(neId, userInfo) + } + ctx.JSON(w, 200, result.OkData(userInfo)) +} + +// UDM签约用户-增加 +// +// POST /{neId} +func (s *UdmUserApi) UdmSubUserAdd(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + var body model.UdmSubUser + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + 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) + } + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.subUser.Insert(neInfo.NeId, body) + } ctx.JSON(w, 200, result.OkData(data)) } + +// UDM签约用户-批量添加 +// +// POST /{neId}/{num} +func (s *UdmUserApi) UdmSubUserAdds(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + num := ctx.Param(r, "num") + if neId == "" || num == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + var body model.UdmSubUser + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("bad 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) + } + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.subUser.Inserts(neInfo.NeId, body, num) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM签约用户-修改 +// +// PUT /{neId} +func (s *UdmUserApi) UdmSubUserEdit(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + var body model.UdmSubUser + err := ctx.ShouldBindJSON(r, &body) + if err != nil || body.Imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + 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) + } + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.subUser.Update(neInfo.NeId, body) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM签约用户-删除 +// +// DELETE /{neId}/{imsi} +func (s *UdmUserApi) UdmSubUserRemove(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + imsi := ctx.Param(r, "imsi") + if neId == "" || imsi == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("del udmuser:imsi=%s", imsi) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.subUser.Delete(neId, imsi) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM签约用户-批量删除 +// +// DELETE /{neId}/{imsi}/{num} +func (s *UdmUserApi) UdmSubUserRemoves(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + imsi := ctx.Param(r, "imsi") + num := ctx.Param(r, "num") + if neId == "" || imsi == "" || num == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("bde udmuser:start_imsi=%s,sub_num=%s", imsi, num) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 命令ok时 + if strings.Contains(data, "ok") { + s.authUser.Deletes(neId, imsi, num) + } + ctx.JSON(w, 200, result.OkData(data)) +} + +// UDM签约用户-导出 +// +// POST /subExport/{neId} +func (s *UdmUserApi) UdmSubUserExport(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + list := s.subUser.List(model.UdmSubUser{NeID: neId}) + // 文件名 + fileName := fmt.Sprintf("OMC_AUTH_USER_EXPORT_%s_%d.csv", neId, time.Now().UnixMilli()) + filePath := fmt.Sprintf("/usr/local/omc/upload/mml/%s", fileName) + // 转换数据 + data := [][]string{} + data = append(data, []string{"imsi", "msisdn", "ambr", "arfb", "sar", "rat", "cn", "smf_sel", "sm_dat", "eps_dat"}) + for _, v := range list { + data = append(data, []string{v.Imsi, v.Msisdn, v.Ambr, v.Arfb, v.Sar, v.Rat, v.Cn, v.SmfSel, v.SmData, v.EpsDat}) + } + // 输出到文件 + err := file.WriterCSVFile(data, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + ctx.FileAttachment(w, r, filePath, fileName) +} + +// UDM签约用户-导入 +// +// POST /subImport/{neId} +func (s *UdmUserApi) UdmSubUserImport(w http.ResponseWriter, r *http.Request) { + neId := ctx.Param(r, "neId") + if neId == "" { + ctx.JSON(w, 400, result.CodeMsg(400, "参数错误")) + return + } + + neInfo, err := NeInfoByUDM(neId) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 文件名 + fileName := fmt.Sprintf("OMC_SUB_USER_IMPORT_%s_%d.csv", neId, time.Now().UnixMilli()) + filePath := fmt.Sprintf("/usr/local/omc/upload/mml/%s", fileName) + dstPath := "/home/agtuser/" + // 输出保存文件 + err = ctx.SaveUploadedFile(r, filePath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + // 复制到远程 + err = file.FileNeSCP(neInfo.Ip, filePath, dstPath) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + + msg := fmt.Sprintf("import udmuser:path=%s", fmt.Sprintf("%s%s", dstPath, fileName)) + + // 发送MML + data, err := mmlclient.MMLSendMsgToString(neInfo.Ip, msg) + if err != nil { + ctx.JSON(w, 200, result.ErrMsg(err.Error())) + return + } + // 命令ok时 + if strings.Contains(data, "ok") { + data := file.ReadCSVFile(filePath) + s.authUser.InsertCSV(neId, data) + } + // ctx.JSON(w, 200, result.OkData(data)) + ctx.FileAttachment(w, r, filePath, fileName) +} diff --git a/features/udm_user/repo/repo_udm_auth_user.go b/features/udm_user/repo/repo_udm_auth_user.go index 532d9f74..c9e6e799 100644 --- a/features/udm_user/repo/repo_udm_auth_user.go +++ b/features/udm_user/repo/repo_udm_auth_user.go @@ -1,6 +1,8 @@ package repo import ( + "fmt" + "strconv" "strings" "ems.agt/features/udm_user/model" @@ -22,7 +24,7 @@ var NewRepoUdmAuthUser = &RepoUdmAuthUser{ "amf": "Amf", "status": "Status", "ki": "Ki", - "algo_index": "AlgoLndex", + "algo_index": "AlgoIndex", "opc": "Opc", "ne_id": "NeID", }, @@ -60,6 +62,10 @@ func (r *RepoUdmAuthUser) SelectPage(query map[string]any) map[string]any { conditions = append(conditions, "msisdn like concat(?, '%')") params = append(params, v) } + if v, ok := query["imsi"]; ok && v != "" { + conditions = append(conditions, "imsi like concat(?, '%')") + params = append(params, v) + } if v, ok := query["neId"]; ok && v != "" { conditions = append(conditions, "ne_id = ?") params = append(params, v) @@ -137,8 +143,8 @@ func (r *RepoUdmAuthUser) SelectList(auth model.UdmAuthUser) []model.UdmAuthUser return r.convertResultRows(results) } -// Insert 清空ne_id后新增实体 -func (r *RepoUdmAuthUser) Inserts(neID string, authArr []model.UdmAuthUser) int64 { +// ClearAndInsert 清空ne_id后新增实体 +func (r *RepoUdmAuthUser) ClearAndInsert(neID string, authArr []model.UdmAuthUser) int64 { var num int64 = 0 // 清空指定ne_id @@ -158,3 +164,98 @@ func (r *RepoUdmAuthUser) Inserts(neID string, authArr []model.UdmAuthUser) int6 } return num } + +// Insert 新增实体 +func (r *RepoUdmAuthUser) Insert(neID string, authUser model.UdmAuthUser) int64 { + authUser.NeID = neID + authUser.Status = "1" + results, err := datasource.DefaultDB().Table("u_auth_user").Insert(authUser) + if err != nil { + return results + } + return results +} + +// Insert 批量添加 +func (r *RepoUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, num string) int64 { + var insertNum int64 + + imsiV, err := strconv.Atoi(authUser.Imsi) + if err != nil { + return 0 + } + + numV, err := strconv.Atoi(num) + if err != nil { + return 0 + } + + authUser.NeID = neID + authUser.Status = "1" + for i := 0; i < numV; i++ { + authUser.Imsi = fmt.Sprint(imsiV + i) + results, err := datasource.DefaultDB().Table("u_auth_user").Insert(authUser) + if err == nil { + insertNum += results + } + } + + return insertNum +} + +// Update 修改更新 +func (r *RepoUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 { + // 查询先 + var user model.UdmAuthUser + err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", authUser.Imsi, neID).Find(&user) + if err != nil { + return 0 + } + + if authUser.Ki != "" && authUser.Ki != user.Ki { + user.Ki = authUser.Ki + } + if authUser.Amf != "" && authUser.Amf != user.Amf { + user.Amf = authUser.Amf + } + if authUser.AlgoIndex != "" && authUser.AlgoIndex != user.AlgoIndex { + user.AlgoIndex = authUser.AlgoIndex + } + if authUser.Opc != "" && authUser.Opc != user.Opc { + user.Opc = authUser.Opc + } + + results, err := datasource.DefaultDB().Table("u_auth_user").Update(user) + if err != nil { + return 0 + } + return results +} + +// Delete 删除实体 +func (r *RepoUdmAuthUser) Delete(neID, imsi string) int64 { + results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", imsi, neID).Delete() + if err != nil { + return results + } + return results +} + +// Delete 删除范围实体 +func (r *RepoUdmAuthUser) 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 + } + + results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi >= ? and imsi <= ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete() + if err != nil { + return results + } + return results +} diff --git a/features/udm_user/repo/repo_udm_sub_user.go b/features/udm_user/repo/repo_udm_sub_user.go index e5f95614..2be6c6a5 100644 --- a/features/udm_user/repo/repo_udm_sub_user.go +++ b/features/udm_user/repo/repo_udm_sub_user.go @@ -1,6 +1,8 @@ package repo import ( + "fmt" + "strconv" "strings" "ems.agt/features/udm_user/model" @@ -12,22 +14,31 @@ import ( // 实例化数据层 RepoUdmSubUser 结构体 var NewRepoUdmSubUser = &RepoUdmSubUser{ selectSql: `select - id, msisdn, imsi, sub_ue_ambr_temp, sub_snssai_temp, rai, forbidden_areas_temp, service_area_restrict_temp, cn_type, sub_data, eps, ne_id + id, msisdn, imsi, ambr, nssai, rat, arfb, sar, cn, sm_data, smf_sel, eps_dat, ne_id, eps_flag, eps_odb, hplmn_odb, ard, epstpl, context_id, apn_context, static_ip from u_sub_user`, resultMap: map[string]string{ - "id": "ID", - "msisdn": "Msisdn", - "imsi": "Imsi", - "sub_ue_ambr_temp": "SubUeAMBRTemp", - "sub_snssai_temp": "subSNSSAITemp", - "rai": "Rai", - "forbidden_areas_temp": "ForbiddenAreasTemp", - "service_area_restrict_temp": "ServiceAreaRestrictTemp", - "cn_type": "CnType", - "sub_data": "SubData", - "eps": "Eps", - "ne_id": "NeID", + "id": "ID", + "msisdn": "Msisdn", + "imsi": "Imsi", + "ambr": "Ambr", + "nssai": "Assai", + "rat": "Rat", + "arfb": "Arfb", + "sar": "Sar", + "cn": "Cn", + "sm_data": "SmData", + "smf_sel": "SmfSel", + "eps_dat": "EpsDat", + "ne_id": "NeID", + "eps_flag": "EpsFlag", + "eps_odb": "EpsOdb", + "hplmn_odb": "HplmnOdb", + "ard": "Ard", + "epstpl": "Epstpl", + "context_id": "ContextId", + "apn_context": "ApnContext", + "static_ip": "StaticIp", }, } @@ -144,8 +155,8 @@ func (r *RepoUdmSubUser) SelectList(auth model.UdmSubUser) []model.UdmSubUser { return r.convertResultRows(results) } -// Insert 清空ne_id后新增实体 -func (r *RepoUdmSubUser) Inserts(neID string, authArr []model.UdmSubUser) int64 { +// ClearAndInsert 清空ne_id后新增实体 +func (r *RepoUdmSubUser) ClearAndInsert(neID string, subArr []model.UdmSubUser) int64 { var num int64 = 0 // 清空指定ne_id @@ -155,7 +166,7 @@ func (r *RepoUdmSubUser) Inserts(neID string, authArr []model.UdmSubUser) int64 log.Errorf("TRUNCATE err => %v", err) } - for _, u := range authArr { + for _, u := range subArr { u.NeID = neID results, err := datasource.DefaultDB().Table("u_sub_user").Insert(u) if err != nil { @@ -165,3 +176,116 @@ func (r *RepoUdmSubUser) Inserts(neID string, authArr []model.UdmSubUser) int64 } return num } + +// Insert 新增实体 +func (r *RepoUdmSubUser) Insert(neID string, subUser model.UdmSubUser) int64 { + subUser.NeID = neID + results, err := datasource.DefaultDB().Table("u_sub_user").Insert(subUser) + if err != nil { + return results + } + return results +} + +// Insert 批量添加 +func (r *RepoUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num string) int64 { + var insertNum int64 + + imsiV, err := strconv.Atoi(subUser.Imsi) + if err != nil { + return 0 + } + msisdnV, err := strconv.Atoi(subUser.Msisdn) + if err != nil { + return 0 + } + + numV, err := strconv.Atoi(num) + if err != nil { + return 0 + } + + subUser.NeID = neID + for i := 0; i < numV; i++ { + subUser.Imsi = fmt.Sprint(imsiV + i) + subUser.Msisdn = fmt.Sprint(msisdnV + i) + results, err := datasource.DefaultDB().Table("u_sub_user").Insert(subUser) + if err == nil { + insertNum += results + } + } + + return insertNum +} + +// Update 修改更新 +func (r *RepoUdmSubUser) Update(neID string, authUser model.UdmSubUser) int64 { + // 查询先 + var user model.UdmSubUser + err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", authUser.Imsi, neID).Find(&user) + if err != nil { + return 0 + } + + if authUser.Msisdn != "" && authUser.Msisdn != user.Msisdn { + user.Msisdn = authUser.Msisdn + } + if authUser.Ambr != "" && authUser.Ambr != user.Ambr { + user.Ambr = authUser.Ambr + } + if authUser.Arfb != "" && authUser.Arfb != user.Arfb { + user.Arfb = authUser.Arfb + } + if authUser.Sar != "" && authUser.Sar != user.Sar { + user.Sar = authUser.Sar + } + if authUser.Rat != "" && authUser.Rat != user.Rat { + user.Rat = authUser.Rat + } + if authUser.Cn != "" && authUser.Cn != user.Cn { + user.Cn = authUser.Cn + } + if authUser.SmfSel != "" && authUser.SmfSel != user.SmfSel { + user.SmfSel = authUser.SmfSel + } + if authUser.SmData != "" && authUser.SmData != user.SmData { + user.SmData = authUser.SmData + } + if authUser.EpsDat != "" && authUser.EpsDat != user.EpsDat { + user.EpsDat = authUser.EpsDat + } + + results, err := datasource.DefaultDB().Table("u_sub_user").Update(user) + if err != nil { + return 0 + } + return results +} + +// Delete 删除实体 +func (r *RepoUdmSubUser) Delete(neID, imsi string) int64 { + results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", imsi, neID).Delete() + if err != nil { + return results + } + return results +} + +// Delete 删除范围实体 +func (r *RepoUdmSubUser) 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 + } + + results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi >= ? and imsi <= ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete() + if err != nil { + return results + } + return results +} diff --git a/features/udm_user/service/service_udm_auth_user.go b/features/udm_user/service/service_udm_auth_user.go index c708ca9c..82b5de23 100644 --- a/features/udm_user/service/service_udm_auth_user.go +++ b/features/udm_user/service/service_udm_auth_user.go @@ -23,7 +23,7 @@ func (r *ServiceUdmAuthUser) Save(neID string) int64 { if len(authArr) == 0 { return num } - return r.repoAuthUser.Inserts(neID, authArr) + return r.repoAuthUser.ClearAndInsert(neID, authArr) } // Page UDM签约用户-分页查询数据库 @@ -35,3 +35,56 @@ func (r *ServiceUdmAuthUser) Page(query map[string]any) map[string]any { func (r *ServiceUdmAuthUser) List(authUser model.UdmAuthUser) []model.UdmAuthUser { return r.repoAuthUser.SelectList(authUser) } + +// Insert UDM鉴权用户-新增单个 +// imsi长度15,ki长度32,opc长度0或者32 +func (r *ServiceUdmAuthUser) Insert(neID string, authUser model.UdmAuthUser) int64 { + return r.repoAuthUser.Insert(neID, authUser) +} + +// Insert UDM鉴权用户-批量添加 +func (r *ServiceUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, num string) int64 { + return r.repoAuthUser.Inserts(neID, authUser, num) +} + +// Insert UDM鉴权用户-批量添加 +func (r *ServiceUdmAuthUser) InsertCSV(neID string, data []map[string]string) int64 { + var num int64 + for _, v := range data { + var authUser model.UdmAuthUser + authUser.NeID = neID + authUser.Status = "1" + if s, ok := v["imsi"]; ok { + authUser.Imsi = s + } + if s, ok := v["ki"]; ok { + authUser.Ki = s + } + if s, ok := v["amf"]; ok { + authUser.Amf = s + } + if s, ok := v["algo"]; ok { + authUser.AlgoIndex = s + } + if s, ok := v["opc"]; ok { + authUser.Opc = s + } + r.repoAuthUser.Insert(neID, authUser) + } + return num +} + +// Insert UDM鉴权用户-修改更新 +func (r *ServiceUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 { + return r.repoAuthUser.Update(neID, authUser) +} + +// Insert UDM鉴权用户-删除单个 +func (r *ServiceUdmAuthUser) Delete(neID, imsi string) int64 { + return r.repoAuthUser.Delete(neID, imsi) +} + +// Insert UDM鉴权用户-删除范围 +func (r *ServiceUdmAuthUser) Deletes(neID, imsi, num string) int64 { + return r.repoAuthUser.Deletes(neID, imsi, num) +} diff --git a/features/udm_user/service/service_udm_sub_user.go b/features/udm_user/service/service_udm_sub_user.go index 9d8d10a4..d2d0ceeb 100644 --- a/features/udm_user/service/service_udm_sub_user.go +++ b/features/udm_user/service/service_udm_sub_user.go @@ -23,7 +23,7 @@ func (r *ServiceUdmSubUser) Save(neID string) int64 { if len(subArr) == 0 { return num } - return r.repoSunUser.Inserts(neID, subArr) + return r.repoSunUser.ClearAndInsert(neID, subArr) } // Page UDM签约用户-分页查询数据库 @@ -35,3 +35,73 @@ func (r *ServiceUdmSubUser) Page(query map[string]any) map[string]any { func (r *ServiceUdmSubUser) List(subUser model.UdmSubUser) []model.UdmSubUser { return r.repoSunUser.SelectList(subUser) } + +// Insert UDM签约用户-新增单个 +// imsi长度15,ki长度32,opc长度0或者32 +func (r *ServiceUdmSubUser) Insert(neID string, subUser model.UdmSubUser) int64 { + return r.repoSunUser.Insert(neID, subUser) +} + +// Insert UDM签约用户-批量添加 +func (r *ServiceUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num string) int64 { + return r.repoSunUser.Inserts(neID, subUser, num) +} + +// Insert UDM签约用户-批量添加 +func (r *ServiceUdmSubUser) InsertCSV(neID string, data []map[string]string) int64 { + var num int64 + for _, v := range data { + var subUser model.UdmSubUser + subUser.NeID = neID + if s, ok := v["imsi"]; ok { + subUser.Imsi = s + } + if s, ok := v["msisdn"]; ok { + subUser.Msisdn = s + } + if s, ok := v["ambr"]; ok { + subUser.Ambr = s + } + if s, ok := v["nssai"]; ok { + subUser.Nssai = s + } + if s, ok := v["arfb"]; ok { + subUser.Arfb = s + } + if s, ok := v["sar"]; ok { + subUser.Sar = s + } + if s, ok := v["rat"]; ok { + subUser.Rat = s + } + if s, ok := v["cn"]; ok { + subUser.Cn = s + } + if s, ok := v["smf_sel"]; ok { + subUser.SmfSel = s + } + if s, ok := v["sm_data"]; ok { + subUser.SmData = s + } + if s, ok := v["eps_dat"]; ok { + subUser.EpsDat = s + } + r.repoSunUser.Insert(neID, subUser) + } + return num +} + +// Insert UDM签约用户-修改更新 +func (r *ServiceUdmSubUser) Update(neID string, subUser model.UdmSubUser) int64 { + return r.repoSunUser.Update(neID, subUser) +} + +// Insert UDM签约用户-删除单个 +func (r *ServiceUdmSubUser) Delete(neID, imsi string) int64 { + return r.repoSunUser.Delete(neID, imsi) +} + +// Insert UDM签约用户-删除范围 +func (r *ServiceUdmSubUser) Deletes(neID, imsi, num string) int64 { + return r.repoSunUser.Deletes(neID, imsi, num) +} From f9596f63637cbde11388e126b0ff600814db441f Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 11 Sep 2023 21:03:53 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E8=AF=BB=E5=8F=96CSV=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E8=BD=AC=E6=8D=A2map=E6=95=B0=E6=8D=AE=E3=80=82?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0scp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/file/csv.go | 43 +++++++++++++++++++++++++++++++++++++++ lib/core/file/ssh.go | 22 ++++++++++++++++++++ lib/core/utils/ctx/ctx.go | 32 +++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 lib/core/file/ssh.go diff --git a/lib/core/file/csv.go b/lib/core/file/csv.go index ad7763f5..f8bcce90 100644 --- a/lib/core/file/csv.go +++ b/lib/core/file/csv.go @@ -4,6 +4,7 @@ import ( "encoding/csv" "os" "path/filepath" + "strings" "ems.agt/lib/log" ) @@ -41,3 +42,45 @@ func WriterCSVFile(data [][]string, filePath string) error { } return nil } + +// 读取CSV文件,转换map数据 +func ReadCSVFile(filePath string) []map[string]string { + // 打开 CSV 文件 + file, err := os.Open(filePath) + if err != nil { + log.Fatal("无法打开 CSV 文件:", err) + } + defer file.Close() + + // 创建 CSV Reader + reader := csv.NewReader(file) + + // 读取 CSV 头部行 + header, err := reader.Read() + if err != nil { + log.Fatal("无法读取 CSV 头部行:", err) + } + + // 创建 map 存储 CSV 数据 + arr := make([]map[string]string, 0) + + // 遍历 CSV 数据行 + for { + // 读取一行数据 + record, err := reader.Read() + if err != nil { + // 到达文件末尾或遇到错误时退出循环 + break + } + + // 将 CSV 数据插入到 map 中 + data := make(map[string]string) + for i, value := range record { + key := strings.ToLower(header[i]) + data[key] = value + } + arr = append(arr, data) + } + + return arr +} diff --git a/lib/core/file/ssh.go b/lib/core/file/ssh.go new file mode 100644 index 00000000..d5d11e80 --- /dev/null +++ b/lib/core/file/ssh.go @@ -0,0 +1,22 @@ +package file + +import ( + "fmt" + "os/exec" + + "ems.agt/lib/core/conf" +) + +// 网元NE 文件复制到远程文件夹 +func FileNeSCP(neIp, filePath, dstPath string) error { + usernameNe := conf.Get("ne.user").(string) + // scp /path/to/local/file.txt user@remote-server:/path/to/remote/directory/ + dstDir := fmt.Sprintf("%s@%s:%s", usernameNe, neIp, dstPath) + cmd := exec.Command("scp", "-r", filePath, dstDir) + out, err := cmd.CombinedOutput() + if err != nil { + return err + } + fmt.Println(out) + return nil +} diff --git a/lib/core/utils/ctx/ctx.go b/lib/core/utils/ctx/ctx.go index 59a5f2e4..f800d7a4 100644 --- a/lib/core/utils/ctx/ctx.go +++ b/lib/core/utils/ctx/ctx.go @@ -6,6 +6,8 @@ import ( "io" "net/http" "net/url" + "os" + "path/filepath" "ems.agt/lib/core/vo" "github.com/gorilla/mux" @@ -67,6 +69,36 @@ func FileAttachment(w http.ResponseWriter, r *http.Request, filepath, filename s http.ServeFile(w, r, filepath) } +// 将文件上传保存到指定目录 +// file, handler, err := r.FormFile("file") +// SaveUploadedFile uploads the form file to specific dst. +func SaveUploadedFile(r *http.Request, dst string) error { + // 解析请求中的文件 + _, handler, err := r.FormFile("file") + if err != nil { + return err + } + + src, err := handler.Open() + if err != nil { + return err + } + defer src.Close() + + if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil { + return err + } + + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, src) + return err +} + /// ==== 登录用户信息, 通过中间件后预置入 // 定义自定义类型作为键 From 344ff25aea100cae2852cd31e365c0aa3b369b42 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Mon, 11 Sep 2023 21:04:17 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix=E5=8F=91=E9=80=81MML=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/mml_client/send.go | 54 ++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/lib/core/mml_client/send.go b/lib/core/mml_client/send.go index 7a637f57..09a008f6 100644 --- a/lib/core/mml_client/send.go +++ b/lib/core/mml_client/send.go @@ -5,10 +5,10 @@ import ( "strings" ) -// 发送MML +// 发送MML原始消息 // ip 网元IP地址 // msg 指令 -func MMLSendMsgToString(ip, msg string) (string, error) { +func MMLSendMsg(ip, msg string) (string, error) { // 创建MMLClient实例 client, err := NewMMLClient(ip) if err != nil { @@ -31,23 +31,55 @@ func MMLSendMsgToString(ip, msg string) (string, error) { return data, nil } +// 发送MML +// ip 网元IP地址 +// msg 指令 +func MMLSendMsgToString(ip, msg string) (string, error) { + // 发送获取数据 + str, err := MMLSendMsg(ip, msg) + if err != nil { + return "", err + } + + // 截断 + index := strings.Index(str, "\nUDM>") + if index != -1 { + str = str[:index] + str = strings.ToLower(str) + } + + // 命令成功 + if strings.HasPrefix(str, "command ok") { + return str, nil + } + + return "", fmt.Errorf(str) +} + // 发送MML // ip 网元IP地址 // msg 指令 func MMLSendMsgToMap(ip, msg string) (map[string]string, error) { // 发送获取数据 - str, err := MMLSendMsgToString(ip, msg) + 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 - // 按照分隔符"\r\n"进行拆分 if strings.Contains(str, "\r\n") { + // 按照分隔符"\r\n"进行拆分 items = strings.Split(str, "\r\n") - } - // 按照分隔符"\n"进行拆分 - if strings.Contains(str, "\n") { + } else if strings.Contains(str, "\n") { + // 按照分隔符"\n"进行拆分 items = strings.Split(str, "\n") } @@ -55,13 +87,11 @@ func MMLSendMsgToMap(ip, msg string) (map[string]string, error) { for _, item := range items { var pair []string - // 按照分隔符"="进行拆分键值对 if strings.Contains(item, "=") { + // 按照分隔符"="进行拆分键值对 pair = strings.Split(item, "=") - } - - // 按照分隔符":"进行拆分键值对 - if strings.Contains(item, ":") { + } else if strings.Contains(item, ":") { + // 按照分隔符":"进行拆分键值对 pair = strings.Split(item, ":") }