2022-09-27 17:59:05 +08:00
|
|
|
package usercommon
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-08-04 15:47:50 +08:00
|
|
|
"github.com/answerdev/answer/internal/base/constant"
|
2022-12-07 10:26:02 +08:00
|
|
|
"strings"
|
2022-09-27 17:59:05 +08:00
|
|
|
|
2022-12-07 10:26:02 +08:00
|
|
|
"github.com/Chain-Zhang/pinyin"
|
|
|
|
"github.com/answerdev/answer/internal/base/reason"
|
2022-10-24 16:51:05 +08:00
|
|
|
"github.com/answerdev/answer/internal/entity"
|
|
|
|
"github.com/answerdev/answer/internal/schema"
|
2023-01-06 14:34:53 +08:00
|
|
|
"github.com/answerdev/answer/internal/service/auth"
|
|
|
|
"github.com/answerdev/answer/internal/service/role"
|
2023-05-29 14:58:58 +08:00
|
|
|
"github.com/answerdev/answer/internal/service/siteinfo_common"
|
2022-12-07 10:26:02 +08:00
|
|
|
"github.com/answerdev/answer/pkg/checker"
|
2023-01-09 16:54:20 +08:00
|
|
|
"github.com/answerdev/answer/pkg/random"
|
2022-12-07 10:26:02 +08:00
|
|
|
"github.com/segmentfault/pacman/errors"
|
2023-01-06 14:34:53 +08:00
|
|
|
"github.com/segmentfault/pacman/log"
|
2022-09-27 17:59:05 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type UserRepo interface {
|
|
|
|
AddUser(ctx context.Context, user *entity.User) (err error)
|
|
|
|
IncreaseAnswerCount(ctx context.Context, userID string, amount int) (err error)
|
|
|
|
IncreaseQuestionCount(ctx context.Context, userID string, amount int) (err error)
|
2023-05-16 16:02:41 +08:00
|
|
|
UpdateQuestionCount(ctx context.Context, userID string, count int64) (err error)
|
|
|
|
UpdateAnswerCount(ctx context.Context, userID string, count int) (err error)
|
2022-09-27 17:59:05 +08:00
|
|
|
UpdateLastLoginDate(ctx context.Context, userID string) (err error)
|
|
|
|
UpdateEmailStatus(ctx context.Context, userID string, emailStatus int) error
|
|
|
|
UpdateNoticeStatus(ctx context.Context, userID string, noticeStatus int) error
|
|
|
|
UpdateEmail(ctx context.Context, userID, email string) error
|
2022-11-02 15:25:27 +08:00
|
|
|
UpdateLanguage(ctx context.Context, userID, language string) error
|
2022-10-28 19:28:08 +08:00
|
|
|
UpdatePass(ctx context.Context, userID, pass string) error
|
2022-09-27 17:59:05 +08:00
|
|
|
UpdateInfo(ctx context.Context, userInfo *entity.User) (err error)
|
|
|
|
GetByUserID(ctx context.Context, userID string) (userInfo *entity.User, exist bool, err error)
|
|
|
|
BatchGetByID(ctx context.Context, ids []string) ([]*entity.User, error)
|
|
|
|
GetByUsername(ctx context.Context, username string) (userInfo *entity.User, exist bool, err error)
|
2023-05-22 18:42:28 +08:00
|
|
|
GetByUsernames(ctx context.Context, usernames []string) ([]*entity.User, error)
|
2022-09-27 17:59:05 +08:00
|
|
|
GetByEmail(ctx context.Context, email string) (userInfo *entity.User, exist bool, err error)
|
2022-11-02 16:29:10 +08:00
|
|
|
GetUserCount(ctx context.Context) (count int64, err error)
|
2023-07-04 11:20:55 +08:00
|
|
|
SearchUserListByName(ctx context.Context, name string, limit int) (userList []*entity.User, err error)
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// UserCommon user service
|
|
|
|
type UserCommon struct {
|
2023-05-29 14:58:58 +08:00
|
|
|
userRepo UserRepo
|
|
|
|
userRoleService *role.UserRoleRelService
|
|
|
|
authService *auth.AuthService
|
2023-06-02 16:53:04 +08:00
|
|
|
siteInfoCommonService siteinfo_common.SiteInfoCommonService
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
|
2023-05-16 16:02:41 +08:00
|
|
|
func NewUserCommon(
|
|
|
|
userRepo UserRepo,
|
2023-01-06 14:34:53 +08:00
|
|
|
userRoleService *role.UserRoleRelService,
|
|
|
|
authService *auth.AuthService,
|
2023-06-02 16:53:04 +08:00
|
|
|
siteInfoCommonService siteinfo_common.SiteInfoCommonService,
|
2023-05-16 16:02:41 +08:00
|
|
|
) *UserCommon {
|
2022-09-27 17:59:05 +08:00
|
|
|
return &UserCommon{
|
2023-05-29 14:58:58 +08:00
|
|
|
userRepo: userRepo,
|
|
|
|
userRoleService: userRoleService,
|
|
|
|
authService: authService,
|
|
|
|
siteInfoCommonService: siteInfoCommonService,
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-24 16:11:43 +08:00
|
|
|
func (us *UserCommon) GetUserBasicInfoByID(ctx context.Context, ID string) (
|
|
|
|
userBasicInfo *schema.UserBasicInfo, exist bool, err error) {
|
2022-09-29 15:27:56 +08:00
|
|
|
userInfo, exist, err := us.userRepo.GetByUserID(ctx, ID)
|
2022-09-27 17:59:05 +08:00
|
|
|
if err != nil {
|
2022-09-29 15:27:56 +08:00
|
|
|
return nil, exist, err
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
2022-11-24 16:11:43 +08:00
|
|
|
info := us.FormatUserBasicInfo(ctx, userInfo)
|
2023-05-29 14:58:58 +08:00
|
|
|
info.Avatar = us.siteInfoCommonService.FormatAvatar(ctx, userInfo.Avatar, userInfo.EMail).GetURL()
|
2022-09-29 15:27:56 +08:00
|
|
|
return info, exist, nil
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UserCommon) GetUserBasicInfoByUserName(ctx context.Context, username string) (*schema.UserBasicInfo, bool, error) {
|
|
|
|
userInfo, exist, err := us.userRepo.GetByUsername(ctx, username)
|
|
|
|
if err != nil {
|
|
|
|
return nil, exist, err
|
|
|
|
}
|
2022-11-24 16:11:43 +08:00
|
|
|
info := us.FormatUserBasicInfo(ctx, userInfo)
|
2023-05-29 14:58:58 +08:00
|
|
|
info.Avatar = us.siteInfoCommonService.FormatAvatar(ctx, userInfo.Avatar, userInfo.EMail).GetURL()
|
2022-09-27 17:59:05 +08:00
|
|
|
return info, exist, nil
|
|
|
|
}
|
|
|
|
|
2023-05-23 12:15:52 +08:00
|
|
|
func (us *UserCommon) BatchGetUserBasicInfoByUserNames(ctx context.Context, usernames []string) (map[string]*schema.UserBasicInfo, error) {
|
|
|
|
infomap := make(map[string]*schema.UserBasicInfo)
|
2023-05-22 18:42:28 +08:00
|
|
|
list, err := us.userRepo.GetByUsernames(ctx, usernames)
|
|
|
|
if err != nil {
|
2023-05-23 12:15:52 +08:00
|
|
|
return infomap, err
|
2023-05-22 18:42:28 +08:00
|
|
|
}
|
2023-05-29 14:58:58 +08:00
|
|
|
avatarMapping := us.siteInfoCommonService.FormatListAvatar(ctx, list)
|
2023-05-22 18:42:28 +08:00
|
|
|
for _, user := range list {
|
|
|
|
info := us.FormatUserBasicInfo(ctx, user)
|
2023-05-29 14:58:58 +08:00
|
|
|
info.Avatar = avatarMapping[user.ID].GetURL()
|
2023-05-23 12:15:52 +08:00
|
|
|
infomap[user.Username] = info
|
2023-05-22 18:42:28 +08:00
|
|
|
}
|
2023-05-23 12:15:52 +08:00
|
|
|
return infomap, nil
|
2023-05-22 18:42:28 +08:00
|
|
|
}
|
|
|
|
|
2022-09-27 17:59:05 +08:00
|
|
|
func (us *UserCommon) UpdateAnswerCount(ctx context.Context, userID string, num int) error {
|
2023-05-16 16:02:41 +08:00
|
|
|
return us.userRepo.UpdateAnswerCount(ctx, userID, num)
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
|
2023-05-16 16:02:41 +08:00
|
|
|
func (us *UserCommon) UpdateQuestionCount(ctx context.Context, userID string, num int64) error {
|
|
|
|
return us.userRepo.UpdateQuestionCount(ctx, userID, num)
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
|
2023-08-30 17:41:44 +08:00
|
|
|
func (us *UserCommon) BatchUserBasicInfoByID(ctx context.Context, userIDs []string) (map[string]*schema.UserBasicInfo, error) {
|
2022-09-27 17:59:05 +08:00
|
|
|
userMap := make(map[string]*schema.UserBasicInfo)
|
2023-08-30 17:41:44 +08:00
|
|
|
if len(userIDs) == 0 {
|
|
|
|
return userMap, nil
|
|
|
|
}
|
|
|
|
userList, err := us.userRepo.BatchGetByID(ctx, userIDs)
|
2022-09-27 17:59:05 +08:00
|
|
|
if err != nil {
|
|
|
|
return userMap, err
|
|
|
|
}
|
2023-05-29 14:58:58 +08:00
|
|
|
avatarMapping := us.siteInfoCommonService.FormatListAvatar(ctx, userList)
|
|
|
|
for _, user := range userList {
|
|
|
|
info := us.FormatUserBasicInfo(ctx, user)
|
|
|
|
info.Avatar = avatarMapping[user.ID].GetURL()
|
|
|
|
userMap[user.ID] = info
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
|
|
|
return userMap, nil
|
|
|
|
}
|
|
|
|
|
2022-11-24 16:11:43 +08:00
|
|
|
// FormatUserBasicInfo format user basic info
|
|
|
|
func (us *UserCommon) FormatUserBasicInfo(ctx context.Context, userInfo *entity.User) *schema.UserBasicInfo {
|
2022-09-29 15:27:56 +08:00
|
|
|
userBasicInfo := &schema.UserBasicInfo{}
|
|
|
|
userBasicInfo.ID = userInfo.ID
|
|
|
|
userBasicInfo.Username = userInfo.Username
|
|
|
|
userBasicInfo.Rank = userInfo.Rank
|
|
|
|
userBasicInfo.DisplayName = userInfo.DisplayName
|
|
|
|
userBasicInfo.Website = userInfo.Website
|
|
|
|
userBasicInfo.Location = userInfo.Location
|
2022-11-01 15:25:44 +08:00
|
|
|
userBasicInfo.IPInfo = userInfo.IPInfo
|
2023-08-04 15:47:50 +08:00
|
|
|
userBasicInfo.Status = constant.ConvertUserStatus(userInfo.Status, userInfo.MailStatus)
|
|
|
|
if userBasicInfo.Status == constant.UserDeleted {
|
2022-09-29 15:27:56 +08:00
|
|
|
userBasicInfo.Avatar = ""
|
|
|
|
userBasicInfo.DisplayName = "Anonymous"
|
|
|
|
}
|
|
|
|
return userBasicInfo
|
2022-09-27 17:59:05 +08:00
|
|
|
}
|
2022-12-07 10:26:02 +08:00
|
|
|
|
|
|
|
// MakeUsername
|
|
|
|
// Generate a unique Username based on the displayName
|
|
|
|
func (us *UserCommon) MakeUsername(ctx context.Context, displayName string) (username string, err error) {
|
|
|
|
// Chinese processing
|
|
|
|
if has := checker.IsChinese(displayName); has {
|
|
|
|
str, err := pinyin.New(displayName).Split("").Mode(pinyin.WithoutTone).Convert()
|
|
|
|
if err != nil {
|
|
|
|
return "", errors.BadRequest(reason.UsernameInvalid)
|
|
|
|
} else {
|
|
|
|
displayName = str
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-06 16:18:57 +08:00
|
|
|
username = strings.ReplaceAll(displayName, " ", "-")
|
2022-12-07 10:26:02 +08:00
|
|
|
username = strings.ToLower(username)
|
|
|
|
suffix := ""
|
|
|
|
|
2023-01-28 10:40:01 +08:00
|
|
|
if checker.IsInvalidUsername(username) {
|
2022-12-07 10:26:02 +08:00
|
|
|
return "", errors.BadRequest(reason.UsernameInvalid)
|
|
|
|
}
|
|
|
|
|
2022-12-28 17:11:24 +08:00
|
|
|
if checker.IsReservedUsername(username) {
|
|
|
|
return "", errors.BadRequest(reason.UsernameInvalid)
|
|
|
|
}
|
|
|
|
|
2022-12-07 10:26:02 +08:00
|
|
|
for {
|
|
|
|
_, has, err := us.userRepo.GetByUsername(ctx, username+suffix)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if !has {
|
|
|
|
break
|
|
|
|
}
|
2023-01-09 16:54:20 +08:00
|
|
|
suffix = random.UsernameSuffix()
|
2022-12-07 10:26:02 +08:00
|
|
|
}
|
|
|
|
return username + suffix, nil
|
|
|
|
}
|
2023-01-06 14:34:53 +08:00
|
|
|
|
2023-04-17 18:04:28 +08:00
|
|
|
func (us *UserCommon) CacheLoginUserInfo(ctx context.Context, userID string, userStatus, emailStatus int, externalID string) (
|
2023-01-06 14:34:53 +08:00
|
|
|
accessToken string, userCacheInfo *entity.UserCacheInfo, err error) {
|
|
|
|
roleID, err := us.userRoleService.GetUserRole(ctx, userID)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
userCacheInfo = &entity.UserCacheInfo{
|
|
|
|
UserID: userID,
|
|
|
|
EmailStatus: emailStatus,
|
|
|
|
UserStatus: userStatus,
|
2023-03-21 11:53:15 +08:00
|
|
|
RoleID: roleID,
|
2023-04-17 18:04:28 +08:00
|
|
|
ExternalID: externalID,
|
2023-01-06 14:34:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
accessToken, err = us.authService.SetUserCacheInfo(ctx, userCacheInfo)
|
|
|
|
if err != nil {
|
|
|
|
return "", nil, err
|
|
|
|
}
|
2023-03-21 11:53:15 +08:00
|
|
|
if userCacheInfo.RoleID == role.RoleAdminID {
|
2023-01-06 14:34:53 +08:00
|
|
|
if err = us.authService.SetAdminUserCacheInfo(ctx, accessToken, &entity.UserCacheInfo{UserID: userID}); err != nil {
|
|
|
|
return "", nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return accessToken, userCacheInfo, nil
|
|
|
|
}
|