Merge branch 'errcode' of github.com:OpenIMSDK/Open-IM-Server into errcode

 Conflicts:
	internal/push/sdk/tpns-server-sdk-go/go/auth/auth.go
	pkg/proto/group/group.proto
test-errcode
wangchuxiao 2 years ago
commit 6eb231aae4

@ -117,7 +117,7 @@ const docTemplate = `{
{
"type": "object",
"properties": {
"Data": {
"Map": {
"$ref": "#/definitions/api_struct.ExpireTime"
}
}
@ -4369,7 +4369,7 @@ const docTemplate = `{
{
"type": "object",
"properties": {
"Data": {
"Map": {
"type": "array",
"items": {
"$ref": "#/definitions/sdkws.PublicUserInfo"

@ -6,7 +6,6 @@ import (
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/common/tokenverify"
"Open_IM/pkg/getcdv3"
rpc "Open_IM/pkg/proto/auth"
open_im_sdk "Open_IM/pkg/proto/sdkws"
"Open_IM/pkg/utils"
@ -149,7 +148,7 @@ func UserToken(c *gin.Context) {
// @Param token header string true "im token"
// @Param req body api.ParseTokenReq true "secret为openIM密钥, 详细见服务端config.yaml secret字段<br>platform为平台ID"
// @Produce json
// @Success 0 {object} api.ParseTokenResp{Data=api.ExpireTime}
// @Success 0 {object} api.ParseTokenResp{Map=api.ExpireTime}
// @Failure 500 {object} api.Swagger500Resp "errCode为500 一般为服务器内部错误"
// @Failure 400 {object} api.Swagger400Resp "errCode为400 一般为参数输入错误, token未带上等"
// @Router /auth/parse_token [post]

@ -343,7 +343,7 @@ package friend
// utils.CopyStructFields(&black, v)
// resp.BlackUserInfoList = append(resp.BlackUserInfoList, &black)
// }
// resp.Data = jsonData.JsonDataList(resp.BlackUserInfoList)
// resp.Map = jsonData.JsonDataList(resp.BlackUserInfoList)
// log.NewInfo(req.CommID.OperationID, "GetBlacklist api return ", resp)
// c.JSON(http.StatusOK, resp)
//}
@ -561,7 +561,7 @@ package friend
// }
//
// resp := api.GetFriendListResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, FriendInfoList: RpcResp.FriendInfoList}
// resp.Data = jsonData.JsonDataList(resp.FriendInfoList)
// resp.Map = jsonData.JsonDataList(resp.FriendInfoList)
// log.NewInfo(req.CommID.OperationID, "GetFriendList api return ", resp)
// c.JSON(http.StatusOK, resp)
// //c.JSON(http.StatusOK, resp)
@ -618,7 +618,7 @@ package friend
// }
//
// resp := api.GetFriendApplyListResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, FriendRequestList: RpcResp.FriendRequestList}
// resp.Data = jsonData.JsonDataList(resp.FriendRequestList)
// resp.Map = jsonData.JsonDataList(resp.FriendRequestList)
// log.NewInfo(req.CommID.OperationID, "GetFriendApplyList api return ", resp)
// c.JSON(http.StatusOK, resp)
//}
@ -672,7 +672,7 @@ package friend
// return
// }
// resp := api.GetSelfApplyListResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, FriendRequestList: RpcResp.FriendRequestList}
// resp.Data = jsonData.JsonDataList(resp.FriendRequestList)
// resp.Map = jsonData.JsonDataList(resp.FriendRequestList)
// log.NewInfo(req.CommID.OperationID, "GetSelfApplyList api return ", resp)
// c.JSON(http.StatusOK, resp)
//}

@ -142,7 +142,7 @@ package group
// }
//
// memberListResp := api.GetGroupMembersInfoResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, MemberList: RpcResp.MemberList}
// memberListResp.Data = jsonData.JsonDataList(RpcResp.MemberList)
// memberListResp.Map = jsonData.JsonDataList(RpcResp.MemberList)
// log.NewInfo(req.OperationID, "GetGroupMembersInfo api return ", memberListResp)
// c.JSON(http.StatusOK, memberListResp)
//}
@ -186,7 +186,7 @@ package group
// }
//
// memberListResp := api.GetGroupMemberListResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, MemberList: RpcResp.MemberList, NextSeq: RpcResp.NextSeq}
// memberListResp.Data = jsonData.JsonDataList(memberListResp.MemberList)
// memberListResp.Map = jsonData.JsonDataList(memberListResp.MemberList)
//
// log.NewInfo(req.OperationID, "FindGroupMemberAll api return ", memberListResp)
// c.JSON(http.StatusOK, memberListResp)
@ -243,7 +243,7 @@ package group
// }
//
// memberListResp := api.GetGroupAllMemberResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, MemberList: RpcResp.MemberList}
// memberListResp.Data = jsonData.JsonDataList(memberListResp.MemberList)
// memberListResp.Map = jsonData.JsonDataList(memberListResp.MemberList)
// log.NewInfo(req.OperationID, "GetGroupAllMember api return ", len(memberListResp.MemberList))
// c.JSON(http.StatusOK, memberListResp)
//}
@ -298,7 +298,7 @@ package group
// }
//
// GroupListResp := api.GetJoinedGroupListResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, GroupInfoList: RpcResp.GroupList}
// GroupListResp.Data = jsonData.JsonDataList(GroupListResp.GroupInfoList)
// GroupListResp.Map = jsonData.JsonDataList(GroupListResp.GroupInfoList)
// log.NewInfo(req.OperationID, "FindJoinedGroup api return ", GroupListResp)
// c.JSON(http.StatusOK, GroupListResp)
//}
@ -437,7 +437,7 @@ package group
//// resp := api.CreateGroupResp{CommResp: api.CommResp{ErrCode: RpcResp.ErrCode, ErrMsg: RpcResp.ErrMsg}}
//// if RpcResp.ErrCode == 0 {
//// utils.CopyStructFields(&resp.GroupInfo, RpcResp.GroupInfo)
//// resp.Data = jsonData.JsonDataOne(&resp.GroupInfo)
//// resp.Map = jsonData.JsonDataOne(&resp.GroupInfo)
//// }
//// log.NewInfo(req.OperationID, "CreateGroup api return ", resp)
//// c.JSON(http.StatusOK, resp)
@ -496,7 +496,7 @@ package group
// }
//
// resp := api.GetGroupApplicationListResp{CommResp: api.CommResp{ErrCode: reply.CommonResp.ErrCode, ErrMsg: reply.CommonResp.ErrMsg}, GroupRequestList: reply.GroupRequestList}
// resp.Data = jsonData.JsonDataList(resp.GroupRequestList)
// resp.Map = jsonData.JsonDataList(resp.GroupRequestList)
// log.NewInfo(req.OperationID, "GetGroupApplicationList api return ", resp)
// c.JSON(http.StatusOK, resp)
//}
@ -567,7 +567,7 @@ package group
// }
//
// resp := api.GetGroupInfoResp{CommResp: api.CommResp{ErrCode: RpcResp.CommonResp.ErrCode, ErrMsg: RpcResp.CommonResp.ErrMsg}, GroupInfoList: RpcResp.GroupInfoList}
// resp.Data = jsonData.JsonDataList(resp.GroupInfoList)
// resp.Map = jsonData.JsonDataList(resp.GroupInfoList)
// log.NewInfo(req.OperationID, "GetGroupsInfo api return ", resp)
// c.JSON(http.StatusOK, resp)
//}

@ -4,8 +4,10 @@ import (
"Open_IM/pkg/api_struct"
"Open_IM/pkg/proto/group"
"context"
"errors"
"github.com/gin-gonic/gin"
"google.golang.org/grpc"
"reflect"
"testing"
)
@ -67,7 +69,8 @@ func KickGroupMember(c *gin.Context) {
// 默认 全部自动
NewRpc(NewApiBind[apistruct.KickGroupMemberReq, apistruct.KickGroupMemberResp](c), "", group.NewGroupClient, group.GroupClient.KickGroupMember).Execute()
// 可以自定义编辑请求和响应
NewRpc(NewApiBind[api_struct.KickGroupMemberReq, api_struct.KickGroupMemberResp](c), "", group.NewGroupClient, group.GroupClient.KickGroupMember).Before(func(apiReq *api_struct.KickGroupMemberReq, rpcReq *group.KickGroupMemberReq, bind func() error) error {
a := NewRpc(NewApiBind[api_struct.KickGroupMemberReq, api_struct.KickGroupMemberResp](c), "", group.NewGroupClient, group.GroupClient.KickGroupMember)
a.Before(func(apiReq *api_struct.KickGroupMemberReq, rpcReq *group.KickGroupMemberReq, bind func() error) error {
return bind()
}).After(func(rpcResp *group.KickGroupMemberResp, apiResp *api_struct.KickGroupMemberResp, bind func() error) error {
return bind()
@ -102,6 +105,22 @@ func (a *RpcRun[A, B, C, D, Z]) After(fn func(rpcResp D, apiResp *B, bind func()
return a
}
func (a *RpcRun[A, B, C, D, Z]) execute() (*B, error) {
userID, err := a.bind.OpUserID()
if err != nil {
return nil, err
}
opID := a.bind.OperationID()
var rpcReq C // C type => *Struct
rpcReq = reflect.New(reflect.TypeOf(rpcReq).Elem()).Interface().(C)
return nil, nil
}
func (a *RpcRun[A, B, C, D, Z]) Execute() {
}
func GetGrpcConn(name string) (*grpc.ClientConn, error) {
return nil, errors.New("todo")
}

@ -46,7 +46,7 @@ package group
// return
// }
// GroupListResp := api.GetJoinedSuperGroupListResp{GetJoinedGroupListResp: api.GetJoinedGroupListResp{CommResp: api.CommResp{ErrCode: rpcResp.CommonResp.ErrCode, ErrMsg: rpcResp.CommonResp.ErrMsg}, GroupInfoList: rpcResp.GroupList}}
// GroupListResp.Data = jsonData.JsonDataList(GroupListResp.GroupInfoList)
// GroupListResp.Map = jsonData.JsonDataList(GroupListResp.GroupInfoList)
// log.NewInfo(req.OperationID, "GetJoinedSuperGroupList api return ", GroupListResp)
// c.JSON(http.StatusOK, GroupListResp)
//}
@ -83,7 +83,7 @@ package group
// }
//
// resp := api.GetSuperGroupsInfoResp{GetGroupInfoResp: api.GetGroupInfoResp{CommResp: api.CommResp{ErrCode: rpcResp.CommonResp.ErrCode, ErrMsg: rpcResp.CommonResp.ErrMsg}, GroupInfoList: rpcResp.GroupInfoList}}
// resp.Data = jsonData.JsonDataList(resp.GroupInfoList)
// resp.Map = jsonData.JsonDataList(resp.GroupInfoList)
// log.NewInfo(req.OperationID, "GetGroupsInfo api return ", resp)
// c.JSON(http.StatusOK, resp)
//}

@ -13,7 +13,6 @@ import (
"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
"Open_IM/pkg/common/log"
"Open_IM/pkg/common/tokenverify"
"Open_IM/pkg/getcdv3"
pbChat "Open_IM/pkg/proto/msg"
open_im_sdk "Open_IM/pkg/proto/sdkws"
"Open_IM/pkg/utils"
@ -165,7 +164,7 @@ func ManagementSendMsg(c *gin.Context) {
}
if err := mapstructure.WeakDecode(params.Content, &data); err != nil {
c.JSON(http.StatusOK, gin.H{"errCode": 401, "errMsg": err.Error()})
log.Error(c.PostForm("operationID"), "content to Data struct err", err.Error())
log.Error(c.PostForm("operationID"), "content to Map struct err", err.Error())
return
} else if err := validate.Struct(data); err != nil {
c.JSON(http.StatusOK, gin.H{"errCode": 403, "errMsg": err.Error()})
@ -298,7 +297,7 @@ func ManagementBatchSendMsg(c *gin.Context) {
}
if err := mapstructure.WeakDecode(params.Content, &data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 401, "errMsg": err.Error()})
log.Error(c.PostForm("operationID"), "content to Data struct err", err.Error())
log.Error(c.PostForm("operationID"), "content to Map struct err", err.Error())
return
} else if err := validate.Struct(data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"errCode": 403, "errMsg": err.Error()})

@ -5,7 +5,6 @@ import (
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/log"
"Open_IM/pkg/common/tokenverify"
"Open_IM/pkg/getcdv3"
pbOffice "Open_IM/pkg/proto/office"
pbCommon "Open_IM/pkg/proto/sdkws"
"Open_IM/pkg/utils"
@ -565,7 +564,7 @@ func GetUserFriendWorkMoments(c *gin.Context) {
if err := utils.CopyStructFields(&resp, respPb.CommonResp); err != nil {
log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "CopyStructFields failed", err.Error())
}
//if err := utils.CopyStructFields(&resp.Data.WorkMoments, respPb.WorkMoments); err != nil {
//if err := utils.CopyStructFields(&resp.Map.WorkMoments, respPb.WorkMoments); err != nil {
// log.NewDebug(req.OperationID, utils.GetSelfFuncName(), "CopyStructFields failed", err.Error())
//}
resp.Data.WorkMoments = []*api.WorkMoment{}

@ -7,7 +7,6 @@ import (
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/log"
"Open_IM/pkg/common/tokenverify"
"Open_IM/pkg/getcdv3"
cacheRpc "Open_IM/pkg/proto/cache"
pbRelay "Open_IM/pkg/proto/relay"
open_im_sdk "Open_IM/pkg/proto/sdkws"
@ -156,7 +155,7 @@ func GetBlackIDListFromCache(c *gin.Context) {
// @Param token header string true "im token"
// @Param req body api.GetUsersInfoReq true "请求体"
// @Produce json
// @Success 0 {object} api.GetUsersInfoResp{Data=[]open_im_sdk.PublicUserInfo}
// @Success 0 {object} api.GetUsersInfoResp{Map=[]open_im_sdk.PublicUserInfo}
// @Failure 500 {object} api.Swagger500Resp "errCode为500 一般为服务器内部错误"
// @Failure 400 {object} api.Swagger400Resp "errCode为400 一般为参数输入错误, token未带上等"
// @Router /user/get_users_info [post]

@ -36,6 +36,7 @@ func NewRpcServer(registerIPInConfig string, port int, registerName string, zkSe
return nil, err
}
s.RegisterCenter = zkClient
return s, nil
}

@ -62,7 +62,7 @@ func (ws *WServer) argsValidate(m *Req, r int32, operationID string) (isPass boo
case constant.WSGetNewestSeq:
data := open_im_sdk.GetMaxAndMinSeqReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.Error(operationID, "Decode Data struct err", err.Error(), r)
log.Error(operationID, "Decode Map struct err", err.Error(), r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
@ -74,7 +74,7 @@ func (ws *WServer) argsValidate(m *Req, r int32, operationID string) (isPass boo
case constant.WSSendMsg:
data := open_im_sdk.MsgData{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.Error(operationID, "Decode Data struct err", err.Error(), r)
log.Error(operationID, "Decode Map struct err", err.Error(), r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
@ -86,7 +86,7 @@ func (ws *WServer) argsValidate(m *Req, r int32, operationID string) (isPass boo
case constant.WSSendSignalMsg:
data := pbRtc.SignalReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.Error(operationID, "Decode Data struct err", err.Error(), r)
log.Error(operationID, "Decode Map struct err", err.Error(), r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
@ -98,7 +98,7 @@ func (ws *WServer) argsValidate(m *Req, r int32, operationID string) (isPass boo
case constant.WSPullMsgBySeqList:
data := open_im_sdk.PullMessageBySeqListReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.Error(operationID, "Decode Data struct err", err.Error(), r)
log.Error(operationID, "Decode Map struct err", err.Error(), r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {
@ -110,7 +110,7 @@ func (ws *WServer) argsValidate(m *Req, r int32, operationID string) (isPass boo
case constant.WsSetBackgroundStatus:
data := open_im_sdk.SetAppBackgroundStatusReq{}
if err := proto.Unmarshal(m.Data, &data); err != nil {
log.Error(operationID, "Decode Data struct err", err.Error(), r)
log.Error(operationID, "Decode Map struct err", err.Error(), r)
return false, 203, err.Error(), nil
}
if err := validate.Struct(data); err != nil {

@ -0,0 +1,62 @@
package auth
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
b64 "encoding/base64"
"encoding/hex"
"fmt"
"net/http"
"strconv"
"time"
)
type Auther struct {
AccessID string
SecretKey string
}
var UseSignAuthored = true
func (a *Auther) Auth(req *http.Request, useSignAuthored bool, auth Auther, reqBody string) {
if useSignAuthored {
now := time.Now()
timeStamp := now.Unix()
req.Header.Add("AccessId", auth.AccessID)
req.Header.Add("TimeStamp", strconv.Itoa(int(timeStamp)))
sign := GenSign(uint64(timeStamp), auth.AccessID, auth.SecretKey, reqBody)
req.Header.Add("Sign", sign)
} else {
author := makeAuthHeader(a.AccessID, a.SecretKey)
//log.Printf("author string:%v", author)
req.Header.Add("Authorization", author)
}
//req.Header.Add("Content-Type", "application/json")
}
func makeAuthHeader(appID, secretKey string) string {
base64Str := base64.StdEncoding.EncodeToString(
[]byte(
fmt.Sprintf("%s:%s", appID, secretKey),
),
)
return fmt.Sprintf("Basic %s", base64Str)
}
func GenSign(timeStamp uint64, accessId string, secretKey, requestBody string) string {
signBody := strconv.Itoa(int(timeStamp)) + accessId + requestBody
// Create a new HMAC by defining the hash type and the key (as byte array)
h := hmac.New(sha256.New, []byte(secretKey))
// Write Map to it
h.Write([]byte(signBody))
// Get result and encode as hexadecimal string
sha := hex.EncodeToString(h.Sum(nil))
//fmt.Println()
//fmt.Println("timeStamp: " + strconv.Itoa(int(timeStamp)) + " accessID:" + accessId + " body:" + requestBody)
sEnc := b64.StdEncoding.EncodeToString([]byte(sha))
//fmt.Println("final Result " + sEnc)
return sEnc
}

@ -5,6 +5,7 @@ import (
"Open_IM/internal/common/rpc_server"
"Open_IM/pkg/common/config"
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/db/cache"
"Open_IM/pkg/common/db/controller"
"Open_IM/pkg/common/log"
promePkg "Open_IM/pkg/common/prometheus"
@ -23,8 +24,11 @@ func NewRpcAuthServer(port int) *rpcAuth {
if err != nil {
panic(err)
}
var redis cache.RedisClient
redis.InitRedis()
return &rpcAuth{
RpcServer: r,
RpcServer: r,
AuthInterface: controller.NewAuthController(redis.GetClient(), config.Config.TokenPolicy.AccessSecret, config.Config.TokenPolicy.AccessExpire),
}
}
@ -64,7 +68,7 @@ func (s *rpcAuth) UserToken(ctx context.Context, req *pbAuth.UserTokenReq) (*pbA
if _, err := check.GetUsersInfo(ctx, req.UserID); err != nil {
return nil, err
}
token, err := s.CreateToken(ctx, req.UserID, int(req.PlatformID), config.Config.TokenPolicy.AccessExpire)
token, err := s.CreateToken(ctx, req.UserID, constant.PlatformIDToName(int(req.PlatformID)))
if err != nil {
return nil, err
}
@ -73,39 +77,41 @@ func (s *rpcAuth) UserToken(ctx context.Context, req *pbAuth.UserTokenReq) (*pbA
return &resp, nil
}
func (s *rpcAuth) parseToken(ctx context.Context, tokensString, operationID string) (claims *tokenverify.Claims, err error) {
func (s *rpcAuth) parseToken(ctx context.Context, tokensString string) (claims *tokenverify.Claims, err error) {
claims, err = tokenverify.GetClaimFromToken(tokensString)
if err != nil {
return nil, utils.Wrap(err, "")
}
m, err := s.GetTokens(ctx, claims.UID, claims.Platform)
m, err := s.GetTokensWithoutError(ctx, claims.UID, claims.Platform)
if err != nil {
return nil, err
}
if len(m) == 0 {
return nil, constant.ErrTokenNotExist.Wrap()
}
if v, ok := m[tokensString]; ok {
switch v {
case constant.NormalToken:
return claims, nil
case constant.KickedToken:
return nil, utils.Wrap(constant.ErrTokenKicked, "this token has been kicked by other same terminal ")
return nil, constant.ErrTokenKicked.Wrap()
default:
return nil, utils.Wrap(constant.ErrTokenUnknown, "")
}
}
return nil, utils.Wrap(constant.ErrTokenNotExist, "redis token map not find")
return nil, constant.ErrTokenNotExist.Wrap()
}
func (s *rpcAuth) ParseToken(ctx context.Context, req *pbAuth.ParseTokenReq) (*pbAuth.ParseTokenResp, error) {
resp := pbAuth.ParseTokenResp{}
claims, err := s.parseToken(ctx, req.Token, req.OperationID)
func (s *rpcAuth) ParseToken(ctx context.Context, req *pbAuth.ParseTokenReq) (resp *pbAuth.ParseTokenResp, err error) {
resp = &pbAuth.ParseTokenResp{}
claims, err := s.parseToken(ctx, req.Token)
if err != nil {
return nil, err
}
resp.UserID = claims.UID
resp.Platform = claims.Platform
resp.ExpireTimeSeconds = claims.ExpiresAt.Unix()
return &resp, nil
return resp, nil
}
func (s *rpcAuth) ForceLogout(ctx context.Context, req *pbAuth.ForceLogoutReq) (*pbAuth.ForceLogoutResp, error) {

@ -119,7 +119,7 @@ func CallbackBeforeMemberJoinGroup(ctx context.Context, operationID string, grou
return err
}
func CallbackBeforeSetGroupMemberInfo(ctx context.Context, req *pbGroup.SetGroupMemberInfoReq) (err error) {
func CallbackBeforeSetGroupMemberInfo(ctx context.Context, req *pbGroup.SetGroupMemberInfo) (err error) {
defer func() {
tracelog.SetCtxInfo(ctx, utils.GetFuncName(1), err, "req", *req)
}()

@ -84,7 +84,7 @@ func DbToPbGroupRequest(m *relation.GroupRequestModel, user *open_im_sdk.PublicU
func DbToPbGroupAbstractInfo(groupID string, groupMemberNumber int32, groupMemberListHash uint64) *pbGroup.GroupAbstractInfo {
return &pbGroup.GroupAbstractInfo{
GroupID: groupID,
GroupMemberNumber: groupMemberNumber,
GroupMemberNumber: uint32(groupMemberNumber),
GroupMemberListHash: groupMemberListHash,
}
}

@ -44,7 +44,7 @@ func UpdateGroupMemberMutedTimeMap(t time.Time) map[string]any {
}
}
func UpdateGroupMemberMap(req *pbGroup.SetGroupMemberInfoReq) map[string]any {
func UpdateGroupMemberMap(req *pbGroup.SetGroupMemberInfo) map[string]any {
m := make(map[string]any)
if req.Nickname != nil {
m["nickname"] = req.Nickname.Value

@ -30,7 +30,6 @@ import (
"github.com/OpenIMSDK/openKeeper"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/wrapperspb"
)
type groupServer struct {
@ -75,7 +74,7 @@ func NewGroupServer(port int) *groupServer {
//conns, err := g.registerCenter.GetConns(config.Config.RpcRegisterName.OpenImConversationName)
g.GroupInterface = controller.NewGroupInterface(controller.NewGroupDatabase(mysql.GormConn(), redis.GetClient(), mongo.GetClient()))
g.GroupInterface = controller.NewGroupInterface(mysql.GormConn(), redis.GetClient(), mongo.GetClient())
return &g
}
@ -191,7 +190,7 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbGroup.CreateGroupR
}
}
}
if err := s.GroupInterface.CreateGroup(ctx, []*relation.GroupModel{group}, groupMembers); err != nil {
if err := s.GroupInterface.CreateGroup(ctx, []*relationTb.GroupModel{group}, groupMembers); err != nil {
return nil, err
}
resp.GroupInfo = DbToPbGroupInfo(group, req.OwnerUserID, uint32(len(userIDs)))
@ -287,9 +286,9 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbGroup.Invite
return nil, constant.ErrNoPermission.Wrap("not in group")
}
if !(member.RoleLevel == constant.GroupOwner || member.RoleLevel == constant.GroupAdmin) {
var requests []*relation.GroupRequestModel
var requests []*relationTb.GroupRequestModel
for _, userID := range req.InvitedUserIDs {
requests = append(requests, &relation.GroupRequestModel{
requests = append(requests, &relationTb.GroupRequestModel{
UserID: userID,
GroupID: req.GroupID,
JoinSource: constant.JoinByInvitation,
@ -951,50 +950,79 @@ func (s *groupServer) CancelMuteGroup(ctx context.Context, req *pbGroup.CancelMu
return resp, nil
}
func (s *groupServer) SetGroupMemberNickname(ctx context.Context, req *pbGroup.SetGroupMemberNicknameReq) (*pbGroup.SetGroupMemberNicknameResp, error) {
_, err := s.SetGroupMemberInfo(ctx, &pbGroup.SetGroupMemberInfoReq{GroupID: req.GroupID, UserID: req.UserID, Nickname: wrapperspb.String(req.Nickname)})
if err != nil {
return nil, err
}
return &pbGroup.SetGroupMemberNicknameResp{}, nil
}
func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbGroup.SetGroupMemberInfoReq) (*pbGroup.SetGroupMemberInfoResp, error) {
resp := &pbGroup.SetGroupMemberInfoResp{}
if req.RoleLevel != nil && req.RoleLevel.Value == constant.GroupOwner {
return nil, constant.ErrNoPermission.Wrap("set group owner")
if len(req.Members) == 0 {
return nil, constant.ErrArgs.Wrap("members empty")
}
group, err := s.GroupInterface.TakeGroup(ctx, req.GroupID)
duplicateMap := make(map[[2]string]struct{})
userIDMap := make(map[string]struct{})
groupIDMap := make(map[string]struct{})
for _, member := range req.Members {
key := [...]string{member.GroupID, member.UserID}
if _, ok := duplicateMap[key]; ok {
return nil, constant.ErrArgs.Wrap("group user duplicate")
}
duplicateMap[key] = struct{}{}
userIDMap[member.UserID] = struct{}{}
groupIDMap[member.GroupID] = struct{}{}
}
groupIDs := utils.Keys(groupIDMap)
userIDs := utils.Keys(userIDMap)
members, err := s.GroupInterface.FindGroupMember(ctx, groupIDs, append(userIDs, tracelog.GetOpUserID(ctx)), nil)
if err != nil {
return nil, err
}
if group.Status == constant.GroupStatusDismissed {
return nil, constant.ErrArgs.Wrap("group status is dismissed")
for _, member := range members {
delete(duplicateMap, [...]string{member.GroupID, member.UserID})
}
member, err := s.GroupInterface.TakeGroupMember(ctx, req.GroupID, req.UserID)
if err != nil {
return nil, err
if len(duplicateMap) > 0 {
return nil, constant.ErrArgs.Wrap("group not found or user not in group")
}
if tracelog.GetOpUserID(ctx) == req.UserID {
if req.RoleLevel != nil {
return nil, constant.ErrArgs.Wrap("update role level")
memberMap := utils.SliceToMap(members, func(e *relationTb.GroupMemberModel) [2]string {
return [...]string{e.GroupID, e.UserID}
})
if !tokenverify.IsAppManagerUid(ctx) {
opUserID := tracelog.GetOpUserID(ctx)
for _, member := range members {
if member.UserID == opUserID {
continue
}
opMember, ok := memberMap[[...]string{member.GroupID, member.UserID}]
if !ok {
return nil, constant.ErrArgs.Wrap(fmt.Sprintf("user %s not in group %s", opUserID, member.GroupID))
}
if member.RoleLevel >= opMember.RoleLevel {
return nil, constant.ErrNoPermission.Wrap(fmt.Sprintf("group %s : %s RoleLevel %d >= %s RoleLevel %d", member.GroupID, member.UserID, member.RoleLevel, opMember.UserID, opMember.RoleLevel))
}
}
} else if !tokenverify.IsAppManagerUid(ctx) {
opMember, err := s.GroupInterface.TakeGroupMember(ctx, req.GroupID, tracelog.GetOpUserID(ctx))
if err != nil {
return nil, err
}
for _, member := range req.Members {
if member.RoleLevel == nil {
continue
}
if opMember.RoleLevel <= member.RoleLevel {
return nil, constant.ErrNoPermission.Wrap(fmt.Sprintf("self RoleLevel %d target %d", opMember.RoleLevel, member.RoleLevel))
if memberMap[[...]string{member.GroupID, member.UserID}].RoleLevel == constant.GroupOwner {
return nil, constant.ErrArgs.Wrap(fmt.Sprintf("group %s user %s is owner", member.GroupID, member.UserID))
}
}
if err := CallbackBeforeSetGroupMemberInfo(ctx, req); err != nil {
return nil, err
for i := 0; i < len(req.Members); i++ {
if err := CallbackBeforeSetGroupMemberInfo(ctx, req.Members[i]); err != nil {
return nil, err
}
}
if err := s.GroupInterface.UpdateGroupMember(ctx, req.GroupID, req.UserID, UpdateGroupMemberMap(req)); err != nil {
err = s.GroupInterface.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbGroup.SetGroupMemberInfo) *controller.BatchUpdateGroupMember {
return &controller.BatchUpdateGroupMember{
GroupID: e.GroupID,
UserID: e.UserID,
Map: UpdateGroupMemberMap(e),
}
}))
if err != nil {
return nil, err
}
chat.GroupMemberInfoSetNotification(tracelog.GetOperationID(ctx), tracelog.GetOpUserID(ctx), req.GroupID, req.UserID)
for _, member := range req.Members {
chat.GroupMemberInfoSetNotification(tracelog.GetOperationID(ctx), tracelog.GetOpUserID(ctx), member.GroupID, member.UserID)
}
return resp, nil
}
@ -1038,3 +1066,13 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbGroup.Ge
})
return resp, nil
}
func (s *groupServer) GetGroupMemberUserID(ctx context.Context, req *pbGroup.GetGroupMemberUserIDReq) (*pbGroup.GetGroupMemberUserIDResp, error) {
resp := &pbGroup.GetGroupMemberUserIDResp{}
userIDs, err := s.GroupInterface.FindGroupMemberUserID(ctx, req.GroupID)
if err != nil {
return nil, err
}
resp.UserIDs = userIDs
return resp, nil
}

@ -58,7 +58,7 @@ package apistruct
//type GetBlackListResp struct {
// CommResp
// BlackUserInfoList []*open_im_sdk.PublicUserInfo `json:"-"`
// Data []map[string]interface{} `json:"data" swaggerignore:"true"`
// Map []map[string]interface{} `json:"data" swaggerignore:"true"`
//}
//
////type PublicUserInfo struct {
@ -100,7 +100,7 @@ package apistruct
//type GetFriendsInfoResp struct {
// CommResp
// FriendInfoList []*open_im_sdk.FriendInfo `json:"-"`
// Data []map[string]interface{} `json:"data" swaggerignore:"true"`
// Map []map[string]interface{} `json:"data" swaggerignore:"true"`
//}
//
//type GetFriendListReq struct {
@ -110,7 +110,7 @@ package apistruct
//type GetFriendListResp struct {
// CommResp
// FriendInfoList []*open_im_sdk.FriendInfo `json:"-"`
// Data []map[string]interface{} `json:"data" swaggerignore:"true"`
// Map []map[string]interface{} `json:"data" swaggerignore:"true"`
//}
//
//type GetFriendApplyListReq struct {
@ -120,7 +120,7 @@ package apistruct
//type GetFriendApplyListResp struct {
// CommResp
// FriendRequestList []*open_im_sdk.FriendRequest `json:"-"`
// Data []map[string]interface{} `json:"data" swaggerignore:"true"`
// Map []map[string]interface{} `json:"data" swaggerignore:"true"`
//}
//
//type GetSelfApplyListReq struct {
@ -130,7 +130,7 @@ package apistruct
//type GetSelfApplyListResp struct {
// CommResp
// FriendRequestList []*open_im_sdk.FriendRequest `json:"-"`
// Data []map[string]interface{} `json:"data" swaggerignore:"true"`
// Map []map[string]interface{} `json:"data" swaggerignore:"true"`
//}
type FriendInfo struct {

@ -92,7 +92,7 @@ type GetGroupAllMemberResp struct {
//type GetGroupAllMemberListBySplitResp struct {
// CommResp
// MemberList []*open_im_sdk.GroupMemberFullInfo `json:"-"`
// Data []map[string]interface{} `json:"data" swaggerignore:"true"`
// Map []map[string]interface{} `json:"data" swaggerignore:"true"`
//}
type CreateGroupReq struct {

@ -621,15 +621,6 @@ func initConfig(config interface{}, configName, configPath string) {
func InitConfig(configPath string) {
initConfig(&Config, "config.yaml", configPath)
initConfig(&UsualConfig, "usualConfig.yaml", configPath)
if Config.Etcd.UserName == "" {
Config.Etcd.UserName = UsualConfig.Etcd.UserName
}
if Config.Etcd.Password == "" {
Config.Etcd.Password = UsualConfig.Etcd.Password
}
if Config.Etcd.Secret == "" {
Config.Etcd.Secret = UsualConfig.Etcd.Secret
}
if Config.Mysql.DBUserName == "" {
Config.Mysql.DBUserName = UsualConfig.Mysql.DBUserName

@ -148,29 +148,6 @@ func (c *ConversationRedis) GetUserConversationIDs1(ctx context.Context, ownerUs
// return t, nil
//}
func GetCache[T any](ctx context.Context, rcClient *rockscache.Client, key string, expire time.Duration, fn func(ctx context.Context) (T, error)) (T, error) {
v, err := rcClient.Fetch(key, expire, func() (string, error) {
v, err := fn(ctx)
if err != nil {
return "", err
}
bs, err := json.Marshal(v)
if err != nil {
return "", utils.Wrap(err, "")
}
return string(bs), nil
})
var t T
if err != nil {
return t, err
}
err = json.Unmarshal([]byte(v), &t)
if err != nil {
return t, utils.Wrap(err, "")
}
return t, nil
}
func (c *ConversationRedis) DelUserConversationIDs(ctx context.Context, ownerUserID string) (err error) {
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "ownerUserID", ownerUserID)

@ -37,19 +37,18 @@ type GroupCache interface {
BatchDelJoinedSuperGroupIDs(ctx context.Context, userIDs []string, fn func(ctx context.Context, userIDs []string) error) (err error)
GetJoinedSuperGroupIDs(ctx context.Context, userID string, fn func(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error)) (joinedSuperGroupIDs []string, err error)
DelJoinedSuperGroupIDs(ctx context.Context, userID string, fn func(ctx context.Context, userID string) error) (err error)
DelJoinedSuperGroupIDs(ctx context.Context, userID string) (err error)
GetGroupMembersHash(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (hashCodeUint64 uint64, err error)) (hashCodeUint64 uint64, err error)
DelGroupMembersHash(ctx context.Context, groupID string) (err error)
GetGroupMemberIDs(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (groupMemberIDs []string, err error)) (groupMemberIDs []string, err error)
DelGroupMemberIDs(ctx context.Context, groupID string)
DelGroupMemberIDs(ctx context.Context, groupID string) error
GetJoinedGroupIDs(ctx context.Context, userID string, fn func(ctx context.Context, userID string) (joinedGroupIDs []string, err error)) (joinedGroupIDs []string, err error)
DelJoinedGroupIDs(ctx context.Context, userID string) (err error)
GetGroupMemberInfo(ctx context.Context, groupID, userID string, fn func(ctx context.Context, groupID, userID string) (groupMember *relationTb.GroupMemberModel, err error)) (groupMember *relationTb.GroupMemberModel, err error)
GetGroupMembersInfo(ctx context.Context, count, offset int32, groupID string, fn func(ctx context.Context, count, offset int32, groupID string) (groupMembers []*relationTb.GroupMemberModel, err error)) (groupMembers []*relationTb.GroupMemberModel, err error)
DelGroupMemberInfo(ctx context.Context, groupID, userID string) (err error)
GetGroupMemberNum(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (num int, err error)) (num int, err error)
@ -57,16 +56,16 @@ type GroupCache interface {
}
type GroupCacheRedis struct {
group *relation.GroupGorm
groupMember *relation.GroupMemberGorm
groupRequest *relation.GroupRequestGorm
group relationTb.GroupModelInterface
groupMember relationTb.GroupMemberModelInterface
groupRequest relationTb.GroupRequestModelInterface
mongoDB *unrelation.SuperGroupMongoDriver
expireTime time.Duration
redisClient *RedisClient
rcClient *rockscache.Client
}
func NewGroupCacheRedis(rdb redis.UniversalClient, groupDB *relation.GroupGorm, groupMemberDB *relation.GroupMemberGorm, groupRequestDB *relation.GroupRequestGorm, mongoClient *unrelation.SuperGroupMongoDriver, opts rockscache.Options) *GroupCacheRedis {
func NewGroupCacheRedis(rdb redis.UniversalClient, groupDB relationTb.GroupModelInterface, groupMemberDB relationTb.GroupMemberModelInterface, groupRequestDB relationTb.GroupRequestModelInterface, mongoClient *unrelation.SuperGroupMongoDriver, opts rockscache.Options) *GroupCacheRedis {
return &GroupCacheRedis{rcClient: rockscache.NewClient(rdb, opts), expireTime: groupExpireTime,
group: groupDB, groupMember: groupMemberDB, groupRequest: groupRequestDB, redisClient: NewRedisClient(rdb),
mongoDB: mongoClient,
@ -106,39 +105,16 @@ func (g *GroupCacheRedis) getGroupMemberNumKey(groupID string) string {
}
// / groupInfo
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relation.Group, err error) {
for _, groupID := range groupIDs {
group, err := g.GetGroupInfo(ctx, groupID)
if err != nil {
return nil, err
}
groups = append(groups, group)
}
return groups, nil
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationTb.GroupModel, err error) {
return GetCacheFor(ctx, g.rcClient, groupIDs, func(ctx context.Context, groupID string) (*relationTb.GroupModel, error) {
return g.GetGroupInfo(ctx, groupID)
})
}
func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID string) (group *relation.GroupGorm, err error) {
getGroup := func() (string, error) {
groupInfo, err := g.group.Take(ctx, groupID)
if err != nil {
return "", utils.Wrap(err, "")
}
bytes, err := json.Marshal(groupInfo)
if err != nil {
return "", utils.Wrap(err, "")
}
return string(bytes), nil
}
group = &relation.GroupGorm{}
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "group", *group)
}()
groupStr, err := g.rcClient.Fetch(g.getGroupInfoKey(groupID), g.expireTime, getGroup)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(groupStr), group)
return group, utils.Wrap(err, "")
func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID string) (group *relationTb.GroupModel, err error) {
return GetCache(ctx, g.rcClient, g.getGroupInfoKey(groupID), g.expireTime, func(ctx context.Context) (*relationTb.GroupModel, error) {
return g.group.Take(ctx, groupID)
})
}
func (g *GroupCacheRedis) DelGroupInfo(ctx context.Context, groupID string) (err error) {
@ -339,6 +315,11 @@ func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userI
return groupMember, utils.Wrap(err, "")
}
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID, userIDs []string) (groupMember *relationTb.GroupMemberModel, err error) {
return nil, err
}
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, count, offset int32, groupID string) (groupMembers []*relation.GroupMember, err error) {
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "count", count, "offset", offset, "groupID", groupID, "groupMember", groupMembers)

@ -20,10 +20,10 @@ import (
)
const (
userIncrSeq = "REDIS_USER_INCR_SEQ:" // user incr seq
appleDeviceToken = "DEVICE_TOKEN"
userMinSeq = "REDIS_USER_MIN_SEQ:"
uidPidToken = "UID_PID_TOKEN_STATUS:"
userIncrSeq = "REDIS_USER_INCR_SEQ:" // user incr seq
appleDeviceToken = "DEVICE_TOKEN"
userMinSeq = "REDIS_USER_MIN_SEQ:"
getuiToken = "GETUI_TOKEN"
getuiTaskID = "GETUI_TASK_ID"
messageCache = "MESSAGE_CACHE:"
@ -94,33 +94,33 @@ func NewRedisClient(rdb redis.UniversalClient) *RedisClient {
return &RedisClient{rdb: rdb}
}
//Perform seq auto-increment operation of user messages
// Perform seq auto-increment operation of user messages
func (r *RedisClient) IncrUserSeq(uid string) (uint64, error) {
key := userIncrSeq + uid
seq, err := r.rdb.Incr(context.Background(), key).Result()
return uint64(seq), err
}
//Get the largest Seq
// Get the largest Seq
func (r *RedisClient) GetUserMaxSeq(uid string) (uint64, error) {
key := userIncrSeq + uid
seq, err := r.rdb.Get(context.Background(), key).Result()
return uint64(utils.StringToInt(seq)), err
}
//set the largest Seq
// set the largest Seq
func (r *RedisClient) SetUserMaxSeq(uid string, maxSeq uint64) error {
key := userIncrSeq + uid
return r.rdb.Set(context.Background(), key, maxSeq, 0).Err()
}
//Set the user's minimum seq
// Set the user's minimum seq
func (r *RedisClient) SetUserMinSeq(uid string, minSeq uint32) (err error) {
key := userMinSeq + uid
return r.rdb.Set(context.Background(), key, minSeq, 0).Err()
}
//Get the smallest Seq
// Get the smallest Seq
func (r *RedisClient) GetUserMinSeq(uid string) (uint64, error) {
key := userMinSeq + uid
seq, err := r.rdb.Get(context.Background(), key).Result()
@ -159,7 +159,7 @@ func (r *RedisClient) SetGroupMinSeq(groupID string, minSeq uint32) error {
return r.rdb.Set(context.Background(), key, minSeq, 0).Err()
}
//Store userid and platform class to redis
// Store userid and platform class to redis
func (r *RedisClient) AddTokenFlag(userID string, platformID int, token string, flag int) error {
key := uidPidToken + userID + ":" + constant.PlatformIDToName(platformID)
log2.NewDebug("", "add token key is ", key)

@ -0,0 +1,75 @@
package cache
import (
"Open_IM/pkg/common/constant"
"Open_IM/pkg/common/tokenverify"
"Open_IM/pkg/utils"
"context"
go_redis "github.com/go-redis/redis/v8"
"github.com/golang-jwt/jwt/v4"
)
const (
uidPidToken = "UID_PID_TOKEN_STATUS:"
)
type Token interface {
//结果为空 不返回错误
GetTokensWithoutError(ctx context.Context, userID, platform string) (map[string]int, error)
//创建token
CreateToken(ctx context.Context, userID string, platformID int) (string, error)
}
type TokenRedis struct {
RedisClient *RedisClient
AccessSecret string
AccessExpire int64
}
func NewTokenRedis(redisClient *RedisClient, accessSecret string, accessExpire int64) *TokenRedis {
return &TokenRedis{redisClient, accessSecret, accessExpire}
}
// 结果为空 不返回错误
func (t *TokenRedis) GetTokensWithoutError(ctx context.Context, userID, platform string) (map[string]int, error) {
key := uidPidToken + userID + ":" + platform
m, err := t.RedisClient.GetClient().HGetAll(context.Background(), key).Result()
if err != nil && err == go_redis.Nil {
return nil, nil
}
mm := make(map[string]int)
for k, v := range m {
mm[k] = utils.StringToInt(v)
}
return mm, utils.Wrap(err, "")
}
// 创建token
func (t *TokenRedis) CreateToken(ctx context.Context, userID string, platform string) (string, error) {
tokens, err := t.GetTokensWithoutError(ctx, userID, platform)
if err != nil {
return "", err
}
var deleteTokenKey []string
for k, v := range tokens {
_, err = tokenverify.GetClaimFromToken(k)
if err != nil || v != constant.NormalToken {
deleteTokenKey = append(deleteTokenKey, k)
}
}
if len(deleteTokenKey) != 0 {
key := uidPidToken + userID + ":" + platform
err := t.RedisClient.GetClient().HDel(context.Background(), key, deleteTokenKey...).Err()
if err != nil {
return "", err
}
}
claims := tokenverify.BuildClaims(userID, platform, t.AccessExpire)
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(t.AccessSecret))
if err != nil {
return "", utils.Wrap(err, "")
}
key := uidPidToken + userID + ":" + platform
return "", utils.Wrap(t.RedisClient.GetClient().HSet(context.Background(), key, tokenString, constant.NormalToken).Err(), "")
}

@ -0,0 +1,49 @@
package cache
import (
"Open_IM/pkg/utils"
"context"
"encoding/json"
"github.com/dtm-labs/rockscache"
"time"
)
func GetCache[T any](ctx context.Context, rcClient *rockscache.Client, key string, expire time.Duration, fn func(ctx context.Context) (T, error)) (T, error) {
var t T
var write bool
v, err := rcClient.Fetch(key, expire, func() (s string, err error) {
t, err = fn(ctx)
if err != nil {
return "", err
}
bs, err := json.Marshal(t)
if err != nil {
return "", utils.Wrap(err, "")
}
write = true
return string(bs), nil
})
if err != nil {
return t, err
}
if write {
return t, nil
}
err = json.Unmarshal([]byte(v), &t)
if err != nil {
return t, utils.Wrap(err, "")
}
return t, nil
}
func GetCacheFor[E any, T any](ctx context.Context, rcClient *rockscache.Client, list []E, fn func(ctx context.Context, item E) (T, error)) ([]T, error) {
rs := make([]T, 0, len(list))
for _, e := range list {
r, err := fn(ctx, e)
if err != nil {
return nil, err
}
rs = append(rs, r)
}
return rs, nil
}

@ -1,9 +1,34 @@
package controller
import "context"
import (
"Open_IM/pkg/common/db/cache"
"context"
"github.com/go-redis/redis/v8"
)
type AuthInterface interface {
GetTokens(ctx context.Context, userID, platform string) (map[string]int, error)
DeleteToken(ctx context.Context, userID, platform string) error
CreateToken(ctx context.Context, userID string, platformID int, ttl int64) (string, error)
//结果为空 不返回错误
GetTokensWithoutError(ctx context.Context, userID, platform string) (map[string]int, error)
//创建token
CreateToken(ctx context.Context, userID string, platform string) (string, error)
}
type AuthController struct {
database *cache.TokenRedis
}
func NewAuthController(rdb redis.UniversalClient, accessSecret string, accessExpire int64) *AuthController {
cache.NewRedisClient(rdb)
return &AuthController{database: cache.NewTokenRedis(cache.NewRedisClient(rdb), accessSecret, accessExpire)}
}
// 结果为空 不返回错误
func (a *AuthController) GetTokensWithoutError(ctx context.Context, userID, platform string) (map[string]int, error) {
return a.database.GetTokensWithoutError(ctx, userID, platform)
}
// 创建token
func (a *AuthController) CreateToken(ctx context.Context, userID string, platform string) (string, error) {
return a.database.CreateToken(ctx, userID, platform)
}

@ -19,6 +19,12 @@ import (
//type GroupInterface GroupDataBaseInterface
type BatchUpdateGroupMember struct {
GroupID string
UserID string
Map map[string]any
}
type GroupInterface interface {
CreateGroup(ctx context.Context, groups []*relationTb.GroupModel, groupMembers []*relationTb.GroupMemberModel) error
TakeGroup(ctx context.Context, groupID string) (group *relationTb.GroupModel, err error)
@ -30,6 +36,7 @@ type GroupInterface interface {
TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationTb.GroupMemberModel, err error)
TakeGroupOwner(ctx context.Context, groupID string) (*relationTb.GroupMemberModel, error)
FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationTb.GroupMemberModel, error)
FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
PageGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationTb.GroupMemberModel, error)
SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationTb.GroupMemberModel, error)
HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationTb.GroupMemberModel) error
@ -37,7 +44,8 @@ type GroupInterface interface {
MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string][]string, error)
MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error)
TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error // 转让群
UpdateGroupMember(ctx context.Context, groupID, userID string, data map[string]any) error
UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error
UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error
// GroupRequest
CreateGroupRequest(ctx context.Context, requests []*relationTb.GroupRequestModel) error
TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationTb.GroupRequestModel, error)
@ -61,6 +69,10 @@ type GroupController struct {
database GroupDataBaseInterface
}
func (g *GroupController) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
return g.database.FindGroupMemberUserID(ctx, groupID)
}
func (g *GroupController) CreateGroup(ctx context.Context, groups []*relationTb.GroupModel, groupMembers []*relationTb.GroupMemberModel) error {
return g.database.CreateGroup(ctx, groups, groupMembers)
}
@ -125,7 +137,11 @@ func (g *GroupController) TransferGroupOwner(ctx context.Context, groupID string
return g.database.TransferGroupOwner(ctx, groupID, oldOwnerUserID, newOwnerUserID, roleLevel)
}
func (g *GroupController) UpdateGroupMember(ctx context.Context, groupID, userID string, data map[string]any) error {
func (g *GroupController) UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error {
return g.database.UpdateGroupMembers(ctx, data)
}
func (g *GroupController) UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error {
return g.database.UpdateGroupMember(ctx, groupID, userID, data)
}
@ -141,9 +157,6 @@ func (g *GroupController) PageGroupRequestUser(ctx context.Context, userID strin
return g.database.PageGroupRequestUser(ctx, userID, pageNumber, showNumber)
}
// func (g *GroupController) TakeSuperGroup(ctx context.Context, groupID string) (superGroup *unrelationTb.SuperGroupModel, err error) {
// return g.database.TakeSuperGroup(ctx, groupID)
// }
func (g *GroupController) FindSuperGroup(ctx context.Context, groupIDs []string) ([]*unrelationTb.SuperGroupModel, error) {
return g.database.FindSuperGroup(ctx, groupIDs)
}
@ -179,6 +192,7 @@ type GroupDataBaseInterface interface {
TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationTb.GroupMemberModel, err error)
TakeGroupOwner(ctx context.Context, groupID string) (*relationTb.GroupMemberModel, error)
FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationTb.GroupMemberModel, error)
FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
PageGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationTb.GroupMemberModel, error)
SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationTb.GroupMemberModel, error)
HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationTb.GroupMemberModel) error
@ -186,7 +200,8 @@ type GroupDataBaseInterface interface {
MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string][]string, error)
MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error)
TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error // 转让群
UpdateGroupMember(ctx context.Context, groupID, userID string, data map[string]any) error
UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error
UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error
// GroupRequest
CreateGroupRequest(ctx context.Context, requests []*relationTb.GroupRequestModel) error
TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationTb.GroupRequestModel, error)
@ -211,7 +226,7 @@ func NewGroupDatabase(db *gorm.DB, rdb redis.UniversalClient, mgoClient *mongo.C
groupMemberDB: groupMemberDB,
groupRequestDB: groupRequestDB,
db: &newDB,
cache: cache.NewGroupCache(rdb, groupDB, groupMemberDB, groupRequestDB, SuperGroupMongoDriver, rockscache.Options{
cache: cache.NewGroupCacheRedis(rdb, groupDB, groupMemberDB, groupRequestDB, SuperGroupMongoDriver, rockscache.Options{
RandomExpireAdjustment: 0.2,
DisableCacheRead: false,
DisableCacheDelete: false,
@ -230,10 +245,36 @@ type GroupDataBase struct {
groupRequestDB relationTb.GroupRequestModelInterface
db *gorm.DB
cache *cache.GroupCache
//cache cache.GroupCache
cache *cache.GroupCacheRedis
mongoDB *unrelation.SuperGroupMongoDriver
}
func (g *GroupDataBase) delGroupMemberCache(ctx context.Context, groupID string, userIDs []string) error {
for _, userID := range userIDs {
if err := g.cache.DelJoinedGroupIDs(ctx, userID); err != nil {
return err
}
if err := g.cache.DelJoinedSuperGroupIDs(ctx, userID); err != nil {
return err
}
}
if err := g.cache.DelGroupMemberIDs(ctx, groupID); err != nil {
return err
}
if err := g.cache.DelGroupMemberNum(ctx, groupID); err != nil {
return err
}
if err := g.cache.DelGroupMembersHash(ctx, groupID); err != nil {
return err
}
return nil
}
func (g *GroupDataBase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
return g.cache.GetGroupMemberIDs(ctx, groupID)
}
func (g *GroupDataBase) CreateGroup(ctx context.Context, groups []*relationTb.GroupModel, groupMembers []*relationTb.GroupMemberModel) error {
if len(groups) > 0 && len(groupMembers) > 0 {
return g.db.Transaction(func(tx *gorm.DB) error {
@ -253,11 +294,11 @@ func (g *GroupDataBase) CreateGroup(ctx context.Context, groups []*relationTb.Gr
}
func (g *GroupDataBase) TakeGroup(ctx context.Context, groupID string) (group *relationTb.GroupModel, err error) {
return g.groupDB.Take(ctx, groupID)
return g.cache.GetGroupInfo(ctx, groupID)
}
func (g *GroupDataBase) FindGroup(ctx context.Context, groupIDs []string) (groups []*relationTb.GroupModel, err error) {
return g.groupDB.Find(ctx, groupIDs)
return g.cache.GetGroupsInfo(ctx, groupIDs)
}
func (g *GroupDataBase) SearchGroup(ctx context.Context, keyword string, pageNumber, showNumber int32) (uint32, []*relationTb.GroupModel, error) {
@ -265,7 +306,15 @@ func (g *GroupDataBase) SearchGroup(ctx context.Context, keyword string, pageNum
}
func (g *GroupDataBase) UpdateGroup(ctx context.Context, groupID string, data map[string]any) error {
return g.groupDB.UpdateMap(ctx, groupID, data)
return g.db.Transaction(func(tx *gorm.DB) error {
if err := g.groupDB.UpdateMap(ctx, groupID, data, tx); err != nil {
return err
}
if err := g.cache.DelGroupInfo(ctx, groupID); err != nil {
return err
}
return nil
})
}
func (g *GroupDataBase) DismissGroup(ctx context.Context, groupID string) error {
@ -273,13 +322,22 @@ func (g *GroupDataBase) DismissGroup(ctx context.Context, groupID string) error
if err := g.groupDB.UpdateStatus(ctx, groupID, constant.GroupStatusDismissed, tx); err != nil {
return err
}
return g.groupMemberDB.DeleteGroup(ctx, []string{groupID}, tx)
if err := g.groupMemberDB.DeleteGroup(ctx, []string{groupID}, tx); err != nil {
return err
}
userIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return err
}
if err := g.delGroupMemberCache(ctx, groupID, userIDs); err != nil {
return err
}
return nil
})
}
func (g *GroupDataBase) TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationTb.GroupMemberModel, err error) {
return g.groupMemberDB.Take(ctx, groupID, userID)
return g.cache.GetGroupMemberInfo(ctx, groupID, userID)
}
func (g *GroupDataBase) TakeGroupOwner(ctx context.Context, groupID string) (*relationTb.GroupMemberModel, error) {
@ -287,6 +345,7 @@ func (g *GroupDataBase) TakeGroupOwner(ctx context.Context, groupID string) (*re
}
func (g *GroupDataBase) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationTb.GroupMemberModel, error) {
//g.cache.GetGroupMembersInfo()
return g.groupMemberDB.Find(ctx, groupIDs, userIDs, roleLevels)
}
@ -299,19 +358,32 @@ func (g *GroupDataBase) SearchGroupMember(ctx context.Context, keyword string, g
}
func (g *GroupDataBase) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationTb.GroupMemberModel) error {
if member == nil {
return g.groupRequestDB.UpdateHandler(ctx, groupID, userID, handledMsg, handleResult)
}
return g.db.Transaction(func(tx *gorm.DB) error {
if err := g.groupRequestDB.UpdateHandler(ctx, groupID, userID, handledMsg, handleResult, tx); err != nil {
return err
}
return g.groupMemberDB.Create(ctx, []*relationTb.GroupMemberModel{member}, tx)
if member != nil {
if err := g.groupMemberDB.Create(ctx, []*relationTb.GroupMemberModel{member}, tx); err != nil {
return err
}
if err := g.delGroupMemberCache(ctx, groupID, []string{userID}); err != nil {
return err
}
}
return nil
})
}
func (g *GroupDataBase) DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error {
return g.groupMemberDB.Delete(ctx, groupID, userIDs)
return g.db.Transaction(func(tx *gorm.DB) error {
if err := g.groupMemberDB.Delete(ctx, groupID, userIDs, tx); err != nil {
return err
}
if err := g.delGroupMemberCache(ctx, groupID, userIDs); err != nil {
return err
}
return nil
})
}
func (g *GroupDataBase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string][]string, error) {
@ -338,12 +410,37 @@ func (g *GroupDataBase) TransferGroupOwner(ctx context.Context, groupID string,
if rowsAffected != 1 {
return utils.Wrap(fmt.Errorf("newOwnerUserID %s rowsAffected = %d", newOwnerUserID, rowsAffected), "")
}
if err := g.delGroupMemberCache(ctx, groupID, []string{oldOwnerUserID, newOwnerUserID}); err != nil {
return err
}
return nil
})
}
func (g *GroupDataBase) UpdateGroupMember(ctx context.Context, groupID, userID string, data map[string]any) error {
return g.groupMemberDB.Update(ctx, groupID, userID, data)
func (g *GroupDataBase) UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error {
return g.db.Transaction(func(tx *gorm.DB) error {
if err := g.groupMemberDB.Update(ctx, groupID, userID, data, tx); err != nil {
return err
}
if err := g.cache.DelGroupMemberInfo(ctx, groupID, userID); err != nil {
return err
}
return nil
})
}
func (g *GroupDataBase) UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error {
return g.db.Transaction(func(tx *gorm.DB) error {
for _, item := range data {
if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map, tx); err != nil {
return err
}
if err := g.cache.DelGroupMemberInfo(ctx, item.GroupID, item.UserID); err != nil {
return err
}
}
return nil
})
}
func (g *GroupDataBase) CreateGroupRequest(ctx context.Context, requests []*relationTb.GroupRequestModel) error {

@ -52,8 +52,7 @@ func (g *GroupLocalCache) GetGroupMemberIDs(ctx context.Context, groupID string)
if ok && localHashInfo.memberListHash == resp.GroupAbstractInfos[0].GroupMemberListHash {
return localHashInfo.userIDs, nil
}
groupMembersResp, err := client.GetGroupMemberList(ctx, &group.GetGroupMemberListReq{
groupMembersResp, err := client.GetGroupMemberUserID(ctx, &group.GetGroupMemberUserIDReq{
GroupID: groupID,
})
if err != nil {
@ -61,7 +60,7 @@ func (g *GroupLocalCache) GetGroupMemberIDs(ctx context.Context, groupID string)
}
g.cache[groupID] = GroupMemberIDsHash{
memberListHash: resp.GroupAbstractInfos[0].GroupMemberListHash,
userIDs: groupMembersResp.Members,
userIDs: groupMembersResp.UserIDs,
}
return g.cache[groupID].userIDs, nil
}

@ -40,13 +40,6 @@ func (g *GroupMemberGorm) DeleteGroup(ctx context.Context, groupIDs []string, tx
return utils.Wrap(getDBConn(g.DB, tx).Where("group_id in (?)", groupIDs).Delete(&relation.GroupMemberModel{}).Error, "")
}
//func (g *GroupMemberGorm) UpdateByMap(ctx context.Context, groupID string, userID string, args map[string]interface{}, tx ...any) (err error) {
// defer func() {
// tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "userID", userID, "args", args)
// }()
// return utils.Wrap(getDBConn(g.DB, tx).Model(&relation.GroupMemberModel{}).Where("group_id = ? and user_id = ?", groupID, userID).Updates(args).Error, "")
//}
func (g *GroupMemberGorm) Update(ctx context.Context, groupID string, userID string, data map[string]any, tx ...any) (err error) {
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "userID", userID, "data", data)
@ -81,23 +74,6 @@ func (g *GroupMemberGorm) Find(ctx context.Context, groupIDs []string, userIDs [
return groupList, utils.Wrap(db.Find(&groupList).Error, "")
}
//func (g *GroupMemberGorm) FindGroupUser(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32, tx ...any) (groupList []*relation.GroupMemberModel, err error) {
// defer func() {
// tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupIDs", groupIDs, "userIDs", userIDs, "groupList", groupList)
// }()
// db := getDBConn(g.DB, tx)
// if len(groupList) > 0 {
// db = db.Where("group_id in (?)", groupIDs)
// }
// if len(userIDs) > 0 {
// db = db.Where("user_id in (?)", userIDs)
// }
// if len(roleLevels) > 0 {
// db = db.Where("role_level in (?)", roleLevels)
// }
// return groupList, utils.Wrap(db.Find(&groupList).Error, "")
//}
func (g *GroupMemberGorm) Take(ctx context.Context, groupID string, userID string, tx ...any) (groupMember *relation.GroupMemberModel, err error) {
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "userID", userID, "groupMember", *groupMember)
@ -149,3 +125,10 @@ func (g *GroupMemberGorm) FindJoinUserID(ctx context.Context, groupIDs []string,
}
return groupUsers, nil
}
func (g *GroupMemberGorm) FindMemberUserID(ctx context.Context, groupID string, tx ...any) (userIDs []string, err error) {
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "userIDs", userIDs)
}()
return userIDs, utils.Wrap(getDBConn(g.DB, tx).Model(&relation.GroupMemberModel{}).Where("group_id = ?", groupID).Pluck("user_id", &userIDs), "")
}

@ -31,11 +31,10 @@ type GroupMemberModelInterface interface {
Create(ctx context.Context, groupMemberList []*GroupMemberModel, tx ...any) (err error)
Delete(ctx context.Context, groupID string, userIDs []string, tx ...any) (err error)
DeleteGroup(ctx context.Context, groupIDs []string, tx ...any) (err error)
//UpdateByMap(ctx context.Context, groupID string, userID string, args map[string]interface{}, tx ...any) (err error)
Update(ctx context.Context, groupID string, userID string, data map[string]any, tx ...any) (err error)
UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32, tx ...any) (rowsAffected int64, err error)
Find(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32, tx ...any) (groupList []*GroupMemberModel, err error)
//FindGroupUser(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32, tx ...any) (groupList []*GroupMemberModel, err error)
FindMemberUserID(ctx context.Context, groupID string, tx ...any) (userIDs []string, err error)
Take(ctx context.Context, groupID string, userID string, tx ...any) (groupMember *GroupMemberModel, err error)
TakeOwner(ctx context.Context, groupID string, tx ...any) (groupMember *GroupMemberModel, err error)
SearchMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32, tx ...any) (total uint32, groupList []*GroupMemberModel, err error)

@ -24,7 +24,7 @@ func (f *fileHook) Levels() []logrus.Level {
}
//func (f *fileHook) Fire(entry *logrus.Entry) error {
// entry.Data["FilePath"] = findCaller(6)
// entry.Map["FilePath"] = findCaller(6)
// utils.GetSelfFuncName()
// return nil
//}

File diff suppressed because it is too large Load Diff

@ -227,17 +227,6 @@ message CancelMuteGroupReq{
message CancelMuteGroupResp{
}
message SetGroupMemberNicknameReq{
string groupID = 1;
string nickname = 2;
string userID = 3;
}
message SetGroupMemberNicknameResp{
}
message GetJoinedSuperGroupListReq {
string userID = 1;
}
@ -254,7 +243,7 @@ message GetSuperGroupsInfoResp {
repeated sdkws.GroupInfo groupInfos = 1;
}
message SetGroupMemberInfoReq{
message SetGroupMemberInfo{
string groupID = 1;
string userID = 2;
google.protobuf.StringValue nickname = 3;
@ -263,6 +252,10 @@ message SetGroupMemberInfoReq{
google.protobuf.StringValue ex = 6;
}
message SetGroupMemberInfoReq{
repeated SetGroupMemberInfo members = 1;
}
message SetGroupMemberInfoResp{
}
@ -281,14 +274,25 @@ message GetGroupAbstractInfoResp{
repeated GroupAbstractInfo groupAbstractInfos = 1;
}
message getUserInGroupMembersReq {
message GetUserInGroupMembersReq {
string userID = 1;
repeated string groupIDs = 2;
}
message getUserInGroupMembersResp{
repeated sdkws.GroupMemberFullInfo members = 1;
}
message GetGroupMemberUserIDReq{
string groupID = 1;
}
message GetGroupMemberUserIDResp{
repeated string userIDs = 1;
}
service group{
//
rpc createGroup(CreateGroupReq) returns(CreateGroupResp);
@ -338,13 +342,14 @@ service group{
//
rpc getSuperGroupsInfo(GetSuperGroupsInfoReq) returns (GetSuperGroupsInfoResp);
//
rpc setGroupMemberNickname(SetGroupMemberNicknameReq) returns (SetGroupMemberNicknameResp);
//
rpc setGroupMemberInfo(SetGroupMemberInfoReq) returns (SetGroupMemberInfoResp);
//hash
rpc getGroupAbstractInfo(GetGroupAbstractInfoReq) returns (GetGroupAbstractInfoResp);
//
rpc getUserInGroupMembers(getUserInGroupMembersReq) returns (getUserInGroupMembersResp);
rpc getUserInGroupMembers(GetUserInGroupMembersReq) returns (GetUserInGroupMembersResp);
//ID
rpc getGroupMemberUserID(GetGroupMemberUserIDReq) returns (GetGroupMemberUserIDResp);
}

Loading…
Cancel
Save