本地 RAG 知识库
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

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();
}
}