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] =?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) +}