213 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package system
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"strconv"
 | |
| 	"time"
 | |
| 
 | |
| 	"management/internal/erpserver/model/dto"
 | |
| 	"management/internal/erpserver/model/form"
 | |
| 	"management/internal/erpserver/model/system"
 | |
| 	"management/internal/erpserver/model/view"
 | |
| 	"management/internal/erpserver/service/v1"
 | |
| 	"management/internal/pkg/crypto"
 | |
| 	"management/internal/pkg/database"
 | |
| 	"management/internal/pkg/know"
 | |
| 	"management/internal/pkg/rand"
 | |
| 
 | |
| 	"github.com/google/uuid"
 | |
| 	"go.uber.org/zap"
 | |
| )
 | |
| 
 | |
| type userService struct {
 | |
| 	*v1.Service
 | |
| 	repo              system.UserRepository
 | |
| 	roleService       v1.RoleService
 | |
| 	departmentService v1.DepartmentService
 | |
| 	loginLogService   v1.LoginLogService
 | |
| }
 | |
| 
 | |
| func NewUserService(
 | |
| 	service *v1.Service,
 | |
| 	repo system.UserRepository,
 | |
| 	roleService v1.RoleService,
 | |
| 	departmentService v1.DepartmentService,
 | |
| 	loginLogService v1.LoginLogService,
 | |
| ) v1.UserService {
 | |
| 	return &userService{
 | |
| 		Service:           service,
 | |
| 		repo:              repo,
 | |
| 		roleService:       roleService,
 | |
| 		departmentService: departmentService,
 | |
| 		loginLogService:   loginLogService,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *userService) Create(ctx context.Context, req *form.User) error {
 | |
| 	salt, err := rand.String(10)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	hashedPassword, err := crypto.BcryptHashPassword(req.Password + salt)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	initTime, err := time.ParseInLocation(time.DateTime, "0001-01-01 00:00:00", time.Local)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	user := &system.User{
 | |
| 		Uuid:             uuid.Must(uuid.NewV7()),
 | |
| 		Email:            req.Email,
 | |
| 		Username:         req.Username,
 | |
| 		HashedPassword:   hashedPassword,
 | |
| 		Salt:             salt,
 | |
| 		Avatar:           req.Avatar,
 | |
| 		Gender:           req.Gender,
 | |
| 		DepartmentID:     req.DepartmentID,
 | |
| 		RoleID:           req.RoleID,
 | |
| 		Status:           *req.Status,
 | |
| 		ChangePasswordAt: initTime,
 | |
| 		CreatedAt:        time.Now(),
 | |
| 		UpdatedAt:        time.Now(),
 | |
| 	}
 | |
| 	err = s.repo.Create(ctx, user)
 | |
| 	if err != nil {
 | |
| 		if database.IsUniqueViolation(err) {
 | |
| 			return errors.New("用户已经存在")
 | |
| 		}
 | |
| 		return err
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (s *userService) Update(ctx context.Context, req *form.User) error {
 | |
| 	user, err := s.repo.Get(ctx, *req.ID)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	user.Username = req.Username
 | |
| 	user.Avatar = req.Avatar
 | |
| 	user.Gender = req.Gender
 | |
| 	user.DepartmentID = req.DepartmentID
 | |
| 	user.RoleID = req.RoleID
 | |
| 	user.Status = *req.Status
 | |
| 	user.UpdatedAt = time.Now()
 | |
| 	if req.ChangePassword == "on" {
 | |
| 		hashedPassword, err := crypto.BcryptHashPassword(req.Password + user.Salt)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		user.HashedPassword = hashedPassword
 | |
| 		user.ChangePasswordAt = time.Now()
 | |
| 	}
 | |
| 	return s.repo.Update(ctx, user)
 | |
| }
 | |
| 
 | |
| func (s *userService) All(ctx context.Context) ([]*system.User, error) {
 | |
| 	return s.repo.All(ctx)
 | |
| }
 | |
| 
 | |
| func (s *userService) List(ctx context.Context, q dto.SearchDto) ([]*system.User, int64, error) {
 | |
| 	count, err := s.repo.Count(ctx, q)
 | |
| 	if err != nil {
 | |
| 		return nil, 0, err
 | |
| 	}
 | |
| 
 | |
| 	res, err := s.repo.List(ctx, q)
 | |
| 	if err != nil {
 | |
| 		return nil, 0, err
 | |
| 	}
 | |
| 
 | |
| 	for _, user := range res {
 | |
| 		user.Role, _ = s.roleService.Get(ctx, user.RoleID)
 | |
| 		user.Department, _ = s.departmentService.Get(ctx, user.DepartmentID)
 | |
| 	}
 | |
| 
 | |
| 	return res, count, nil
 | |
| }
 | |
| 
 | |
| func (s *userService) Get(ctx context.Context, id int32) (*system.User, error) {
 | |
| 	return s.repo.Get(ctx, id)
 | |
| }
 | |
| 
 | |
| func (s *userService) XmSelect(ctx context.Context) ([]*view.XmSelect, error) {
 | |
| 	all, err := s.repo.All(ctx)
 | |
| 	if err != nil || len(all) == 0 {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	var res []*view.XmSelect
 | |
| 	for _, user := range all {
 | |
| 		res = append(res, &view.XmSelect{
 | |
| 			Name:  user.Username,
 | |
| 			Value: strconv.Itoa(int(user.ID)),
 | |
| 		})
 | |
| 	}
 | |
| 	return res, nil
 | |
| }
 | |
| 
 | |
| func (s *userService) Login(ctx context.Context, req *form.Login) error {
 | |
| 	l := system.NewLoginLog(req.Email, req.Os, req.Ip, req.Browser, req.Url, req.Referrer)
 | |
| 	err := s.login(ctx, req)
 | |
| 	if err != nil {
 | |
| 		if err := s.loginLogService.Create(ctx, l.SetMessage(err.Error())); err != nil {
 | |
| 			s.Log.Error(err.Error(), err, zap.Any("login_log", l))
 | |
| 		}
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err := s.loginLogService.Create(ctx, l.SetOk("登录成功")); err != nil {
 | |
| 		s.Log.Error(err.Error(), err, zap.Any("login_log", l))
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (s *userService) login(ctx context.Context, req *form.Login) error {
 | |
| 	user, err := s.repo.GetByEmail(ctx, req.Email)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	err = crypto.BcryptComparePassword(user.HashedPassword, req.Password+user.Salt)
 | |
| 	if err != nil {
 | |
| 		return errors.New("账号或密码错误")
 | |
| 	}
 | |
| 
 | |
| 	user.Role, err = s.roleService.Get(ctx, user.RoleID)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if user.Role == nil || user.Role.ID == 0 {
 | |
| 		return errors.New("账号没有配置角色, 请联系管理员")
 | |
| 	}
 | |
| 
 | |
| 	// 登陆成功
 | |
| 	err = s.loginSuccess(ctx, user, req)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (s *userService) loginSuccess(ctx context.Context, user *system.User, req *form.Login) error {
 | |
| 	return s.Session.PutUser(ctx, know.StoreName, dto.AuthorizeUser{
 | |
| 		ID:       user.ID,
 | |
| 		Uuid:     user.Uuid,
 | |
| 		Email:    user.Email,
 | |
| 		Username: user.Username,
 | |
| 		Avatar:   user.Avatar,
 | |
| 		RoleID:   user.Role.ID,
 | |
| 		RoleName: user.Role.DisplayName,
 | |
| 		OS:       req.Os,
 | |
| 		IP:       req.Ip,
 | |
| 		Browser:  req.Browser,
 | |
| 	})
 | |
| }
 |