You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

107 lines
4.3 KiB

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<String, Object> 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<User> 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<AccountDeletion> 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<String, Object> 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<String, Object> getCurrentUser(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));
Map<String, Object> 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;
}
}