From f1a0c9555b8317927a35e7d058503a44334fbd4a Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Thu, 7 Sep 2023 19:13:09 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat=E5=8A=A0=E5=85=A5redis=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 4 + lib/core/redis/redis.go | 237 ++++++++++++++++++++++++++++++++++++ restagent/etc/restconf.yaml | 7 ++ restagent/restagent.go | 5 + 5 files changed, 254 insertions(+) create mode 100644 lib/core/redis/redis.go diff --git a/go.mod b/go.mod index 4cdb3132..e05e85d4 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 xorm.io/xorm v1.3.2 + github.com/redis/go-redis/v9 v9.1.0 ) require ( diff --git a/go.sum b/go.sum index 28897b8c..5a079b72 100644 --- a/go.sum +++ b/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.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0= +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/go.mod h1:tC0JZxZCdJN4DCB31cGxgjgf/ye1R4LLNJQd5ecjg08= 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.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 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/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI= github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas= diff --git a/lib/core/redis/redis.go b/lib/core/redis/redis.go new file mode 100644 index 00000000..26e89440 --- /dev/null +++ b/lib/core/redis/redis.go @@ -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) +} diff --git a/restagent/etc/restconf.yaml b/restagent/etc/restconf.yaml index ef3da907..7963c0c5 100644 --- a/restagent/etc/restconf.yaml +++ b/restagent/etc/restconf.yaml @@ -43,6 +43,13 @@ database: name: omc_db backup: d:/local.git/ems.agt/restagent/database +# Redis 缓存数据 +redis: + port: 6379 + host: "192.168.4.228" + password: "" + db: 0 + mml: port: 4100 sleep: 200 diff --git a/restagent/restagent.go b/restagent/restagent.go index 16925e0f..336e172c 100644 --- a/restagent/restagent.go +++ b/restagent/restagent.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" + "ems.agt/lib/core/redis" "ems.agt/lib/dborm" "ems.agt/lib/global" "ems.agt/lib/log" @@ -133,6 +134,7 @@ func main() { fmt.Printf("OMC restagent version: %s\n", global.Version) log.Infof("========================= OMC restagent startup =========================") 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, conf.Database.Host, conf.Database.Port, conf.Database.Name) if err != nil { @@ -164,6 +166,9 @@ func main() { os.Exit(4) } + // 连接redis + redis.Connect() + router := routes.NewRouter() // 开启监控采集 From 36549c89d4f987431e9657163fe283f95c71e41c Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Thu, 7 Sep 2023 19:13:35 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E7=BD=91=E5=85=83=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E6=8E=A5=E5=8F=97json=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/dborm/dborm.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/dborm/dborm.go b/lib/dborm/dborm.go index 32fd2b58..8c8d196f 100644 --- a/lib/dborm/dborm.go +++ b/lib/dborm/dborm.go @@ -181,17 +181,17 @@ func InsertDataWithJson(insertData interface{}) (int64, error) { type NeInfo struct { Id int `json:"id" xorm:"pk 'id' autoincr"` - NeType string `json:"neType" xorm:"ne_type"` - NeId string `json:"neId" xorm:"ne_id"` // neUID/rmUID 网元唯一标识 - RmUID string `json:"rmUID" xorm:"rm_uid"` // neUID/rmUID网元UID - NeName string `json:"neName" xorm:"ne_name"` // NeName/UserLabel 网元名称/网元设备友好名称 + NeType string `json:"ne_type" xorm:"ne_type"` + NeId string `json:"ne_id" xorm:"ne_id"` // neUID/rmUID 网元唯一标识 + RmUID string `json:"rm_uid" xorm:"rm_uid"` // neUID/rmUID网元UID + NeName string `json:"ne_name" xorm:"ne_name"` // NeName/UserLabel 网元名称/网元设备友好名称 Ip string `json:"ip" xorm:"ip"` Port string `json:"port" xorm:"port"` - PvFlag string `json:"pvFlag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理 - NeAddress string `json:"neAddress" xorm:"ne_address"` // 只对PNF - Province string `json:"province" xorm:"province"` // 网元所在省份 - VendorName string `json:"vendorName" xorm:"vendor_name"` // 厂商名称 - Dn string `json:"dn" xorm:"dn"` // 网络标识 + PvFlag string `json:"pv_flag" xorm:"pv_flag"` // 网元虚实性标识 VNF/PNF: 虚拟/物理 + NeAddress string `json:"ne_address" xorm:"ne_address"` // 只对PNF + Province string `json:"province" xorm:"province"` // 网元所在省份 + VendorName string `json:"vendor_name" xorm:"vendor_name"` // 厂商名称 + Dn string `json:"dn" xorm:"dn"` // 网络标识 Status int `json:"status" xorm:"status"` UpdateTime string `json:"-" xorm:"-"` } From 7b243bf0dda02baec8e5033a58a57b563e5fcf81 Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Thu, 7 Sep 2023 19:15:25 +0800 Subject: [PATCH 3/4] =?UTF-8?q?UDM=20=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=B7=BB=E5=8A=A0=E5=88=B0=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/udm_user/api_udm_user.go | 75 ++++++++++ features/udm_user/model/udm_ausf_user.go | 12 ++ features/udm_user/model/udm_sd_user.go | 16 +++ features/udm_user/repo/repo_udm_user.go | 129 ++++++++++++++++++ features/udm_user/service/service_udm_user.go | 90 ++++++++++++ lib/routes/routes.go | 6 + 6 files changed, 328 insertions(+) create mode 100644 features/udm_user/api_udm_user.go create mode 100644 features/udm_user/model/udm_ausf_user.go create mode 100644 features/udm_user/model/udm_sd_user.go create mode 100644 features/udm_user/repo/repo_udm_user.go create mode 100644 features/udm_user/service/service_udm_user.go diff --git a/features/udm_user/api_udm_user.go b/features/udm_user/api_udm_user.go new file mode 100644 index 00000000..af3d55ef --- /dev/null +++ b/features/udm_user/api_udm_user.go @@ -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)) +} diff --git a/features/udm_user/model/udm_ausf_user.go b/features/udm_user/model/udm_ausf_user.go new file mode 100644 index 00000000..896272ad --- /dev/null +++ b/features/udm_user/model/udm_ausf_user.go @@ -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"` +} diff --git a/features/udm_user/model/udm_sd_user.go b/features/udm_user/model/udm_sd_user.go new file mode 100644 index 00000000..64000218 --- /dev/null +++ b/features/udm_user/model/udm_sd_user.go @@ -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"` +} diff --git a/features/udm_user/repo/repo_udm_user.go b/features/udm_user/repo/repo_udm_user.go new file mode 100644 index 00000000..cedf05b0 --- /dev/null +++ b/features/udm_user/repo/repo_udm_user.go @@ -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, + } +} diff --git a/features/udm_user/service/service_udm_user.go b/features/udm_user/service/service_udm_user.go new file mode 100644 index 00000000..734e537f --- /dev/null +++ b/features/udm_user/service/service_udm_user.go @@ -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 +} diff --git a/lib/routes/routes.go b/lib/routes/routes.go index d5b959b4..decf76b5 100644 --- a/lib/routes/routes.go +++ b/lib/routes/routes.go @@ -25,6 +25,7 @@ import ( sysrole "ems.agt/features/sys_role" sysuser "ems.agt/features/sys_user" "ems.agt/features/trace" + udmuser "ems.agt/features/udm_user" "ems.agt/lib/midware" "ems.agt/lib/services" @@ -327,6 +328,11 @@ func init() { for _, v := range sysuser.Routers() { 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 From 4f3878e4a283e22e54f866a9419ca02d6d50140b Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Thu, 7 Sep 2023 21:04:29 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E8=B7=A8=E5=9F=9F=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/utils/ctx/ctx.go | 10 ------ lib/midware/cors.go | 64 +++++++++++++++++++++++++++++++++++++++ lib/midware/midhandle.go | 2 ++ lib/routes/routes.go | 3 +- 4 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 lib/midware/cors.go diff --git a/lib/core/utils/ctx/ctx.go b/lib/core/utils/ctx/ctx.go index 128e5005..21570310 100644 --- a/lib/core/utils/ctx/ctx.go +++ b/lib/core/utils/ctx/ctx.go @@ -47,16 +47,6 @@ func ShouldBindJSON(r *http.Request, args any) error { // JSON 相应json数据 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") response, err := json.Marshal(data) diff --git a/lib/midware/cors.go b/lib/midware/cors.go new file mode 100644 index 00000000..9eb024a3 --- /dev/null +++ b/lib/midware/cors.go @@ -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) + }) +} diff --git a/lib/midware/midhandle.go b/lib/midware/midhandle.go index eb7be9af..14cb958a 100644 --- a/lib/midware/midhandle.go +++ b/lib/midware/midhandle.go @@ -37,6 +37,7 @@ func LoggerTrace(next http.Handler) http.Handler { }) } +// 已禁用 func OptionProcess(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" { @@ -48,6 +49,7 @@ func OptionProcess(next http.Handler) http.Handler { }) } +// 已禁用 func CheckPermission(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("AccessToken") diff --git a/lib/routes/routes.go b/lib/routes/routes.go index decf76b5..555aa8c2 100644 --- a/lib/routes/routes.go +++ b/lib/routes/routes.go @@ -348,7 +348,8 @@ func NewRouter() *mux.Router { r.MethodNotAllowedHandler = services.CustomResponseMethodNotAllowed405Handler() r.Use(midware.LoggerTrace) - r.Use(midware.OptionProcess) + r.Use(midware.Cors) + // r.Use(midware.OptionProcess) // r.Use(midware.ArrowIPAddr) for _, router := range routers {