203 lines
7.2 KiB
Go
203 lines
7.2 KiB
Go
package chat
|
||
|
||
import (
|
||
"context"
|
||
"regexp"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"git.imall.cloud/openim/chat/pkg/common/db/dbutil"
|
||
table "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||
"git.imall.cloud/openim/chat/pkg/eerrs"
|
||
"git.imall.cloud/openim/chat/pkg/protocol/chat"
|
||
"git.imall.cloud/openim/chat/pkg/protocol/common"
|
||
"github.com/openimsdk/tools/errs"
|
||
"github.com/openimsdk/tools/utils/datautil"
|
||
"github.com/openimsdk/tools/utils/stringutil"
|
||
)
|
||
|
||
func DbToPbAttribute(attribute *table.Attribute) *common.UserPublicInfo {
|
||
if attribute == nil {
|
||
return nil
|
||
}
|
||
return &common.UserPublicInfo{
|
||
UserID: attribute.UserID,
|
||
Account: attribute.Account,
|
||
Email: attribute.Email,
|
||
Nickname: attribute.Nickname,
|
||
FaceURL: attribute.FaceURL,
|
||
Gender: attribute.Gender,
|
||
Level: attribute.Level,
|
||
UserType: attribute.UserType,
|
||
}
|
||
}
|
||
|
||
func DbToPbAttributes(attributes []*table.Attribute) []*common.UserPublicInfo {
|
||
return datautil.Slice(attributes, DbToPbAttribute)
|
||
}
|
||
|
||
func DbToPbUserFullInfo(attribute *table.Attribute) *common.UserFullInfo {
|
||
return &common.UserFullInfo{
|
||
UserID: attribute.UserID,
|
||
Password: "",
|
||
Account: attribute.Account,
|
||
PhoneNumber: attribute.PhoneNumber,
|
||
AreaCode: attribute.AreaCode,
|
||
Email: attribute.Email,
|
||
Nickname: attribute.Nickname,
|
||
FaceURL: attribute.FaceURL,
|
||
Gender: attribute.Gender,
|
||
Level: attribute.Level,
|
||
UserType: attribute.UserType,
|
||
Birth: attribute.BirthTime.UnixMilli(),
|
||
AllowAddFriend: attribute.AllowAddFriend,
|
||
AllowBeep: attribute.AllowBeep,
|
||
AllowVibration: attribute.AllowVibration,
|
||
GlobalRecvMsgOpt: attribute.GlobalRecvMsgOpt,
|
||
RegisterType: attribute.RegisterType,
|
||
UserFlag: attribute.UserFlag,
|
||
CreateTime: attribute.CreateTime.UnixMilli(),
|
||
Ip: "", // 默认空字符串
|
||
}
|
||
}
|
||
|
||
func DbToPbUserFullInfos(attributes []*table.Attribute) []*common.UserFullInfo {
|
||
return datautil.Slice(attributes, DbToPbUserFullInfo)
|
||
}
|
||
|
||
func DbToPbUserFullInfoWithIP(attribute *table.Attribute, ip string) *common.UserFullInfo {
|
||
return &common.UserFullInfo{
|
||
UserID: attribute.UserID,
|
||
Password: "",
|
||
Account: attribute.Account,
|
||
PhoneNumber: attribute.PhoneNumber,
|
||
AreaCode: attribute.AreaCode,
|
||
Email: attribute.Email,
|
||
Nickname: attribute.Nickname,
|
||
FaceURL: attribute.FaceURL,
|
||
Gender: attribute.Gender,
|
||
Level: attribute.Level,
|
||
UserType: attribute.UserType,
|
||
Birth: attribute.BirthTime.UnixMilli(),
|
||
AllowAddFriend: attribute.AllowAddFriend,
|
||
AllowBeep: attribute.AllowBeep,
|
||
AllowVibration: attribute.AllowVibration,
|
||
GlobalRecvMsgOpt: attribute.GlobalRecvMsgOpt,
|
||
RegisterType: attribute.RegisterType,
|
||
UserFlag: attribute.UserFlag,
|
||
CreateTime: attribute.CreateTime.UnixMilli(),
|
||
Ip: ip,
|
||
}
|
||
}
|
||
|
||
func DbToPbUserFullInfosWithIP(attributes []*table.Attribute, userIPMap map[string]string) []*common.UserFullInfo {
|
||
result := make([]*common.UserFullInfo, 0, len(attributes))
|
||
for _, attr := range attributes {
|
||
ip := userIPMap[attr.UserID]
|
||
result = append(result, DbToPbUserFullInfoWithIP(attr, ip))
|
||
}
|
||
return result
|
||
}
|
||
|
||
// DbToPbUserFullInfosWithRealNameAuth 转换用户信息(包含实名认证信息)
|
||
func DbToPbUserFullInfosWithRealNameAuth(attributes []*table.Attribute, walletMap map[string]*table.Wallet) []*common.UserFullInfo {
|
||
result := make([]*common.UserFullInfo, 0, len(attributes))
|
||
for _, attr := range attributes {
|
||
userInfo := DbToPbUserFullInfo(attr)
|
||
// 填充实名认证信息
|
||
if wallet, ok := walletMap[attr.UserID]; ok {
|
||
userInfo.IdCard = wallet.RealNameAuth.IDCard
|
||
userInfo.RealName = wallet.RealNameAuth.Name
|
||
userInfo.IdCardPhotoFront = wallet.RealNameAuth.IDCardPhotoFront
|
||
userInfo.IdCardPhotoBack = wallet.RealNameAuth.IDCardPhotoBack
|
||
userInfo.AuditStatus = wallet.RealNameAuth.AuditStatus
|
||
}
|
||
result = append(result, userInfo)
|
||
}
|
||
return result
|
||
}
|
||
|
||
// DbToPbUserFullInfosWithRealNameAuthAndIP 转换用户信息(包含实名认证信息和IP)
|
||
func DbToPbUserFullInfosWithRealNameAuthAndIP(attributes []*table.Attribute, walletMap map[string]*table.Wallet, userIPMap map[string]string) []*common.UserFullInfo {
|
||
result := make([]*common.UserFullInfo, 0, len(attributes))
|
||
for _, attr := range attributes {
|
||
ip := userIPMap[attr.UserID]
|
||
userInfo := DbToPbUserFullInfoWithIP(attr, ip)
|
||
// 填充实名认证信息
|
||
if wallet, ok := walletMap[attr.UserID]; ok {
|
||
userInfo.IdCard = wallet.RealNameAuth.IDCard
|
||
userInfo.RealName = wallet.RealNameAuth.Name
|
||
userInfo.IdCardPhotoFront = wallet.RealNameAuth.IDCardPhotoFront
|
||
userInfo.IdCardPhotoBack = wallet.RealNameAuth.IDCardPhotoBack
|
||
userInfo.AuditStatus = wallet.RealNameAuth.AuditStatus
|
||
}
|
||
result = append(result, userInfo)
|
||
}
|
||
return result
|
||
}
|
||
|
||
func BuildCredentialPhone(areaCode, phone string) string {
|
||
return areaCode + " " + phone
|
||
}
|
||
|
||
func (o *chatSvr) checkRegisterInfo(ctx context.Context, user *chat.RegisterUserInfo, isAdmin bool) error {
|
||
if user == nil {
|
||
return errs.ErrArgs.WrapMsg("user is nil")
|
||
}
|
||
user.Account = strings.TrimSpace(user.Account)
|
||
// 如果提供了account,则不需要验证phone和email
|
||
if user.Account != "" {
|
||
// account验证逻辑在后面,这里直接跳过"至少需要一个账号"的检查
|
||
} else if user.Email == "" && !(user.PhoneNumber != "" && user.AreaCode != "") && !isAdmin {
|
||
// 如果没有account,也没有email,也没有完整的phone(phoneNumber和areaCode都提供),且不是管理员,则报错
|
||
return errs.ErrArgs.WrapMsg("at least one valid account is required")
|
||
}
|
||
if user.PhoneNumber != "" {
|
||
if !strings.HasPrefix(user.AreaCode, "+") {
|
||
user.AreaCode = "+" + user.AreaCode
|
||
}
|
||
if _, err := strconv.ParseUint(user.AreaCode[1:], 10, 64); err != nil {
|
||
return errs.ErrArgs.WrapMsg("area code must be number")
|
||
}
|
||
if _, err := strconv.ParseUint(user.PhoneNumber, 10, 64); err != nil {
|
||
return errs.ErrArgs.WrapMsg("phone number must be number")
|
||
}
|
||
_, err := o.Database.TakeAttributeByPhone(ctx, user.AreaCode, user.PhoneNumber)
|
||
if err == nil {
|
||
return eerrs.ErrPhoneAlreadyRegister.Wrap()
|
||
} else if !dbutil.IsDBNotFound(err) {
|
||
return err
|
||
}
|
||
}
|
||
if user.Account != "" {
|
||
// 验证长度:6到20位
|
||
if len(user.Account) < 6 || len(user.Account) > 20 {
|
||
return errs.ErrArgs.WrapMsg("account must be between 6 and 20 characters")
|
||
}
|
||
// 验证格式:只能包含数字、字母、下划线(_)、横线(-)
|
||
pattern := `^[a-zA-Z0-9_-]+$`
|
||
matched, err := regexp.MatchString(pattern, user.Account)
|
||
if err != nil || !matched {
|
||
return errs.ErrArgs.WrapMsg("account must contain only letters, numbers, underscores, and hyphens")
|
||
}
|
||
_, err = o.Database.TakeAttributeByAccount(ctx, user.Account)
|
||
if err == nil {
|
||
return eerrs.ErrAccountAlreadyRegister.Wrap()
|
||
} else if !dbutil.IsDBNotFound(err) {
|
||
return err
|
||
}
|
||
}
|
||
if user.Email != "" {
|
||
if !stringutil.IsValidEmail(user.Email) {
|
||
return errs.ErrArgs.WrapMsg("invalid email")
|
||
}
|
||
_, err := o.Database.TakeAttributeByAccount(ctx, user.Email)
|
||
if err == nil {
|
||
return eerrs.ErrEmailAlreadyRegister.Wrap()
|
||
} else if !dbutil.IsDBNotFound(err) {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|