mirror of https://gitee.com/answerdev/answer.git
feat(user): backend add user and change user password
This commit is contained in:
parent
149751153c
commit
42756c0742
|
@ -116,14 +116,14 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
roleRepo := role.NewRoleRepo(dataData)
|
||||
roleService := role2.NewRoleService(roleRepo)
|
||||
userRoleRelService := role2.NewUserRoleRelService(userRoleRelRepo, roleService)
|
||||
userService := service.NewUserService(userRepo, userActiveActivityRepo, emailService, authService, serviceConf, siteInfoCommonService, userRoleRelService)
|
||||
userCommon := usercommon.NewUserCommon(userRepo)
|
||||
userService := service.NewUserService(userRepo, userActiveActivityRepo, emailService, authService, serviceConf, siteInfoCommonService, userRoleRelService, userCommon)
|
||||
captchaRepo := captcha.NewCaptchaRepo(dataData)
|
||||
captchaService := action.NewCaptchaService(captchaRepo)
|
||||
uploaderService := uploader.NewUploaderService(serviceConf, siteInfoCommonService)
|
||||
userController := controller.NewUserController(authService, userService, captchaService, emailService, uploaderService)
|
||||
commentRepo := comment.NewCommentRepo(dataData, uniqueIDRepo)
|
||||
commentCommonRepo := comment.NewCommentCommonRepo(dataData, uniqueIDRepo)
|
||||
userCommon := usercommon.NewUserCommon(userRepo)
|
||||
answerRepo := answer.NewAnswerRepo(dataData, uniqueIDRepo, userRankRepo, activityRepo)
|
||||
questionRepo := question.NewQuestionRepo(dataData, uniqueIDRepo)
|
||||
tagCommonRepo := tag_common.NewTagCommonRepo(dataData, uniqueIDRepo)
|
||||
|
@ -180,7 +180,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
reportBackyardService := report_backyard.NewReportBackyardService(reportRepo, userCommon, commonRepo, answerRepo, questionRepo, commentCommonRepo, reportHandle, configRepo)
|
||||
controller_backyardReportController := controller_backyard.NewReportController(reportBackyardService)
|
||||
userBackyardRepo := user.NewUserBackyardRepo(dataData, authRepo)
|
||||
userBackyardService := user_backyard.NewUserBackyardService(userBackyardRepo, userRoleRelService, authService)
|
||||
userBackyardService := user_backyard.NewUserBackyardService(userBackyardRepo, userRoleRelService, authService, userCommon)
|
||||
userBackyardController := controller_backyard.NewUserBackyardController(userBackyardService)
|
||||
reasonRepo := reason.NewReasonRepo(configRepo)
|
||||
reasonService := reason2.NewReasonService(reasonRepo)
|
||||
|
|
|
@ -60,6 +60,50 @@ func (uc *UserBackyardController) UpdateUserRole(ctx *gin.Context) {
|
|||
handler.HandleResponse(ctx, err, nil)
|
||||
}
|
||||
|
||||
// AddUser add user
|
||||
// @Summary add user
|
||||
// @Description add user
|
||||
// @Security ApiKeyAuth
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body schema.AddUserReq true "user"
|
||||
// @Success 200 {object} handler.RespBody
|
||||
// @Router /answer/admin/api/user [post]
|
||||
func (uc *UserBackyardController) AddUser(ctx *gin.Context) {
|
||||
req := &schema.AddUserReq{}
|
||||
if handler.BindAndCheck(ctx, req) {
|
||||
return
|
||||
}
|
||||
|
||||
req.LoginUserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||
|
||||
err := uc.userService.AddUser(ctx, req)
|
||||
handler.HandleResponse(ctx, err, nil)
|
||||
}
|
||||
|
||||
// UpdateUserPassword update user password
|
||||
// @Summary update user password
|
||||
// @Description update user password
|
||||
// @Security ApiKeyAuth
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body schema.UpdateUserPasswordReq true "user"
|
||||
// @Success 200 {object} handler.RespBody
|
||||
// @Router /answer/admin/api/user/password [put]
|
||||
func (uc *UserBackyardController) UpdateUserPassword(ctx *gin.Context) {
|
||||
req := &schema.UpdateUserPasswordReq{}
|
||||
if handler.BindAndCheck(ctx, req) {
|
||||
return
|
||||
}
|
||||
|
||||
req.LoginUserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||
|
||||
err := uc.userService.UpdateUserPassword(ctx, req)
|
||||
handler.HandleResponse(ctx, err, nil)
|
||||
}
|
||||
|
||||
// GetUserPage get user page
|
||||
// @Summary get user page
|
||||
// @Description get user page
|
||||
|
|
|
@ -61,6 +61,24 @@ func (ur *userBackyardRepo) UpdateUserStatus(ctx context.Context, userID string,
|
|||
return
|
||||
}
|
||||
|
||||
// AddUser add user
|
||||
func (ur *userBackyardRepo) AddUser(ctx context.Context, user *entity.User) (err error) {
|
||||
_, err = ur.data.DB.Insert(user)
|
||||
if err != nil {
|
||||
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateUserPassword update user password
|
||||
func (ur *userBackyardRepo) UpdateUserPassword(ctx context.Context, userID string, password string) (err error) {
|
||||
_, err = ur.data.DB.ID(userID).Update(&entity.User{Pass: password})
|
||||
if err != nil {
|
||||
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetUserInfo get user info
|
||||
func (ur *userBackyardRepo) GetUserInfo(ctx context.Context, userID string) (user *entity.User, exist bool, err error) {
|
||||
user = &entity.User{}
|
||||
|
|
|
@ -234,6 +234,8 @@ func (a *AnswerAPIRouter) RegisterAnswerCmsAPIRouter(r *gin.RouterGroup) {
|
|||
r.GET("/users/page", a.backyardUserController.GetUserPage)
|
||||
r.PUT("/user/status", a.backyardUserController.UpdateUserStatus)
|
||||
r.PUT("/user/role", a.backyardUserController.UpdateUserRole)
|
||||
r.POST("/user", a.backyardUserController.AddUser)
|
||||
r.PUT("/user/password", a.backyardUserController.UpdateUserPassword)
|
||||
|
||||
// reason
|
||||
r.GET("/reasons", a.reasonController.Reasons)
|
||||
|
|
|
@ -84,3 +84,18 @@ type UpdateUserRoleReq struct {
|
|||
// login user id
|
||||
LoginUserID string `json:"-"`
|
||||
}
|
||||
|
||||
// AddUserReq add user request
|
||||
type AddUserReq struct {
|
||||
DisplayName string `validate:"required,gt=4,lte=30" json:"display_name"`
|
||||
Email string `validate:"required,email,gt=0,lte=500" json:"email"`
|
||||
Password string `validate:"required,gte=8,lte=32" json:"password"`
|
||||
LoginUserID string `json:"-"`
|
||||
}
|
||||
|
||||
// UpdateUserPasswordReq update user password request
|
||||
type UpdateUserPasswordReq struct {
|
||||
UserID string `validate:"required" json:"user_id"`
|
||||
Password string `validate:"required,gte=8,lte=32" json:"password"`
|
||||
LoginUserID string `json:"-"`
|
||||
}
|
||||
|
|
|
@ -14,9 +14,11 @@ import (
|
|||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/auth"
|
||||
"github.com/answerdev/answer/internal/service/role"
|
||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/segmentfault/pacman/errors"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// UserBackyardRepo user repository
|
||||
|
@ -25,6 +27,8 @@ type UserBackyardRepo interface {
|
|||
GetUserInfo(ctx context.Context, userID string) (user *entity.User, exist bool, err error)
|
||||
GetUserPage(ctx context.Context, page, pageSize int, user *entity.User,
|
||||
usernameOrDisplayName string, isStaff bool) (users []*entity.User, total int64, err error)
|
||||
AddUser(ctx context.Context, user *entity.User) (err error)
|
||||
UpdateUserPassword(ctx context.Context, userID string, password string) (err error)
|
||||
}
|
||||
|
||||
// UserBackyardService user service
|
||||
|
@ -32,6 +36,7 @@ type UserBackyardService struct {
|
|||
userRepo UserBackyardRepo
|
||||
userRoleRelService *role.UserRoleRelService
|
||||
authService *auth.AuthService
|
||||
userCommonService *usercommon.UserCommon
|
||||
}
|
||||
|
||||
// NewUserBackyardService new user backyard service
|
||||
|
@ -39,11 +44,13 @@ func NewUserBackyardService(
|
|||
userRepo UserBackyardRepo,
|
||||
userRoleRelService *role.UserRoleRelService,
|
||||
authService *auth.AuthService,
|
||||
userCommonService *usercommon.UserCommon,
|
||||
) *UserBackyardService {
|
||||
return &UserBackyardService{
|
||||
userRepo: userRepo,
|
||||
userRoleRelService: userRoleRelService,
|
||||
authService: authService,
|
||||
userCommonService: userCommonService,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,6 +101,57 @@ func (us *UserBackyardService) UpdateUserRole(ctx context.Context, req *schema.U
|
|||
return
|
||||
}
|
||||
|
||||
// AddUser add user
|
||||
func (us *UserBackyardService) AddUser(ctx context.Context, req *schema.AddUserReq) (err error) {
|
||||
hashPwd, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userInfo := &entity.User{}
|
||||
userInfo.EMail = req.Email
|
||||
userInfo.DisplayName = req.DisplayName
|
||||
userInfo.Pass = string(hashPwd)
|
||||
|
||||
userInfo.Username, err = us.userCommonService.MakeUsername(ctx, userInfo.DisplayName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userInfo.MailStatus = entity.EmailStatusAvailable
|
||||
userInfo.Status = entity.UserStatusAvailable
|
||||
userInfo.Rank = 1
|
||||
|
||||
err = us.userRepo.AddUser(ctx, userInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateUserPassword update user password
|
||||
func (us *UserBackyardService) UpdateUserPassword(ctx context.Context, req *schema.UpdateUserPasswordReq) (err error) {
|
||||
userInfo, exist, err := us.userRepo.GetUserInfo(ctx, req.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
return errors.BadRequest(reason.UserNotFound)
|
||||
}
|
||||
|
||||
hashPwd, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = us.userRepo.UpdateUserPassword(ctx, userInfo.ID, string(hashPwd))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// logout this user
|
||||
us.authService.RemoveAllUserTokens(ctx, req.UserID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetUserInfo get user one
|
||||
func (us *UserBackyardService) GetUserInfo(ctx context.Context, userID string) (resp *schema.GetUserInfoResp, err error) {
|
||||
user, exist, err := us.userRepo.GetUserInfo(ctx, userID)
|
||||
|
|
|
@ -2,9 +2,17 @@ package usercommon
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Chain-Zhang/pinyin"
|
||||
"github.com/answerdev/answer/internal/base/reason"
|
||||
"github.com/answerdev/answer/internal/entity"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/pkg/checker"
|
||||
"github.com/segmentfault/pacman/errors"
|
||||
)
|
||||
|
||||
type UserRepo interface {
|
||||
|
@ -94,3 +102,41 @@ func (us *UserCommon) FormatUserBasicInfo(ctx context.Context, userInfo *entity.
|
|||
}
|
||||
return userBasicInfo
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
username = strings.ReplaceAll(displayName, " ", "_")
|
||||
username = strings.ToLower(username)
|
||||
suffix := ""
|
||||
|
||||
re := regexp.MustCompile(`^[a-z0-9._-]{4,30}$`)
|
||||
match := re.MatchString(username)
|
||||
if !match {
|
||||
return "", errors.BadRequest(reason.UsernameInvalid)
|
||||
}
|
||||
|
||||
for {
|
||||
_, has, err := us.userRepo.GetByUsername(ctx, username+suffix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !has {
|
||||
break
|
||||
}
|
||||
bytes := make([]byte, 2)
|
||||
_, _ = rand.Read(bytes)
|
||||
suffix = hex.EncodeToString(bytes)
|
||||
}
|
||||
return username + suffix, nil
|
||||
}
|
||||
|
|
|
@ -2,14 +2,9 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Chain-Zhang/pinyin"
|
||||
"github.com/answerdev/answer/internal/base/handler"
|
||||
"github.com/answerdev/answer/internal/base/reason"
|
||||
"github.com/answerdev/answer/internal/base/translator"
|
||||
|
@ -23,7 +18,6 @@ import (
|
|||
"github.com/answerdev/answer/internal/service/service_config"
|
||||
"github.com/answerdev/answer/internal/service/siteinfo_common"
|
||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||
"github.com/answerdev/answer/pkg/checker"
|
||||
"github.com/google/uuid"
|
||||
"github.com/segmentfault/pacman/errors"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
|
@ -34,13 +28,14 @@ import (
|
|||
|
||||
// UserService user service
|
||||
type UserService struct {
|
||||
userRepo usercommon.UserRepo
|
||||
userActivity activity.UserActiveActivityRepo
|
||||
serviceConfig *service_config.ServiceConfig
|
||||
emailService *export.EmailService
|
||||
authService *auth.AuthService
|
||||
siteInfoService *siteinfo_common.SiteInfoCommonService
|
||||
userRoleService *role.UserRoleRelService
|
||||
userCommonService *usercommon.UserCommon
|
||||
userRepo usercommon.UserRepo
|
||||
userActivity activity.UserActiveActivityRepo
|
||||
serviceConfig *service_config.ServiceConfig
|
||||
emailService *export.EmailService
|
||||
authService *auth.AuthService
|
||||
siteInfoService *siteinfo_common.SiteInfoCommonService
|
||||
userRoleService *role.UserRoleRelService
|
||||
}
|
||||
|
||||
func NewUserService(userRepo usercommon.UserRepo,
|
||||
|
@ -50,15 +45,17 @@ func NewUserService(userRepo usercommon.UserRepo,
|
|||
serviceConfig *service_config.ServiceConfig,
|
||||
siteInfoService *siteinfo_common.SiteInfoCommonService,
|
||||
userRoleService *role.UserRoleRelService,
|
||||
userCommonService *usercommon.UserCommon,
|
||||
) *UserService {
|
||||
return &UserService{
|
||||
userRepo: userRepo,
|
||||
userActivity: userActivity,
|
||||
emailService: emailService,
|
||||
serviceConfig: serviceConfig,
|
||||
authService: authService,
|
||||
siteInfoService: siteInfoService,
|
||||
userRoleService: userRoleService,
|
||||
userCommonService: userCommonService,
|
||||
userRepo: userRepo,
|
||||
userActivity: userActivity,
|
||||
emailService: emailService,
|
||||
serviceConfig: serviceConfig,
|
||||
authService: authService,
|
||||
siteInfoService: siteInfoService,
|
||||
userRoleService: userRoleService,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +304,7 @@ func (us *UserService) UserRegisterByEmail(ctx context.Context, registerUserInfo
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userInfo.Username, err = us.makeUsername(ctx, registerUserInfo.Name)
|
||||
userInfo.Username, err = us.userCommonService.MakeUsername(ctx, registerUserInfo.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -456,44 +453,6 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// makeUsername
|
||||
// Generate a unique Username based on the displayName
|
||||
func (us *UserService) 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 "", err
|
||||
} else {
|
||||
displayName = str
|
||||
}
|
||||
}
|
||||
|
||||
username = strings.ReplaceAll(displayName, " ", "_")
|
||||
username = strings.ToLower(username)
|
||||
suffix := ""
|
||||
|
||||
re := regexp.MustCompile(`^[a-z0-9._-]{4,30}$`)
|
||||
match := re.MatchString(username)
|
||||
if !match {
|
||||
return "", errors.BadRequest(reason.UsernameInvalid)
|
||||
}
|
||||
|
||||
for {
|
||||
_, has, err := us.userRepo.GetByUsername(ctx, username+suffix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !has {
|
||||
break
|
||||
}
|
||||
bytes := make([]byte, 2)
|
||||
_, _ = rand.Read(bytes)
|
||||
suffix = hex.EncodeToString(bytes)
|
||||
}
|
||||
return username + suffix, nil
|
||||
}
|
||||
|
||||
// verifyPassword
|
||||
// Compare whether the password is correct
|
||||
func (us *UserService) verifyPassword(ctx context.Context, LoginPass, UserPass string) bool {
|
||||
|
|
Loading…
Reference in New Issue