feat: optimize friend and group applications

This commit is contained in:
withchao 2025-05-23 15:39:29 +08:00
parent 2806fb3606
commit f86b90fbfb
6 changed files with 109 additions and 27 deletions

4
go.mod
View File

@ -12,7 +12,7 @@ require (
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.1
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/openimsdk/protocol v0.0.73-alpha.8 github.com/openimsdk/protocol v0.0.73-alpha.10
github.com/openimsdk/tools v0.0.50-alpha.83 github.com/openimsdk/tools v0.0.50-alpha.83
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_golang v1.18.0
@ -219,3 +219,5 @@ require (
golang.org/x/crypto v0.27.0 // indirect golang.org/x/crypto v0.27.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
) )
//replace github.com/openimsdk/protocol => /Users/chao/Desktop/code/protocol

4
go.sum
View File

@ -347,8 +347,8 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/openimsdk/gomake v0.0.15-alpha.5 h1:eEZCEHm+NsmcO3onXZPIUbGFCYPYbsX5beV3ZyOsGhY= github.com/openimsdk/gomake v0.0.15-alpha.5 h1:eEZCEHm+NsmcO3onXZPIUbGFCYPYbsX5beV3ZyOsGhY=
github.com/openimsdk/gomake v0.0.15-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= github.com/openimsdk/gomake v0.0.15-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
github.com/openimsdk/protocol v0.0.73-alpha.8 h1:GqksOHXWZSqRQaGYvuVQ4IzA7kFhIXSk7NZk0LGk35A= github.com/openimsdk/protocol v0.0.73-alpha.10 h1:gytT3OaDj+WvccptvGXRqxtLSotIV0ZbzO0eymaUZRo=
github.com/openimsdk/protocol v0.0.73-alpha.8/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw= github.com/openimsdk/protocol v0.0.73-alpha.10/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw=
github.com/openimsdk/tools v0.0.50-alpha.83 h1:7c1D40YGqIWUmGfCII5pduETGC/8c2DyS9SQ4LvoplU= github.com/openimsdk/tools v0.0.50-alpha.83 h1:7c1D40YGqIWUmGfCII5pduETGC/8c2DyS9SQ4LvoplU=
github.com/openimsdk/tools v0.0.50-alpha.83/go.mod h1:n2poR3asX1e1XZce4O+MOWAp+X02QJRFvhcLCXZdzRo= github.com/openimsdk/tools v0.0.50-alpha.83/go.mod h1:n2poR3asX1e1XZce4O+MOWAp+X02QJRFvhcLCXZdzRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=

View File

@ -25,7 +25,6 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/dbbuild" "github.com/openimsdk/open-im-server/v3/pkg/dbbuild"
"github.com/openimsdk/open-im-server/v3/pkg/rpcli" "github.com/openimsdk/open-im-server/v3/pkg/rpcli"
"google.golang.org/grpc" "google.golang.org/grpc"
"github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/authverify"
@ -153,10 +152,14 @@ func (g *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgro
func (g *groupServer) CheckGroupAdmin(ctx context.Context, groupID string) error { func (g *groupServer) CheckGroupAdmin(ctx context.Context, groupID string) error {
if !authverify.IsAdmin(ctx) { if !authverify.IsAdmin(ctx) {
groupMember, err := g.db.TakeGroupMember(ctx, groupID, mcontext.GetOpUserID(ctx)) members, err := g.db.FindGroupMembers(ctx, groupID, []string{mcontext.GetOpUserID(ctx)})
if err != nil { if err != nil {
return err return err
} }
if len(members) == 0 {
return errs.ErrNoPermission.WrapMsg("op user not in group")
}
groupMember := members[0]
if !(groupMember.RoleLevel == constant.GroupOwner || groupMember.RoleLevel == constant.GroupAdmin) { if !(groupMember.RoleLevel == constant.GroupOwner || groupMember.RoleLevel == constant.GroupAdmin) {
return errs.ErrNoPermission.WrapMsg("no group owner or admin") return errs.ErrNoPermission.WrapMsg("no group owner or admin")
} }
@ -685,15 +688,34 @@ func (g *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
if err := authverify.CheckAccess(ctx, req.FromUserID); err != nil { if err := authverify.CheckAccess(ctx, req.FromUserID); err != nil {
return nil, err return nil, err
} }
groupIDs, err := g.db.FindUserManagedGroupID(ctx, req.FromUserID) var (
groupIDs []string
err error
)
if len(req.GroupIDs) == 0 {
groupIDs, err = g.db.FindUserManagedGroupID(ctx, req.FromUserID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else {
req.GroupIDs = datautil.Distinct(req.GroupIDs)
if !authverify.IsAdmin(ctx) {
for _, groupID := range req.GroupIDs {
if err := g.CheckGroupAdmin(ctx, groupID); err != nil {
return nil, err
}
}
}
groupIDs = req.GroupIDs
}
resp := &pbgroup.GetGroupApplicationListResp{} resp := &pbgroup.GetGroupApplicationListResp{}
if len(groupIDs) == 0 { if len(groupIDs) == 0 {
return resp, nil return resp, nil
} }
total, groupRequests, err := g.db.PageGroupRequest(ctx, groupIDs, req.Pagination) handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
return int(e)
})
total, groupRequests, err := g.db.PageGroupRequest(ctx, groupIDs, handleResults, req.Pagination)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -758,6 +780,23 @@ func (g *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup.GetGroupsI
}, nil }, nil
} }
func (g *groupServer) GetGroupApplicationUnhandledCount(ctx context.Context, req *pbgroup.GetGroupApplicationUnhandledCountReq) (*pbgroup.GetGroupApplicationUnhandledCountResp, error) {
if err := authverify.CheckAccess(ctx, req.UserID); err != nil {
return nil, err
}
groupIDs, err := g.db.FindUserManagedGroupID(ctx, req.UserID)
if err != nil {
return nil, err
}
count, err := g.db.GetGroupApplicationUnhandledCount(ctx, groupIDs, req.Time)
if err != nil {
return nil, err
}
return &pbgroup.GetGroupApplicationUnhandledCountResp{
Count: count,
}, nil
}
func (g *groupServer) getGroupsInfo(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) { func (g *groupServer) getGroupsInfo(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) {
if len(groupIDs) == 0 { if len(groupIDs) == 0 {
return nil, nil return nil, nil
@ -1322,11 +1361,17 @@ func (g *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGr
} }
func (g *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgroup.GetUserReqApplicationListReq) (*pbgroup.GetUserReqApplicationListResp, error) { func (g *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgroup.GetUserReqApplicationListReq) (*pbgroup.GetUserReqApplicationListResp, error) {
if err := authverify.CheckAccess(ctx, req.UserID); err != nil {
return nil, err
}
user, err := g.userClient.GetUserInfo(ctx, req.UserID) user, err := g.userClient.GetUserInfo(ctx, req.UserID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
total, requests, err := g.db.PageGroupRequestUser(ctx, req.UserID, req.Pagination) handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
return int(e)
})
total, requests, err := g.db.PageGroupRequestUser(ctx, req.UserID, req.GroupIDs, handleResults, req.Pagination)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1767,6 +1812,9 @@ func (g *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
} }
func (g *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *pbgroup.GetGroupUsersReqApplicationListReq) (*pbgroup.GetGroupUsersReqApplicationListResp, error) { func (g *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *pbgroup.GetGroupUsersReqApplicationListReq) (*pbgroup.GetGroupUsersReqApplicationListResp, error) {
if err := g.CheckGroupAdmin(ctx, req.GroupID); err != nil {
return nil, err
}
requests, err := g.db.FindGroupRequests(ctx, req.GroupID, req.UserIDs) requests, err := g.db.FindGroupRequests(ctx, req.GroupID, req.UserIDs)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -68,7 +68,7 @@ type GroupDatabase interface {
// FindUserManagedGroupID retrieves group IDs managed by a user. // FindUserManagedGroupID retrieves group IDs managed by a user.
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
// PageGroupRequest paginates through group requests for specified groups. // PageGroupRequest paginates through group requests for specified groups.
PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) PageGroupRequest(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
// GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level. // GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level.
GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
@ -100,7 +100,7 @@ type GroupDatabase interface {
// FindGroupRequests retrieves multiple group join requests. // FindGroupRequests retrieves multiple group join requests.
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
// PageGroupRequestUser paginates through group join requests made by a user. // PageGroupRequestUser paginates through group join requests made by a user.
PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) PageGroupRequestUser(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
// CountTotal counts the total number of groups as of a certain date. // CountTotal counts the total number of groups as of a certain date.
CountTotal(ctx context.Context, before *time.Time) (count int64, err error) CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
@ -124,6 +124,8 @@ type GroupDatabase interface {
SearchJoinGroup(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error) SearchJoinGroup(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error)
FindJoinGroupID(ctx context.Context, userID string) ([]string, error) FindJoinGroupID(ctx context.Context, userID string) ([]string, error)
GetGroupApplicationUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error)
} }
func NewGroupDatabase( func NewGroupDatabase(
@ -304,8 +306,8 @@ func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID strin
return g.groupMemberDB.FindUserManagedGroupID(ctx, userID) return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
} }
func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) { func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination) return g.groupRequestDB.PageGroup(ctx, groupIDs, handleResults, pagination)
} }
func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) { func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) {
@ -463,16 +465,12 @@ func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*mode
}) })
} }
func (g *groupDatabase) TakeGroupRequest( func (g *groupDatabase) TakeGroupRequest(ctx context.Context, groupID string, userID string) (*model.GroupRequest, error) {
ctx context.Context,
groupID string,
userID string,
) (*model.GroupRequest, error) {
return g.groupRequestDB.Take(ctx, groupID, userID) return g.groupRequestDB.Take(ctx, groupID, userID)
} }
func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) { func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
return g.groupRequestDB.Page(ctx, userID, pagination) return g.groupRequestDB.Page(ctx, userID, groupIDs, handleResults, pagination)
} }
func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
@ -565,3 +563,7 @@ func (g *groupDatabase) MemberGroupIncrVersion(ctx context.Context, groupID stri
} }
return g.cache.DelMaxGroupMemberVersion(groupID).ChainExecDel(ctx) return g.cache.DelMaxGroupMemberVersion(groupID).ChainExecDel(ctx)
} }
func (g *groupDatabase) GetGroupApplicationUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) {
return g.groupRequestDB.GetUnhandledCount(ctx, groupIDs, ts)
}

View File

@ -16,6 +16,7 @@ package database
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
"github.com/openimsdk/tools/db/pagination" "github.com/openimsdk/tools/db/pagination"
) )
@ -26,6 +27,7 @@ type GroupRequest interface {
UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error) UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
Take(ctx context.Context, groupID string, userID string) (groupRequest *model.GroupRequest, err error) Take(ctx context.Context, groupID string, userID string) (groupRequest *model.GroupRequest, err error)
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) Page(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) PageGroup(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
GetUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error)
} }

View File

@ -16,8 +16,10 @@ package mgo
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
"github.com/openimsdk/tools/utils/datautil"
"github.com/openimsdk/tools/db/mongoutil" "github.com/openimsdk/tools/db/mongoutil"
"github.com/openimsdk/tools/db/pagination" "github.com/openimsdk/tools/db/pagination"
@ -66,10 +68,36 @@ func (g *GroupRequestMgo) FindGroupRequests(ctx context.Context, groupID string,
return mongoutil.Find[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}}) return mongoutil.Find[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
} }
func (g *GroupRequestMgo) Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) { func (g *GroupRequestMgo) sort() any {
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, bson.M{"user_id": userID}, pagination) return bson.E{Key: "_id", Value: -1}
} }
func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) { func (g *GroupRequestMgo) Page(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) {
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination) filter := bson.M{"user_id": userID}
if len(groupIDs) > 0 {
filter["group_id"] = bson.M{"$in": datautil.Distinct(groupIDs)}
}
if len(handleResults) > 0 {
filter["handle_result"] = bson.M{"$in": handleResults}
}
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, filter, pagination, options.Find().SetSort(g.sort()))
}
func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) {
if len(groupIDs) == 0 {
return 0, nil, nil
}
filter := bson.M{"group_id": bson.M{"$in": groupIDs}}
if len(handleResults) > 0 {
filter["handle_result"] = bson.M{"$in": handleResults}
}
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, filter, pagination, options.Find().SetSort(g.sort()))
}
func (g *GroupRequestMgo) GetUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) {
if len(groupIDs) == 0 {
return 0, nil
}
return 0, nil
} }