feat: 在AccountService中添加用户删除逻辑的详细检查,包括关联数据的验证和日志记录,增强用户管理的安全性
This commit is contained in:
@@ -1,29 +1,47 @@
|
|||||||
package com.gameplatform.server.service.account;
|
package com.gameplatform.server.service.account;
|
||||||
|
|
||||||
import com.gameplatform.server.mapper.account.UserAccountMapper;
|
import com.gameplatform.server.mapper.account.UserAccountMapper;
|
||||||
|
import com.gameplatform.server.mapper.agent.AgentPointsTxMapper;
|
||||||
|
import com.gameplatform.server.mapper.agent.LinkBatchMapper;
|
||||||
|
import com.gameplatform.server.mapper.agent.LinkTaskMapper;
|
||||||
import com.gameplatform.server.model.dto.account.AccountCreateRequest;
|
import com.gameplatform.server.model.dto.account.AccountCreateRequest;
|
||||||
import com.gameplatform.server.model.dto.account.AccountResponse;
|
import com.gameplatform.server.model.dto.account.AccountResponse;
|
||||||
import com.gameplatform.server.model.dto.account.AccountUpdateRequest;
|
import com.gameplatform.server.model.dto.account.AccountUpdateRequest;
|
||||||
import com.gameplatform.server.model.dto.account.PointsBalanceResponse;
|
import com.gameplatform.server.model.dto.account.PointsBalanceResponse;
|
||||||
import com.gameplatform.server.model.dto.common.PageResult;
|
import com.gameplatform.server.model.dto.common.PageResult;
|
||||||
import com.gameplatform.server.model.entity.account.UserAccount;
|
import com.gameplatform.server.model.entity.account.UserAccount;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AccountService {
|
public class AccountService {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AccountService.class);
|
||||||
|
|
||||||
private final UserAccountMapper mapper;
|
private final UserAccountMapper mapper;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final LinkTaskMapper linkTaskMapper;
|
||||||
|
private final LinkBatchMapper linkBatchMapper;
|
||||||
|
private final AgentPointsTxMapper agentPointsTxMapper;
|
||||||
|
|
||||||
public AccountService(UserAccountMapper mapper, PasswordEncoder passwordEncoder) {
|
public AccountService(UserAccountMapper mapper,
|
||||||
|
PasswordEncoder passwordEncoder,
|
||||||
|
LinkTaskMapper linkTaskMapper,
|
||||||
|
LinkBatchMapper linkBatchMapper,
|
||||||
|
AgentPointsTxMapper agentPointsTxMapper) {
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.linkTaskMapper = linkTaskMapper;
|
||||||
|
this.linkBatchMapper = linkBatchMapper;
|
||||||
|
this.agentPointsTxMapper = agentPointsTxMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mono<PageResult<AccountResponse>> list(String userType, String status, String keyword,
|
public Mono<PageResult<AccountResponse>> list(String userType, String status, String keyword,
|
||||||
@@ -166,27 +184,74 @@ public class AccountService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public Mono<Boolean> delete(Long id, Long currentUserId) {
|
public Mono<Boolean> delete(Long id, Long currentUserId) {
|
||||||
return Mono.fromCallable(() -> {
|
return Mono.fromCallable(() -> {
|
||||||
// 检查用户是否存在
|
log.info("开始删除用户账户: id={}, 操作者={}", id, currentUserId);
|
||||||
|
|
||||||
|
// 1. 检查用户是否存在
|
||||||
UserAccount user = mapper.selectById(id);
|
UserAccount user = mapper.selectById(id);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
|
log.warn("用户不存在: id={}", id);
|
||||||
throw new IllegalArgumentException("用户不存在");
|
throw new IllegalArgumentException("用户不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 不能删除自己
|
log.info("准备删除用户: username={}, userType={}", user.getUsername(), user.getUserType());
|
||||||
|
|
||||||
|
// 2. 不能删除自己
|
||||||
if (id.equals(currentUserId)) {
|
if (id.equals(currentUserId)) {
|
||||||
|
log.warn("尝试删除自己: userId={}", id);
|
||||||
throw new IllegalArgumentException("不能删除当前登录的用户");
|
throw new IllegalArgumentException("不能删除当前登录的用户");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果要删除的是管理员,检查是否是最后一个管理员
|
// 3. 如果要删除的是管理员,检查是否是最后一个管理员
|
||||||
if ("ADMIN".equals(user.getUserType())) {
|
if ("ADMIN".equals(user.getUserType())) {
|
||||||
long adminCount = mapper.countByFilter("ADMIN", "ENABLED", null);
|
long adminCount = mapper.countByFilter("ADMIN", "ENABLED", null);
|
||||||
if (adminCount <= 1) {
|
if (adminCount <= 1) {
|
||||||
|
log.warn("尝试删除最后一个管理员: userId={}", id);
|
||||||
throw new IllegalArgumentException("不能删除最后一个管理员账户");
|
throw new IllegalArgumentException("不能删除最后一个管理员账户");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行删除
|
// 4. 检查是否有关联数据(对所有用户类型都检查)
|
||||||
return mapper.deleteById(id) > 0;
|
List<String> blockReasons = new ArrayList<>();
|
||||||
|
|
||||||
|
// 检查链接任务
|
||||||
|
long linkTaskCount = linkTaskMapper.countByAgentId(id);
|
||||||
|
if (linkTaskCount > 0) {
|
||||||
|
blockReasons.add(String.format("该用户还有 %d 个链接任务", linkTaskCount));
|
||||||
|
log.info("用户 {} 有 {} 个链接任务", id, linkTaskCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查批次记录
|
||||||
|
long batchCount = linkBatchMapper.countByAgentId(id);
|
||||||
|
if (batchCount > 0) {
|
||||||
|
blockReasons.add(String.format("该用户还有 %d 个批次记录", batchCount));
|
||||||
|
log.info("用户 {} 有 {} 个批次记录", id, batchCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查积分交易记录
|
||||||
|
long pointsTxCount = agentPointsTxMapper.countByAccountId(id);
|
||||||
|
if (pointsTxCount > 0) {
|
||||||
|
blockReasons.add(String.format("该用户还有 %d 条积分交易记录", pointsTxCount));
|
||||||
|
log.info("用户 {} 有 {} 条积分交易记录", id, pointsTxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有阻止删除的原因,抛出友好的错误提示
|
||||||
|
if (!blockReasons.isEmpty()) {
|
||||||
|
String errorMessage = String.format("无法删除用户 '%s':%s。请先清理这些数据后再删除。",
|
||||||
|
user.getUsername(),
|
||||||
|
String.join(";", blockReasons));
|
||||||
|
log.warn("删除用户被阻止: userId={}, 原因: {}", id, errorMessage);
|
||||||
|
throw new IllegalArgumentException(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 执行删除
|
||||||
|
boolean deleted = mapper.deleteById(id) > 0;
|
||||||
|
if (deleted) {
|
||||||
|
log.info("用户删除成功: id={}, username={}", id, user.getUsername());
|
||||||
|
} else {
|
||||||
|
log.warn("用户删除失败: id={}", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleted;
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.boundedElastic());
|
.subscribeOn(Schedulers.boundedElastic());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user