electricity_bill_calc_service/service/user.go

151 lines
5.4 KiB
Go

package service
import (
"electricity_bill_calc/cache"
"electricity_bill_calc/config"
"electricity_bill_calc/exceptions"
"electricity_bill_calc/logger"
"electricity_bill_calc/model"
"electricity_bill_calc/repository"
"electricity_bill_calc/tools"
"electricity_bill_calc/tools/serial"
"electricity_bill_calc/types"
"time"
"github.com/fufuok/utils/xhash"
"github.com/google/uuid"
"github.com/samber/lo"
"go.uber.org/zap"
)
type _UserService struct {
log *zap.Logger
}
var UserService = _UserService{
log: logger.Named("Service", "User"),
}
func (us _UserService) MatchUserPassword(controlCode, testCode string) bool {
hashedCode := xhash.Sha512Hex(testCode)
return controlCode == hashedCode
}
// 处理用户登录的通用过程。
func (us _UserService) processUserLogin(username, password string, userType []int16) (*model.User, *model.UserDetail, error) {
us.log.Info("处理用户登录。", zap.String("username", username))
user, err := repository.UserRepository.FindUserByUsername(username)
if err != nil {
us.log.Error("处理用户登录失败。", zap.String("username", username), zap.Error(err))
return nil, nil, err
}
if user == nil {
us.log.Warn("处理用户登录失败,用户不存在。", zap.String("username", username))
return nil, nil, exceptions.NewAuthenticationError(404, "用户不存在。")
}
if !lo.Contains(userType, user.UserType) {
us.log.Warn("处理用户登录失败,用户类型错误。", zap.String("username", username), zap.Int16s("user type", userType))
return nil, nil, exceptions.NewAuthenticationError(400, "用户类型不正确。")
}
if !user.Enabled {
us.log.Warn("处理用户登录失败,用户已被禁用。", zap.String("username", username))
return nil, nil, exceptions.NewAuthenticationError(403, "用户已被禁用。")
}
if user.ResetNeeded {
us.log.Warn("处理用户登录失败,用户需要重置密码。", zap.String("username", username))
authErr := exceptions.NewAuthenticationError(401, "用户凭据已失效。")
authErr.NeedReset = true
return nil, nil, authErr
}
if !us.MatchUserPassword(user.Password, password) {
us.log.Warn("处理用户登录失败,密码错误。", zap.String("username", username))
return nil, nil, exceptions.NewAuthenticationError(402, "用户凭据不正确。")
}
userDetail, err := repository.UserRepository.FindUserDetailById(user.Id)
if err != nil {
us.log.Error("处理企业用户登录失败,查询用户详细信息失败。", zap.String("username", username), zap.Error(err))
return nil, nil, err
}
if userDetail.ServiceExpiration.Before(time.Now()) {
us.log.Warn("处理企业用户登录失败,用户服务已过期。", zap.String("username", username))
return nil, nil, exceptions.NewAuthenticationError(406, "用户服务期限已过。")
}
return user, userDetail, nil
}
// 处理企业用户登录
func (us _UserService) ProcessEnterpriseUserLogin(username, password string) (*model.Session, error) {
user, userDetail, err := us.processUserLogin(username, password, []int16{model.USER_TYPE_ENT})
if err != nil {
us.log.Error("处理企业用户登录失败。", zap.String("username", username), zap.Error(err))
return nil, err
}
token, _ := uuid.NewRandom() //生成uuid作为会话的token使用
userSession := &model.Session{
Uid: user.Id,
Name: user.Username,
Type: user.UserType,
Token: token.String(),
ExpiresAt: types.Now().Add(config.ServiceSettings.MaxSessionLife),
}
if userDetail != nil && userDetail.Name != nil {
userSession.Name = *userDetail.Name
}
err = cache.CacheSession(userSession)
if err != nil {
us.log.Error("处理企业用户登录失败,缓存用户会话失败。", zap.String("username", username), zap.Error(err))
return nil, err
}
return userSession, nil
}
// 处理运维、监管用户登录
func (us _UserService) ProcessManagementUserLogin(username, password string) (*model.Session, error) {
user, userDetail, err := us.processUserLogin(username, password, []int16{model.USER_TYPE_OPS, model.USER_TYPE_SUP})
if err != nil {
us.log.Error("处理运维、监管用户登录失败。", zap.String("username", username), zap.Error(err))
return nil, err
}
token, _ := uuid.NewRandom()
userSession := &model.Session{
Uid: user.Id,
Name: user.Username,
Type: user.UserType,
Token: token.String(),
ExpiresAt: time.Now().Add(config.ServiceSettings.MaxSessionLife),
}
if userDetail != nil {
userSession.Name = *userDetail.Name
}
err = cache.CacheSession(userSession)
if err != nil {
us.log.Error("处理运维、监管用户登录失败,缓存用户会话失败。", zap.String("username", username), zap.Error(err))
return nil, err
}
return userSession, nil
}
// 创建用户账号的通用方法。
func (us _UserService) CreateUserAccount(user *model.User, detail *model.UserDetail) (*string, error) {
if lo.IsEmpty(user.Id) {
var prefix string
if user.UserType == model.USER_TYPE_ENT {
prefix = "E"
} else {
prefix = "S"
}
serial.StringSerialRequestChan <- 1
user.Id = serial.Prefix(prefix, <-serial.StringSerialResponseChan)
detail.Id = user.Id
}
verifyCode := tools.RandStr(10)
user.Password = xhash.Sha512Hex(verifyCode)
user.ResetNeeded = true
res, err := repository.UserRepository.CreateUser(*user, *detail, nil)
if err != nil || !res {
us.log.Error("创建用户账号失败。", zap.String("username", user.Username), zap.Error(err))
return nil, err
}
return &verifyCode, nil
}