package system import ( "context" "encoding/json" "errors" "strconv" "time" "management/internal/db/model/dto" db "management/internal/db/sqlc" "management/internal/erpserver/model/form" "management/internal/erpserver/model/system" "management/internal/erpserver/model/view" v1 "management/internal/erpserver/service/v1" "management/internal/pkg/crypto" "management/internal/pkg/know" "management/internal/pkg/rand" "management/internal/pkg/session" "github.com/drhin/logger" "github.com/google/uuid" "go.uber.org/zap" ) type userService struct { session session.Session log *logger.Logger repo system.UserRepository roleService v1.RoleService loginLogService v1.LoginLogService } var _ v1.UserService = (*userService)(nil) func NewUserService(session session.Session, log *logger.Logger, repo system.UserRepository, roleService v1.RoleService, loginLogService v1.LoginLogService) *userService { return &userService{ session: session, log: log, repo: repo, roleService: roleService, loginLogService: loginLogService, } } func (b *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 = b.repo.Create(ctx, user) if err != nil { if db.IsUniqueViolation(err) { return errors.New("用户已经存在") } return err } return nil } func (b *userService) Update(ctx context.Context, req *form.User) error { user, err := b.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 b.repo.Update(ctx, user) } func (b *userService) All(ctx context.Context) ([]*system.User, error) { return b.repo.All(ctx) } func (b *userService) List(ctx context.Context, q dto.SearchDto) ([]*system.User, int64, error) { return b.repo.List(ctx, q) } func (b *userService) Get(ctx context.Context, id int32) (*system.User, error) { return b.repo.Get(ctx, id) } func (b *userService) XmSelect(ctx context.Context) ([]*view.XmSelect, error) { all, err := b.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 (b *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 := b.login(ctx, req) if err != nil { if err := b.loginLogService.Create(ctx, l.SetMessage(err.Error())); err != nil { b.log.Error(err.Error(), err, zap.Any("login_log", l)) } return err } if err := b.loginLogService.Create(ctx, l.SetOk("登录成功")); err != nil { b.log.Error(err.Error(), err, zap.Any("login_log", l)) } return nil } func (b *userService) login(ctx context.Context, req *form.Login) error { user, err := b.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 = b.roleService.Get(ctx, user.RoleID) if err != nil { return err } if user.Role == nil || user.Role.ID == 0 { return errors.New("账号没有配置角色, 请联系管理员") } // 登陆成功 err = b.loginSuccess(ctx, user, req) if err != nil { return err } return nil } func (b *userService) loginSuccess(ctx context.Context, user *system.User, req *form.Login) error { auth := 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, } gob, err := json.Marshal(auth) if err != nil { return err } b.session.Put(ctx, know.StoreName, gob) return nil }