You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
9.2 KiB
256 lines
9.2 KiB
package com.wok.supportbot.controller;
|
|
|
|
import com.wok.supportbot.entity.ApiKey;
|
|
import com.wok.supportbot.entity.SysUser;
|
|
import com.wok.supportbot.service.ApiKeyService;
|
|
import com.wok.supportbot.service.SysUserService;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* API Key 管理接口
|
|
* 提供 API Key 的创建、吊销、启用、删除、分页查询、角色绑定等操作。
|
|
*/
|
|
@Slf4j
|
|
@RestController
|
|
@RequestMapping("/api-key")
|
|
public class ApiKeyController {
|
|
|
|
@Autowired
|
|
private ApiKeyService apiKeyService;
|
|
|
|
@Autowired
|
|
private SysUserService sysUserService;
|
|
|
|
/**
|
|
* 分页查询 API Key 列表
|
|
*/
|
|
@GetMapping("/list")
|
|
@PreAuthorize("hasRole('admin')")
|
|
public ResponseEntity<Map<String, Object>> list(
|
|
@RequestParam(defaultValue = "1") int page,
|
|
@RequestParam(defaultValue = "20") int size) {
|
|
try {
|
|
Map<String, Object> result = apiKeyService.listKeys(page, size);
|
|
|
|
Map<String, Object> data = new java.util.HashMap<>();
|
|
data.put("success", true);
|
|
data.put("data", result.get("records"));
|
|
data.put("total", result.get("total"));
|
|
data.put("page", result.get("page"));
|
|
data.put("size", result.get("size"));
|
|
data.put("pages", result.get("pages"));
|
|
return ResponseEntity.ok(data);
|
|
} catch (Exception e) {
|
|
log.error("查询 API Key 列表失败", e);
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "查询失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建 API Key
|
|
*
|
|
* @param body 请求体,包含 name, description, rateLimit, maxCalls, expireTime, roleIds(可选)
|
|
*/
|
|
@PostMapping
|
|
@PreAuthorize("hasRole('admin')")
|
|
public ResponseEntity<Map<String, Object>> create(@RequestBody Map<String, Object> body) {
|
|
try {
|
|
String name = (String) body.get("name");
|
|
if (name == null || name.isBlank()) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", "名称不能为空"
|
|
));
|
|
}
|
|
|
|
String description = (String) body.getOrDefault("description", "");
|
|
Integer rateLimit = body.containsKey("rateLimit") && body.get("rateLimit") != null
|
|
? ((Number) body.get("rateLimit")).intValue() : null;
|
|
Long maxCalls = body.containsKey("maxCalls") && body.get("maxCalls") != null
|
|
? ((Number) body.get("maxCalls")).longValue() : null;
|
|
|
|
Date expireTime = null;
|
|
if (body.get("expireTime") != null) {
|
|
if (body.get("expireTime") instanceof Number num) {
|
|
expireTime = new Date(num.longValue());
|
|
} else if (body.get("expireTime") instanceof String str && !str.isBlank()) {
|
|
expireTime = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm").parse(str);
|
|
}
|
|
}
|
|
|
|
// 从 SecurityContext 获取当前登录用户 ID
|
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
if (auth == null || !auth.isAuthenticated() || "anonymousUser".equals(auth.getPrincipal())) {
|
|
return ResponseEntity.status(401).body(Map.of(
|
|
"success", false,
|
|
"message", "未登录,无法创建 API Key"
|
|
));
|
|
}
|
|
SysUser currentUser = sysUserService.getUserByUsername(auth.getName());
|
|
Long userId = (currentUser != null) ? currentUser.getId() : null;
|
|
|
|
ApiKey apiKey = apiKeyService.generateKey(userId, name, description, rateLimit, maxCalls, expireTime);
|
|
|
|
// 绑定角色(可选)
|
|
if (body.containsKey("roleIds")) {
|
|
List<Long> roleIds = parseRoleIds(body.get("roleIds"));
|
|
apiKeyService.updateKeyRoles(apiKey.getId(), roleIds);
|
|
}
|
|
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "创建成功",
|
|
"data", apiKey
|
|
));
|
|
} catch (IllegalArgumentException e) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", e.getMessage()
|
|
));
|
|
} catch (Exception e) {
|
|
log.error("创建 API Key 失败", e);
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "创建失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 吊销 API Key
|
|
*/
|
|
@PutMapping("/{id}/revoke")
|
|
@PreAuthorize("hasRole('admin')")
|
|
public ResponseEntity<Map<String, Object>> revoke(@PathVariable Long id) {
|
|
try {
|
|
apiKeyService.revokeKey(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "已吊销"
|
|
));
|
|
} catch (IllegalArgumentException e) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", e.getMessage()
|
|
));
|
|
} catch (Exception e) {
|
|
log.error("吊销 API Key 失败", e);
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "吊销失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 启用 API Key
|
|
*/
|
|
@PutMapping("/{id}/enable")
|
|
@PreAuthorize("hasRole('admin')")
|
|
public ResponseEntity<Map<String, Object>> enable(@PathVariable Long id) {
|
|
try {
|
|
apiKeyService.enableKey(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "已启用"
|
|
));
|
|
} catch (IllegalArgumentException e) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", e.getMessage()
|
|
));
|
|
} catch (Exception e) {
|
|
log.error("启用 API Key 失败", e);
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "启用失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 删除 API Key
|
|
*/
|
|
@DeleteMapping("/{id}")
|
|
@PreAuthorize("hasRole('admin')")
|
|
public ResponseEntity<Map<String, Object>> delete(@PathVariable Long id) {
|
|
try {
|
|
apiKeyService.deleteKey(id);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "删除成功"
|
|
));
|
|
} catch (IllegalArgumentException e) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", e.getMessage()
|
|
));
|
|
} catch (Exception e) {
|
|
log.error("删除 API Key 失败", e);
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "删除失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新 API Key 绑定的客服角色
|
|
* 空数组表示不限制(返回所有启用角色)
|
|
*/
|
|
@PutMapping("/{id}/roles")
|
|
@PreAuthorize("hasRole('admin')")
|
|
public ResponseEntity<Map<String, Object>> updateRoles(
|
|
@PathVariable Long id,
|
|
@RequestBody Map<String, Object> body) {
|
|
try {
|
|
List<Long> roleIds = parseRoleIds(body.get("roleIds"));
|
|
apiKeyService.updateKeyRoles(id, roleIds);
|
|
return ResponseEntity.ok(Map.of(
|
|
"success", true,
|
|
"message", "角色绑定更新成功"
|
|
));
|
|
} catch (IllegalArgumentException e) {
|
|
return ResponseEntity.badRequest().body(Map.of(
|
|
"success", false,
|
|
"message", e.getMessage()
|
|
));
|
|
} catch (Exception e) {
|
|
log.error("更新 API Key 角色绑定失败", e);
|
|
return ResponseEntity.status(500).body(Map.of(
|
|
"success", false,
|
|
"message", "更新失败:" + e.getMessage()
|
|
));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 解析请求体中的 roleIds 列表
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
private List<Long> parseRoleIds(Object raw) {
|
|
if (!(raw instanceof List<?> list)) {
|
|
return List.of();
|
|
}
|
|
return list.stream()
|
|
.filter(Objects::nonNull)
|
|
.map(item -> item instanceof Number n ? n.longValue() : Long.parseLong(item.toString()))
|
|
.filter(id -> id > 0)
|
|
.distinct()
|
|
.toList();
|
|
}
|
|
}
|