|
|
|
package user
|
|
|
|
|
|
|
|
import (
|
|
|
|
"Open_IM/internal/common/convert"
|
|
|
|
chat "Open_IM/internal/rpc/msg"
|
|
|
|
"Open_IM/pkg/common/config"
|
|
|
|
"Open_IM/pkg/common/constant"
|
|
|
|
"Open_IM/pkg/common/db/controller"
|
|
|
|
"Open_IM/pkg/common/db/relation"
|
|
|
|
relation2 "Open_IM/pkg/common/db/table/relation"
|
|
|
|
"Open_IM/pkg/common/log"
|
|
|
|
promePkg "Open_IM/pkg/common/prometheus"
|
|
|
|
"Open_IM/pkg/common/token_verify"
|
|
|
|
"Open_IM/pkg/common/tracelog"
|
|
|
|
"Open_IM/pkg/getcdv3"
|
|
|
|
pbFriend "Open_IM/pkg/proto/friend"
|
|
|
|
pbGroup "Open_IM/pkg/proto/group"
|
|
|
|
pbUser "Open_IM/pkg/proto/user"
|
|
|
|
"Open_IM/pkg/utils"
|
|
|
|
"context"
|
|
|
|
"github.com/golang/protobuf/ptypes/wrappers"
|
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
grpcPrometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
|
|
|
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
)
|
|
|
|
|
|
|
|
type userServer struct {
|
|
|
|
rpcPort int
|
|
|
|
rpcRegisterName string
|
|
|
|
etcdSchema string
|
|
|
|
etcdAddr []string
|
|
|
|
controller.UserInterface
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUserServer(port int) *userServer {
|
|
|
|
log.NewPrivateLog(constant.LogFileName)
|
|
|
|
u := userServer{
|
|
|
|
rpcPort: port,
|
|
|
|
rpcRegisterName: config.Config.RpcRegisterName.OpenImUserName,
|
|
|
|
etcdSchema: config.Config.Etcd.EtcdSchema,
|
|
|
|
etcdAddr: config.Config.Etcd.EtcdAddr,
|
|
|
|
}
|
|
|
|
//mysql init
|
|
|
|
var mysql relation.Mysql
|
|
|
|
var model relation.UserGorm
|
|
|
|
err := mysql.InitConn().AutoMigrateModel(&model)
|
|
|
|
if err != nil {
|
|
|
|
panic("db init err:" + err.Error())
|
|
|
|
}
|
|
|
|
if mysql.GormConn() != nil {
|
|
|
|
model.DB = mysql.GormConn()
|
|
|
|
} else {
|
|
|
|
panic("db init err:" + "conn is nil")
|
|
|
|
}
|
|
|
|
u.UserInterface = controller.NewUserController(model.DB)
|
|
|
|
return &u
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) Run() {
|
|
|
|
log.NewInfo("", "rpc user start...")
|
|
|
|
|
|
|
|
listenIP := ""
|
|
|
|
if config.Config.ListenIP == "" {
|
|
|
|
listenIP = "0.0.0.0"
|
|
|
|
} else {
|
|
|
|
listenIP = config.Config.ListenIP
|
|
|
|
}
|
|
|
|
address := listenIP + ":" + strconv.Itoa(s.rpcPort)
|
|
|
|
|
|
|
|
//listener network
|
|
|
|
listener, err := net.Listen("tcp", address)
|
|
|
|
if err != nil {
|
|
|
|
panic("listening err:" + err.Error() + s.rpcRegisterName)
|
|
|
|
}
|
|
|
|
log.NewInfo("", "listen network success, address ", address, listener)
|
|
|
|
defer listener.Close()
|
|
|
|
//grpc server
|
|
|
|
var grpcOpts []grpc.ServerOption
|
|
|
|
if config.Config.Prometheus.Enable {
|
|
|
|
promePkg.NewGrpcRequestCounter()
|
|
|
|
promePkg.NewGrpcRequestFailedCounter()
|
|
|
|
promePkg.NewGrpcRequestSuccessCounter()
|
|
|
|
grpcOpts = append(grpcOpts, []grpc.ServerOption{
|
|
|
|
// grpc.UnaryInterceptor(promePkg.UnaryServerInterceptorProme),
|
|
|
|
grpc.StreamInterceptor(grpcPrometheus.StreamServerInterceptor),
|
|
|
|
grpc.UnaryInterceptor(grpcPrometheus.UnaryServerInterceptor),
|
|
|
|
}...)
|
|
|
|
}
|
|
|
|
srv := grpc.NewServer(grpcOpts...)
|
|
|
|
defer srv.GracefulStop()
|
|
|
|
//Service registers with etcd
|
|
|
|
pbUser.RegisterUserServer(srv, s)
|
|
|
|
rpcRegisterIP := config.Config.RpcRegisterIP
|
|
|
|
if config.Config.RpcRegisterIP == "" {
|
|
|
|
rpcRegisterIP, err = utils.GetLocalIP()
|
|
|
|
if err != nil {
|
|
|
|
log.Error("", "GetLocalIP failed ", err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err = getcdv3.RegisterEtcd(s.etcdSchema, strings.Join(s.etcdAddr, ","), rpcRegisterIP, s.rpcPort, s.rpcRegisterName, 10, "")
|
|
|
|
if err != nil {
|
|
|
|
log.NewError("", "RegisterEtcd failed ", err.Error(), s.etcdSchema, strings.Join(s.etcdAddr, ","), rpcRegisterIP, s.rpcPort, s.rpcRegisterName)
|
|
|
|
panic(utils.Wrap(err, "register user module rpc to etcd err"))
|
|
|
|
}
|
|
|
|
err = srv.Serve(listener)
|
|
|
|
if err != nil {
|
|
|
|
log.NewError("", "Serve failed ", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.NewInfo("", "rpc user success")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) SyncJoinedGroupMemberFaceURL(ctx context.Context, userID string, faceURL string, operationID string, opUserID string) {
|
|
|
|
etcdConn, err := getcdv3.GetConn(ctx, config.Config.RpcRegisterName.OpenImFriendName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
client := pbGroup.NewGroupClient(etcdConn)
|
|
|
|
newReq := &pbGroup.GetJoinedGroupListReq{FromUserID: userID}
|
|
|
|
rpcResp, err := client.GetJoinedGroupList(ctx, newReq)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, group := range rpcResp.Groups {
|
|
|
|
req := &pbGroup.SetGroupMemberInfoReq{GroupID: group.GroupID, UserID: userID, FaceURL: &wrappers.StringValue{Value: faceURL}}
|
|
|
|
_, err := client.SetGroupMemberInfo(ctx, req)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
chat.GroupMemberInfoSetNotification(operationID, opUserID, group.GroupID, userID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) SyncJoinedGroupMemberNickname(ctx context.Context, userID string, newNickname, oldNickname string, operationID string, opUserID string) {
|
|
|
|
etcdConn, err := getcdv3.GetConn(ctx, config.Config.RpcRegisterName.OpenImFriendName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
client := pbGroup.NewGroupClient(etcdConn)
|
|
|
|
newReq := &pbGroup.GetJoinedGroupListReq{FromUserID: userID}
|
|
|
|
rpcResp, err := client.GetJoinedGroupList(ctx, newReq)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
req := pbGroup.GetUserInGroupMembersReq{UserID: userID}
|
|
|
|
for _, group := range rpcResp.Groups {
|
|
|
|
req.GroupIDs = append(req.GroupIDs, group.GroupID)
|
|
|
|
}
|
|
|
|
resp, err := client.GetUserInGroupMembers(ctx, &req)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, v := range resp.Members {
|
|
|
|
if v.Nickname == oldNickname {
|
|
|
|
req := pbGroup.SetGroupMemberNicknameReq{Nickname: newNickname, GroupID: v.GroupID, UserID: v.UserID}
|
|
|
|
_, err := client.SetGroupMemberNickname(ctx, &req)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
chat.GroupMemberInfoSetNotification(operationID, opUserID, v.GroupID, userID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) GetUsersInfo(ctx context.Context, req *pbUser.GetUsersInfoReq) (*pbUser.GetUsersInfoResp, error) {
|
|
|
|
resp := &pbUser.GetUsersInfoResp{}
|
|
|
|
users, err := s.Find(ctx, req.UserIDs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.UsersInfo, err = (*convert.DBUser)(nil).DB2PB(users)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbUser.UpdateUserInfoReq) (*pbUser.UpdateUserInfoResp, error) {
|
|
|
|
resp := pbUser.UpdateUserInfoResp{}
|
|
|
|
err := token_verify.CheckAccessV3(ctx, req.UserInfo.UserID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
oldNickname := ""
|
|
|
|
if req.UserInfo.Nickname != "" {
|
|
|
|
u, err := s.Find(ctx, []string{req.UserInfo.UserID})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
oldNickname = u[0].Nickname
|
|
|
|
}
|
|
|
|
user, err := convert.NewPBUser(req.UserInfo).Convert()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = s.Update(ctx, []*relation2.UserModel{user})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
etcdConn, err := getcdv3.GetConn(ctx, config.Config.RpcRegisterName.OpenImFriendName)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
client := pbFriend.NewFriendClient(etcdConn)
|
|
|
|
newReq := &pbFriend.GetFriendsReq{UserID: req.UserInfo.UserID}
|
|
|
|
rpcResp, err := client.GetFriends(context.Background(), newReq)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
for _, v := range rpcResp.FriendsInfo {
|
|
|
|
chat.FriendInfoUpdatedNotification(ctx, req.UserInfo.UserID, v.FriendUser.UserID, tracelog.GetOpUserID(ctx))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
chat.UserInfoUpdatedNotification(ctx, tracelog.GetOpUserID(ctx), req.UserInfo.UserID)
|
|
|
|
if req.UserInfo.FaceURL != "" {
|
|
|
|
s.SyncJoinedGroupMemberFaceURL(ctx, req.UserInfo.UserID, req.UserInfo.FaceURL, tracelog.GetOperationID(ctx), tracelog.GetOpUserID(ctx))
|
|
|
|
}
|
|
|
|
if req.UserInfo.Nickname != "" {
|
|
|
|
s.SyncJoinedGroupMemberNickname(ctx, req.UserInfo.UserID, req.UserInfo.Nickname, oldNickname, tracelog.GetOperationID(ctx), tracelog.GetOpUserID(ctx))
|
|
|
|
}
|
|
|
|
return &resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req *pbUser.SetGlobalRecvMessageOptReq) (*pbUser.SetGlobalRecvMessageOptResp, error) {
|
|
|
|
resp := pbUser.SetGlobalRecvMessageOptResp{}
|
|
|
|
m := make(map[string]interface{}, 1)
|
|
|
|
m["global_recv_msg_opt"] = req.GlobalRecvMsgOpt
|
|
|
|
err := s.UpdateByMap(ctx, req.UserID, m)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
chat.UserInfoUpdatedNotification(ctx, req.UserID, req.UserID)
|
|
|
|
return &resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) AccountCheck(ctx context.Context, req *pbUser.AccountCheckReq) (*pbUser.AccountCheckResp, error) {
|
|
|
|
resp := pbUser.AccountCheckResp{}
|
|
|
|
err := token_verify.CheckAdmin(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
user, err := s.Find(ctx, req.CheckUserIDs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
uidList := make([]string, 0)
|
|
|
|
for _, v := range user {
|
|
|
|
uidList = append(uidList, v.UserID)
|
|
|
|
}
|
|
|
|
var r []*pbUser.AccountCheckRespSingleUserStatus
|
|
|
|
for _, v := range req.CheckUserIDs {
|
|
|
|
temp := new(pbUser.AccountCheckRespSingleUserStatus)
|
|
|
|
temp.UserID = v
|
|
|
|
if utils.IsContain(v, uidList) {
|
|
|
|
temp.AccountStatus = constant.Registered
|
|
|
|
} else {
|
|
|
|
temp.AccountStatus = constant.UnRegistered
|
|
|
|
}
|
|
|
|
r = append(r, temp)
|
|
|
|
}
|
|
|
|
return &resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) GetUsers(ctx context.Context, req *pbUser.GetUsersReq) (*pbUser.GetUsersResp, error) {
|
|
|
|
resp := pbUser.GetUsersResp{}
|
|
|
|
var err error
|
|
|
|
if req.UserID != "" {
|
|
|
|
u, err := s.Find(ctx, []string{req.UserID})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Total = 1
|
|
|
|
u1, err := convert.NewDBUser(u[0]).Convert()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Users = append(resp.Users, u1)
|
|
|
|
return &resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.UserName != "" {
|
|
|
|
usersDB, total, err := s.GetByName(ctx, req.UserName, req.Pagination.ShowNumber, req.Pagination.PageNumber)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Total = int32(total)
|
|
|
|
for _, v := range usersDB {
|
|
|
|
u1, err := convert.NewDBUser(v).Convert()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Users = append(resp.Users, u1)
|
|
|
|
}
|
|
|
|
return &resp, nil
|
|
|
|
} else if req.Content != "" {
|
|
|
|
usersDB, total, err := s.GetByNameAndID(ctx, req.UserName, req.Pagination.ShowNumber, req.Pagination.PageNumber)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Total = int32(total)
|
|
|
|
for _, v := range usersDB {
|
|
|
|
u1, err := convert.NewDBUser(v).Convert()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Users = append(resp.Users, u1)
|
|
|
|
}
|
|
|
|
return &resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
usersDB, total, err := s.Get(ctx, req.Pagination.ShowNumber, req.Pagination.PageNumber)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
resp.Total = int32(total)
|
|
|
|
|
|
|
|
for _, userDB := range usersDB {
|
|
|
|
u, err := convert.NewDBUser(userDB).Convert()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
resp.Users = append(resp.Users, u)
|
|
|
|
}
|
|
|
|
return &resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *userServer) UserRegister(ctx context.Context, req *pbUser.UserRegisterReq) (*pbUser.UserRegisterResp, error) {
|
|
|
|
resp := pbUser.UserRegisterResp{}
|
|
|
|
userIDs := make([]string, 0)
|
|
|
|
for _, v := range req.Users {
|
|
|
|
userIDs = append(userIDs, v.UserID)
|
|
|
|
}
|
|
|
|
exist, err := s.IsExist(ctx, userIDs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if exist {
|
|
|
|
return nil, constant.ErrRegisteredAlready.Wrap("exist")
|
|
|
|
}
|
|
|
|
users, err := (*convert.PBUser)(nil).PB2DB(req.Users)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = s.Create(ctx, users)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &resp, nil
|
|
|
|
}
|