Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
54b9c17744
Merge d8919998382f9b46c481c3acf356584dfede685f into 175a7bb0673eca18e9d1b10bff4f728da6b1b513 2026-09-01 07:24:11 +05:30
dsx137
175a7bb067
fix(core): trigger after-join webhooks for invited members (#3796) 2026-08-31 03:40:46 +00:00
dsx137
defc929ef8
fix(core): filter invalid and outdated conversation messages (#3791) 2026-08-26 03:23:57 +00:00
Leo225
676ad0f02e
refactor(tests): simplify loop constructs in compressor tests and benchmarks (#3776) 2026-08-04 11:06:03 +00:00
dsx137
193870b2f9
fix(core): enforce admin access for queries (#3781) 2026-08-04 07:19:40 +00:00
dependabot[bot]
d891999838
build(deps): bump golang.org/x/image from 0.39.0 to 0.41.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.39.0 to 0.41.0.
- [Commits](https://github.com/golang/image/compare/v0.39.0...v0.41.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.41.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-03 10:30:30 +00:00
8 changed files with 87 additions and 32 deletions

2
go.mod
View File

@ -196,7 +196,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/image v0.39.0 // indirect
golang.org/x/image v0.41.0 // indirect
golang.org/x/net v0.55.0 // indirect
golang.org/x/oauth2 v0.34.0 // indirect
golang.org/x/sys v0.45.0 // indirect

4
go.sum
View File

@ -531,8 +531,8 @@ golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGb
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
golang.org/x/image v0.41.0 h1:8wS72eGJMJaBxK6okTzd4WaXumUlTVlb753MlsSvTCo=
golang.org/x/image v0.41.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=

View File

@ -143,14 +143,16 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
if err != nil {
return nil, err
}
msgs, err := x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, datautil.Slice(sortList, func(c *msg.ActiveConversation) *msg.ConversationSeqs {
return &msg.ConversationSeqs{
ConversationID: c.ConversationID,
Seqs: []int64{c.MaxSeq},
maxSeqs := datautil.SliceToMapAny(sortList, func(c *msg.ActiveConversation) (string, int64) {
return c.ConversationID, c.MaxSeq
})
conversationSeqs := x.filterConversationSeqs(conversations, maxSeqs)
var msgs map[string]*sdkws.PullMsgs
if len(conversationSeqs) > 0 {
msgs, err = x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, conversationSeqs)
if err != nil {
return nil, err
}
}))
if err != nil {
return nil, err
}
x.checkMessagesAndGetLastMessage(ctx, req.OwnerUserID, msgs)
conversationMap := datautil.SliceToMap(conversations, func(c *conversation.Conversation) string {
@ -208,15 +210,7 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
if err != nil {
return nil, err
}
conversationSeqs := make([]*msg.ConversationSeqs, 0, len(conversations))
for _, c := range conversations {
if seq := maxSeqs[c.ConversationID]; seq > 0 {
conversationSeqs = append(conversationSeqs, &msg.ConversationSeqs{
ConversationID: c.ConversationID,
Seqs: []int64{seq},
})
}
}
conversationSeqs := x.filterConversationSeqs(conversations, maxSeqs)
var msgs map[string]*sdkws.PullMsgs
if len(conversationSeqs) > 0 {
msgs, err = x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, conversationSeqs)
@ -253,6 +247,21 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
}, nil
}
func (x *JSSdk) filterConversationSeqs(conversations []*conversation.Conversation, maxSeqs map[string]int64) []*msg.ConversationSeqs {
conversationSeqs := make([]*msg.ConversationSeqs, 0, len(conversations))
for _, c := range conversations {
seq := maxSeqs[c.ConversationID]
if seq == 0 || (c.MinSeq > 0 && seq < c.MinSeq) {
continue
}
conversationSeqs = append(conversationSeqs, &msg.ConversationSeqs{
ConversationID: c.ConversationID,
Seqs: []int64{seq},
})
}
return conversationSeqs
}
// This function checks whether the latest MaxSeq message is valid.
// If not, it needs to fetch a valid message again.
func (x *JSSdk) checkMessagesAndGetLastMessage(ctx context.Context, userID string, messages map[string]*sdkws.PullMsgs) {

View File

@ -32,7 +32,7 @@ func TestCompressDecompress(t *testing.T) {
compressor := NewGzipCompressor()
for i := 0; i < 2000; i++ {
for range 2000 {
src := mockRandom()
// compress
@ -58,10 +58,8 @@ func TestCompressDecompressWithConcurrency(t *testing.T) {
wg := sync.WaitGroup{}
compressor := NewGzipCompressor()
for i := 0; i < 200; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range 200 {
wg.Go(func() {
src := mockRandom()
// compress
@ -80,8 +78,7 @@ func TestCompressDecompressWithConcurrency(t *testing.T) {
// check
assert.EqualValues(t, src, res)
}()
})
}
wg.Wait()
}
@ -90,7 +87,7 @@ func BenchmarkCompress(b *testing.B) {
src := mockRandom()
compressor := NewGzipCompressor()
for i := 0; i < b.N; i++ {
for b.Loop() {
_, err := compressor.Compress(src)
assert.Equal(b, nil, err)
}
@ -100,7 +97,7 @@ func BenchmarkCompressWithSyncPool(b *testing.B) {
src := mockRandom()
compressor := NewGzipCompressor()
for i := 0; i < b.N; i++ {
for b.Loop() {
_, err := compressor.CompressWithPool(src)
assert.Equal(b, nil, err)
}
@ -114,7 +111,7 @@ func BenchmarkDecompress(b *testing.B) {
assert.Equal(b, nil, err)
for i := 0; i < b.N; i++ {
for b.Loop() {
_, err := compressor.DeCompress(comdata)
assert.Equal(b, nil, err)
}
@ -127,7 +124,7 @@ func BenchmarkDecompressWithSyncPool(b *testing.B) {
comdata, err := compressor.Compress(src)
assert.Equal(b, nil, err)
for i := 0; i < b.N; i++ {
for b.Loop() {
_, err := compressor.DecompressWithPool(comdata)
assert.Equal(b, nil, err)
}

View File

@ -287,6 +287,19 @@ func (g *groupServer) webhookAfterJoinGroup(ctx context.Context, after *config.A
g.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &callbackstruct.CallbackAfterJoinGroupResp{}, after)
}
func afterJoinGroupRequests(members []*model.GroupMember, reqMessage string) []*group.JoinGroupReq {
requests := make([]*group.JoinGroupReq, 0, len(members))
for _, member := range members {
requests = append(requests, &group.JoinGroupReq{
GroupID: member.GroupID,
ReqMessage: reqMessage,
JoinSource: member.JoinSource,
InviterUserID: member.UserID,
})
}
return requests
}
func (g *groupServer) webhookBeforeSetGroupInfo(ctx context.Context, before *config.BeforeConfig, req *group.SetGroupInfoReq) error {
return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
cbReq := &callbackstruct.CallbackBeforeSetGroupInfoReq{

View File

@ -23,9 +23,10 @@ import (
"strings"
"time"
"github.com/openimsdk/tools/utils/stringutil"
"google.golang.org/grpc"
"github.com/openimsdk/tools/utils/stringutil"
"github.com/openimsdk/open-im-server/v3/pkg/dbbuild"
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
@ -477,6 +478,9 @@ func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
if err := g.setMemberJoinSeq(ctx, req.GroupID, req.InvitedUserIDs); err != nil {
return nil, err
}
for _, joinReq := range afterJoinGroupRequests(groupMembers, req.Reason) {
g.webhookAfterJoinGroup(ctx, &g.config.WebhooksConfig.AfterJoinGroup, joinReq)
}
return &pbgroup.InviteUserToGroupResp{}, nil
}
@ -913,6 +917,9 @@ func (g *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
if err := g.setMemberJoinSeq(ctx, req.GroupID, []string{req.FromUserID}); err != nil {
return nil, err
}
for _, joinReq := range afterJoinGroupRequests([]*model.GroupMember{member}, groupRequest.ReqMsg) {
g.webhookAfterJoinGroup(ctx, &g.config.WebhooksConfig.AfterJoinGroup, joinReq)
}
}
case constant.GroupResponseRefuse:
g.notification.GroupApplicationRejectedNotification(ctx, req)
@ -1315,6 +1322,9 @@ func (g *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
}
func (g *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq) (*pbgroup.GetGroupsResp, error) {
if err := authverify.CheckAdmin(ctx); err != nil {
return nil, err
}
var (
group []*model.Group
err error

View File

@ -22,6 +22,8 @@ import (
"sync"
"time"
"google.golang.org/grpc"
"github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
@ -46,7 +48,6 @@ import (
"github.com/openimsdk/tools/discovery"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/utils/datautil"
"google.golang.org/grpc"
)
const (
@ -268,6 +269,9 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
}
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
if err = authverify.CheckAdmin(ctx); err != nil {
return nil, err
}
if req.UserID == "" && req.NickName == "" {
total, users, err := s.db.PageFindUser(ctx, constant.IMOrdinaryUser, constant.AppOrdinaryUsers, req.Pagination)
if err != nil {
@ -353,6 +357,9 @@ func (s *userServer) GetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Ge
// GetAllUserID Get user account by page.
func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDReq) (resp *pbuser.GetAllUserIDResp, err error) {
if err = authverify.CheckAdmin(ctx); err != nil {
return nil, err
}
total, userIDs, err := s.db.GetAllUserID(ctx, req.Pagination)
if err != nil {
return nil, err

View File

@ -835,6 +835,25 @@ func (db *commonMsgDatabase) GetLastMessage(ctx context.Context, conversationIDs
}
return nil, err
}
if msg == nil || msg.Msg == nil {
continue
}
if userID != "" {
userMinSeq, err := db.seqUser.GetUserMinSeq(ctx, conversationID, userID)
if err != nil {
return nil, err
}
minSeq, err := db.seqConversation.GetMinSeq(ctx, conversationID)
if err != nil {
return nil, err
}
if userMinSeq > minSeq {
minSeq = userMinSeq
}
if msg.Msg.Seq < minSeq {
continue
}
}
tmp := []*model.MsgInfoModel{msg}
db.handlerDeleteAndRevoked(ctx, userID, tmp)
db.handlerQuote(ctx, userID, conversationID, tmp)