Merge remote-tracking branch 'origin/errcode' into errcode

This commit is contained in:
skiffer-git
2023-01-30 21:47:38 +08:00
103 changed files with 1914 additions and 2482 deletions
@@ -1,4 +1,4 @@
package base_info
package api_struct
//UserID string `protobuf:"bytes,1,opt,name=UserID" json:"UserID,omitempty"`
// Nickname string `protobuf:"bytes,2,opt,name=Nickname" json:"Nickname,omitempty"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
type AwsStorageCredentialReq struct {
OperationID string `json:"operationID"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
type SetClientInitConfigReq struct {
OperationID string `json:"operationID" binding:"required"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
type RequestPagination struct {
PageNumber int `json:"pageNumber" binding:"required"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
type OptResult struct {
ConversationID string `json:"conversationID"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
import sts "github.com/tencentyun/qcloud-cos-sts-sdk/go"
@@ -1,4 +1,4 @@
package base_info
package api_struct
//type ParamsCommFriend struct {
// OperationID string `json:"operationID" binding:"required"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
import (
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
@@ -1,4 +1,4 @@
package base_info
package api_struct
import (
pbRelay "Open_IM/pkg/proto/relay"
@@ -1,4 +1,4 @@
package base_info
package api_struct
import (
"Open_IM/pkg/proto/msg"
@@ -1,4 +1,4 @@
package base_info
package api_struct
import (
pbOffice "Open_IM/pkg/proto/office"
@@ -1,4 +1,4 @@
package base_info
package api_struct
import open_im_sdk "Open_IM/pkg/proto/sdk_ws"
@@ -1,4 +1,4 @@
package base_info
package api_struct
type OSSCredentialReq struct {
OperationID string `json:"operationID"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
type Pagination struct {
PageNumber int32 `json:"pageNumber" binding:"required"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
import (
"net/http"
@@ -1,4 +1,4 @@
package base_info
package api_struct
type GetJoinedSuperGroupListReq struct {
GetJoinedGroupListReq
@@ -1,4 +1,4 @@
package base_info
package api_struct
type Swagger400Resp struct {
ErrCode int32 `json:"errCode" example:"400"`
@@ -1,4 +1,4 @@
package base_info
package api_struct
import "mime/multipart"
@@ -1,4 +1,4 @@
package base_info
package api_struct
import (
open_im_sdk "Open_IM/pkg/proto/sdk_ws"
@@ -1,4 +1,4 @@
package base_info
package api_struct
import "Open_IM/pkg/proto/office"
@@ -1,7 +1,7 @@
package cms_api_struct
package cms_struct
import (
"Open_IM/pkg/base_info"
"Open_IM/pkg/api_struct"
server_api_params "Open_IM/pkg/proto/sdk_ws"
)
@@ -47,10 +47,10 @@ type ReduceUserRegisterAddFriendIDListResponse struct {
type GetUserRegisterAddFriendIDListRequest struct {
OperationID string `json:"operationID" binding:"required"`
base_info.RequestPagination
api_struct.RequestPagination
}
type GetUserRegisterAddFriendIDListResponse struct {
Users []*server_api_params.UserInfo `json:"users"`
base_info.ResponsePagination
api_struct.ResponsePagination
}
@@ -1,4 +1,4 @@
package cms_api_struct
package cms_struct
type RequestPagination struct {
PageNumber int `json:"pageNumber" binding:"required"`
@@ -1,4 +1,4 @@
package cms_api_struct
package cms_struct
type GetFriendsReq struct {
OperationID string `json:"operationID"`
@@ -1,4 +1,4 @@
package cms_api_struct
package cms_struct
type GroupResponse struct {
GroupOwnerName string `json:"GroupOwnerName"`
@@ -1,4 +1,4 @@
package cms_api_struct
package cms_struct
import (
pbCommon "Open_IM/pkg/proto/sdk_ws"
@@ -1,4 +1,4 @@
package cms_api_struct
package cms_struct
type GetStatisticsRequest struct {
From string `json:"from" binding:"required"`
@@ -1,4 +1,4 @@
package cms_api_struct
package cms_struct
type UserResponse struct {
FaceURL string `json:"faceURL"`
+7 -5
View File
@@ -158,13 +158,15 @@ func (g *GroupDataBase) FindGroupsByID(ctx context.Context, groupIDs []string) (
return g.cache.GetGroupsInfo(ctx, groupIDs)
}
func (g *GroupDataBase) CreateGroup(ctx context.Context, groups []*relation.Group, groupMember []*relation.GroupMember) error {
func (g *GroupDataBase) CreateGroup(ctx context.Context, groups []*relation.Group, groupMembers []*relation.GroupMember) error {
return g.db.Transaction(func(tx *gorm.DB) error {
if err := g.groupDB.Create(ctx, groups, tx); err != nil {
return err
if len(groups) > 0 {
if err := g.groupDB.Create(ctx, groups, tx); err != nil {
return err
}
}
if len(groupMember) > 0 {
if err := g.groupMemberDB.Create(ctx, groupMember, tx); err != nil {
if len(groupMembers) > 0 {
if err := g.groupMemberDB.Create(ctx, groupMembers, tx); err != nil {
return err
}
}
+5
View File
@@ -19,6 +19,11 @@ type Friend struct {
DB *gorm.DB `gorm:"-"`
}
type FriendUser struct {
Friend
Nickname string `gorm:"column:name;size:255"`
}
func NewFriendDB(db *gorm.DB) *Friend {
var friend Friend
friend.DB = initModel(db, friend)
+42
View File
@@ -1,6 +1,10 @@
package middleware
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/common/token_verify"
"Open_IM/pkg/utils"
"bytes"
"encoding/json"
"github.com/gin-gonic/gin"
@@ -8,6 +12,44 @@ import (
"net/http"
)
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
ok, userID, errInfo := token_verify.GetUserIDFromToken(c.Request.Header.Get("token"), "")
// log.NewInfo("0", utils.GetSelfFuncName(), "userID: ", userID)
c.Set("userID", userID)
if !ok {
log.NewError("", "GetUserIDFromToken false ", c.Request.Header.Get("token"))
c.Abort()
c.JSON(http.StatusOK, gin.H{"errCode": 400, "errMsg": errInfo})
return
} else {
if !utils.IsContain(userID, config.Config.Manager.AppManagerUid) {
c.Abort()
c.JSON(http.StatusOK, gin.H{"errCode": 400, "errMsg": "user is not admin"})
return
}
log.NewInfo("0", utils.GetSelfFuncName(), "failed: ", errInfo)
}
}
}
func CorsHandler() gin.HandlerFunc {
return func(context *gin.Context) {
context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
context.Header("Access-Control-Allow-Methods", "*")
context.Header("Access-Control-Allow-Headers", "*")
context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析
context.Header("Access-Control-Max-Age", "172800") // 缓存请求信息 单位为秒
context.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息 默认设置为true
context.Header("content-type", "application/json") // 设置返回格式是json
//Release all option pre-requests
if context.Request.Method == http.MethodOptions {
context.JSON(http.StatusOK, "Options Request!")
}
context.Next()
}
}
func GinParseOperationID(c *gin.Context) {
if c.Request.Method == http.MethodPost {
operationID := c.Request.Header.Get("operationID")
+3 -4
View File
@@ -5,7 +5,6 @@ import (
"Open_IM/pkg/common/constant"
commonDB "Open_IM/pkg/common/db"
"Open_IM/pkg/common/log"
"Open_IM/pkg/common/tools"
"Open_IM/pkg/common/tracelog"
"Open_IM/pkg/utils"
"context"
@@ -160,7 +159,7 @@ func CheckAccess(ctx context.Context, OpUserID string, OwnerUserID string) bool
}
func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
opUserID := tools.OpUserID(ctx)
opUserID := utils.OpUserID(ctx)
defer func() {
tracelog.SetCtxInfo(ctx, utils.GetFuncName(1), err, "OpUserID", opUserID, "ownerUserID", ownerUserID)
}()
@@ -174,11 +173,11 @@ func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
}
func IsAppManagerUid(ctx context.Context) bool {
return utils.IsContain(tools.OpUserID(ctx), config.Config.Manager.AppManagerUid)
return utils.IsContain(utils.OpUserID(ctx), config.Config.Manager.AppManagerUid)
}
func CheckAdmin(ctx context.Context) error {
if utils.IsContain(tools.OpUserID(ctx), config.Config.Manager.AppManagerUid) {
if utils.IsContain(utils.OpUserID(ctx), config.Config.Manager.AppManagerUid) {
return nil
}
return constant.ErrIdentity.Wrap()
-13
View File
@@ -1,13 +0,0 @@
package tools
import "context"
func OperationID(ctx context.Context) string {
s, _ := ctx.Value("operationID").(string)
return s
}
func OpUserID(ctx context.Context) string {
s, _ := ctx.Value("opUserID").(string)
return s
}
+3 -82
View File
@@ -1,28 +1,20 @@
package tracelog
import (
"Open_IM/pkg/common/constant"
"Open_IM/pkg/utils"
"context"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/status"
"runtime"
"strings"
//"errors"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
const TraceLogKey = "tracelog"
func NewCtx(c *gin.Context, api string) context.Context {
req := &ApiInfo{ApiName: api, GinCtx: c, Funcs: &[]FuncInfo{}}
return context.WithValue(c, TraceLogKey, req)
}
func NewCtx1(c *gin.Context, api string) context.Context {
req := &ApiInfo{ApiName: api, GinCtx: c, OperationID: c.GetHeader("operationID"), Funcs: &[]FuncInfo{}}
return context.WithValue(c, TraceLogKey, req)
}
@@ -42,77 +34,11 @@ func GetOperationID(ctx context.Context) string {
return ctx.Value(TraceLogKey).(*ApiInfo).OperationID
}
//func ShowLog(ctx context.Context) {
// t := ctx.Value(TraceLogKey).(*ApiInfo)
// if ctx.Value(TraceLogKey).(*ApiInfo).GinCtx != nil {
// log.Info(t.OperationID, "api: ", t.ApiName)
// } else {
// log.Info(t.OperationID, "rpc: ", t.ApiName)
// }
// for _, v := range *t.Funcs {
// if v.Err != nil {
// log.Error(t.OperationID, "func: ", v.FuncName, " args: ", v.Args, v.Err.Error())
// } else {
// switch v.LogLevel {
// case logrus.InfoLevel:
// log.Info(t.OperationID, "func: ", v.FuncName, " args: ", v.Args)
// case logrus.DebugLevel:
// log.Debug(t.OperationID, "func: ", v.FuncName, " args: ", v.Args)
// case logrus.WarnLevel:
// log.Debug(t.OperationID, "func: ", v.FuncName, " args: ", v.Args)
// }
// }
// }
//}
func WriteErrorResponse(ctx context.Context, funcName string, err error, args ...interface{}) {
SetCtxInfo(ctx, funcName, err, args)
e := Unwrap(err)
switch t := e.(type) {
case *constant.ErrInfo:
ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, baseResp{ErrCode: t.ErrCode, ErrMsg: t.ErrMsg, ErrDtl: t.DetailErrMsg})
//ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": t.ErrCode, "errMsg": t.ErrMsg, "errDtl": t.DetailErrMsg})
return
default:
s, ok := status.FromError(e)
if !ok {
ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, &baseResp{ErrCode: constant.ErrDefaultOther.ErrCode, ErrMsg: err.Error(), ErrDtl: fmt.Sprintf("%+v", err)})
//ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": constant.ErrDefaultOther.ErrCode, "errMsg": err.Error(), "errDtl": fmt.Sprintf("%+v", err)})
return
}
var details []string
if err != e {
details = append(details, fmt.Sprintf("%+v", err))
}
for _, s := range s.Details() {
details = append(details, fmt.Sprintf("%+v", s))
}
ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, &baseResp{ErrCode: int32(s.Code()), ErrMsg: s.Message(), ErrDtl: strings.Join(details, "\n")})
//ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": s.Code(), "errMsg": s.Message(), "errDtl": strings.Join(details, "\n")})
return
}
func GetOpUserID(ctx context.Context) string {
s, _ := ctx.Value("opUserID").(string)
return s
}
type baseResp struct {
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
ErrDtl string `json:"errDtl"`
Data interface{} `json:"data"`
}
//func WriteErrorResponse(ctx context.Context, funcName string, err error, args ...interface{}) {
// SetCtxInfo(ctx, funcName, err, args)
// e := new(constant.ErrInfo)
// switch {
// case errors.As(err, &e):
// ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": e.ErrCode, "errMsg": e.ErrMsg})
// return
// default:
// ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": constant.ErrDefaultOther.ErrCode, "errMsg": constant.ErrDefaultOther.ErrMsg, "errDtl": err.Error()})
// return
// }
//}
func Unwrap(err error) error {
for err != nil {
unwrap, ok := err.(interface {
@@ -211,11 +137,6 @@ func SetRpcRespInfo(ctx context.Context, funcName string, resp string) {
*t.Funcs = append(*t.Funcs, funcInfo)
}
func SetSuccess(ctx context.Context, funcName string, data interface{}) {
SetCtxInfo(ctx, funcName, nil, "data", data)
ctx.Value(TraceLogKey).(*ApiInfo).GinCtx.JSON(http.StatusOK, gin.H{"errCode": 0, "errMsg": "", "errDtl": "", "data": data})
}
func argsHandle(args []interface{}, fields map[string]interface{}) {
for i := 0; i < len(args); i += 2 {
if i+1 < len(args) {
+4 -3
View File
@@ -1,7 +1,8 @@
package utils
package getcdv3
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/utils"
"context"
"fmt"
"github.com/OpenIMSDK/getcdv3"
@@ -32,8 +33,8 @@ func RegisterConf() {
if err != nil {
panic(err.Error())
}
secretMD5 := Md5(config.Config.Etcd.Secret)
confBytes, err := AesEncrypt(bytes, []byte(secretMD5[0:16]))
secretMD5 := utils.Md5(config.Config.Etcd.Secret)
confBytes, err := utils.AesEncrypt(bytes, []byte(secretMD5[0:16]))
if err != nil {
panic(err.Error())
}
@@ -1,4 +1,4 @@
package callback
package utils
import (
"Open_IM/pkg/common/constant"
@@ -10,11 +10,6 @@ func GetContent(msg *server_api_params.MsgData) string {
if msg.ContentType >= constant.NotificationBegin && msg.ContentType <= constant.NotificationEnd {
var tips server_api_params.TipsComm
_ = proto.Unmarshal(msg.Content, &tips)
//marshaler := jsonpb.Marshaler{
// OrigName: true,
// EnumsAsInts: false,
// EmitDefaults: false,
//}
content := tips.JsonDetail
return content
} else {
+292
View File
@@ -0,0 +1,292 @@
package utils
import (
"Open_IM/pkg/common/db/relation"
sdk "Open_IM/pkg/proto/sdk_ws"
utils "github.com/OpenIMSDK/open_utils"
"time"
)
func getUsersInfo(userIDs []string) ([]*sdk.UserInfo, error) {
return nil, nil
}
func getGroupOwnerInfo(groupID string) (*sdk.GroupMemberFullInfo, error) {
return nil, nil
}
func getNumberOfGroupMember(groupID string) (int32, error) {
return 0, nil
}
type DBFriend struct {
*relation.Friend
}
func NewDBFriend(friend *relation.Friend) *DBFriend {
return &DBFriend{Friend: friend}
}
type PBFriend struct {
*sdk.FriendInfo
}
func NewPBFriend(friendInfo *sdk.FriendInfo) *PBFriend {
return &PBFriend{FriendInfo: friendInfo}
}
func (db *DBFriend) convert() (*sdk.FriendInfo, error) {
pbFriend := &sdk.FriendInfo{FriendUser: &sdk.UserInfo{}}
utils.CopyStructFields(pbFriend, db)
user, err := getUsersInfo([]string{db.FriendUserID})
if err != nil {
return nil, err
}
utils2.CopyStructFields(pbFriend.FriendUser, user[0])
pbFriend.CreateTime = uint32(db.CreateTime.Unix())
pbFriend.FriendUser.CreateTime = uint32(db.CreateTime.Unix())
return pbFriend, nil
}
func (pb *PBFriend) Convert() (*relation.Friend, error) {
dbFriend := &relation.Friend{}
utils2.CopyStructFields(dbFriend, pb)
dbFriend.FriendUserID = pb.FriendUser.UserID
dbFriend.CreateTime = utils2.UnixSecondToTime(int64(pb.CreateTime))
return dbFriend, nil
}
type DBFriendRequest struct {
*relation.FriendRequest
}
func NewDBFriendRequest(friendRequest *relation.FriendRequest) *DBFriendRequest {
return &DBFriendRequest{FriendRequest: friendRequest}
}
type PBFriendRequest struct {
*sdk.FriendRequest
}
func NewPBFriendRequest(friendRequest *sdk.FriendRequest) *PBFriendRequest {
return &PBFriendRequest{FriendRequest: friendRequest}
}
func (pb *PBFriendRequest) Convert() (*relation.FriendRequest, error) {
dbFriendRequest := &relation.FriendRequest{}
utils.CopyStructFields(dbFriendRequest, pb)
dbFriendRequest.CreateTime = utils.UnixSecondToTime(int64(pb.CreateTime))
dbFriendRequest.HandleTime = utils.UnixSecondToTime(int64(pb.HandleTime))
return dbFriendRequest, nil
}
func (db *DBFriendRequest) Convert() (*sdk.FriendRequest, error) {
pbFriendRequest := &sdk.FriendRequest{}
utils.CopyStructFields(pbFriendRequest, db)
user, err := getUsersInfo([]string{db.FromUserID})
if err != nil {
return nil, err
}
pbFriendRequest.FromNickname = user[0].Nickname
pbFriendRequest.FromFaceURL = user[0].FaceURL
pbFriendRequest.FromGender = user[0].Gender
user, err = getUsersInfo([]string{db.ToUserID})
if err != nil {
return nil, err
}
pbFriendRequest.ToNickname = user[0].Nickname
pbFriendRequest.ToFaceURL = user[0].FaceURL
pbFriendRequest.ToGender = user[0].Gender
pbFriendRequest.CreateTime = uint32(db.CreateTime.Unix())
pbFriendRequest.HandleTime = uint32(db.HandleTime.Unix())
return pbFriendRequest, nil
}
type DBBlack struct {
*relation.Black
}
func NewDBBlack(black *relation.Black) *DBBlack {
return &DBBlack{Black: black}
}
type PBBlack struct {
*sdk.BlackInfo
}
func NewPBBlack(blackInfo *sdk.BlackInfo) *PBBlack {
return &PBBlack{BlackInfo: blackInfo}
}
func (pb *PBBlack) Convert() (*relation.Black, error) {
dbBlack := &relation.Black{}
dbBlack.BlockUserID = pb.BlackUserInfo.UserID
dbBlack.CreateTime = utils.UnixSecondToTime(int64(pb.CreateTime))
return dbBlack, nil
}
func (db *DBBlack) Convert() (*sdk.BlackInfo, error) {
pbBlack := &sdk.BlackInfo{}
utils.CopyStructFields(pbBlack, db)
pbBlack.CreateTime = uint32(db.CreateTime.Unix())
user, err := getUsersInfo([]string{db.BlockUserID})
if err != nil {
return nil, err
}
utils.CopyStructFields(pbBlack.BlackUserInfo, user)
return pbBlack, nil
}
type DBGroup struct {
*relation.Group
}
func NewDBGroup(group *relation.Group) *DBGroup {
return &DBGroup{Group: group}
}
type PBGroup struct {
*sdk.GroupInfo
}
func NewPBGroup(groupInfo *sdk.GroupInfo) *PBGroup {
return &PBGroup{GroupInfo: groupInfo}
}
func (pb *PBGroup) Convert() *relation.Group {
dst := &relation.Group{}
_ = utils.CopyStructFields(dst, pb)
return dst
}
func (db *DBGroup) Convert() (*sdk.GroupInfo, error) {
dst := &sdk.GroupInfo{}
utils.CopyStructFields(dst, db)
user, err := getGroupOwnerInfo(db.GroupID)
if err != nil {
return nil, err
}
dst.OwnerUserID = user.UserID
memberCount, err := getNumberOfGroupMember(db.GroupID)
if err != nil {
return nil, err
}
dst.MemberCount = uint32(memberCount)
dst.CreateTime = uint32(db.CreateTime.Unix())
dst.NotificationUpdateTime = uint32(db.NotificationUpdateTime.Unix())
if db.NotificationUpdateTime.Unix() < 0 {
dst.NotificationUpdateTime = 0
}
return dst, nil
}
type DBGroupMember struct {
*relation.GroupMember
}
func NewDBGroupMember(groupMember *relation.GroupMember) *DBGroupMember {
return &DBGroupMember{GroupMember: groupMember}
}
type PBGroupMember struct {
*sdk.GroupMemberFullInfo
}
func NewPBGroupMember(groupMemberFullInfo *sdk.GroupMemberFullInfo) *PBGroupMember {
return &PBGroupMember{GroupMemberFullInfo: groupMemberFullInfo}
}
func (pb *PBGroupMember) Convert() (*relation.GroupMember, error) {
dst := &relation.GroupMember{}
utils.CopyStructFields(dst, pb)
dst.JoinTime = utils.UnixSecondToTime(int64(pb.JoinTime))
dst.MuteEndTime = utils.UnixSecondToTime(int64(pb.MuteEndTime))
return dst, nil
}
func (db *DBGroupMember) Convert() (*sdk.GroupMemberFullInfo, error) {
dst := &sdk.GroupMemberFullInfo{}
utils.CopyStructFields(dst, db)
user, err := getUsersInfo([]string{db.UserID})
if err != nil {
return nil, err
}
dst.AppMangerLevel = user[0].AppMangerLevel
dst.JoinTime = int32(db.JoinTime.Unix())
if db.JoinTime.Unix() < 0 {
dst.JoinTime = 0
}
dst.MuteEndTime = uint32(db.MuteEndTime.Unix())
if dst.MuteEndTime < uint32(time.Now().Unix()) {
dst.MuteEndTime = 0
}
return dst, nil
}
type DBGroupRequest struct {
*relation.GroupRequest
}
func NewDBGroupRequest(groupRequest *relation.GroupRequest) *DBGroupRequest {
return &DBGroupRequest{GroupRequest: groupRequest}
}
type PBGroupRequest struct {
*sdk.GroupRequest
}
func NewPBGroupRequest(groupRequest *sdk.GroupRequest) *PBGroupRequest {
return &PBGroupRequest{GroupRequest: groupRequest}
}
func (pb *PBGroupRequest) Convert() (*relation.GroupRequest, error) {
dst := &relation.GroupRequest{}
utils.CopyStructFields(dst, pb)
dst.ReqTime = utils.UnixSecondToTime(int64(pb.ReqTime))
dst.HandledTime = utils.UnixSecondToTime(int64(pb.HandleTime))
return dst, nil
}
func (db *DBGroupRequest) Convert() (*sdk.GroupRequest, error) {
dst := &sdk.GroupRequest{}
utils.CopyStructFields(dst, db)
dst.ReqTime = uint32(db.ReqTime.Unix())
dst.HandleTime = uint32(db.HandledTime.Unix())
return dst, nil
}
type DBUser struct {
*relation.User
}
func NewDBUser(user *relation.User) *DBUser {
return &DBUser{User: user}
}
type PBUser struct {
*sdk.UserInfo
}
func NewPBUser(userInfo *sdk.UserInfo) *PBUser {
return &PBUser{UserInfo: userInfo}
}
func (pb *PBUser) Convert() (*relation.User, error) {
dst := &relation.User{}
utils.CopyStructFields(dst, pb)
dst.Birth = utils.UnixSecondToTime(pb.Birthday)
dst.CreateTime = utils.UnixSecondToTime(int64(pb.CreateTime))
return dst, nil
}
func (db *DBUser) Convert() (*sdk.UserInfo, error) {
dst := &sdk.UserInfo{}
utils.CopyStructFields(dst, db)
dst.CreateTime = db.CreateTime.Unix()
dst.Birthday = db.Birth.Unix()
return dst, nil
}
func (db *DBUser) ConvertPublic() (*sdk.PublicUserInfo, error) {
dst := &sdk.PublicUserInfo{}
utils.CopyStructFields(dst, db)
return dst, nil
}
-24
View File
@@ -1,24 +0,0 @@
package utils
import (
"net/http"
"github.com/gin-gonic/gin"
)
func CorsHandler() gin.HandlerFunc {
return func(context *gin.Context) {
context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
context.Header("Access-Control-Allow-Methods", "*")
context.Header("Access-Control-Allow-Headers", "*")
context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析
context.Header("Access-Control-Max-Age", "172800") // 缓存请求信息 单位为秒
context.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息 默认设置为true
context.Header("content-type", "application/json") // 设置返回格式是json
//Release all option pre-requests
if context.Request.Method == http.MethodOptions {
context.JSON(http.StatusOK, "Options Request!")
}
context.Next()
}
}
+28
View File
@@ -0,0 +1,28 @@
package utils
import (
"github.com/bwmarrin/snowflake"
)
func init() {
var err error
idGenerator, err = snowflake.NewNode(getNodeNum())
if err != nil {
panic(err)
}
}
func getNodeNum() int64 {
return 1
}
var idGenerator *snowflake.Node
func GenID() string {
return idGenerator.Generate().String()
}
func GenIDs(count int) []string {
//impl
return []string{}
}
+15
View File
@@ -0,0 +1,15 @@
package utils
import "testing"
func TestGenID(t *testing.T) {
m := map[string]struct{}{}
for i := 0; i < 2000; i++ {
got := GenID()
if _, ok := m[got]; !ok {
m[got] = struct{}{}
} else {
t.Error("id generate error", got)
}
}
}
+27
View File
@@ -0,0 +1,27 @@
package utils
import (
"path/filepath"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
var (
_, b, _, _ = runtime.Caller(0)
// Root folder of this project
Root = filepath.Join(filepath.Dir(b), "../..")
)
func Test_GenSmallImage(t *testing.T) {
println(Root)
err := GenSmallImage(Root+"/docs/open-im-logo.png", Root+"/out-test/open-im-logo-test.png")
assert.Nil(t, err)
err = GenSmallImage(Root+"/docs/open-im-logo.png", "out-test/open-im-logo-test.png")
assert.Nil(t, err)
err = GenSmallImage(Root+"/docs/Architecture.jpg", "out-test/Architecture-test.jpg")
assert.Nil(t, err)
}
+89
View File
@@ -0,0 +1,89 @@
package utils
import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/token_verify"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func Test_BuildClaims(t *testing.T) {
uid := "1"
platform := "PC"
ttl := int64(-1)
claim := token_verify.BuildClaims(uid, platform, ttl)
now := time.Now().Unix()
assert.Equal(t, claim.UID, uid, "uid should equal")
assert.Equal(t, claim.Platform, platform, "platform should equal")
assert.Equal(t, claim.RegisteredClaims.ExpiresAt, int64(-1), "StandardClaims.ExpiresAt should be equal")
// time difference within 1s
assert.Equal(t, claim.RegisteredClaims.IssuedAt, now, "StandardClaims.IssuedAt should be equal")
assert.Equal(t, claim.RegisteredClaims.NotBefore, now, "StandardClaims.NotBefore should be equal")
ttl = int64(60)
now = time.Now().Unix()
claim = token_verify.BuildClaims(uid, platform, ttl)
// time difference within 1s
assert.Equal(t, claim.RegisteredClaims.ExpiresAt, int64(60)+now, "StandardClaims.ExpiresAt should be equal")
assert.Equal(t, claim.RegisteredClaims.IssuedAt, now, "StandardClaims.IssuedAt should be equal")
assert.Equal(t, claim.RegisteredClaims.NotBefore, now, "StandardClaims.NotBefore should be equal")
}
func Test_CreateToken(t *testing.T) {
uid := "1"
platform := int32(1)
now := time.Now().Unix()
tokenString, expiresAt, err := token_verify.CreateToken(uid, int(platform))
assert.NotEmpty(t, tokenString)
assert.Equal(t, expiresAt, 604800+now)
assert.Nil(t, err)
}
func Test_VerifyToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := token_verify.CreateToken(uid, int(platform))
result, _ := token_verify.VerifyToken(tokenString, uid)
assert.True(t, result)
result, _ = token_verify.VerifyToken(tokenString, "2")
assert.False(t, result)
}
func Test_ParseRedisInterfaceToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := token_verify.CreateToken(uid, int(platform))
claims, err := token_verify.ParseRedisInterfaceToken([]uint8(tokenString))
assert.Nil(t, err)
assert.Equal(t, claims.UID, uid)
// timeout
config.Config.TokenPolicy.AccessExpire = -80
tokenString, _, _ = token_verify.CreateToken(uid, int(platform))
claims, err = token_verify.ParseRedisInterfaceToken([]uint8(tokenString))
assert.Equal(t, err, constant.ExpiredToken)
assert.Nil(t, claims)
}
func Test_ParseToken(t *testing.T) {
uid := "1"
platform := int32(1)
tokenString, _, _ := token_verify.CreateToken(uid, int(platform))
claims, err := token_verify.ParseToken(tokenString, "")
if err == nil {
assert.Equal(t, claims.UID, uid)
}
}
func Test_GetClaimFromToken(t *testing.T) {
token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVSUQiOiJvcGVuSU0xMjM0NTYiLCJQbGF0Zm9ybSI6IiIsImV4cCI6MTYzODg0NjQ3NiwibmJmIjoxNjM4MjQxNjc2LCJpYXQiOjE2MzgyNDE2NzZ9.W8RZB7ec5ySFj-rGE2Aho2z32g3MprQMdCyPiQu_C2I"
c, err := token_verify.GetClaimFromToken(token)
assert.Nil(t, c)
assert.Nil(t, err)
}
+78
View File
@@ -0,0 +1,78 @@
package utils
import (
"Open_IM/pkg/common/config"
rocksCache "Open_IM/pkg/common/db/rocks_cache"
"Open_IM/pkg/common/log"
"Open_IM/pkg/getcdv3"
pbCache "Open_IM/pkg/proto/cache"
"context"
"errors"
"sync"
)
type GroupMemberUserIDListHash struct {
MemberListHash uint64
UserIDList []string
}
var CacheGroupMemberUserIDList = make(map[string]*GroupMemberUserIDListHash, 0)
var CacheGroupMtx sync.RWMutex
func GetGroupMemberUserIDList(ctx context.Context, groupID string, operationID string) ([]string, error) {
groupHashRemote, err := GetGroupMemberUserIDListHashFromRemote(ctx, groupID)
if err != nil {
CacheGroupMtx.Lock()
defer CacheGroupMtx.Unlock()
delete(CacheGroupMemberUserIDList, groupID)
log.Error(operationID, "GetGroupMemberUserIDListHashFromRemote failed ", err.Error(), groupID)
return nil, Wrap(err, groupID)
}
CacheGroupMtx.Lock()
defer CacheGroupMtx.Unlock()
if groupHashRemote == 0 {
log.Info(operationID, "groupHashRemote == 0 ", groupID)
delete(CacheGroupMemberUserIDList, groupID)
return []string{}, nil
}
groupInLocalCache, ok := CacheGroupMemberUserIDList[groupID]
if ok && groupInLocalCache.MemberListHash == groupHashRemote {
log.Debug(operationID, "in local cache ", groupID)
return groupInLocalCache.UserIDList, nil
}
log.Debug(operationID, "not in local cache or hash changed", groupID, " remote hash ", groupHashRemote, " in cache ", ok)
memberUserIDListRemote, err := GetGroupMemberUserIDListFromRemote(groupID, operationID)
if err != nil {
log.Error(operationID, "GetGroupMemberUserIDListFromRemote failed ", err.Error(), groupID)
return nil, Wrap(err, groupID)
}
CacheGroupMemberUserIDList[groupID] = &GroupMemberUserIDListHash{MemberListHash: groupHashRemote, UserIDList: memberUserIDListRemote}
return memberUserIDListRemote, nil
}
func GetGroupMemberUserIDListHashFromRemote(ctx context.Context, groupID string) (uint64, error) {
return rocksCache.GetGroupMemberListHashFromCache(ctx, groupID)
}
func GetGroupMemberUserIDListFromRemote(groupID string, operationID string) ([]string, error) {
getGroupMemberIDListFromCacheReq := &pbCache.GetGroupMemberIDListFromCacheReq{OperationID: operationID, GroupID: groupID}
etcdConn, err := getcdv3.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImCacheName)
if err != nil {
return nil, err
}
client := pbCache.NewCacheClient(etcdConn)
cacheResp, err := client.GetGroupMemberIDListFromCache(context.Background(), getGroupMemberIDListFromCacheReq)
if err != nil {
log.NewError(operationID, "GetGroupMemberIDListFromCache rpc call failed ", err.Error())
return nil, Wrap(err, "GetGroupMemberIDListFromCache rpc call failed")
}
if cacheResp.CommonResp.ErrCode != 0 {
errMsg := operationID + "GetGroupMemberIDListFromCache rpc logic call failed " + cacheResp.CommonResp.ErrMsg
log.NewError(operationID, errMsg)
return nil, errors.New("errMsg")
}
return cacheResp.UserIDList, nil
}
+15
View File
@@ -0,0 +1,15 @@
package utils
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_Md5(t *testing.T) {
result := Md5("go")
assert.Equal(t, result, "34d1f91fb2e514b8576fab1a75a89a6b")
result2 := Md5("go")
assert.Equal(t, result, result2)
}
@@ -0,0 +1,46 @@
package utils
import (
"Open_IM/pkg/common/constant"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_PlatformIDToName(t *testing.T) {
assert.Equal(t, constant.PlatformIDToName(1), "IOS")
assert.Equal(t, constant.PlatformIDToName(2), "Android")
assert.Equal(t, constant.PlatformIDToName(3), "Windows")
assert.Equal(t, constant.PlatformIDToName(4), "OSX")
assert.Equal(t, constant.PlatformIDToName(5), "Web")
assert.Equal(t, constant.PlatformIDToName(6), "MiniWeb")
assert.Equal(t, constant.PlatformIDToName(7), "Linux")
assert.Equal(t, constant.PlatformIDToName(0), "")
}
func Test_PlatformNameToID(t *testing.T) {
assert.Equal(t, constant.PlatformNameToID("IOS"), int32(1))
assert.Equal(t, constant.PlatformNameToID("Android"), int32(2))
assert.Equal(t, constant.PlatformNameToID("Windows"), int32(3))
assert.Equal(t, constant.PlatformNameToID("OSX"), int32(4))
assert.Equal(t, constant.PlatformNameToID("Web"), int32(5))
assert.Equal(t, constant.PlatformNameToID("MiniWeb"), int32(6))
assert.Equal(t, constant.PlatformNameToID("Linux"), int32(7))
assert.Equal(t, constant.PlatformNameToID("UnknownDevice"), int32(0))
assert.Equal(t, constant.PlatformNameToID(""), int32(0))
}
func Test_PlatformNameToClass(t *testing.T) {
assert.Equal(t, constant.PlatformNameToClass("IOS"), "Mobile")
assert.Equal(t, constant.PlatformNameToClass("Android"), "Mobile")
assert.Equal(t, constant.PlatformNameToClass("OSX"), "PC")
assert.Equal(t, constant.PlatformNameToClass("Windows"), "PC")
assert.Equal(t, constant.PlatformNameToClass("Web"), "PC")
assert.Equal(t, constant.PlatformNameToClass("MiniWeb"), "Mobile")
assert.Equal(t, constant.PlatformNameToClass("Linux"), "PC")
assert.Equal(t, constant.PlatformNameToClass("UnknownDevice"), "")
assert.Equal(t, constant.PlatformNameToClass(""), "")
}
+43
View File
@@ -8,6 +8,7 @@ import (
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"math/rand"
"reflect"
"runtime"
"strconv"
"strings"
@@ -166,6 +167,7 @@ func Map2Pb(m map[string]string) (pb proto.Message, err error) {
}
return pb, nil
}
func Pb2Map(pb proto.Message) (map[string]interface{}, error) {
_buffer := bytes.Buffer{}
jsonbMarshaller := &jsonpb.Marshaler{
@@ -179,3 +181,44 @@ func Pb2Map(pb proto.Message) (map[string]interface{}, error) {
err := json.Unmarshal(jsonCnt, &out)
return out, err
}
func JsonDataList(resp interface{}) []map[string]interface{} {
var list []proto.Message
if reflect.TypeOf(resp).Kind() == reflect.Slice {
s := reflect.ValueOf(resp)
for i := 0; i < s.Len(); i++ {
ele := s.Index(i)
list = append(list, ele.Interface().(proto.Message))
}
}
result := make([]map[string]interface{}, 0)
for _, v := range list {
m := ProtoToMap(v, false)
result = append(result, m)
}
return result
}
func JsonDataOne(pb proto.Message) map[string]interface{} {
return ProtoToMap(pb, false)
}
func ProtoToMap(pb proto.Message, idFix bool) map[string]interface{} {
marshaler := jsonpb.Marshaler{
OrigName: true,
EnumsAsInts: false,
EmitDefaults: false,
}
s, _ := marshaler.MarshalToString(pb)
out := make(map[string]interface{})
json.Unmarshal([]byte(s), &out)
if idFix {
if _, ok := out["id"]; ok {
out["_id"] = out["id"]
delete(out, "id")
}
}
return out
}