Merge branch 'main' of http://192.168.0.229:3180/OMC/ems_backend
This commit is contained in:
75
features/udm_user/api_udm_user.go
Normal file
75
features/udm_user/api_udm_user.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package udmuser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"ems.agt/features/udm_user/service"
|
||||||
|
"ems.agt/lib/core/utils/ctx"
|
||||||
|
"ems.agt/lib/core/vo/result"
|
||||||
|
"ems.agt/lib/services"
|
||||||
|
"ems.agt/restagent/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UDM 用户信息接口添加到路由
|
||||||
|
func Routers() []services.RouterItem {
|
||||||
|
// 实例化控制层 SysDictTypeApi 结构体
|
||||||
|
var apis = &UdmUserApi{
|
||||||
|
sysDictTypeService: *service.NewServiceUdmUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
rs := [...]services.RouterItem{
|
||||||
|
{
|
||||||
|
Method: "GET",
|
||||||
|
Pattern: "/ausfList",
|
||||||
|
Handler: apis.AusfList,
|
||||||
|
Middleware: nil, //midware.Authorize(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "GET",
|
||||||
|
Pattern: "/sdList",
|
||||||
|
Handler: apis.SdList,
|
||||||
|
Middleware: nil, //midware.Authorize(nil),
|
||||||
|
},
|
||||||
|
// 添加更多的 Router 对象...
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成两组前缀路由
|
||||||
|
rsPrefix := []services.RouterItem{}
|
||||||
|
for _, v := range rs {
|
||||||
|
path := "/udmUserManage/{apiVersion}" + v.Pattern
|
||||||
|
// 固定前缀
|
||||||
|
v.Pattern = config.DefaultUriPrefix + path
|
||||||
|
rsPrefix = append(rsPrefix, v)
|
||||||
|
// 可配置
|
||||||
|
v.Pattern = config.UriPrefix + path
|
||||||
|
rsPrefix = append(rsPrefix, v)
|
||||||
|
}
|
||||||
|
return rsPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDM 用户
|
||||||
|
//
|
||||||
|
// PATH /udmUserManage
|
||||||
|
type UdmUserApi struct {
|
||||||
|
sysDictTypeService service.ServiceUdmUser
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDM鉴权用户
|
||||||
|
//
|
||||||
|
// GET /ausfList
|
||||||
|
func (s *UdmUserApi) AusfList(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// querys := ctx.QueryMap(r)
|
||||||
|
|
||||||
|
data := s.sysDictTypeService.ReadAusfList()
|
||||||
|
ctx.JSON(w, 200, result.OkData(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDM签约用户
|
||||||
|
//
|
||||||
|
// GET /sdList
|
||||||
|
func (s *UdmUserApi) SdList(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// querys := ctx.QueryMap(r)
|
||||||
|
|
||||||
|
data := s.sysDictTypeService.ReadSdList()
|
||||||
|
ctx.JSON(w, 200, result.OkData(data))
|
||||||
|
}
|
||||||
12
features/udm_user/model/udm_ausf_user.go
Normal file
12
features/udm_user/model/udm_ausf_user.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// UdmAusfUser UDM鉴权用户
|
||||||
|
type UdmAusfUser struct {
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Imsi string `json:"imssi"`
|
||||||
|
Amf string `json:"amf" binding:"required"`
|
||||||
|
Status string `json:"status" binding:"required"`
|
||||||
|
Ki string `json:"ki"`
|
||||||
|
AlgoIndex string `json:"algo_index"`
|
||||||
|
Opc string `json:"opc"`
|
||||||
|
}
|
||||||
16
features/udm_user/model/udm_sd_user.go
Normal file
16
features/udm_user/model/udm_sd_user.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// UdmSdUser UDM签约用户
|
||||||
|
type UdmSdUser struct {
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Imsi string `json:"imssi"`
|
||||||
|
Msisdn string `json:"msisdn"`
|
||||||
|
SubUeAMBRTemp string `json:"subUeAMBRTemp" binding:"required"`
|
||||||
|
SubSNSSAITemp string `json:"subSNSSAITemp" binding:"required"`
|
||||||
|
Rai string `json:"rai"`
|
||||||
|
ForbiddenAreasTemp string `json:"forbiddenAreasTemp"`
|
||||||
|
ServiceAreaRestrictTemp string `json:"serviceAreaRestrictTemp"`
|
||||||
|
CnType string `json:"cnType"`
|
||||||
|
SubData string `json:"subData"`
|
||||||
|
Eps string `json:"eps"`
|
||||||
|
}
|
||||||
129
features/udm_user/repo/repo_udm_user.go
Normal file
129
features/udm_user/repo/repo_udm_user.go
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"ems.agt/lib/core/datasource"
|
||||||
|
"ems.agt/lib/core/utils/date"
|
||||||
|
"ems.agt/lib/core/utils/parse"
|
||||||
|
"ems.agt/lib/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化数据层 RepoUdmUser 结构体
|
||||||
|
var NewRepoUdmUser = &RepoUdmUser{
|
||||||
|
selectSql: `select
|
||||||
|
dict_id, dict_name, dict_type, status, create_by, create_time, remark
|
||||||
|
from sys_dict_type`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"dict_id": "DictID",
|
||||||
|
"dict_name": "DictName",
|
||||||
|
"dict_type": "DictType",
|
||||||
|
"remark": "Remark",
|
||||||
|
"status": "Status",
|
||||||
|
"create_by": "CreateBy",
|
||||||
|
"create_time": "CreateTime",
|
||||||
|
"update_by": "UpdateBy",
|
||||||
|
"update_time": "UpdateTime",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoUdmUser 字典类型表 数据层处理
|
||||||
|
type RepoUdmUser struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *RepoUdmUser) convertResultRows(rows []map[string]any) []any {
|
||||||
|
arr := make([]any, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
UdmUser := []any{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
datasource.SetFieldValue(&UdmUser, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, UdmUser)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectDictTypePage 根据条件分页查询字典类型
|
||||||
|
func (r *RepoUdmUser) SelectDictTypePage(query map[string]any) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if v, ok := query["dictName"]; ok && v != "" {
|
||||||
|
conditions = append(conditions, "dict_name like concat(?, '%')")
|
||||||
|
params = append(params, v)
|
||||||
|
}
|
||||||
|
if v, ok := query["dictType"]; ok && v != "" {
|
||||||
|
conditions = append(conditions, "dict_type like concat(?, '%')")
|
||||||
|
params = append(params, v)
|
||||||
|
}
|
||||||
|
if v, ok := query["status"]; ok && v != "" {
|
||||||
|
conditions = append(conditions, "status = ?")
|
||||||
|
params = append(params, v)
|
||||||
|
}
|
||||||
|
beginTime, ok := query["beginTime"]
|
||||||
|
if !ok {
|
||||||
|
beginTime, ok = query["params[beginTime]"]
|
||||||
|
}
|
||||||
|
if ok && beginTime != "" {
|
||||||
|
conditions = append(conditions, "create_time >= ?")
|
||||||
|
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
||||||
|
params = append(params, beginDate.UnixMilli())
|
||||||
|
}
|
||||||
|
endTime, ok := query["endTime"]
|
||||||
|
if !ok {
|
||||||
|
endTime, ok = query["params[endTime]"]
|
||||||
|
}
|
||||||
|
if ok && endTime != "" {
|
||||||
|
conditions = append(conditions, "create_time <= ?")
|
||||||
|
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
||||||
|
params = append(params, endDate.UnixMilli())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
totalSql := "select count(1) as 'total' from sys_dict_type"
|
||||||
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("total err => %v", err)
|
||||||
|
}
|
||||||
|
total := parse.Number(totalRows[0]["total"])
|
||||||
|
if total == 0 {
|
||||||
|
return map[string]any{
|
||||||
|
"total": total,
|
||||||
|
"rows": nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
||||||
|
pageSql := " limit ?,? "
|
||||||
|
params = append(params, pageNum*pageSize)
|
||||||
|
params = append(params, pageSize)
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + pageSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
rows := r.convertResultRows(results)
|
||||||
|
return map[string]any{
|
||||||
|
"total": total,
|
||||||
|
"rows": rows,
|
||||||
|
}
|
||||||
|
}
|
||||||
90
features/udm_user/service/service_udm_user.go
Normal file
90
features/udm_user/service/service_udm_user.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"ems.agt/features/udm_user/model"
|
||||||
|
"ems.agt/lib/core/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化服务层 ServiceUdmUser 结构体
|
||||||
|
var NewServiceUdmUser = &ServiceUdmUser{}
|
||||||
|
|
||||||
|
// ServiceUdmUser UDM 服务层处理
|
||||||
|
type ServiceUdmUser struct{}
|
||||||
|
|
||||||
|
// phoneImsiList 获取所有imsi
|
||||||
|
func (r *ServiceUdmUser) phoneImsiList() map[string]string {
|
||||||
|
phoneKeys := redis.GetKeys("1*********")
|
||||||
|
phoneAndImsiArr := make(map[string]string, 0)
|
||||||
|
for _, phone := range phoneKeys {
|
||||||
|
imsi := redis.Get(phone)
|
||||||
|
phoneAndImsiArr[phone] = imsi
|
||||||
|
}
|
||||||
|
return phoneAndImsiArr
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAusfList UDM鉴权用户
|
||||||
|
func (r *ServiceUdmUser) ReadAusfList() []model.UdmAusfUser {
|
||||||
|
phoneAndImsiArr := r.phoneImsiList()
|
||||||
|
user := []model.UdmAusfUser{}
|
||||||
|
for phone, imsi := range phoneAndImsiArr {
|
||||||
|
key := fmt.Sprintf("ausf:%s", imsi)
|
||||||
|
m := redis.GetHash(key)
|
||||||
|
|
||||||
|
status := "0"
|
||||||
|
if _, ok := m["auth_success"]; ok {
|
||||||
|
status = "1"
|
||||||
|
}
|
||||||
|
a := model.UdmAusfUser{
|
||||||
|
Phone: phone,
|
||||||
|
Imsi: imsi,
|
||||||
|
Amf: m["amf"],
|
||||||
|
Status: status,
|
||||||
|
Ki: m["ki"],
|
||||||
|
AlgoIndex: m["algo"],
|
||||||
|
Opc: m["opc"],
|
||||||
|
}
|
||||||
|
user = append(user, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(len(user))
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSdList UDM签约用户
|
||||||
|
func (r *ServiceUdmUser) ReadSdList() []model.UdmSdUser {
|
||||||
|
phoneAndImsiArr := r.phoneImsiList()
|
||||||
|
user := []model.UdmSdUser{}
|
||||||
|
for phone, imsi := range phoneAndImsiArr {
|
||||||
|
key := fmt.Sprintf("udm-sd:%s", imsi)
|
||||||
|
m := redis.GetHash(key)
|
||||||
|
|
||||||
|
a := model.UdmSdUser{
|
||||||
|
Phone: phone,
|
||||||
|
Imsi: imsi,
|
||||||
|
Msisdn: m["gpsi"],
|
||||||
|
SubData: m["sm-dat"],
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
if v, ok := m["eps-dat"]; ok {
|
||||||
|
arr := strings.Split(v, ",")
|
||||||
|
a.Eps = arr[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
user = append(user, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(len(user))
|
||||||
|
return user
|
||||||
|
}
|
||||||
1
go.mod
1
go.mod
@@ -30,6 +30,7 @@ require (
|
|||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
xorm.io/xorm v1.3.2
|
xorm.io/xorm v1.3.2
|
||||||
|
github.com/redis/go-redis/v9 v9.1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -67,6 +67,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
|||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
|
||||||
|
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||||
github.com/bsm/redislock v0.8.2 h1:W0aDRjt6FNmAZovbG2fPyjl1YZZdlqMkCKKCffJew1o=
|
github.com/bsm/redislock v0.8.2 h1:W0aDRjt6FNmAZovbG2fPyjl1YZZdlqMkCKKCffJew1o=
|
||||||
github.com/bsm/redislock v0.8.2/go.mod h1:tC0JZxZCdJN4DCB31cGxgjgf/ye1R4LLNJQd5ecjg08=
|
github.com/bsm/redislock v0.8.2/go.mod h1:tC0JZxZCdJN4DCB31cGxgjgf/ye1R4LLNJQd5ecjg08=
|
||||||
github.com/bytedance/go-tagexpr/v2 v2.7.12 h1:qL2f0j11S8DHQsUWUA6aacLNBcbPTbNKuzVjaW4kF/M=
|
github.com/bytedance/go-tagexpr/v2 v2.7.12 h1:qL2f0j11S8DHQsUWUA6aacLNBcbPTbNKuzVjaW4kF/M=
|
||||||
@@ -571,6 +573,8 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R
|
|||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
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.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
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=
|
||||||
github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM=
|
github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM=
|
||||||
github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI=
|
github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI=
|
||||||
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas=
|
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas=
|
||||||
|
|||||||
237
lib/core/redis/redis.go
Normal file
237
lib/core/redis/redis.go
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"ems.agt/lib/core/conf"
|
||||||
|
"ems.agt/lib/log"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Redis连接实例
|
||||||
|
var rdb *redis.Client
|
||||||
|
|
||||||
|
// 声明定义限流脚本命令
|
||||||
|
var rateLimitCommand = redis.NewScript(`
|
||||||
|
local key = KEYS[1]
|
||||||
|
local time = tonumber(ARGV[1])
|
||||||
|
local count = tonumber(ARGV[2])
|
||||||
|
local current = redis.call('get', key);
|
||||||
|
if current and tonumber(current) >= count then
|
||||||
|
return tonumber(current);
|
||||||
|
end
|
||||||
|
current = redis.call('incr', key)
|
||||||
|
if tonumber(current) == 1 then
|
||||||
|
redis.call('expire', key, time)
|
||||||
|
end
|
||||||
|
return tonumber(current);`)
|
||||||
|
|
||||||
|
// 连接Redis实例
|
||||||
|
func Connect() {
|
||||||
|
ctx := context.Background()
|
||||||
|
client := conf.Get("redis").(map[string]any)
|
||||||
|
address := fmt.Sprintf("%s:%d", client["host"], client["port"])
|
||||||
|
// 创建连接
|
||||||
|
rdb = redis.NewClient(&redis.Options{
|
||||||
|
Addr: address,
|
||||||
|
Password: client["password"].(string),
|
||||||
|
DB: client["db"].(int),
|
||||||
|
})
|
||||||
|
// 测试数据库连接
|
||||||
|
pong, err := rdb.Ping(ctx).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed error ping redis: %v", err)
|
||||||
|
}
|
||||||
|
log.Infof("redis %s connection is successful.", pong)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭Redis实例
|
||||||
|
func Close() {
|
||||||
|
if err := rdb.Close(); err != nil {
|
||||||
|
log.Fatalf("fatal error db close: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info 获取redis服务信息
|
||||||
|
func Info() map[string]map[string]string {
|
||||||
|
ctx := context.Background()
|
||||||
|
info, err := rdb.Info(ctx).Result()
|
||||||
|
if err != nil {
|
||||||
|
return map[string]map[string]string{}
|
||||||
|
}
|
||||||
|
infoObj := make(map[string]map[string]string)
|
||||||
|
lines := strings.Split(info, "\r\n")
|
||||||
|
label := ""
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.Contains(line, "#") {
|
||||||
|
label = strings.Fields(line)[len(strings.Fields(line))-1]
|
||||||
|
label = strings.ToLower(label)
|
||||||
|
infoObj[label] = make(map[string]string)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kvArr := strings.Split(line, ":")
|
||||||
|
if len(kvArr) >= 2 {
|
||||||
|
key := strings.TrimSpace(kvArr[0])
|
||||||
|
value := strings.TrimSpace(kvArr[len(kvArr)-1])
|
||||||
|
infoObj[label][key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return infoObj
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeySize 获取redis当前连接可用键Key总数信息
|
||||||
|
func KeySize() int64 {
|
||||||
|
ctx := context.Background()
|
||||||
|
size, err := rdb.DBSize(ctx).Result()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandStats 获取redis命令状态信息
|
||||||
|
func CommandStats() []map[string]string {
|
||||||
|
ctx := context.Background()
|
||||||
|
commandstats, err := rdb.Info(ctx, "commandstats").Result()
|
||||||
|
if err != nil {
|
||||||
|
return []map[string]string{}
|
||||||
|
}
|
||||||
|
statsObjArr := make([]map[string]string, 0)
|
||||||
|
lines := strings.Split(commandstats, "\r\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if !strings.HasPrefix(line, "cmdstat_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kvArr := strings.Split(line, ":")
|
||||||
|
key := kvArr[0]
|
||||||
|
valueStr := kvArr[len(kvArr)-1]
|
||||||
|
statsObj := make(map[string]string)
|
||||||
|
statsObj["name"] = key[8:]
|
||||||
|
statsObj["value"] = valueStr[6:strings.Index(valueStr, ",usec=")]
|
||||||
|
statsObjArr = append(statsObjArr, statsObj)
|
||||||
|
}
|
||||||
|
return statsObjArr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取键的剩余有效时间(秒)
|
||||||
|
func GetExpire(key string) float64 {
|
||||||
|
ctx := context.Background()
|
||||||
|
ttl, err := rdb.TTL(ctx, key).Result()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return ttl.Seconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得缓存数据的key列表
|
||||||
|
func GetKeys(pattern string) []string {
|
||||||
|
// 初始化变量
|
||||||
|
var keys []string
|
||||||
|
var cursor uint64 = 0
|
||||||
|
ctx := context.Background()
|
||||||
|
// 循环遍历获取匹配的键
|
||||||
|
for {
|
||||||
|
// 使用 SCAN 命令获取匹配的键
|
||||||
|
batchKeys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 100).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to scan keys: %v", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cursor = nextCursor
|
||||||
|
keys = append(keys, batchKeys...)
|
||||||
|
// 当 cursor 为 0,表示遍历完成
|
||||||
|
if cursor == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量获得缓存数据
|
||||||
|
func GetBatch(keys []string) []any {
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return []any{}
|
||||||
|
}
|
||||||
|
// 获取缓存数据
|
||||||
|
result, err := rdb.MGet(context.Background(), keys...).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to get batch data: %v", err)
|
||||||
|
return []any{}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得缓存数据
|
||||||
|
func Get(key string) string {
|
||||||
|
ctx := context.Background()
|
||||||
|
value, err := rdb.Get(ctx, key).Result()
|
||||||
|
if err == redis.Nil || err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得缓存数据Hash
|
||||||
|
func GetHash(key string) map[string]string {
|
||||||
|
ctx := context.Background()
|
||||||
|
value, err := rdb.HGetAll(ctx, key).Result()
|
||||||
|
if err == redis.Nil || err != nil {
|
||||||
|
return map[string]string{}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否存在
|
||||||
|
func Has(keys ...string) bool {
|
||||||
|
ctx := context.Background()
|
||||||
|
exists, err := rdb.Exists(ctx, keys...).Result()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return exists >= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置缓存数据
|
||||||
|
func Set(key string, value any) bool {
|
||||||
|
ctx := context.Background()
|
||||||
|
err := rdb.Set(ctx, key, value, 0).Err()
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置缓存数据与过期时间
|
||||||
|
func SetByExpire(key string, value any, expiration time.Duration) bool {
|
||||||
|
ctx := context.Background()
|
||||||
|
err := rdb.Set(ctx, key, value, expiration).Err()
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除单个
|
||||||
|
func Del(key string) bool {
|
||||||
|
ctx := context.Background()
|
||||||
|
err := rdb.Del(ctx, key).Err()
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除多个
|
||||||
|
func DelKeys(keys []string) bool {
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
err := rdb.Del(ctx, keys...).Err()
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限流查询并记录
|
||||||
|
func RateLimit(limitKey string, time, count int64) int64 {
|
||||||
|
ctx := context.Background()
|
||||||
|
result, err := rateLimitCommand.Run(ctx, rdb, []string{limitKey}, time, count).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("redis lua script err %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return result.(int64)
|
||||||
|
}
|
||||||
@@ -47,16 +47,6 @@ func ShouldBindJSON(r *http.Request, args any) error {
|
|||||||
|
|
||||||
// JSON 相应json数据
|
// JSON 相应json数据
|
||||||
func JSON(w http.ResponseWriter, code int, data any) {
|
func JSON(w http.ResponseWriter, code int, data any) {
|
||||||
// 跨域响应头
|
|
||||||
// To solve cross domain issue
|
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
||||||
// w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
|
|
||||||
w.Header().Set("Access-Control-Allow-Methods", "*")
|
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
|
||||||
// w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
|
||||||
// w.Header().Set("Access-Control-Allow-Headers", "AccessToken")
|
|
||||||
w.Header().Set("Access-Control-Expose-Headers", "Access-Control-Allow-Headers, Token")
|
|
||||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
||||||
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||||
|
|
||||||
response, err := json.Marshal(data)
|
response, err := json.Marshal(data)
|
||||||
|
|||||||
@@ -181,17 +181,17 @@ func InsertDataWithJson(insertData interface{}) (int64, error) {
|
|||||||
|
|
||||||
type NeInfo struct {
|
type NeInfo struct {
|
||||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||||
NeType string `json:"neType" xorm:"ne_type"`
|
NeType string `json:"ne_type" xorm:"ne_type"`
|
||||||
NeId string `json:"neId" xorm:"ne_id"` // neUID/rmUID 网元唯一标识
|
NeId string `json:"ne_id" xorm:"ne_id"` // neUID/rmUID 网元唯一标识
|
||||||
RmUID string `json:"rmUID" xorm:"rm_uid"` // neUID/rmUID网元UID
|
RmUID string `json:"rm_uid" xorm:"rm_uid"` // neUID/rmUID网元UID
|
||||||
NeName string `json:"neName" xorm:"ne_name"` // NeName/UserLabel 网元名称/网元设备友好名称
|
NeName string `json:"ne_name" xorm:"ne_name"` // NeName/UserLabel 网元名称/网元设备友好名称
|
||||||
Ip string `json:"ip" xorm:"ip"`
|
Ip string `json:"ip" xorm:"ip"`
|
||||||
Port string `json:"port" xorm:"port"`
|
Port string `json:"port" xorm:"port"`
|
||||||
PvFlag string `json:"pvFlag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
|
PvFlag string `json:"pv_flag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理
|
||||||
NeAddress string `json:"neAddress" xorm:"ne_address"` // 只对PNF
|
NeAddress string `json:"ne_address" xorm:"ne_address"` // 只对PNF
|
||||||
Province string `json:"province" xorm:"province"` // 网元所在省份
|
Province string `json:"province" xorm:"province"` // 网元所在省份
|
||||||
VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称
|
VendorName string `json:"vendor_name" xorm:"vendor_name"` // 厂商名称
|
||||||
Dn string `json:"dn" xorm:"dn"` // 网络标识
|
Dn string `json:"dn" xorm:"dn"` // 网络标识
|
||||||
Status int `json:"status" xorm:"status"`
|
Status int `json:"status" xorm:"status"`
|
||||||
UpdateTime string `json:"-" xorm:"-"`
|
UpdateTime string `json:"-" xorm:"-"`
|
||||||
}
|
}
|
||||||
|
|||||||
64
lib/midware/cors.go
Normal file
64
lib/midware/cors.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package midware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
}
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", strings.Join(allowHeaders, ","))
|
||||||
|
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暴露请求头
|
||||||
|
exposeHeaders := []string{"X-RepeatSubmit-Rest", "AccessToken"}
|
||||||
|
w.Header().Set("Access-Control-Expose-Headers", strings.Join(exposeHeaders, ","))
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ func LoggerTrace(next http.Handler) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 已禁用
|
||||||
func OptionProcess(next http.Handler) http.Handler {
|
func OptionProcess(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == "OPTIONS" {
|
if r.Method == "OPTIONS" {
|
||||||
@@ -48,6 +49,7 @@ func OptionProcess(next http.Handler) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 已禁用
|
||||||
func CheckPermission(next http.Handler) http.Handler {
|
func CheckPermission(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
token := r.Header.Get("AccessToken")
|
token := r.Header.Get("AccessToken")
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
sysrole "ems.agt/features/sys_role"
|
sysrole "ems.agt/features/sys_role"
|
||||||
sysuser "ems.agt/features/sys_user"
|
sysuser "ems.agt/features/sys_user"
|
||||||
"ems.agt/features/trace"
|
"ems.agt/features/trace"
|
||||||
|
udmuser "ems.agt/features/udm_user"
|
||||||
"ems.agt/lib/midware"
|
"ems.agt/lib/midware"
|
||||||
"ems.agt/lib/services"
|
"ems.agt/lib/services"
|
||||||
|
|
||||||
@@ -327,6 +328,11 @@ func init() {
|
|||||||
for _, v := range sysuser.Routers() {
|
for _, v := range sysuser.Routers() {
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UDM 用户信息接口添加到路由
|
||||||
|
for _, v := range udmuser.Routers() {
|
||||||
|
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
||||||
@@ -342,7 +348,8 @@ func NewRouter() *mux.Router {
|
|||||||
r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler()
|
r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler()
|
||||||
|
|
||||||
r.Use(midware.LoggerTrace)
|
r.Use(midware.LoggerTrace)
|
||||||
r.Use(midware.OptionProcess)
|
r.Use(midware.Cors)
|
||||||
|
// r.Use(midware.OptionProcess)
|
||||||
// r.Use(midware.ArrowIPAddr)
|
// r.Use(midware.ArrowIPAddr)
|
||||||
|
|
||||||
for _, router := range routers {
|
for _, router := range routers {
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ database:
|
|||||||
name: omc_db
|
name: omc_db
|
||||||
backup: d:/local.git/ems.agt/restagent/database
|
backup: d:/local.git/ems.agt/restagent/database
|
||||||
|
|
||||||
|
# Redis 缓存数据
|
||||||
|
redis:
|
||||||
|
port: 6379
|
||||||
|
host: "192.168.4.228"
|
||||||
|
password: ""
|
||||||
|
db: 0
|
||||||
|
|
||||||
mml:
|
mml:
|
||||||
port: 4100
|
port: 4100
|
||||||
sleep: 200
|
sleep: 200
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"ems.agt/lib/core/redis"
|
||||||
"ems.agt/lib/dborm"
|
"ems.agt/lib/dborm"
|
||||||
"ems.agt/lib/global"
|
"ems.agt/lib/global"
|
||||||
"ems.agt/lib/log"
|
"ems.agt/lib/log"
|
||||||
@@ -133,6 +134,7 @@ func main() {
|
|||||||
fmt.Printf("OMC restagent version: %s\n", global.Version)
|
fmt.Printf("OMC restagent version: %s\n", global.Version)
|
||||||
log.Infof("========================= OMC restagent startup =========================")
|
log.Infof("========================= OMC restagent startup =========================")
|
||||||
log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
|
log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
|
||||||
|
|
||||||
err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
||||||
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
conf.Database.Host, conf.Database.Port, conf.Database.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -164,6 +166,9 @@ func main() {
|
|||||||
os.Exit(4)
|
os.Exit(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 连接redis
|
||||||
|
redis.Connect()
|
||||||
|
|
||||||
router := routes.NewRouter()
|
router := routes.NewRouter()
|
||||||
|
|
||||||
// 开启监控采集
|
// 开启监控采集
|
||||||
|
|||||||
Reference in New Issue
Block a user