From f268d91db6597d99a291d6ad2b17122fbbb24b14 Mon Sep 17 00:00:00 2001 From: hawklin2017 <32898629+hawklin2017@users.noreply.github.com> Date: Thu, 7 May 2026 23:20:44 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BE=A4=E9=82=80=E8=AF=B7=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/api/router.go | 1 + internal/api/user.go | 4 ++++ internal/rpc/group/group.go | 31 +++++++++++++++++++++++++++++++ internal/rpc/user/user.go | 31 +++++++++++++++++++++++++++++++ pkg/common/convert/user.go | 10 +++++++--- pkg/common/storage/model/user.go | 9 +++++++++ protocol | 2 +- 7 files changed, 84 insertions(+), 4 deletions(-) diff --git a/internal/api/router.go b/internal/api/router.go index 9430cc7ed..1003ff62b 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -170,6 +170,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co userRouterGroup.POST("/set_phone_visibility", u.SetPhoneVisibility) userRouterGroup.POST("/set_call_accept_setting", u.SetCallAcceptSetting) userRouterGroup.POST("/set_msg_receive_setting", u.SetMsgReceiveSetting) + userRouterGroup.POST("/set_group_invite_setting", u.SetGroupInviteSetting) // 根据手机号精确查找用户(phoneSearchVisibility=true 时遵守 phone_visibility 设置) userRouterGroup.POST("/get_user_by_phone", u.GetUserByPhone) // 根据昵称精确查询用户(可多结果,与 getPaginationUsers 模糊搜索不同) diff --git a/internal/api/user.go b/internal/api/user.go index 356251406..d5c8b4203 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -351,6 +351,10 @@ func (u *UserApi) SetMsgReceiveSetting(c *gin.Context) { a2r.Call(c, user.UserClient.SetMsgReceiveSetting, u.Client) } +func (u *UserApi) SetGroupInviteSetting(c *gin.Context) { + a2r.Call(c, user.UserClient.SetGroupInviteSetting, u.Client) +} + func (u *UserApi) GetUserByPhone(c *gin.Context) { a2r.Call(c, user.UserClient.GetUserByPhone, u.Client) } diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index d9d8fd427..fbe918c5e 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -67,6 +67,7 @@ type groupServer struct { msgClient *rpcli.MsgClient conversationClient *rpcli.ConversationClient cryptoClient *rpcli.CryptoClient + relationClient *rpcli.RelationClient } type Config struct { @@ -122,6 +123,10 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg if err != nil { return err } + friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend) + if err != nil { + return err + } //cryptoConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Crypto) //if err != nil { // return err @@ -132,6 +137,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg userClient: rpcli.NewUserClient(userConn), msgClient: rpcli.NewMsgClient(msgConn), conversationClient: rpcli.NewConversationClient(conversationConn), + relationClient: rpcli.NewRelationClient(friendConn), //cryptoClient: rpcli.NewCryptoClient(cryptoConn), } gs.db = controller.NewGroupDatabase(rdb, &config.LocalCacheConfig, groupDB, groupMemberDB, groupRequestDB, groupPinnedMsgDB, mgocli.GetTx(), grouphash.NewGroupHashFromGroupServer(&gs)) @@ -457,6 +463,31 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite return nil, errs.ErrRecordNotFound.WrapMsg("user not found") } + // 检查受邀用户的群邀请权限设置(管理员操作跳过) + if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) { + inviterID := mcontext.GetOpUserID(ctx) + for _, userID := range req.InvitedUserIDs { + info, ok := userMap[userID] + if !ok { + continue + } + switch info.GroupInviteSetting { + case 2: // GroupInviteSettingNobody:所有人不可邀请 + return nil, errs.ErrNoPermission.WrapMsg("user has disabled group invitations", "userID", userID) + case 1: // GroupInviteSettingFriends:仅好友可邀请 + isFriend, err := s.relationClient.IsFriend(ctx, inviterID, userID) + if err != nil { + log.ZError(ctx, "InviteUserToGroup: IsFriend check failed", err, + "inviterID", inviterID, "invitedUserID", userID) + return nil, err + } + if !isFriend { + return nil, errs.ErrNoPermission.WrapMsg("user only allows friends to invite them to groups", "userID", userID) + } + } + } + } + var groupMember *model.GroupMember var opUserID string if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) { diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 1d4099ec5..d5d3a84a1 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -393,6 +393,37 @@ func (s *userServer) SetMsgReceiveSetting(ctx context.Context, req *pbuser.SetMs return &pbuser.SetMsgReceiveSettingResp{}, nil } +// SetGroupInviteSetting 设置群邀请权限(0=所有人可邀请,1=仅好友可邀请,2=所有人不可邀请)。 +// 只允许本人或管理员操作。 +func (s *userServer) SetGroupInviteSetting(ctx context.Context, req *pbuser.SetGroupInviteSettingReq) (*pbuser.SetGroupInviteSettingResp, error) { + if req.UserID == "" { + return nil, errs.ErrArgs.WrapMsg("userID is required") + } + if req.GroupInviteSetting < 0 || req.GroupInviteSetting > 2 { + return nil, errs.ErrArgs.WrapMsg("groupInviteSetting must be 0, 1 or 2") + } + if err := authverify.CheckAccessV3(ctx, req.UserID, s.config.Share.IMAdminUserID); err != nil { + log.ZWarn(ctx, "SetGroupInviteSetting: access denied", err, + "opUserID", mcontext.GetOpUserID(ctx), "targetUserID", req.UserID) + return nil, err + } + if _, err := s.db.FindWithError(ctx, []string{req.UserID}); err != nil { + log.ZError(ctx, "SetGroupInviteSetting: user not found or db error", err, + "opUserID", mcontext.GetOpUserID(ctx), "targetUserID", req.UserID) + return nil, err + } + if err := s.db.UpdateByMap(ctx, req.UserID, map[string]any{ + "group_invite_setting": req.GroupInviteSetting, + }); err != nil { + log.ZError(ctx, "SetGroupInviteSetting: UpdateByMap failed", err, + "opUserID", mcontext.GetOpUserID(ctx), "targetUserID", req.UserID, + "groupInviteSetting", req.GroupInviteSetting) + return nil, err + } + s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserID) + return &pbuser.SetGroupInviteSettingResp{}, nil +} + // GetUserByPhone 根据精确手机号查询用户。 // // phone_visibility 仅控制用户资料中手机号字段是否展示,不影响搜索本身: diff --git a/pkg/common/convert/user.go b/pkg/common/convert/user.go index 2c4063cbf..1a45d6ff8 100644 --- a/pkg/common/convert/user.go +++ b/pkg/common/convert/user.go @@ -48,9 +48,10 @@ func UserDB2Pb(user *relationtb.User) *sdkws.UserInfo { Phone: user.Phone, AreaCode: user.AreaCode, PhoneVisibility: user.PhoneVisibility, - CallAcceptSetting: user.CallAcceptSetting, - MsgReceiveSetting: user.MsgReceiveSetting, - CallRingtoneURL: user.CallRingtoneURL, + CallAcceptSetting: user.CallAcceptSetting, + MsgReceiveSetting: user.MsgReceiveSetting, + GroupInviteSetting: user.GroupInviteSetting, + CallRingtoneURL: user.CallRingtoneURL, } } @@ -156,6 +157,9 @@ func UserPb2DBMapEx(user *sdkws.UserInfoWithEx) map[string]any { if user.MsgReceiveSetting != nil { val["msg_receive_setting"] = user.MsgReceiveSetting.Value } + if user.GroupInviteSetting != nil { + val["group_invite_setting"] = user.GroupInviteSetting.Value + } if user.CallRingtoneURL != nil { val["call_ringtone_url"] = user.CallRingtoneURL.Value } diff --git a/pkg/common/storage/model/user.go b/pkg/common/storage/model/user.go index 4290f1828..dea729a49 100644 --- a/pkg/common/storage/model/user.go +++ b/pkg/common/storage/model/user.go @@ -42,6 +42,14 @@ const ( MsgReceiveSettingNobody int32 = 2 ) +// GroupInviteSetting 群邀请权限枚举。 +// 0=所有人可邀请, 1=仅好友可邀请, 2=所有人不可邀请 +const ( + GroupInviteSettingPublic int32 = 0 + GroupInviteSettingFriends int32 = 1 + GroupInviteSettingNobody int32 = 2 +) + // UserStatus 用户账号状态枚举。 // 0=正常;1=冻结(可登录,不能收发消息);2=黑名单(不可登录,自动踢下线,不能收发消息) const ( @@ -66,6 +74,7 @@ type User struct { PhoneVisibility int32 `bson:"phone_visibility"` CallAcceptSetting int32 `bson:"call_accept_setting"` MsgReceiveSetting int32 `bson:"msg_receive_setting"` + GroupInviteSetting int32 `bson:"group_invite_setting"` // CallRingtoneURL 用户自定义来电铃声 URL;对方来电时播放此铃声 CallRingtoneURL string `bson:"call_ringtone_url"` // Status 账号状态:0=正常,1=冻结,2=黑名单 diff --git a/protocol b/protocol index 3b211f91d..de7a73dfc 160000 --- a/protocol +++ b/protocol @@ -1 +1 @@ -Subproject commit 3b211f91d0e6b98797f91ba34fa64a7b47df5645 +Subproject commit de7a73dfcf97ac618dacdad970da0f3cbd7f0ac8