package com.mydreamjob.auth; import com.mydreamjob.audit.AuditService; import com.mydreamjob.common.exception.BusinessException; import com.mydreamjob.common.exception.ErrorCode; import com.mydreamjob.deletion.AccountDeletion; import com.mydreamjob.deletion.AccountDeletionPhoneHasher; import com.mydreamjob.deletion.AccountDeletionRepository; import com.mydreamjob.deletion.DeletionStatus; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; /** * Mock 认证服务 - 仅用于开发/测试环境登录原型 */ @Slf4j @Service @RequiredArgsConstructor public class AuthService { private final UserRepository userRepository; private final JwtTokenProvider jwtTokenProvider; private final SmsVerificationService smsVerificationService; private final AuditService auditService; private final AccountDeletionRepository accountDeletionRepository; private final AccountDeletionPhoneHasher accountDeletionPhoneHasher; /** * Mock 登录:验证短信验证码后自动创建/登录用户 */ @Transactional public Map mockLogin(String phone, String code, String purpose, String requestId, String ipAddress, String userAgent) { // 验证验证码(传入 purpose,确保验证码用途匹配) smsVerificationService.verifyCode(phone, code, purpose); // 原手机号禁止重新注册:已注销账号的手机号墓碑(HMAC 摘要)命中则拒绝, // 且不得自动创建新用户(不把原手机号明文写入注销表或审计)。 String phoneHash = accountDeletionPhoneHasher.hash(phone); if (accountDeletionRepository.findByDeletedPhoneHash(phoneHash).isPresent()) { throw new BusinessException(ErrorCode.ACCOUNT_DELETED); } // 查找或创建用户 Optional userOpt = userRepository.findByPhone(phone); User user; if (userOpt.isEmpty()) { user = User.builder() .phone(phone) .nickname("用户_" + phone.substring(7)) .role(User.Role.STUDENT) .active(true) .verified(true) .build(); user = userRepository.save(user); log.info("Auto-created user: id={}, phone={}", user.getId(), phone); } else { user = userOpt.get(); } // 已注销(COMPLETED)用户禁止登录 java.util.Optional deletion = accountDeletionRepository.findByUserId(user.getId()); if (deletion.isPresent() && deletion.get().getStatus() == DeletionStatus.COMPLETED) { throw new BusinessException(ErrorCode.ACCOUNT_DELETED); } // 生成 token String accessToken = jwtTokenProvider.generateAccessToken(user.getId(), user.getPhone(), Map.of("role", user.getRole().name())); String refreshToken = jwtTokenProvider.generateRefreshToken(user.getId(), user.getPhone()); auditService.logLogin(user.getId(), ipAddress, userAgent, requestId); Map result = new HashMap<>(); result.put("userId", user.getId()); result.put("phone", user.getPhone()); result.put("nickname", user.getNickname()); result.put("role", user.getRole()); result.put("accessToken", accessToken); result.put("refreshToken", refreshToken); result.put("expiresIn", 86400); return result; } /** * 获取当前用户信息 */ public Map getCurrentUser(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)); Map result = new HashMap<>(); result.put("id", user.getId()); result.put("phone", user.getPhone()); result.put("email", user.getEmail()); result.put("nickname", user.getNickname()); result.put("avatarUrl", user.getAvatarUrl()); result.put("role", user.getRole()); result.put("active", user.getActive()); result.put("verified", user.getVerified()); result.put("createdAt", user.getCreatedAt()); return result; } }