| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- package com.ymwk.supervisionserver.service.impl;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.ymwk.supervisionserver.component.PageResult;
- import com.ymwk.supervisionserver.component.ResponseDTO;
- import com.ymwk.supervisionserver.component.SmartPageUtil;
- import com.ymwk.supervisionserver.entity.ApplicationCredentials;
- import com.ymwk.supervisionserver.mapper.ApplicationCredentialsMapper;
- import com.ymwk.supervisionserver.model.CredentialsAddRequest;
- import com.ymwk.supervisionserver.model.CredentialsListRequest;
- import com.ymwk.supervisionserver.model.CredentialsUpdateRequest;
- import com.ymwk.supervisionserver.service.ApplicationCredentialsService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.dao.DuplicateKeyException;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.StringUtils;
- import java.util.List;
- import java.util.UUID;
- @Service
- @Slf4j
- public class ApplicationCredentialsServiceImpl implements ApplicationCredentialsService {
- private static final String DEFAULT_OPERATOR = "admin";
- private final ApplicationCredentialsMapper credentialsMapper;
- public ApplicationCredentialsServiceImpl(ApplicationCredentialsMapper credentialsMapper) {
- this.credentialsMapper = credentialsMapper;
- }
- @Override
- public ResponseDTO<PageResult<ApplicationCredentials>> list(CredentialsListRequest request) {
- LambdaQueryWrapper<ApplicationCredentials> wrapper = new LambdaQueryWrapper<>();
- wrapper.like(StringUtils.hasText(request.getName()), ApplicationCredentials::getName, request.getName());
- wrapper.like(StringUtils.hasText(request.getCredIden()), ApplicationCredentials::getCredIden, request.getCredIden());
- wrapper.eq(request.getStatus() != null, ApplicationCredentials::getStatus, request.getStatus());
- wrapper.orderByDesc(ApplicationCredentials::getId);
- Page<ApplicationCredentials> page = new Page<>(request.getPageNum(), request.getPageSize());
- Page<ApplicationCredentials> resultPage = credentialsMapper.selectPage(page, wrapper);
- // api_secret 脱敏:保留前4后4,中间以 * 代替
- List<ApplicationCredentials> records = resultPage.getRecords();
- records.forEach(record -> record.setApiSecret(maskSecret(record.getApiSecret())));
- PageResult<ApplicationCredentials> pageResult = SmartPageUtil.convert2PageResult(resultPage, records);
- return ResponseDTO.ok(pageResult);
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public ResponseDTO<ApplicationCredentials> create(CredentialsAddRequest request) {
- String name = request.getName().trim();
- // name 有唯一索引,先查重给出友好提示
- Long dupCount = credentialsMapper.selectCount(
- new LambdaQueryWrapper<ApplicationCredentials>().eq(ApplicationCredentials::getName, name));
- if (dupCount != null && dupCount > 0) {
- return ResponseDTO.error(100001, "应用名称已存在:" + name);
- }
- ApplicationCredentials entity = new ApplicationCredentials();
- entity.setCredIden(uuid32());
- entity.setName(name);
- entity.setApiKey(uuid32());
- entity.setApiSecret(uuid32());
- entity.setHmacAlgo(ApplicationCredentials.HMAC_ALGO);
- entity.setStatus(ApplicationCredentials.STATUS_ENABLED);
- entity.setDescription(request.getDescription());
- entity.setCreatedBy(DEFAULT_OPERATOR);
- entity.setUpdatedBy(DEFAULT_OPERATOR);
- try {
- credentialsMapper.insert(entity);
- } catch (DuplicateKeyException e) {
- // 并发下撞唯一索引(credIden/apiKey 理论上不可能重复,name 则已在前面查过)
- log.warn("创建应用凭证撞唯一索引: name={}", name);
- return ResponseDTO.error(100001, "应用名称已存在:" + name);
- }
- log.info("应用凭证创建成功: id={}, name={}, credIden={}", entity.getId(), entity.getName(), entity.getCredIden());
- // 返回内容中秘密同样脱敏,需要明文走专用查询接口
- entity.setApiSecret(maskSecret(entity.getApiSecret()));
- return ResponseDTO.ok(entity);
- }
- @Override
- public ResponseDTO<Void> delete(Long id) {
- if (id == null) {
- return ResponseDTO.error(100001, "凭证ID不能为空");
- }
- ApplicationCredentials entity = credentialsMapper.selectById(id);
- if (entity == null) {
- return ResponseDTO.error(100001, "凭证不存在");
- }
- credentialsMapper.deleteById(id);
- log.info("应用凭证删除成功: id={}, name={}", id, entity.getName());
- return ResponseDTO.okMsg("删除成功");
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public ResponseDTO<ApplicationCredentials> update(CredentialsUpdateRequest request) {
- if (request == null || request.getId() == null) {
- return ResponseDTO.error(100001, "凭证ID不能为空");
- }
- ApplicationCredentials entity = credentialsMapper.selectById(request.getId());
- if (entity == null) {
- return ResponseDTO.error(100001, "凭证不存在");
- }
- String name = request.getName().trim();
- // name 有唯一索引,查重时排除自己
- Long dupCount = credentialsMapper.selectCount(
- new LambdaQueryWrapper<ApplicationCredentials>()
- .eq(ApplicationCredentials::getName, name)
- .ne(ApplicationCredentials::getId, request.getId()));
- if (dupCount != null && dupCount > 0) {
- return ResponseDTO.error(100001, "应用名称已存在:" + name);
- }
- entity.setName(name);
- entity.setDescription(request.getDescription());
- entity.setUpdatedBy(DEFAULT_OPERATOR);
- try {
- credentialsMapper.updateById(entity);
- } catch (DuplicateKeyException e) {
- log.warn("修改应用凭证撞唯一索引: id={}, name={}", request.getId(), name);
- return ResponseDTO.error(100001, "应用名称已存在:" + name);
- }
- log.info("应用凭证修改成功: id={}, name={}", entity.getId(), name);
- entity.setApiSecret(maskSecret(entity.getApiSecret()));
- return ResponseDTO.ok(entity);
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public ResponseDTO<ApplicationCredentials> resetSecret(Long id) {
- if (id == null) {
- return ResponseDTO.error(100001, "凭证ID不能为空");
- }
- ApplicationCredentials entity = credentialsMapper.selectById(id);
- if (entity == null) {
- return ResponseDTO.error(100001, "凭证不存在");
- }
- entity.setApiSecret(uuid32());
- entity.setUpdatedBy(DEFAULT_OPERATOR);
- credentialsMapper.updateById(entity);
- log.info("应用凭证密钥已重新生成: id={}, name={}", id, entity.getName());
- entity.setApiSecret(maskSecret(entity.getApiSecret()));
- return ResponseDTO.ok(entity, "api_secret 已重新生成,请通过专用查询接口获取明文");
- }
- @Override
- public ResponseDTO<String> getSecret(Long id) {
- if (id == null) {
- return ResponseDTO.error(100001, "凭证ID不能为空");
- }
- ApplicationCredentials entity = credentialsMapper.selectById(id);
- if (entity == null) {
- return ResponseDTO.error(100001, "凭证不存在");
- }
- return ResponseDTO.ok(entity.getApiSecret());
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public ResponseDTO<ApplicationCredentials> changeStatus(Long id, Integer status) {
- if (id == null) {
- return ResponseDTO.error(100001, "凭证ID不能为空");
- }
- if (!ApplicationCredentials.STATUS_ENABLED.equals(status)
- && !ApplicationCredentials.STATUS_DISABLED.equals(status)) {
- return ResponseDTO.error(100001, "状态值只支持 1(启用)或 2(禁用)");
- }
- ApplicationCredentials entity = credentialsMapper.selectById(id);
- if (entity == null) {
- return ResponseDTO.error(100001, "凭证不存在");
- }
- if (!status.equals(entity.getStatus())) {
- entity.setStatus(status);
- entity.setUpdatedBy(DEFAULT_OPERATOR);
- credentialsMapper.updateById(entity);
- }
- entity.setApiSecret(maskSecret(entity.getApiSecret()));
- return ResponseDTO.ok(entity);
- }
- /**
- * api_secret 脱敏:保留前4后4,中间替换为 *
- */
- private String maskSecret(String secret) {
- if (secret == null) {
- return null;
- }
- int length = secret.length();
- if (length <= 8) {
- return "*".repeat(length);
- }
- return secret.substring(0, 4)
- + "*".repeat(length - 8)
- + secret.substring(length - 4);
- }
- /**
- * 生成32位无连字符大写UUID
- */
- private String uuid32() {
- return UUID.randomUUID().toString().replace("-", "").toUpperCase();
- }
- }
|