Files
tyapi-server/internal/application/user/user_application_service_impl.go

304 lines
10 KiB
Go
Raw Normal View History

2025-07-13 16:36:20 +08:00
package user
import (
"context"
"fmt"
"go.uber.org/zap"
"tyapi-server/internal/application/user/dto/commands"
"tyapi-server/internal/application/user/dto/queries"
"tyapi-server/internal/application/user/dto/responses"
"tyapi-server/internal/domains/user/entities"
"tyapi-server/internal/domains/user/events"
user_service "tyapi-server/internal/domains/user/services"
"tyapi-server/internal/shared/interfaces"
"tyapi-server/internal/shared/middleware"
)
// UserApplicationServiceImpl 用户应用服务实现
2025-07-20 20:53:26 +08:00
// 负责业务流程编排、事务管理、数据转换,不直接操作仓库
2025-07-13 16:36:20 +08:00
type UserApplicationServiceImpl struct {
2025-07-20 20:53:26 +08:00
userManagementService *user_service.UserManagementService
userAuthService *user_service.UserAuthService
smsCodeService *user_service.SMSCodeService
enterpriseService *user_service.EnterpriseService
eventBus interfaces.EventBus
jwtAuth *middleware.JWTAuthMiddleware
logger *zap.Logger
2025-07-13 16:36:20 +08:00
}
// NewUserApplicationService 创建用户应用服务
func NewUserApplicationService(
2025-07-20 20:53:26 +08:00
userManagementService *user_service.UserManagementService,
userAuthService *user_service.UserAuthService,
2025-07-13 16:36:20 +08:00
smsCodeService *user_service.SMSCodeService,
2025-07-20 20:53:26 +08:00
enterpriseService *user_service.EnterpriseService,
2025-07-13 16:36:20 +08:00
eventBus interfaces.EventBus,
jwtAuth *middleware.JWTAuthMiddleware,
logger *zap.Logger,
) UserApplicationService {
return &UserApplicationServiceImpl{
2025-07-20 20:53:26 +08:00
userManagementService: userManagementService,
userAuthService: userAuthService,
smsCodeService: smsCodeService,
enterpriseService: enterpriseService,
eventBus: eventBus,
jwtAuth: jwtAuth,
logger: logger,
2025-07-13 16:36:20 +08:00
}
}
// Register 用户注册
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证短信验证码 2. 创建用户 3. 发布注册事件
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) Register(ctx context.Context, cmd *commands.RegisterUserCommand) (*responses.RegisterUserResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 验证短信验证码
2025-07-13 16:36:20 +08:00
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneRegister); err != nil {
return nil, fmt.Errorf("验证码错误或已过期")
}
2025-07-20 20:53:26 +08:00
// 2. 创建用户
user, err := s.userManagementService.CreateUser(ctx, cmd.Phone, cmd.Password)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-20 20:53:26 +08:00
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 发布用户注册事件
2025-07-13 16:36:20 +08:00
event := events.NewUserRegisteredEvent(user, "")
if err := s.eventBus.Publish(ctx, event); err != nil {
s.logger.Warn("发布用户注册事件失败", zap.Error(err))
}
s.logger.Info("用户注册成功", zap.String("user_id", user.ID), zap.String("phone", user.Phone))
return &responses.RegisterUserResponse{
2025-07-20 20:53:26 +08:00
ID: user.ID,
2025-07-13 16:36:20 +08:00
Phone: user.Phone,
}, nil
}
// LoginWithPassword 密码登录
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证用户密码 2. 生成访问令牌 3. 更新登录统计 4. 获取用户权限
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) LoginWithPassword(ctx context.Context, cmd *commands.LoginWithPasswordCommand) (*responses.LoginUserResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 验证用户密码
user, err := s.userAuthService.ValidatePassword(ctx, cmd.Phone, cmd.Password)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-20 20:53:26 +08:00
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 2. 生成包含用户类型的token
accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone, user.UserType)
if err != nil {
s.logger.Error("生成令牌失败", zap.Error(err))
return nil, fmt.Errorf("生成访问令牌失败")
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 如果是管理员,更新登录统计
if user.IsAdmin() {
if err := s.userManagementService.UpdateLoginStats(ctx, user.ID); err != nil {
s.logger.Error("更新登录统计失败", zap.Error(err))
}
// 重新获取用户信息以获取最新的登录统计
updatedUser, err := s.userManagementService.GetUserByID(ctx, user.ID)
if err != nil {
s.logger.Error("重新获取用户信息失败", zap.Error(err))
} else {
user = updatedUser
}
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 4. 获取用户权限(仅管理员)
var permissions []string
if user.IsAdmin() {
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
if err != nil {
s.logger.Error("获取用户权限失败", zap.Error(err))
permissions = []string{}
}
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 5. 构建用户信息
userProfile := &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
Permissions: permissions,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
return &responses.LoginUserResponse{
User: userProfile,
AccessToken: accessToken,
TokenType: "Bearer",
ExpiresIn: 86400, // 24h
LoginMethod: "password",
}, nil
}
// LoginWithSMS 短信验证码登录
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证短信验证码 2. 验证用户登录状态 3. 生成访问令牌 4. 更新登录统计 5. 获取用户权限
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) LoginWithSMS(ctx context.Context, cmd *commands.LoginWithSMSCommand) (*responses.LoginUserResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 验证短信验证码
2025-07-13 16:36:20 +08:00
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneLogin); err != nil {
return nil, fmt.Errorf("验证码错误或已过期")
}
2025-07-20 20:53:26 +08:00
// 2. 验证用户登录状态
user, err := s.userAuthService.ValidateUserLogin(ctx, cmd.Phone)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-20 20:53:26 +08:00
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 生成包含用户类型的token
accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone, user.UserType)
2025-07-13 16:36:20 +08:00
if err != nil {
s.logger.Error("生成令牌失败", zap.Error(err))
return nil, fmt.Errorf("生成访问令牌失败")
}
2025-07-20 20:53:26 +08:00
// 4. 如果是管理员,更新登录统计
if user.IsAdmin() {
if err := s.userManagementService.UpdateLoginStats(ctx, user.ID); err != nil {
s.logger.Error("更新登录统计失败", zap.Error(err))
}
// 重新获取用户信息以获取最新的登录统计
updatedUser, err := s.userManagementService.GetUserByID(ctx, user.ID)
if err != nil {
s.logger.Error("重新获取用户信息失败", zap.Error(err))
} else {
user = updatedUser
}
}
// 5. 获取用户权限(仅管理员)
var permissions []string
if user.IsAdmin() {
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
if err != nil {
s.logger.Error("获取用户权限失败", zap.Error(err))
permissions = []string{}
}
}
// 6. 构建用户信息
userProfile := &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
Permissions: permissions,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
return &responses.LoginUserResponse{
User: userProfile,
AccessToken: accessToken,
TokenType: "Bearer",
2025-07-20 20:53:26 +08:00
ExpiresIn: int64(s.jwtAuth.GetExpiresIn().Seconds()), // 168h
2025-07-13 16:36:20 +08:00
LoginMethod: "sms",
}, nil
}
2025-07-20 20:53:26 +08:00
// SendSMS 发送短信验证码
// 业务流程1. 发送短信验证码
func (s *UserApplicationServiceImpl) SendSMS(ctx context.Context, cmd *commands.SendCodeCommand) error {
return s.smsCodeService.SendCode(ctx, cmd.Phone, entities.SMSScene(cmd.Scene), "", "")
}
2025-07-13 16:36:20 +08:00
// ChangePassword 修改密码
2025-07-20 20:53:26 +08:00
// 业务流程1. 修改用户密码
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) ChangePassword(ctx context.Context, cmd *commands.ChangePasswordCommand) error {
2025-07-20 20:53:26 +08:00
return s.userAuthService.ChangePassword(ctx, cmd.UserID, cmd.OldPassword, cmd.NewPassword)
2025-07-13 16:36:20 +08:00
}
2025-07-15 13:21:34 +08:00
// ResetPassword 重置密码
2025-07-20 20:53:26 +08:00
// 业务流程1. 验证短信验证码 2. 重置用户密码
2025-07-15 13:21:34 +08:00
func (s *UserApplicationServiceImpl) ResetPassword(ctx context.Context, cmd *commands.ResetPasswordCommand) error {
2025-07-20 20:53:26 +08:00
// 1. 验证短信验证码
2025-07-15 13:21:34 +08:00
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneResetPassword); err != nil {
return fmt.Errorf("验证码错误或已过期")
}
2025-07-20 20:53:26 +08:00
// 2. 重置用户密码
return s.userAuthService.ResetPassword(ctx, cmd.Phone, cmd.NewPassword)
2025-07-15 13:21:34 +08:00
}
2025-07-20 20:53:26 +08:00
// GetUserProfile 获取用户资料
// 业务流程1. 获取用户信息 2. 获取企业信息 3. 构建响应数据
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) GetUserProfile(ctx context.Context, userID string) (*responses.UserProfileResponse, error) {
2025-07-20 20:53:26 +08:00
// 1. 获取用户信息(包含企业信息)
user, err := s.enterpriseService.GetUserWithEnterpriseInfo(ctx, userID)
if err != nil {
return nil, err
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 2. 获取用户权限(仅管理员)
var permissions []string
if user.IsAdmin() {
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
if err != nil {
s.logger.Error("获取用户权限失败", zap.Error(err))
permissions = []string{}
}
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 3. 构建用户信息
userProfile := &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
Permissions: permissions,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// 4. 添加企业信息
if user.EnterpriseInfo != nil {
userProfile.EnterpriseInfo = &responses.EnterpriseInfoResponse{
ID: user.EnterpriseInfo.ID,
CompanyName: user.EnterpriseInfo.CompanyName,
UnifiedSocialCode: user.EnterpriseInfo.UnifiedSocialCode,
LegalPersonName: user.EnterpriseInfo.LegalPersonName,
LegalPersonID: user.EnterpriseInfo.LegalPersonID,
CreatedAt: user.EnterpriseInfo.CreatedAt,
UpdatedAt: user.EnterpriseInfo.UpdatedAt,
2025-07-13 16:36:20 +08:00
}
}
2025-07-20 20:53:26 +08:00
return userProfile, nil
2025-07-13 16:36:20 +08:00
}
2025-07-20 20:53:26 +08:00
// GetUser 获取用户信息
// 业务流程1. 获取用户信息 2. 构建响应数据
2025-07-13 16:36:20 +08:00
func (s *UserApplicationServiceImpl) GetUser(ctx context.Context, query *queries.GetUserQuery) (*responses.UserProfileResponse, error) {
2025-07-20 20:53:26 +08:00
user, err := s.userManagementService.GetUserByID(ctx, query.UserID)
if err != nil {
return nil, err
}
return &responses.UserProfileResponse{
ID: user.ID,
Phone: user.Phone,
Username: user.Username,
UserType: user.UserType,
IsActive: user.Active,
LastLoginAt: user.LastLoginAt,
LoginCount: user.LoginCount,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}, nil
2025-07-13 16:36:20 +08:00
}