package com.xuqm.tenant.service; import com.xuqm.common.exception.BusinessException; import com.xuqm.tenant.dto.CreateSubAccountRequest; import com.xuqm.tenant.entity.TenantEntity; import com.xuqm.tenant.repository.TenantRepository; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.security.SecureRandom; import java.time.LocalDateTime; import java.util.Base64; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @Service public class SubAccountService { private final TenantRepository tenantRepository; private final PasswordEncoder passwordEncoder; private final EmailService emailService; private final StringRedisTemplate redis; private static final String SUB_VERIFY_PREFIX = "sub_verified:"; private static final SecureRandom random = new SecureRandom(); public SubAccountService(TenantRepository tenantRepository, PasswordEncoder passwordEncoder, EmailService emailService, StringRedisTemplate redis) { this.tenantRepository = tenantRepository; this.passwordEncoder = passwordEncoder; this.emailService = emailService; this.redis = redis; } public boolean isEmailVerifiedInSession(String tenantId) { return Boolean.TRUE.toString().equals(redis.opsForValue().get(SUB_VERIFY_PREFIX + tenantId)); } public void verifyEmail(String tenantId, String email, String code) { emailService.verify(email, code, "SUB_ACCOUNT"); redis.opsForValue().set(SUB_VERIFY_PREFIX + tenantId, Boolean.TRUE.toString(), 24, TimeUnit.HOURS); } public TenantEntity create(String parentId, CreateSubAccountRequest req) { if (tenantRepository.existsByUsername(req.username())) { throw new BusinessException("用户名已存在"); } TenantEntity sub = new TenantEntity(); sub.setId(UUID.randomUUID().toString()); sub.setUsername(req.username()); sub.setPassword(passwordEncoder.encode(req.password())); sub.setEmail(req.email() != null ? req.email() : ""); sub.setNickname(req.nickname()); sub.setPhone(req.phone()); sub.setType(TenantEntity.Type.SUB); sub.setStatus(TenantEntity.Status.ACTIVE); sub.setParentId(parentId); sub.setCreatedAt(LocalDateTime.now()); return tenantRepository.save(sub); } public List listByParent(String parentId) { return tenantRepository.findByParentId(parentId); } public void disable(String subId, String parentId) { TenantEntity sub = tenantRepository.findById(subId) .orElseThrow(() -> new BusinessException(404, "子账号不存在")); if (!parentId.equals(sub.getParentId())) { throw new BusinessException(403, "无权操作"); } sub.setStatus(TenantEntity.Status.DISABLED); tenantRepository.save(sub); } public String generatePassword() { byte[] bytes = new byte[9]; random.nextBytes(bytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); } }