复制项目
This commit is contained in:
623
internal/rpc/chat/user.go
Normal file
623
internal/rpc/chat/user.go
Normal file
@@ -0,0 +1,623 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.imall.cloud/openim/protocol/wrapperspb"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/dbutil"
|
||||
chatdb "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
constantpb "git.imall.cloud/openim/protocol/constant"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/constant"
|
||||
"git.imall.cloud/openim/chat/pkg/common/mctx"
|
||||
"git.imall.cloud/openim/chat/pkg/eerrs"
|
||||
"git.imall.cloud/openim/chat/pkg/protocol/chat"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
func (o *chatSvr) checkUpdateInfo(ctx context.Context, req *chat.UpdateUserInfoReq) error {
|
||||
if req.AreaCode != nil || req.PhoneNumber != nil {
|
||||
if !(req.AreaCode != nil && req.PhoneNumber != nil) {
|
||||
return errs.ErrArgs.WrapMsg("areaCode and phoneNumber must be set together")
|
||||
}
|
||||
if req.AreaCode.Value == "" || req.PhoneNumber.Value == "" {
|
||||
if req.AreaCode.Value != req.PhoneNumber.Value {
|
||||
return errs.ErrArgs.WrapMsg("areaCode and phoneNumber must be set together")
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.UserID == "" {
|
||||
return errs.ErrArgs.WrapMsg("user id is empty")
|
||||
}
|
||||
|
||||
credentials, err := o.Database.TakeCredentialsByUserID(ctx, req.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(credentials) == 0 {
|
||||
return errs.ErrArgs.WrapMsg("user not found")
|
||||
}
|
||||
var (
|
||||
credNum, delNum, addNum = len(credentials), 0, 0
|
||||
)
|
||||
|
||||
addFunc := func(s *wrapperspb.StringValue) {
|
||||
if s != nil {
|
||||
if s.Value != "" {
|
||||
addNum++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range []*wrapperspb.StringValue{req.Account, req.PhoneNumber, req.Email} {
|
||||
addFunc(s)
|
||||
}
|
||||
|
||||
for _, credential := range credentials {
|
||||
switch credential.Type {
|
||||
case constant.CredentialAccount:
|
||||
if req.Account != nil {
|
||||
if req.Account.Value == credential.Account {
|
||||
req.Account = nil
|
||||
} else if req.Account.Value == "" {
|
||||
delNum += 1
|
||||
}
|
||||
}
|
||||
case constant.CredentialPhone:
|
||||
if req.PhoneNumber != nil {
|
||||
phoneAccount := BuildCredentialPhone(req.AreaCode.Value, req.PhoneNumber.Value)
|
||||
if phoneAccount == credential.Account {
|
||||
req.AreaCode = nil
|
||||
req.PhoneNumber = nil
|
||||
} else if req.PhoneNumber.Value == "" {
|
||||
delNum += 1
|
||||
}
|
||||
}
|
||||
case constant.CredentialEmail:
|
||||
if req.Email != nil {
|
||||
if req.Email.Value == credential.Account {
|
||||
req.Email = nil
|
||||
} else if req.Email.Value == "" {
|
||||
delNum += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if addNum+credNum-delNum <= 0 {
|
||||
return errs.ErrArgs.WrapMsg("a login method must exist")
|
||||
}
|
||||
|
||||
if req.PhoneNumber.GetValue() != "" {
|
||||
if !strings.HasPrefix(req.AreaCode.GetValue(), "+") {
|
||||
req.AreaCode.Value = "+" + req.AreaCode.Value
|
||||
}
|
||||
if _, err := strconv.ParseUint(req.AreaCode.Value[1:], 10, 64); err != nil {
|
||||
return errs.ErrArgs.WrapMsg("area code must be number")
|
||||
}
|
||||
if _, err := strconv.ParseUint(req.PhoneNumber.GetValue(), 10, 64); err != nil {
|
||||
return errs.ErrArgs.WrapMsg("phone number must be number")
|
||||
}
|
||||
phoneAccount := BuildCredentialPhone(req.AreaCode.GetValue(), req.PhoneNumber.GetValue())
|
||||
existingCredential, err := o.Database.TakeCredentialByAccount(ctx, phoneAccount)
|
||||
if err == nil {
|
||||
// 如果手机号已存在,检查是否是当前用户的手机号
|
||||
if existingCredential.UserID == req.UserID {
|
||||
// 是当前用户的手机号,允许更新(实际上是相同值,不需要更新)
|
||||
req.AreaCode = nil
|
||||
req.PhoneNumber = nil
|
||||
} else {
|
||||
// 是其他用户的手机号,返回错误
|
||||
return eerrs.ErrPhoneAlreadyRegister.Wrap()
|
||||
}
|
||||
} else if !dbutil.IsDBNotFound(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.Account.GetValue() != "" {
|
||||
accountValue := req.Account.GetValue()
|
||||
// 验证长度:6到20位
|
||||
if len(accountValue) < 6 || len(accountValue) > 20 {
|
||||
return errs.ErrArgs.WrapMsg("account must be between 6 and 20 characters")
|
||||
}
|
||||
// 验证格式:只能包含数字、字母、下划线(_)、横线(-)
|
||||
pattern := `^[a-zA-Z0-9_-]+$`
|
||||
matched, err := regexp.MatchString(pattern, accountValue)
|
||||
if err != nil || !matched {
|
||||
return errs.ErrArgs.WrapMsg("account must contain only letters, numbers, underscores, and hyphens")
|
||||
}
|
||||
existingCredential, err := o.Database.TakeCredentialByAccount(ctx, accountValue)
|
||||
if err == nil {
|
||||
// 如果账户已存在,检查是否是当前用户的账户
|
||||
if existingCredential.UserID == req.UserID {
|
||||
// 是当前用户的账户,允许更新(实际上是相同值,不需要更新)
|
||||
req.Account = nil
|
||||
|
||||
} else {
|
||||
// 是其他用户的账户,返回错误
|
||||
return eerrs.ErrAccountAlreadyRegister.Wrap()
|
||||
}
|
||||
} else if !dbutil.IsDBNotFound(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.Email.GetValue() != "" {
|
||||
if !stringutil.IsValidEmail(req.Email.GetValue()) {
|
||||
return errs.ErrArgs.WrapMsg("invalid email")
|
||||
}
|
||||
existingCredential, err := o.Database.TakeCredentialByAccount(ctx, req.Email.GetValue())
|
||||
if err == nil {
|
||||
// 如果邮箱已存在,检查是否是当前用户的邮箱
|
||||
if existingCredential.UserID == req.UserID {
|
||||
// 是当前用户的邮箱,允许更新(实际上是相同值,不需要更新)
|
||||
req.Email = nil
|
||||
} else {
|
||||
// 是其他用户的邮箱,返回错误
|
||||
return eerrs.ErrEmailAlreadyRegister.Wrap()
|
||||
}
|
||||
} else if !dbutil.IsDBNotFound(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) UpdateUserInfo(ctx context.Context, req *chat.UpdateUserInfoReq) (*chat.UpdateUserInfoResp, error) {
|
||||
opUserID, userType, err := mctx.Check(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = o.checkUpdateInfo(ctx, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch userType {
|
||||
case constant.NormalUser:
|
||||
if req.RegisterType != nil {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("registerType can not be updated")
|
||||
}
|
||||
if req.UserID != opUserID {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("only admin can update other user info")
|
||||
}
|
||||
// 普通用户不能修改自己的用户类型
|
||||
if req.UserType != 0 {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("normal user can not update userType")
|
||||
}
|
||||
|
||||
case constant.AdminUser:
|
||||
// 管理员可以修改用户类型,但需要验证值
|
||||
if req.UserType < 0 || req.UserType > 3 {
|
||||
return nil, errs.ErrArgs.WrapMsg("invalid userType: must be 0-3")
|
||||
}
|
||||
default:
|
||||
return nil, errs.ErrNoPermission.WrapMsg("user type error")
|
||||
}
|
||||
|
||||
update, err := ToDBAttributeUpdate(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userType == constant.NormalUser {
|
||||
delete(update, "user_flag")
|
||||
delete(update, "user_type")
|
||||
}
|
||||
|
||||
credUpdate, credDel, err := ToDBCredentialUpdate(req, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(update) > 0 {
|
||||
if err := o.Database.UpdateUseInfo(ctx, req.UserID, update, credUpdate, credDel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &chat.UpdateUserInfoResp{}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) FindUserPublicInfo(ctx context.Context, req *chat.FindUserPublicInfoReq) (*chat.FindUserPublicInfoResp, error) {
|
||||
if len(req.UserIDs) == 0 {
|
||||
return nil, errs.ErrArgs.WrapMsg("UserIDs is empty")
|
||||
}
|
||||
attributes, err := o.Database.FindAttribute(ctx, req.UserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chat.FindUserPublicInfoResp{
|
||||
Users: DbToPbAttributes(attributes),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) AddUserAccount(ctx context.Context, req *chat.AddUserAccountReq) (*chat.AddUserAccountResp, error) {
|
||||
if _, _, err := mctx.Check(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := o.checkRegisterInfo(ctx, req.User, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.User.UserID == "" {
|
||||
for i := 0; i < 20; i++ {
|
||||
userID := o.genUserID()
|
||||
_, err := o.Database.GetUser(ctx, userID)
|
||||
if err == nil {
|
||||
continue
|
||||
} else if dbutil.IsDBNotFound(err) {
|
||||
req.User.UserID = userID
|
||||
break
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if req.User.UserID == "" {
|
||||
return nil, errs.ErrInternalServer.WrapMsg("gen user id failed")
|
||||
}
|
||||
} else {
|
||||
_, err := o.Database.GetUser(ctx, req.User.UserID)
|
||||
if err == nil {
|
||||
return nil, errs.ErrArgs.WrapMsg("appoint user id already register")
|
||||
} else if !dbutil.IsDBNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
credentials []*chatdb.Credential
|
||||
)
|
||||
|
||||
if req.User.PhoneNumber != "" {
|
||||
credentials = append(credentials, &chatdb.Credential{
|
||||
UserID: req.User.UserID,
|
||||
Account: BuildCredentialPhone(req.User.AreaCode, req.User.PhoneNumber),
|
||||
Type: constant.CredentialPhone,
|
||||
AllowChange: true,
|
||||
})
|
||||
}
|
||||
|
||||
if req.User.Account != "" {
|
||||
credentials = append(credentials, &chatdb.Credential{
|
||||
UserID: req.User.UserID,
|
||||
Account: req.User.Account,
|
||||
Type: constant.CredentialAccount,
|
||||
AllowChange: true,
|
||||
})
|
||||
}
|
||||
|
||||
if req.User.Email != "" {
|
||||
credentials = append(credentials, &chatdb.Credential{
|
||||
UserID: req.User.UserID,
|
||||
Account: req.User.Email,
|
||||
Type: constant.CredentialEmail,
|
||||
AllowChange: true,
|
||||
})
|
||||
}
|
||||
|
||||
register := &chatdb.Register{
|
||||
UserID: req.User.UserID,
|
||||
DeviceID: req.DeviceID,
|
||||
IP: req.Ip,
|
||||
Platform: constantpb.PlatformID2Name[int(req.Platform)],
|
||||
AccountType: "",
|
||||
Mode: constant.UserMode,
|
||||
CreateTime: time.Now(),
|
||||
}
|
||||
account := &chatdb.Account{
|
||||
UserID: req.User.UserID,
|
||||
Password: req.User.Password,
|
||||
OperatorUserID: mcontext.GetOpUserID(ctx),
|
||||
ChangeTime: register.CreateTime,
|
||||
CreateTime: register.CreateTime,
|
||||
}
|
||||
attribute := &chatdb.Attribute{
|
||||
UserID: req.User.UserID,
|
||||
Account: req.User.Account,
|
||||
PhoneNumber: req.User.PhoneNumber,
|
||||
AreaCode: req.User.AreaCode,
|
||||
Email: req.User.Email,
|
||||
Nickname: req.User.Nickname,
|
||||
FaceURL: req.User.FaceURL,
|
||||
Gender: req.User.Gender,
|
||||
BirthTime: time.UnixMilli(req.User.Birth),
|
||||
ChangeTime: register.CreateTime,
|
||||
CreateTime: register.CreateTime,
|
||||
AllowVibration: constant.DefaultAllowVibration,
|
||||
AllowBeep: constant.DefaultAllowBeep,
|
||||
AllowAddFriend: constant.DefaultAllowAddFriend,
|
||||
}
|
||||
|
||||
if err := o.Database.RegisterUser(ctx, register, account, attribute, credentials); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chat.AddUserAccountResp{}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) SearchUserPublicInfo(ctx context.Context, req *chat.SearchUserPublicInfoReq) (*chat.SearchUserPublicInfoResp, error) {
|
||||
if _, _, err := mctx.Check(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, list, err := o.Database.Search(ctx, constant.FinDAllUser, req.Keyword, req.Genders, nil, nil, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chat.SearchUserPublicInfoResp{
|
||||
Total: uint32(total),
|
||||
Users: DbToPbAttributes(list),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) FindUserFullInfo(ctx context.Context, req *chat.FindUserFullInfoReq) (*chat.FindUserFullInfoResp, error) {
|
||||
if _, _, err := mctx.Check(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(req.UserIDs) == 0 {
|
||||
return nil, errs.ErrArgs.WrapMsg("UserIDs is empty")
|
||||
}
|
||||
attributes, err := o.Database.FindAttribute(ctx, req.UserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取每个用户的最新登录IP
|
||||
userIPMap := make(map[string]string)
|
||||
for _, attr := range attributes {
|
||||
ip, err := o.Database.GetLatestLoginIP(ctx, attr.UserID)
|
||||
if err != nil {
|
||||
// 如果获取IP失败,记录错误但继续处理其他用户
|
||||
continue
|
||||
}
|
||||
userIPMap[attr.UserID] = ip
|
||||
}
|
||||
|
||||
return &chat.FindUserFullInfoResp{Users: DbToPbUserFullInfosWithIP(attributes, userIPMap)}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) SearchUserFullInfo(ctx context.Context, req *chat.SearchUserFullInfoReq) (*chat.SearchUserFullInfoResp, error) {
|
||||
if _, _, err := mctx.Check(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 解析时间戳为 time.Time(毫秒时间戳)
|
||||
var startTime, endTime *time.Time
|
||||
if req.StartTime > 0 {
|
||||
st := time.UnixMilli(req.StartTime)
|
||||
startTime = &st
|
||||
}
|
||||
if req.EndTime > 0 {
|
||||
// 将endTime加1000毫秒,确保包含到当天的最后一毫秒
|
||||
// 例如:endTime=1727740799000 (2025-11-01 23:59:59) 会被转换为 1727740800000 (2025-11-02 00:00:00)
|
||||
// 这样使用 $lt 查询时,会包含 2025-11-01 23:59:59.999 但不包含 2025-11-02 00:00:00
|
||||
et := time.UnixMilli(req.EndTime + 1000)
|
||||
endTime = &et
|
||||
}
|
||||
// 使用支持实名信息搜索的方法
|
||||
total, list, err := o.Database.SearchWithRealNameAuth(ctx, req.Normal, req.Keyword, req.Genders, startTime, endTime, req.RealNameKeyword, req.IdCardKeyword, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 批量获取钱包信息(用于填充实名信息)
|
||||
userIDs := make([]string, 0, len(list))
|
||||
for _, attr := range list {
|
||||
userIDs = append(userIDs, attr.UserID)
|
||||
}
|
||||
walletMap := make(map[string]*chatdb.Wallet)
|
||||
if len(userIDs) > 0 {
|
||||
wallets, err := o.Database.GetWalletsByUserIDs(ctx, userIDs)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Failed to get wallets for user search", err, "userIDs", userIDs)
|
||||
} else {
|
||||
for _, wallet := range wallets {
|
||||
walletMap[wallet.UserID] = wallet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取每个用户的最新登录IP
|
||||
userIPMap := make(map[string]string)
|
||||
for _, attr := range list {
|
||||
ip, err := o.Database.GetLatestLoginIP(ctx, attr.UserID)
|
||||
if err != nil {
|
||||
// 如果获取IP失败,记录错误但继续处理其他用户
|
||||
log.ZWarn(ctx, "Failed to get latest login IP for user", err, "userID", attr.UserID)
|
||||
// 即使出错也设置空字符串,确保map中有该用户的记录
|
||||
userIPMap[attr.UserID] = ""
|
||||
continue
|
||||
}
|
||||
// 记录获取到的IP(用于调试)
|
||||
if ip != "" {
|
||||
log.ZDebug(ctx, "Got latest login IP for user", "userID", attr.UserID, "ip", ip)
|
||||
} else {
|
||||
log.ZDebug(ctx, "No login IP found for user (empty string)", "userID", attr.UserID)
|
||||
}
|
||||
userIPMap[attr.UserID] = ip
|
||||
}
|
||||
// 统计有IP的用户数量
|
||||
usersWithIP := 0
|
||||
for _, ip := range userIPMap {
|
||||
if ip != "" {
|
||||
usersWithIP++
|
||||
}
|
||||
}
|
||||
log.ZInfo(ctx, "User IP map summary", "totalUsers", len(list), "ipMapSize", len(userIPMap), "usersWithIP", usersWithIP)
|
||||
|
||||
return &chat.SearchUserFullInfoResp{
|
||||
Total: uint32(total),
|
||||
Users: DbToPbUserFullInfosWithRealNameAuthAndIP(list, walletMap, userIPMap),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetUserLoginRecords 查询用户登录记录
|
||||
func (o *chatSvr) GetUserLoginRecords(ctx context.Context, req *chat.GetUserLoginRecordsReq) (*chat.GetUserLoginRecordsResp, error) {
|
||||
// 检查管理员权限
|
||||
if _, err := mctx.CheckAdmin(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询登录记录
|
||||
total, records, err := o.Database.SearchUserLoginRecords(ctx, req.UserId, req.Ip, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 收集所有用户ID
|
||||
userIDs := make([]string, 0, len(records))
|
||||
userIDSet := make(map[string]bool)
|
||||
for _, record := range records {
|
||||
if !userIDSet[record.UserID] {
|
||||
userIDs = append(userIDs, record.UserID)
|
||||
userIDSet[record.UserID] = true
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取用户属性(头像和昵称)
|
||||
userAttrMap := make(map[string]*chatdb.Attribute)
|
||||
if len(userIDs) > 0 {
|
||||
attributes, err := o.Database.FindAttribute(ctx, userIDs)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Failed to get user attributes for login records", err, "userIDs", userIDs)
|
||||
} else {
|
||||
for _, attr := range attributes {
|
||||
userAttrMap[attr.UserID] = attr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换结果
|
||||
var recordInfos []*chat.UserLoginRecordInfo
|
||||
for _, record := range records {
|
||||
recordInfo := &chat.UserLoginRecordInfo{
|
||||
UserId: record.UserID,
|
||||
LoginTime: record.LoginTime.UnixMilli(),
|
||||
Ip: record.IP,
|
||||
DeviceId: record.DeviceID,
|
||||
Platform: record.Platform,
|
||||
}
|
||||
// 填充用户头像和昵称
|
||||
if attr, ok := userAttrMap[record.UserID]; ok {
|
||||
recordInfo.FaceUrl = attr.FaceURL
|
||||
recordInfo.Nickname = attr.Nickname
|
||||
}
|
||||
recordInfos = append(recordInfos, recordInfo)
|
||||
}
|
||||
|
||||
return &chat.GetUserLoginRecordsResp{
|
||||
Total: uint32(total),
|
||||
Records: recordInfos,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) FindUserAccount(ctx context.Context, req *chat.FindUserAccountReq) (*chat.FindUserAccountResp, error) {
|
||||
if len(req.UserIDs) == 0 {
|
||||
return nil, errs.ErrArgs.WrapMsg("user id list must be set")
|
||||
}
|
||||
if _, _, err := mctx.CheckAdminOrUser(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attributes, err := o.Database.FindAttribute(ctx, req.UserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userAccountMap := make(map[string]string)
|
||||
for _, attribute := range attributes {
|
||||
userAccountMap[attribute.UserID] = attribute.Account
|
||||
}
|
||||
return &chat.FindUserAccountResp{UserAccountMap: userAccountMap}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) FindAccountUser(ctx context.Context, req *chat.FindAccountUserReq) (*chat.FindAccountUserResp, error) {
|
||||
if len(req.Accounts) == 0 {
|
||||
return nil, errs.ErrArgs.WrapMsg("account list must be set")
|
||||
}
|
||||
if _, _, err := mctx.CheckAdminOrUser(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attributes, err := o.Database.FindAttribute(ctx, req.Accounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accountUserMap := make(map[string]string)
|
||||
for _, attribute := range attributes {
|
||||
accountUserMap[attribute.Account] = attribute.UserID
|
||||
}
|
||||
return &chat.FindAccountUserResp{AccountUserMap: accountUserMap}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) SearchUserInfo(ctx context.Context, req *chat.SearchUserInfoReq) (*chat.SearchUserInfoResp, error) {
|
||||
if _, _, err := mctx.Check(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, list, err := o.Database.SearchUser(ctx, req.Keyword, req.UserIDs, req.Genders, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chat.SearchUserInfoResp{
|
||||
Total: uint32(total),
|
||||
Users: DbToPbUserFullInfos(list),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) CheckUserExist(ctx context.Context, req *chat.CheckUserExistReq) (resp *chat.CheckUserExistResp, err error) {
|
||||
if req.User == nil {
|
||||
return nil, errs.ErrArgs.WrapMsg("user is nil")
|
||||
}
|
||||
if req.User.PhoneNumber != "" {
|
||||
account, err := o.Database.TakeCredentialByAccount(ctx, BuildCredentialPhone(req.User.AreaCode, req.User.PhoneNumber))
|
||||
// err != nil is not found User
|
||||
if err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, err
|
||||
}
|
||||
if account != nil {
|
||||
return &chat.CheckUserExistResp{Userid: account.UserID, IsRegistered: true}, nil
|
||||
}
|
||||
}
|
||||
if req.User.Email != "" {
|
||||
account, err := o.Database.TakeCredentialByAccount(ctx, req.User.AreaCode)
|
||||
if err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, err
|
||||
}
|
||||
if account != nil {
|
||||
return &chat.CheckUserExistResp{Userid: account.UserID, IsRegistered: true}, nil
|
||||
}
|
||||
}
|
||||
if req.User.Account != "" {
|
||||
account, err := o.Database.TakeCredentialByAccount(ctx, req.User.Account)
|
||||
if err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, err
|
||||
}
|
||||
if account != nil {
|
||||
return &chat.CheckUserExistResp{Userid: account.UserID, IsRegistered: true}, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (o *chatSvr) DelUserAccount(ctx context.Context, req *chat.DelUserAccountReq) (resp *chat.DelUserAccountResp, err error) {
|
||||
if err := o.Database.DelUserAccount(ctx, req.UserIDs); err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
Reference in New Issue
Block a user