194 lines
4.6 KiB
Go
194 lines
4.6 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
|
|
loginLogService v1.LoginLogService
|
|
}
|
|
|
|
func NewUserService(
|
|
service *v1.Service,
|
|
repo system.UserRepository,
|
|
roleService v1.RoleService,
|
|
loginLogService v1.LoginLogService,
|
|
) v1.UserService {
|
|
return &userService{
|
|
Service: service,
|
|
repo: repo,
|
|
roleService: roleService,
|
|
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) {
|
|
return s.repo.List(ctx, q)
|
|
}
|
|
|
|
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,
|
|
RoleID: user.Role.ID,
|
|
RoleName: user.Role.DisplayName,
|
|
OS: req.Os,
|
|
IP: req.Ip,
|
|
Browser: req.Browser,
|
|
})
|
|
}
|