From 311ead0e8980bf2decad1d2be53b64d549a97400 Mon Sep 17 00:00:00 2001 From: mediabot-pt <295750538+mediabot-pt@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:56:00 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=BD=BB=E5=BA=95=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=20apiSecret=20=E8=AE=A4=E8=AF=81=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=EF=BC=8C=E4=BB=85=E4=BF=9D=E7=95=99=20Bearer=20+=20PSK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除: - HmacUtil: deriveApiKey/deriveApiSecret/verifyMediabotPsk - HmacAuthInterceptor: apiSecret 验签/自动创建账户/readBody - AccountService: generateApiCredentials/registerByInterceptor - AccountDTO: apiKey 字段 - AuthController: register 返回 apiSecret - AdminController: generateApiKey 端点 - Users.vue: API Key 列/生成密钥弹窗 - api/index.js: genApiKey 认证方式简化为两种: Bearer Token → Web 管理后台 PSK 签名 → 外部集成客户端 --- .../par/api/controller/AdminController.java | 23 ------ .../par/api/controller/AuthController.java | 28 ++----- .../java/com/par/common/util/HmacUtil.java | 21 ----- .../java/com/par/core/dto/AccountDTO.java | 5 +- .../core/interceptor/HmacAuthInterceptor.java | 78 ++++--------------- .../com/par/core/service/AccountService.java | 57 ++------------ .../java/com/par/core/service/PskService.java | 27 ++++--- .../core/service/impl/AccountServiceImpl.java | 75 ++---------------- web/src/api/index.js | 2 +- web/src/views/Users.vue | 55 +------------ 10 files changed, 56 insertions(+), 315 deletions(-) diff --git a/par-api/src/main/java/com/par/api/controller/AdminController.java b/par-api/src/main/java/com/par/api/controller/AdminController.java index 976dff3..4c00d1e 100644 --- a/par-api/src/main/java/com/par/api/controller/AdminController.java +++ b/par-api/src/main/java/com/par/api/controller/AdminController.java @@ -159,29 +159,6 @@ public class AdminController { return ApiResponse.success(); } - /** - * 生成/重置 API Key - */ - @PostMapping("/accounts/{accountId}/api-key") - public ApiResponse> generateApiKey( - @PathVariable Long accountId, - HttpServletRequest request) { - checkAdmin(request); - - var account = accountMapper.selectById(accountId); - if (account == null) { - return ApiResponse.error(404, "Account not found"); - } - - String[] keys = accountService.generateApiCredentials(accountId); - Map result = new java.util.LinkedHashMap<>(); - result.put("apiKey", keys[0]); - result.put("apiSecret", keys[1]); - // secret 只在生成时返回一次,前端需要立即保存 - log.info("API key generated for account: id={}", accountId); - return ApiResponse.success(result); - } - /** * 绑定额外邮箱 */ diff --git a/par-api/src/main/java/com/par/api/controller/AuthController.java b/par-api/src/main/java/com/par/api/controller/AuthController.java index 836bf48..fdf7a4a 100644 --- a/par-api/src/main/java/com/par/api/controller/AuthController.java +++ b/par-api/src/main/java/com/par/api/controller/AuthController.java @@ -36,8 +36,8 @@ public class AuthController { } /** - * 用户注册(自动生成 API Key) - * 携带 PSK 签名头 → 自动提权为 TRUSTED + * 用户注册(密码可选) + * 携带 PSK 头自动提权为 TRUSTED */ @PostMapping("/register") public ApiResponse> register( @@ -45,24 +45,18 @@ public class AuthController { HttpServletRequest httpRequest) { Account account = accountService.register(request); - // PSK 签名验证通过 → 自动提权 if (verifyMediabotPsk(httpRequest, request.getEmail())) { account.setTrustLevel(com.par.core.enums.TrustLevel.TRUSTED); accountService.updateAccount(account); - log.info("Account auto-trusted via PSK: email={}", account.getEmail()); } - AccountDTO dto = accountService.toDTO(account); Map result = new LinkedHashMap<>(); - result.put("account", dto); - result.put("apiKey", account.getApiKey()); - result.put("apiSecret", account.getApiSecret()); + result.put("account", accountService.toDTO(account)); return ApiResponse.success(result); } /** - * 账户恢复(DB 重置后无需管理员介入) - * PSK 签名验证通过 → 返回/重建凭据 + * PSK 签名恢复账户 */ @PostMapping("/recover") public ApiResponse> recover( @@ -79,44 +73,34 @@ public class AuthController { return ApiResponse.error(403, "Invalid PSK signature"); } - // 查找或创建账户 Account account = accountService.findByAnyEmail(email); if (account == null) { - // 自动创建 + 提权 RegisterRequest req = new RegisterRequest(); req.setEmail(email); account = accountService.register(req); } - // 确保是 TRUSTED if (account.getTrustLevel().ordinal() < com.par.core.enums.TrustLevel.TRUSTED.ordinal()) { account.setTrustLevel(com.par.core.enums.TrustLevel.TRUSTED); accountService.updateAccount(account); } - AccountDTO dto = accountService.toDTO(account); Map result = new LinkedHashMap<>(); - result.put("account", dto); - result.put("apiKey", account.getApiKey()); - result.put("apiSecret", account.getApiSecret()); + result.put("account", accountService.toDTO(account)); log.info("Account recovered via PSK: email={}", email); return ApiResponse.success(result); } /** - * 用户登录,返回 Bearer token + api_key + * 用户登录,返回 Bearer token */ @PostMapping("/login") public ApiResponse login(@Valid @RequestBody LoginRequest request) { Account account = accountService.login(request); AccountDTO dto = accountService.toDTO(account); dto.setToken(hmacAuthInterceptor.generateToken(account.getEmail())); - dto.setApiKey(account.getApiKey()); return ApiResponse.success(dto); } - /** - * 验证 X-Medibot-Timestamp + X-Medibot-Signature(通过 PskService) - */ private boolean verifyMediabotPsk(HttpServletRequest request, String email) { String ts = request.getHeader("X-Medibot-Timestamp"); String sig = request.getHeader("X-Medibot-Signature"); diff --git a/par-common/src/main/java/com/par/common/util/HmacUtil.java b/par-common/src/main/java/com/par/common/util/HmacUtil.java index 1c52682..fe64ff2 100644 --- a/par-common/src/main/java/com/par/common/util/HmacUtil.java +++ b/par-common/src/main/java/com/par/common/util/HmacUtil.java @@ -80,27 +80,6 @@ public class HmacUtil { return sign(hmacSecret, input); } - /** - * 验证 medibot PSK 签名(用于账户恢复 / 自动提权) - * signContent = email + ":" + timestamp - */ - public static boolean verifyMediabotPsk(String email, long timestamp, String signature, String psk) { - if (psk == null || psk.isBlank()) return false; - long now = System.currentTimeMillis() / 1000; - if (Math.abs(now - timestamp) > 300) return false; // 5 分钟窗口 - String payload = email.toLowerCase().trim() + ":" + timestamp; - return verify(psk, payload, signature); - } - - /** - * 从 email + 服务端密钥确定性推导 api_key - */ - public static String deriveApiKey(String email, String hmacSecret) { - String input = email.toLowerCase().trim() + ":par-api-key"; - String hash = sign(hmacSecret, input); - return "par_" + sha256(hash).substring(0, 16); - } - private static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { diff --git a/par-core/src/main/java/com/par/core/dto/AccountDTO.java b/par-core/src/main/java/com/par/core/dto/AccountDTO.java index 8c8d67e..829a806 100644 --- a/par-core/src/main/java/com/par/core/dto/AccountDTO.java +++ b/par-core/src/main/java/com/par/core/dto/AccountDTO.java @@ -7,7 +7,7 @@ import lombok.Data; import java.time.LocalDateTime; /** - * 账户信息 DTO(响应用,不包含敏感字段) + * 账户信息 DTO */ @Data @JsonInclude(JsonInclude.Include.NON_NULL) @@ -22,7 +22,4 @@ public class AccountDTO { /** 登录 token(仅登录接口返回) */ private String token; - - /** API Key(管理员可见,用于外部集成) */ - private String apiKey; } diff --git a/par-core/src/main/java/com/par/core/interceptor/HmacAuthInterceptor.java b/par-core/src/main/java/com/par/core/interceptor/HmacAuthInterceptor.java index 0f7dc2a..1e6e70f 100644 --- a/par-core/src/main/java/com/par/core/interceptor/HmacAuthInterceptor.java +++ b/par-core/src/main/java/com/par/core/interceptor/HmacAuthInterceptor.java @@ -6,7 +6,6 @@ import com.par.core.service.AccountService; import com.par.core.service.PskService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -18,14 +17,11 @@ import java.util.Base64; /** * API 鉴权拦截器 - *

- * 支持两种认证方式(按优先级): - * 1. Bearer Token — Web 管理后台使用,登录后由服务端签发 - * 2. HMAC 请求签名 — 外部 API 客户端使用,以 X-Signature/X-Timestamp/X-Email 头携带 + * 1. Bearer Token — Web 管理后台 + * 2. PSK 签名 — 外部集成客户端 */ @Slf4j @Component -@RequiredArgsConstructor public class HmacAuthInterceptor implements HandlerInterceptor { private final AccountService accountService; @@ -37,20 +33,20 @@ public class HmacAuthInterceptor implements HandlerInterceptor { private static final String HEADER_SIGNATURE = "X-Signature"; private static final String HEADER_TIMESTAMP = "X-Timestamp"; private static final String HEADER_EMAIL = "X-Email"; - private static final String HEADER_AUTHORIZATION = "Authorization"; - /** Token 有效期(小时) */ private static final long TOKEN_EXPIRY_HOURS = 24; - /** HMAC 时间窗口(秒) */ - private static final long HMAC_WINDOW_SECONDS = 60; + + public HmacAuthInterceptor(AccountService accountService, PskService pskService) { + this.accountService = accountService; + this.pskService = pskService; + } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - // ======== 方式 1:Bearer Token 认证(Web 管理后台) ======== - String authHeader = request.getHeader(HEADER_AUTHORIZATION); + // 方式 1:Bearer Token + String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { - String token = authHeader.substring(7); - String email = verifyBearerToken(token); + String email = verifyBearerToken(authHeader.substring(7)); if (email != null) { Account account = accountService.findByEmail(email); if (account != null && Boolean.TRUE.equals(account.getIsActive())) { @@ -63,18 +59,15 @@ public class HmacAuthInterceptor implements HandlerInterceptor { return false; } - // ======== 方式 2:PSK 签名认证(mediabot 等集成客户端) ======== - String pskSig = request.getHeader(HEADER_SIGNATURE); + // 方式 2:PSK 签名 + String sig = request.getHeader(HEADER_SIGNATURE); String ts = request.getHeader(HEADER_TIMESTAMP); String email = request.getHeader(HEADER_EMAIL); - if (pskSig != null && ts != null && email != null) { + if (sig != null && ts != null && email != null) { try { - long timestamp = Long.parseLong(ts); - String pskVersion = pskService.verify(email, timestamp, pskSig); - if (pskVersion != null) { + if (pskService.verify(email, Long.parseLong(ts), sig) != null) { request.setAttribute("accountId", 0L); request.setAttribute("trustLevel", com.par.core.enums.TrustLevel.TRUSTED); - request.setAttribute("pskVersion", pskVersion); return true; } } catch (NumberFormatException ignored) {} @@ -82,72 +75,33 @@ public class HmacAuthInterceptor implements HandlerInterceptor { return false; } - // ======== 方式 3:无有效认证头 → 拒绝 ======== writeError(response, 401, "Missing or invalid authentication"); return false; } - private String readBody(HttpServletRequest request) throws IOException { - if (request.getContentLength() <= 0) { - return ""; - } - try (var reader = request.getReader()) { - return reader.lines().collect(Collectors.joining("\n")); - } - } - private void writeError(HttpServletResponse response, int status, String message) throws IOException { response.setStatus(status); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(String.format("{\"code\":%d,\"message\":\"%s\",\"data\":null}", status, message)); } - /** - * 生成登录 token(供 AuthController 调用) - * 格式: Base64(email:expiryTimestamp:HmacSHA256(email:expiry, hmacSecret)) - */ public String generateToken(String email) { long expiry = System.currentTimeMillis() / 1000 + TOKEN_EXPIRY_HOURS * 3600; String payload = email + ":" + expiry; String sig = HmacUtil.sign(hmacSecret, payload); - String token = payload + ":" + sig; - return Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString((payload + ":" + sig).getBytes(StandardCharsets.UTF_8)); } - /** - * 自动创建账户(DB 重置后首次 HMAC 请求触发恢复) - */ - private Account autoCreateAccount(String email) { - var account = new Account(); - account.setEmail(email.toLowerCase().trim()); - account.setApiKey(HmacUtil.deriveApiKey(email, hmacSecret)); - account.setApiSecret(HmacUtil.deriveApiSecret(email, hmacSecret)); - account.setTrustLevel(com.par.core.enums.TrustLevel.MEMBER); - account.setIsActive(true); - accountService.registerByInterceptor(account); - log.info("Auto-created account via HMAC: email={}", email); - return account; - } - - /** - * 校验 Bearer token,返回 email(失败返回 null) - */ private String verifyBearerToken(String token) { try { String decoded = new String(Base64.getDecoder().decode(token), StandardCharsets.UTF_8); String[] parts = decoded.split(":", 3); if (parts.length != 3) return null; - String email = parts[0]; long expiry = Long.parseLong(parts[1]); - String sig = parts[2]; - if (System.currentTimeMillis() / 1000 > expiry) return null; - String payload = email + ":" + expiry; - if (HmacUtil.verify(hmacSecret, payload, sig)) { - return email; - } + if (HmacUtil.verify(hmacSecret, payload, parts[2])) return email; } catch (Exception e) { log.debug("Bearer token validation failed: {}", e.getMessage()); } diff --git a/par-core/src/main/java/com/par/core/service/AccountService.java b/par-core/src/main/java/com/par/core/service/AccountService.java index fc66cb3..d241c3f 100644 --- a/par-core/src/main/java/com/par/core/service/AccountService.java +++ b/par-core/src/main/java/com/par/core/service/AccountService.java @@ -3,79 +3,32 @@ package com.par.core.service; import com.par.core.dto.AccountDTO; import com.par.core.dto.LoginRequest; import com.par.core.dto.RegisterRequest; -import java.util.List; - import com.par.core.entity.Account; +import java.util.List; + /** * 账户服务接口 */ public interface AccountService { - /** - * 用户注册 - * - * @param request 注册请求 - * @return 注册成功的账户 - */ Account register(RegisterRequest request); - /** - * 用户登录(验证密码) - * - * @param request 登录请求 - * @return 登录成功的账户 - */ Account login(LoginRequest request); - /** - * 根据邮箱查找账户 - */ Account findByEmail(String email); - /** - * 根据ID查找账户 - */ Account findById(Long id); - /** - * 拦截器直接创建账户(HMAC 自动恢复场景) - */ - void registerByInterceptor(Account account); - - /** - * 更新账户 - */ - void updateAccount(Account account); - - /** - * 转换为 DTO(脱敏) - */ - AccountDTO toDTO(Account account); - - /** - * 根据任意绑定邮箱查找账户 - */ Account findByAnyEmail(String email); - /** - * 生成/重置 API Key 密钥对 - * @return [apiKey, apiSecret] - */ - String[] generateApiCredentials(Long accountId); + void updateAccount(Account account); + + AccountDTO toDTO(Account account); - /** - * 绑定额外邮箱 - */ void bindEmail(Long accountId, String email); - /** - * 解绑邮箱 - */ void unbindEmail(Long emailId); - /** - * 获取账户的所有绑定邮箱 - */ List listEmails(Long accountId); } diff --git a/par-core/src/main/java/com/par/core/service/PskService.java b/par-core/src/main/java/com/par/core/service/PskService.java index c86e158..2614669 100644 --- a/par-core/src/main/java/com/par/core/service/PskService.java +++ b/par-core/src/main/java/com/par/core/service/PskService.java @@ -84,20 +84,29 @@ public class PskService { /** * 使用所有活跃 PSK 逐一验证签名 + * signContent = email + ":" + timestamp * @return 匹配的 PSK 版本号,null 表示验证失败 */ public String verify(String email, long timestamp, String signature) { - for (Psk psk : pskMapper.selectActive()) { - if (HmacUtil.verifyMediabotPsk(email, timestamp, signature, psk.getSecret())) { - return psk.getVersion(); - } - } - // fallback: 也试 env PSK(DB 丢失时仍可用) - if (envPsk != null && !envPsk.isBlank()) { - if (HmacUtil.verifyMediabotPsk(email, timestamp, signature, envPsk)) { - return "env"; + long now = System.currentTimeMillis() / 1000; + if (Math.abs(now - timestamp) > 300) return null; // 5 分钟窗口 + String payload = email.toLowerCase().trim() + ":" + timestamp; + + String[] secrets = getActiveSecrets(); + for (String secret : secrets) { + if (HmacUtil.verify(secret, payload, signature)) { + return "ok"; } } return null; } + + private String[] getActiveSecrets() { + List secrets = pskMapper.selectActive().stream() + .map(Psk::getSecret).collect(java.util.stream.Collectors.toList()); + if (envPsk != null && !envPsk.isBlank()) { + secrets.add(envPsk); + } + return secrets.toArray(new String[0]); + } } diff --git a/par-core/src/main/java/com/par/core/service/impl/AccountServiceImpl.java b/par-core/src/main/java/com/par/core/service/impl/AccountServiceImpl.java index 95576ea..d3e87ae 100644 --- a/par-core/src/main/java/com/par/core/service/impl/AccountServiceImpl.java +++ b/par-core/src/main/java/com/par/core/service/impl/AccountServiceImpl.java @@ -15,7 +15,6 @@ import com.par.core.mapper.AnonymousStatMapper; import com.par.core.service.AccountService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -37,15 +36,11 @@ public class AccountServiceImpl implements AccountService { private final AnonymousStatMapper anonymousStatMapper; private final AccountEmailMapper accountEmailMapper; - @Value("${hmac.secret}") - private String hmacSecret; - private static final SecureRandom SECURE_RANDOM = new SecureRandom(); @Override @Transactional public Account register(RegisterRequest request) { - // 检查邮箱是否已注册 Account existing = accountMapper.selectByEmail(request.getEmail()); if (existing != null) { throw new IllegalArgumentException("该邮箱已被注册"); @@ -54,7 +49,6 @@ public class AccountServiceImpl implements AccountService { Account account = new Account(); account.setEmail(request.getEmail().toLowerCase().trim()); - // 密码为空则自动生成(机器注册场景) String password = request.getPassword(); if (password == null || password.isBlank()) { byte[] pwdBytes = new byte[16]; @@ -66,13 +60,8 @@ public class AccountServiceImpl implements AccountService { account.setTrustLevel(TrustLevel.MEMBER); account.setIsActive(true); - // 确定性推导 API Key(同 email + 同 HMAC_SECRET → 永远相同) - account.setApiKey(HmacUtil.deriveApiKey(account.getEmail(), hmacSecret)); - account.setApiSecret(HmacUtil.deriveApiSecret(account.getEmail(), hmacSecret)); - accountMapper.insert(account); - // 关联匿名统计记录 if (request.getAnonymousId() != null && !request.getAnonymousId().isBlank()) { associateAnonymousStats(request.getAnonymousId(), account.getId(), request.getEmail()); } @@ -107,14 +96,13 @@ public class AccountServiceImpl implements AccountService { } @Override - @Transactional - public void registerByInterceptor(Account account) { - // 自动生成随机密码 - byte[] pwdBytes = new byte[16]; - SECURE_RANDOM.nextBytes(pwdBytes); - account.setPasswordHash(PasswordUtil.encode( - Base64.getUrlEncoder().withoutPadding().encodeToString(pwdBytes))); - accountMapper.insert(account); + public Account findByAnyEmail(String email) { + email = email.toLowerCase().trim(); + Account account = accountMapper.selectByEmail(email); + if (account != null) return account; + AccountEmail ae = accountEmailMapper.selectByEmail(email); + if (ae != null) return accountMapper.selectById(ae.getAccountId()); + return null; } @Override @@ -132,43 +120,9 @@ public class AccountServiceImpl implements AccountService { dto.setTrustLevel(account.getTrustLevel()); dto.setIsActive(account.getIsActive()); dto.setCreatedAt(account.getCreatedAt()); - dto.setApiKey(account.getApiKey()); return dto; } - @Override - public Account findByAnyEmail(String email) { - email = email.toLowerCase().trim(); - // 先查主邮箱 - Account account = accountMapper.selectByEmail(email); - if (account != null) return account; - // 再查关联邮箱 - AccountEmail ae = accountEmailMapper.selectByEmail(email); - if (ae != null) return accountMapper.selectById(ae.getAccountId()); - return null; - } - - @Override - @Transactional - public String[] generateApiCredentials(Long accountId) { - Account account = accountMapper.selectById(accountId); - if (account == null) throw new IllegalArgumentException("Account not found"); - - byte[] keyBytes = new byte[12]; - SECURE_RANDOM.nextBytes(keyBytes); - String apiKey = "par_" + bytesToHex(keyBytes); - - byte[] secretBytes = new byte[32]; - SECURE_RANDOM.nextBytes(secretBytes); - String apiSecret = Base64.getUrlEncoder().withoutPadding().encodeToString(secretBytes); - - account.setApiKey(apiKey); - account.setApiSecret(apiSecret); - accountMapper.updateById(account); - - return new String[]{apiKey, apiSecret}; - } - @Override @Transactional public void bindEmail(Long accountId, String email) { @@ -189,8 +143,6 @@ public class AccountServiceImpl implements AccountService { public void unbindEmail(Long emailId) { AccountEmail ae = accountEmailMapper.selectById(emailId); if (ae == null) throw new IllegalArgumentException("Email binding not found"); - - // 检查是否是唯一邮箱:主邮箱 + 至少保留一个关联邮箱 Account account = accountMapper.selectById(ae.getAccountId()); long emailCount = accountEmailMapper.selectByAccountId(ae.getAccountId()).size(); if (account.getEmail().equals(ae.getEmail()) && emailCount <= 1) { @@ -205,24 +157,13 @@ public class AccountServiceImpl implements AccountService { if (account == null) return Collections.emptyList(); List emails = accountEmailMapper.selectByAccountId(accountId) .stream().map(AccountEmail::getEmail).collect(Collectors.toList()); - // 确保主邮箱在列表首位 if (!emails.contains(account.getEmail())) { emails.add(0, account.getEmail()); } return emails; } - private static String bytesToHex(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) sb.append(String.format("%02x", b)); - return sb.toString(); - } - - /** - * 注册时关联匿名统计记录 - */ private void associateAnonymousStats(String anonymousId, Long accountId, String email) { - // 先按 anonymous_id 查找 AnonymousStat stat = anonymousStatMapper.selectByAnonymousId(anonymousId); if (stat != null && stat.getAssociatedAccountId() == null) { stat.setAssociatedAccountId(accountId); @@ -230,8 +171,6 @@ public class AccountServiceImpl implements AccountService { log.info("Associated anonymous stat {} with account {}", anonymousId, accountId); return; } - - // 再按邮箱哈希查找(可能匿名ID不匹配但邮箱相同) String emailHash = HmacUtil.sha256(email.toLowerCase().trim()); AnonymousStat byHash = anonymousStatMapper.selectByRawEmailHash(emailHash); if (byHash != null && byHash.getAssociatedAccountId() == null) { diff --git a/web/src/api/index.js b/web/src/api/index.js index a7b03ac..eaa884c 100644 --- a/web/src/api/index.js +++ b/web/src/api/index.js @@ -45,7 +45,7 @@ export default { users: { list: () => api.get('/admin/accounts'), setTrustLevel: (id, level) => api.post(`/admin/accounts/${id}/trust-level`, null, { params: { level } }), - genApiKey: (id) => api.post(`/admin/accounts/${id}/api-key`) + }, health: () => api.get('/health', { baseURL: '' }) } diff --git a/web/src/views/Users.vue b/web/src/views/Users.vue index 55e17a3..1fd6216 100644 --- a/web/src/views/Users.vue +++ b/web/src/views/Users.vue @@ -6,12 +6,6 @@ - - - - + - - - - Secret 仅在生成时显示一次,请立即复制保存! - - - - - - - - - - - - - - - - @@ -95,9 +63,6 @@ const loading = ref(false) const dialogVisible = ref(false) const saving = ref(false) const levelForm = reactive({ id: null, email: '', level: '' }) -const keyDialogVisible = ref(false) -const keyResult = reactive({ apiKey: '', apiSecret: '' }) - const trustLevelType = (level) => { const map = { MEMBER: '', TRUSTED: 'warning', ADMIN: 'danger' } return map[level] || '' @@ -120,22 +85,6 @@ const fetchUsers = async () => { } } -const handleGenKey = async (row) => { - try { - const res = await api.users.genApiKey(row.id) - keyResult.apiKey = res.data.apiKey - keyResult.apiSecret = res.data.apiSecret - keyDialogVisible.value = true - fetchUsers() - } catch (e) { - ElMessage.error(e.response?.data?.message || '生成失败') - } -} - -const copyText = (text) => { - navigator.clipboard.writeText(text).then(() => ElMessage.success('已复制')) -} - const handleSetLevel = (row) => { levelForm.id = row.id levelForm.email = row.email