package com.nanxiislet.admin.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.nanxiislet.admin.common.base.BasePageQuery; import com.nanxiislet.admin.common.exception.BusinessException; import com.nanxiislet.admin.common.result.PageResult; import com.nanxiislet.admin.common.result.R; import com.nanxiislet.admin.common.result.ResultCode; import com.nanxiislet.admin.dto.CertificateApplyRequest; import com.nanxiislet.admin.dto.CertificateApplyResult; import com.nanxiislet.admin.entity.PlatformCertificate; import com.nanxiislet.admin.service.PlatformCertificateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; /** * 证书管理控制器 * * @author NanxiIslet * @since 2026-01-13 */ @RestController @RequestMapping("/platform/certificate") @Tag(name = "证书管理", description = "管理SSL/TLS证书,整合1Panel证书功能") public class PlatformCertificateController { @Resource private PlatformCertificateService certificateService; @Resource private com.nanxiislet.admin.service.PlatformServerService serverService; // ==================== 证书 CRUD ==================== @GetMapping("/list") @Operation(summary = "证书列表", description = "获取指定服务器的证书列表") public R> list( @RequestParam(required = false) Long serverId, BasePageQuery query) { Page page = certificateService.listPage(serverId, query); return R.ok(PageResult.of(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize())); } @GetMapping("/{id}") @Operation(summary = "证书详情", description = "获取证书详情,包含证书内容和私钥") public R getDetail(@PathVariable Long id) { PlatformCertificate cert = certificateService.getCertificateDetail(id); if (cert == null) { throw new BusinessException(ResultCode.DATA_NOT_EXIST); } return R.ok(cert); } @DeleteMapping("/{id}") @Operation(summary = "删除证书", description = "删除证书,同时从1Panel删除") public R delete(@PathVariable Long id) { boolean success = certificateService.deleteCertificate(id); if (!success) { throw new BusinessException("删除失败"); } return R.ok(); } @PutMapping("/{id}/settings") @Operation(summary = "更新证书设置", description = "更新自动续签和备注") public R updateSettings( @PathVariable Long id, @RequestParam(required = false) Boolean autoRenew, @RequestParam(required = false) String description) { certificateService.updateCertificateSettings(id, autoRenew, description); return R.ok(); } // ==================== 证书申请 ==================== @PostMapping("/apply") @Operation(summary = "申请证书", description = "调用1Panel API申请SSL证书") public R apply(@Valid @RequestBody CertificateApplyRequest request) { CertificateApplyResult result = certificateService.applyCertificate(request); return R.ok(result); } // ==================== 证书同步 ==================== @PostMapping("/sync/{serverId}") @Operation(summary = "同步证书", description = "从1Panel同步证书列表到本地数据库") public R> sync(@PathVariable Long serverId) { int count = certificateService.syncCertificatesFromPanel(serverId); return R.ok(Map.of("syncCount", count, "message", "同步完成,共 " + count + " 个证书")); } // ==================== 1Panel 账户查询 ==================== @GetMapping("/acme-accounts/{serverId}") @Operation(summary = "获取Acme账户列表", description = "从1Panel获取Acme账户列表") public R>> getAcmeAccounts(@PathVariable Long serverId) { return R.ok(certificateService.getAcmeAccounts(serverId)); } @GetMapping("/dns-accounts/{serverId}") @Operation(summary = "获取DNS账户列表", description = "从1Panel获取DNS账户列表") public R>> getDnsAccounts(@PathVariable Long serverId) { return R.ok(certificateService.getDnsAccounts(serverId)); } @GetMapping("/websites/{serverId}") @Operation(summary = "获取网站列表", description = "从1Panel获取网站列表") public R>> getWebsites(@PathVariable Long serverId) { return R.ok(certificateService.getWebsites(serverId)); } // ==================== 调试接口 ==================== @GetMapping("/debug/server/{serverId}") @Operation(summary = "检查服务器1Panel配置", description = "用于调试:检查服务器是否正确配置了1Panel API") public R> debugServerConfig(@PathVariable Long serverId) { var server = serverService.getById(serverId); if (server == null) { return R.ok(Map.of("error", "服务器不存在", "serverId", serverId)); } return R.ok(Map.of( "serverId", serverId, "serverName", server.getName() != null ? server.getName() : "", "ip", server.getIp() != null ? server.getIp() : "", "panelUrl", server.getPanelUrl() != null ? server.getPanelUrl() : "(未配置)", "panelPort", server.getPanelPort() != null ? server.getPanelPort() : 42588, "panelApiKeyConfigured", server.getPanelApiKey() != null && !server.getPanelApiKey().isEmpty(), "panelApiKeyLength", server.getPanelApiKey() != null ? server.getPanelApiKey().length() : 0 )); } }