Skip to content

Commit

Permalink
feat: implement GetSpecifiedUserGroupRequestInfo interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
mo3et committed Sep 25, 2024
1 parent d279a5f commit ac071ae
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 19 deletions.
4 changes: 2 additions & 2 deletions config/mongodb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ uri:
# List of MongoDB server addresses
address: [ localhost:37017 ]
# Name of the database
database: openim_v3
database: openIM_v3
# Username for database authentication
username: openIM
# Password for database authentication
password: openIM123
password: openIM123456
# Maximum number of connections in the connection pool
maxPoolSize: 100
# Maximum number of retry attempts for a failed database connection
Expand Down
6 changes: 2 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/openimsdk/open-im-server/v3
go 1.21.2

require (
firebase.google.com/go/v4 v4.13.0
firebase.google.com/go/v4 v4.14.1
github.com/dtm-labs/rockscache v0.1.1
github.com/gin-gonic/gin v1.9.1
github.com/go-playground/validator/v10 v10.20.0
Expand All @@ -27,7 +27,6 @@ require (
require github.com/google/uuid v1.6.0

require (
firebase.google.com/go/v4 v4.14.1
github.com/IBM/sarama v1.43.0
github.com/fatih/color v1.14.1
github.com/gin-contrib/gzip v1.0.1
Expand Down Expand Up @@ -180,9 +179,8 @@ require (
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/appengine/v2 v2.0.2 // indirect
google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe // indirect
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
gorm.io/gorm v1.25.8 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,6 @@ google.golang.org/api v0.170.0 h1:zMaruDePM88zxZBG+NG8+reALO2rfLhe/JShitLyT48=
google.golang.org/api v0.170.0/go.mod h1:/xql9M2btF85xac/VAm4PsLMTLVGUOpq4BE9R8jyNy8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/appengine/v2 v2.0.2 h1:MSqyWy2shDLwG7chbwBJ5uMyw6SNqJzhJHNDwYB0Akk=
google.golang.org/appengine/v2 v2.0.2/go.mod h1:PkgRUWz4o1XOvbqtWTkBtCitEJ5Tp4HoVEdMMYQR/8E=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
Expand Down
4 changes: 4 additions & 0 deletions internal/api/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func (o *GroupApi) GetGroupUsersReqApplicationList(c *gin.Context) {
a2r.Call(group.GroupClient.GetGroupUsersReqApplicationList, o.Client, c)
}

func (o *GroupApi) GetSpecifiedUserGroupRequestInfo(c *gin.Context) {
a2r.Call(group.GroupClient.GetSpecifiedUserGroupRequestInfo, o.Client, c)
}

func (o *GroupApi) GetGroupsInfo(c *gin.Context) {
a2r.Call(group.GroupClient.GetGroupsInfo, o.Client, c)
//a2r.Call(group.GroupClient.GetGroupsInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupsInfo))
Expand Down
1 change: 1 addition & 0 deletions internal/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func newGinRouter(disCov discovery.SvcDiscoveryRegistry, config *Config) *gin.En
groupRouterGroup.POST("/get_recv_group_applicationList", g.GetRecvGroupApplicationList)
groupRouterGroup.POST("/get_user_req_group_applicationList", g.GetUserReqGroupApplicationList)
groupRouterGroup.POST("/get_group_users_req_application_list", g.GetGroupUsersReqApplicationList)
groupRouterGroup.POST("/get_specified_user_group_request_info", g.GetSpecifiedUserGroupRequestInfo)
groupRouterGroup.POST("/get_groups_info", g.GetGroupsInfo)
groupRouterGroup.POST("/kick_group", g.KickGroupMember)
groupRouterGroup.POST("/get_group_members_info", g.GetGroupMembersInfo)
Expand Down
79 changes: 78 additions & 1 deletion internal/rpc/group/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -1685,44 +1685,121 @@ func (g *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
if err != nil {
return nil, err
}

if len(requests) == 0 {
return &pbgroup.GetGroupUsersReqApplicationListResp{}, nil
}

groupIDs := datautil.Distinct(datautil.Slice(requests, func(e *model.GroupRequest) string {
return e.GroupID
}))

groups, err := g.db.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}

groupMap := datautil.SliceToMap(groups, func(e *model.Group) string {
return e.GroupID
})

if ids := datautil.Single(groupIDs, datautil.Keys(groupMap)); len(ids) > 0 {
return nil, servererrs.ErrGroupIDNotFound.WrapMsg(strings.Join(ids, ","))
}

userMap, err := g.user.GetPublicUserInfoMap(ctx, req.UserIDs)
if err != nil {
return nil, err
}

owners, err := g.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}

if err := g.PopulateGroupMember(ctx, owners...); err != nil {
return nil, err
}

ownerMap := datautil.SliceToMap(owners, func(e *model.GroupMember) string {
return e.GroupID
})

groupMemberNum, err := g.db.MapGroupMemberNum(ctx, groupIDs)
if err != nil {
return nil, err
}

return &pbgroup.GetGroupUsersReqApplicationListResp{
Total: int64(len(requests)),
GroupRequests: datautil.Slice(requests, func(e *model.GroupRequest) *sdkws.GroupRequest {
var ownerUserID string
if owner, ok := ownerMap[e.GroupID]; ok {
ownerUserID = owner.UserID
}
return convert.Db2PbGroupRequest(e, nil, convert.Db2PbGroupInfo(groupMap[e.GroupID], ownerUserID, groupMemberNum[e.GroupID]))

var userInfo *sdkws.PublicUserInfo
if user, ok := userMap[e.UserID]; !ok {
userInfo = user
}

return convert.Db2PbGroupRequest(e, userInfo, convert.Db2PbGroupInfo(groupMap[e.GroupID], ownerUserID, groupMemberNum[e.GroupID]))
}),
}, nil
}

func (g *groupServer) GetSpecifiedUserGroupRequestInfo(ctx context.Context, req *pbgroup.GetSpecifiedUserGroupRequestInfoReq) (*pbgroup.GetSpecifiedUserGroupRequestInfoResp, error) {
opUserID := mcontext.GetOpUserID(ctx)

if req.UserID != opUserID {
req.UserID = mcontext.GetOpUserID(ctx)
memberIDs, err := g.db.GetGroupAdminLevelMemberIDs(ctx, req.GroupID)
if err != nil {
return nil, err
}

if !datautil.Contain(req.UserID, memberIDs...) {
return nil, errs.ErrNoPermission.WrapMsg("opUser no permission")
}
}
requests, err := g.db.FindGroupRequests(ctx, req.GroupID, []string{req.UserID})
if err != nil {
return nil, err
}

if len(requests) == 0 {
return &pbgroup.GetSpecifiedUserGroupRequestInfoResp{}, nil
}

groups, err := g.db.FindGroup(ctx, []string{req.GroupID})
if err != nil {
return nil, err
}

userInfos, err := g.user.GetPublicUserInfos(ctx, []string{req.UserID})
if err != nil {
return nil, err
}

owners, err := g.db.FindGroupsOwner(ctx, []string{req.GroupID})
if err != nil {
return nil, err
}

groupMemberNum, err := g.db.MapGroupMemberNum(ctx, []string{req.GroupID})
if err != nil {
return nil, err
}

resp := &pbgroup.GetSpecifiedUserGroupRequestInfoResp{
GroupRequests: make([]*sdkws.GroupRequest, 0, len(requests)),
}

for _, request := range requests {
resp.GroupRequests = append(resp.GroupRequests, convert.Db2PbGroupRequest(request, userInfos[0], convert.Db2PbGroupInfo(groups[0], owners[0].UserID, groupMemberNum[groups[0].GroupID])))
}

resp.Total = uint32(len(requests))

return resp, nil
}
25 changes: 15 additions & 10 deletions pkg/common/storage/cache/cachekey/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ import (
)

const (
groupExpireTime = time.Second * 60 * 60 * 12
GroupInfoKey = "GROUP_INFO:"
GroupMemberIDsKey = "GROUP_MEMBER_IDS:"
GroupMembersHashKey = "GROUP_MEMBERS_HASH2:"
GroupMemberInfoKey = "GROUP_MEMBER_INFO:"
JoinedGroupsKey = "JOIN_GROUPS_KEY:"
GroupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
GroupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
GroupMemberMaxVersionKey = "GROUP_MEMBER_MAX_VERSION:"
GroupJoinMaxVersionKey = "GROUP_JOIN_MAX_VERSION:"
groupExpireTime = time.Second * 60 * 60 * 12
GroupInfoKey = "GROUP_INFO:"
GroupMemberIDsKey = "GROUP_MEMBER_IDS:"
GroupMembersHashKey = "GROUP_MEMBERS_HASH2:"
GroupMemberInfoKey = "GROUP_MEMBER_INFO:"
JoinedGroupsKey = "JOIN_GROUPS_KEY:"
GroupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
GroupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
GroupAdminLevelMemberIDsKey = "GROUP_ADMIN_LEVEL_MEMBER_IDS:"
GroupMemberMaxVersionKey = "GROUP_MEMBER_MAX_VERSION:"
GroupJoinMaxVersionKey = "GROUP_JOIN_MAX_VERSION:"
)

func GetGroupInfoKey(groupID string) string {
Expand Down Expand Up @@ -60,6 +61,10 @@ func GetGroupRoleLevelMemberIDsKey(groupID string, roleLevel int32) string {
return GroupRoleLevelMemberIDsKey + groupID + "-" + strconv.Itoa(int(roleLevel))
}

func GetGroupAdminLevelMemberIDsKey(groupID string) string {
return GroupAdminLevelMemberIDsKey + groupID
}

func GetGroupMemberMaxVersionKey(groupID string) string {
return GroupMemberMaxVersionKey + groupID
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/common/storage/cache/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package cache

import (
"context"

"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
)
Expand Down Expand Up @@ -48,6 +49,7 @@ type GroupCache interface {
FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*model.GroupMember, error)

GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
GetGroupAdminLevelMemberIDs(ctx context.Context, groupID string) ([]string, error)
GetGroupOwner(ctx context.Context, groupID string) (*model.GroupMember, error)
GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*model.GroupMember, error)
DelGroupRoleLevel(groupID string, roleLevel []int32) GroupCache
Expand Down
10 changes: 10 additions & 0 deletions pkg/common/storage/cache/redis/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ func (g *GroupCacheRedis) getGroupRoleLevelMemberIDsKey(groupID string, roleLeve
return cachekey.GetGroupRoleLevelMemberIDsKey(groupID, roleLevel)
}

func (g *GroupCacheRedis) getGroupAdminLevelMemberIDsKey(groupID string) string {
return cachekey.GetGroupAdminLevelMemberIDsKey(groupID)
}

func (g *GroupCacheRedis) getGroupMemberMaxVersionKey(groupID string) string {
return cachekey.GetGroupMemberMaxVersionKey(groupID)
}
Expand Down Expand Up @@ -328,6 +332,12 @@ func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Context, groupI
})
}

func (g *GroupCacheRedis) GetGroupAdminLevelMemberIDs(ctx context.Context, groupID string) ([]string, error) {
return getCache(ctx, g.rcClient, g.getGroupAdminLevelMemberIDsKey(groupID), g.expireTime, func(ctx context.Context) ([]string, error) {
return g.groupMemberDB.FindAdminLevelUserIDs(ctx, groupID)
})
}

func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*model.GroupMember, error) {
userIDs, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions pkg/common/storage/controller/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ type GroupDatabase interface {
PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
// GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level.
GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
// GetGroupAdminLevelMemberIDs retrieves user IDs of group members with an admin role level.
GetGroupAdminLevelMemberIDs(ctx context.Context, groupID string) ([]string, error)

// PageGetJoinGroup paginates through groups that a user has joined.
PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error)
Expand Down Expand Up @@ -180,6 +182,10 @@ func (g *groupDatabase) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID
return g.cache.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
}

func (g *groupDatabase) GetGroupAdminLevelMemberIDs(ctx context.Context, groupID string) ([]string, error) {
return g.cache.GetGroupAdminLevelMemberIDs(ctx, groupID)
}

func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*model.Group, groupMembers []*model.GroupMember) error {
if len(groups)+len(groupMembers) == 0 {
return nil
Expand Down
1 change: 1 addition & 0 deletions pkg/common/storage/database/group_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type GroupMember interface {
TakeOwner(ctx context.Context, groupID string) (groupMember *model.GroupMember, err error)
SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*model.GroupMember, err error)
FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
FindAdminLevelUserIDs(ctx context.Context, groupID string) ([]string, error)
FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
Expand Down
6 changes: 6 additions & 0 deletions pkg/common/storage/database/mgo/group_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ func (g *GroupMemberMgo) FindRoleLevelUserIDs(ctx context.Context, groupID strin
return mongoutil.Find[string](ctx, g.coll, bson.M{"group_id": groupID, "role_level": roleLevel}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
}

func (g *GroupMemberMgo) FindAdminLevelUserIDs(ctx context.Context, groupID string) ([]string, error) {
return mongoutil.Find[string](ctx, g.coll,
bson.M{"group_id": groupID, "role_level": bson.M{"$gte": constant.GroupAdmin}},
options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
}

func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*model.GroupMember, error) {
filter := bson.M{"group_id": groupID, "nickname": bson.M{"$regex": keyword}}
return mongoutil.FindPage[*model.GroupMember](ctx, g.coll, filter, pagination, options.Find().SetSort(g.memberSort()))
Expand Down

0 comments on commit ac071ae

Please sign in to comment.