From a5ac7f2a8117ec6b283c74a9d6a4db578a2bdd37 Mon Sep 17 00:00:00 2001 From: icey-yu <119291641+icey-yu@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:33:19 +0800 Subject: [PATCH] feat: add nickname for adminUser (#3435) * feat: add nickname for adminUser * feat: add nickname for adminUser * feat: add nickname for adminUser --- config/share.yml | 9 ++++++++- internal/api/router.go | 6 +++--- internal/msggateway/ws_server.go | 2 +- internal/push/push_handler.go | 4 ++-- internal/rpc/auth/auth.go | 12 +++++++----- internal/rpc/group/group.go | 4 +++- internal/rpc/msg/revoke.go | 4 ++-- internal/rpc/msg/server.go | 4 +++- internal/rpc/msg/verify.go | 4 ++-- internal/rpc/user/user.go | 13 ++++++++++--- internal/tools/cron/cron_task.go | 3 +-- pkg/common/config/config.go | 7 +++++-- pkg/common/startrpc/start.go | 4 ++-- pkg/common/storage/controller/user.go | 24 +++++++++++++++++++++--- test/stress-test-v2/main.go | 2 +- test/stress-test/main.go | 2 +- 16 files changed, 72 insertions(+), 32 deletions(-) diff --git a/config/share.yml b/config/share.yml index 2e9821436..a42bdcdd7 100644 --- a/config/share.yml +++ b/config/share.yml @@ -1,6 +1,13 @@ secret: openIM123 -imAdminUserID: [imAdmin] +# imAdminUser: Configuration for instant messaging system administrators +imAdminUser: + # userIDs: List of administrator user IDs. + # Each entry here corresponds by index to the matching entry in the nicknames list below. + userIDs: [imAdmin] + # nicknames: List of administrator display names. + # Each entry here corresponds by index to the matching entry in the userIDs list above. + nicknames: [superAdmin] # 1: For Android, iOS, Windows, Mac, and web platforms, only one instance can be online at a time multiLogin: diff --git a/internal/api/router.go b/internal/api/router.go index 43456f6d6..8a4199581 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -98,7 +98,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf r.Use(gzip.Gzip(gzip.BestSpeed)) } r.Use(api.GinLogger(), prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(), - mw.GinParseOperationID(), GinParseToken(rpcli.NewAuthClient(authConn)), setGinIsAdmin(cfg.Share.IMAdminUserID)) + mw.GinParseOperationID(), GinParseToken(rpcli.NewAuthClient(authConn)), setGinIsAdmin(cfg.Share.IMAdminUser.UserIDs)) u := NewUserApi(user.NewUserClient(userConn), client, cfg.Discovery.RpcService) { @@ -232,7 +232,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf objectGroup.GET("/*name", t.ObjectRedirect) } // Message - m := NewMessageApi(msg.NewMsgClient(msgConn), rpcli.NewUserClient(userConn), cfg.Share.IMAdminUserID) + m := NewMessageApi(msg.NewMsgClient(msgConn), rpcli.NewUserClient(userConn), cfg.Share.IMAdminUser.UserIDs) { msgGroup := r.Group("/msg") msgGroup.POST("/newest_seq", m.GetSeq) @@ -309,7 +309,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf if cfg.Discovery.Enable == config.ETCD { etcdClient = client.(*etcd.SvcDiscoveryRegistryImpl).GetClient() } - cm := NewConfigManager(cfg.Share.IMAdminUserID, &cfg.AllConfig, etcdClient, string(cfg.ConfigPath)) + cm := NewConfigManager(cfg.Share.IMAdminUser.UserIDs, &cfg.AllConfig, etcdClient, string(cfg.ConfigPath)) { configGroup := r.Group("/config", cm.CheckAdmin) configGroup.POST("/get_config_list", cm.GetConfigList) diff --git a/internal/msggateway/ws_server.go b/internal/msggateway/ws_server.go index 211482cb1..9b7343938 100644 --- a/internal/msggateway/ws_server.go +++ b/internal/msggateway/ws_server.go @@ -130,7 +130,7 @@ func NewWsServer(msgGatewayConfig *Config, opts ...Option) *WsServer { for _, o := range opts { o(&config) } - //userRpcClient := rpcclient.NewUserRpcClient(client, config.Discovery.RpcService.User, config.Share.IMAdminUserID) + //userRpcClient := rpcclient.NewUserRpcClient(client, config.Discovery.RpcService.User, config.Share.IMAdminUser) v := validator.New() return &WsServer{ diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go index 7b1efe3bf..4f1964084 100644 --- a/internal/push/push_handler.go +++ b/internal/push/push_handler.go @@ -317,8 +317,8 @@ func (c *ConsumerHandler) groupMessagesHandler(ctx context.Context, groupID stri return err } log.ZDebug(ctx, "GroupDismissedNotificationInfo****", "groupID", groupID, "num", len(*pushToUserIDs), "list", pushToUserIDs) - if len(c.config.Share.IMAdminUserID) > 0 { - ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0]) + if len(c.config.Share.IMAdminUser.UserIDs) > 0 { + ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUser.UserIDs[0]) } defer func(groupID string) { if err := c.groupClient.DismissGroup(ctx, groupID, true); err != nil { diff --git a/internal/rpc/auth/auth.go b/internal/rpc/auth/auth.go index 5ed9cdf12..7a8607164 100644 --- a/internal/rpc/auth/auth.go +++ b/internal/rpc/auth/auth.go @@ -49,6 +49,7 @@ type authServer struct { RegisterCenter discovery.Conn config *Config userClient *rpcli.UserClient + adminUserIDs []string } type Config struct { @@ -90,10 +91,11 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg config.Share.Secret, config.RpcConfig.TokenPolicy.Expire, config.Share.MultiLogin, - config.Share.IMAdminUserID, + config.Share.IMAdminUser.UserIDs, ), - config: config, - userClient: rpcli.NewUserClient(userConn), + config: config, + userClient: rpcli.NewUserClient(userConn), + adminUserIDs: config.Share.IMAdminUser.UserIDs, }) return nil } @@ -104,8 +106,8 @@ func (s *authServer) GetAdminToken(ctx context.Context, req *pbauth.GetAdminToke return nil, errs.ErrNoPermission.WrapMsg("secret invalid") } - if !datautil.Contain(req.UserID, s.config.Share.IMAdminUserID...) { - return nil, errs.ErrArgs.WrapMsg("userID is error.", "userID", req.UserID, "adminUserID", s.config.Share.IMAdminUserID) + if !datautil.Contain(req.UserID, s.adminUserIDs...) { + return nil, errs.ErrArgs.WrapMsg("userID is error.", "userID", req.UserID, "adminUserID", s.adminUserIDs) } diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index ce8a2c7aa..3700c054a 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -63,6 +63,7 @@ type groupServer struct { userClient *rpcli.UserClient msgClient *rpcli.MsgClient conversationClient *rpcli.ConversationClient + adminUserIDs []string } type Config struct { @@ -116,6 +117,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg userClient: rpcli.NewUserClient(userConn), msgClient: rpcli.NewMsgClient(msgConn), conversationClient: rpcli.NewConversationClient(conversationConn), + adminUserIDs: config.Share.IMAdminUser.UserIDs, } gs.db = controller.NewGroupDatabase(rdb, &config.LocalCacheConfig, groupDB, groupMemberDB, groupRequestDB, mgocli.GetTx(), grouphash.NewGroupHashFromGroupServer(&gs)) gs.notification = NewNotificationSender(gs.db, config, gs.userClient, gs.msgClient, gs.conversationClient) @@ -1901,7 +1903,7 @@ func (g *groupServer) GetSpecifiedUserGroupRequestInfo(ctx context.Context, req } adminIDs = append(adminIDs, owners[0].UserID) - adminIDs = append(adminIDs, g.config.Share.IMAdminUserID...) + adminIDs = append(adminIDs, g.adminUserIDs...) if !datautil.Contain(opUserID, adminIDs...) { return nil, errs.ErrNoPermission.WrapMsg("opUser no permission") diff --git a/internal/rpc/msg/revoke.go b/internal/rpc/msg/revoke.go index bd1d66ba1..1f4d6be68 100644 --- a/internal/rpc/msg/revoke.go +++ b/internal/rpc/msg/revoke.go @@ -109,8 +109,8 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. revokerUserID := mcontext.GetOpUserID(ctx) var flag bool - if len(m.config.Share.IMAdminUserID) > 0 { - flag = datautil.Contain(revokerUserID, m.config.Share.IMAdminUserID...) + if len(m.config.Share.IMAdminUser.UserIDs) > 0 { + flag = datautil.Contain(revokerUserID, m.adminUserIDs...) } tips := sdkws.RevokeMsgTips{ RevokerUserID: revokerUserID, diff --git a/internal/rpc/msg/server.go b/internal/rpc/msg/server.go index 9d5391cc9..48101cdd7 100644 --- a/internal/rpc/msg/server.go +++ b/internal/rpc/msg/server.go @@ -22,7 +22,6 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/dbbuild" "github.com/openimsdk/open-im-server/v3/pkg/mqbuild" "github.com/openimsdk/open-im-server/v3/pkg/rpcli" - "google.golang.org/grpc" "github.com/openimsdk/open-im-server/v3/pkg/common/config" @@ -71,6 +70,8 @@ type msgServer struct { config *Config // Global configuration settings. webhookClient *webhook.Client conversationClient *rpcli.ConversationClient + + adminUserIDs []string } func (m *msgServer) addInterceptorHandler(interceptorFunc ...MessageInterceptorFunc) { @@ -145,6 +146,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg config: config, webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL), conversationClient: conversationClient, + adminUserIDs: config.Share.IMAdminUser.UserIDs, } s.notificationSender = notification.NewNotificationSender(&config.NotificationConfig, notification.WithLocalSendMsg(s.SendMsg)) diff --git a/internal/rpc/msg/verify.go b/internal/rpc/msg/verify.go index 213545d83..d0f36a388 100644 --- a/internal/rpc/msg/verify.go +++ b/internal/rpc/msg/verify.go @@ -54,7 +54,7 @@ type MessageRevoked struct { func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgReq) error { switch data.MsgData.SessionType { case constant.SingleChatType: - if datautil.Contain(data.MsgData.SendID, m.config.Share.IMAdminUserID...) { + if datautil.Contain(data.MsgData.SendID, m.adminUserIDs...) { return nil } if data.MsgData.ContentType <= constant.NotificationEnd && @@ -102,7 +102,7 @@ func (m *msgServer) messageVerification(ctx context.Context, data *msg.SendMsgRe return nil } - if datautil.Contain(data.MsgData.SendID, m.config.Share.IMAdminUserID...) { + if datautil.Contain(data.MsgData.SendID, m.adminUserIDs...) { return nil } if data.MsgData.ContentType <= constant.NotificationEnd && diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 28461ae0a..91dfe736e 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -65,6 +65,8 @@ type userServer struct { groupClient *rpcli.GroupClient relationClient *rpcli.RelationClient clientConfig controller.ClientConfigDatabase + + adminUserIDs []string } type Config struct { @@ -92,8 +94,12 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg users := make([]*tablerelation.User, 0) - for _, v := range config.Share.IMAdminUserID { - users = append(users, &tablerelation.User{UserID: v, Nickname: v, AppMangerLevel: constant.AppAdmin}) + for i := range config.Share.IMAdminUser.UserIDs { + users = append(users, &tablerelation.User{ + UserID: config.Share.IMAdminUser.UserIDs[i], + Nickname: config.Share.IMAdminUser.Nicknames[i], + AppMangerLevel: constant.AppAdmin, + }) } userDB, err := mgo.NewUserMongo(mgocli.GetDB()) if err != nil { @@ -130,6 +136,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg clientConfig: controller.NewClientConfigDatabase(clientConfigDB, redis.NewClientConfigCache(rdb, clientConfigDB), mgocli.GetTx()), groupClient: rpcli.NewGroupClient(groupConn), relationClient: rpcli.NewRelationClient(friendConn), + adminUserIDs: config.Share.IMAdminUser.UserIDs, } pbuser.RegisterUserServer(server, u) return u.db.InitOnce(context.Background(), users) @@ -648,7 +655,7 @@ func (s *userServer) userModelToResp(users []*tablerelation.User, pagination pag accounts := make([]*pbuser.NotificationAccountInfo, 0) var total int64 for _, v := range users { - if v.AppMangerLevel >= constant.AppNotificationAdmin && !datautil.Contain(v.UserID, s.config.Share.IMAdminUserID...) { + if v.AppMangerLevel >= constant.AppNotificationAdmin && !datautil.Contain(v.UserID, s.adminUserIDs...) { if appManagerLevel != nil { if v.AppMangerLevel != *appManagerLevel { continue diff --git a/internal/tools/cron/cron_task.go b/internal/tools/cron/cron_task.go index a6740ab6e..2c8655d4a 100644 --- a/internal/tools/cron/cron_task.go +++ b/internal/tools/cron/cron_task.go @@ -10,7 +10,6 @@ import ( "github.com/openimsdk/protocol/third" "github.com/openimsdk/tools/discovery" "github.com/openimsdk/tools/discovery/etcd" - "github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/log" "github.com/openimsdk/tools/mcontext" @@ -32,7 +31,7 @@ func Start(ctx context.Context, conf *Config, client discovery.SvcDiscoveryRegis <-ctx.Done() return nil } - ctx = mcontext.SetOpUserID(ctx, conf.Share.IMAdminUserID[0]) + ctx = mcontext.SetOpUserID(ctx, conf.Share.IMAdminUser.UserIDs[0]) msgConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Msg) if err != nil { diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 619571064..43914310e 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -356,8 +356,11 @@ type AfterConfig struct { } type Share struct { - Secret string `yaml:"secret"` - IMAdminUserID []string `yaml:"imAdminUserID"` + Secret string `yaml:"secret"` + IMAdminUser struct { + UserIDs []string `yaml:"userIDs"` + Nicknames []string `yaml:"nicknames"` + } `yaml:"imAdminUser"` MultiLogin MultiLogin `yaml:"multiLogin"` RPCMaxBodySize MaxRequestBody `yaml:"rpcMaxBodySize"` } diff --git a/pkg/common/startrpc/start.go b/pkg/common/startrpc/start.go index 06e19d8d2..9715f2aac 100644 --- a/pkg/common/startrpc/start.go +++ b/pkg/common/startrpc/start.go @@ -69,8 +69,8 @@ func Start[T any](ctx context.Context, disc *conf.Discovery, prometheusConfig *c grpcsrv.GrpcServerRequestValidate(), grpcsrv.GrpcServerPanicCapture(), ) - if shareConfig != nil && len(shareConfig.IMAdminUserID) > 0 { - options = append(options, grpcServerIMAdminUserID(shareConfig.IMAdminUserID)) + if shareConfig != nil && len(shareConfig.IMAdminUser.UserIDs) > 0 { + options = append(options, grpcServerIMAdminUserID(shareConfig.IMAdminUser.UserIDs)) } var clientOptions []grpc.DialOption if maxRequestBody != nil { diff --git a/pkg/common/storage/controller/user.go b/pkg/common/storage/controller/user.go index f97c5330b..d747ce2fa 100644 --- a/pkg/common/storage/controller/user.go +++ b/pkg/common/storage/controller/user.go @@ -97,16 +97,34 @@ func (u *userDatabase) InitOnce(ctx context.Context, users []*model.User) error } // Determine which users are missing from the database. - missingUsers := datautil.SliceAnySub(users, existingUsers, func(e *model.User) string { + var ( + missing, update []*model.User + ) + existMap := datautil.SliceToMap(existingUsers, func(e *model.User) string { return e.UserID }) + orgMap := datautil.SliceToMap(users, func(e *model.User) string { return e.UserID }) + for k, u1 := range orgMap { + if u2, ok := existMap[k]; !ok { + missing = append(missing, u1) + } else if u1.Nickname != u2.Nickname { + update = append(update, u1) + } + } // Create records for missing users. - if len(missingUsers) > 0 { - if err := u.userDB.Create(ctx, missingUsers); err != nil { + if len(missing) > 0 { + if err := u.userDB.Create(ctx, missing); err != nil { return err } } + if len(update) > 0 { + for i := range update { + if err := u.userDB.UpdateByMap(ctx, update[i].UserID, map[string]any{"nickname": update[i].Nickname}); err != nil { + return err + } + } + } return nil } diff --git a/test/stress-test-v2/main.go b/test/stress-test-v2/main.go index 0e4609964..63ce77065 100644 --- a/test/stress-test-v2/main.go +++ b/test/stress-test-v2/main.go @@ -446,7 +446,7 @@ func main() { Share: *share, Api: *apiConfig, }, - AdminUserID: share.IMAdminUserID[0], + AdminUserID: share.IMAdminUser.UserIDs[0], Ctx: ctx, Cancel: cancel, HttpClient: &http.Client{ diff --git a/test/stress-test/main.go b/test/stress-test/main.go index 6adbd12ee..d7822e51b 100755 --- a/test/stress-test/main.go +++ b/test/stress-test/main.go @@ -319,7 +319,7 @@ func main() { Share: *share, Api: *apiConfig, }, - AdminUserID: share.IMAdminUserID[0], + AdminUserID: share.IMAdminUser.UserIDs[0], Ctx: ctx, Cancel: cancel, HttpClient: &http.Client{