feat: 分组密钥检查增加状态选项 (#86)
This commit is contained in:
@@ -62,6 +62,12 @@ type GroupIDRequest struct {
|
|||||||
GroupID uint `json:"group_id" binding:"required"`
|
GroupID uint `json:"group_id" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateGroupKeysRequest defines the payload for validating keys in a group.
|
||||||
|
type ValidateGroupKeysRequest struct {
|
||||||
|
GroupID uint `json:"group_id" binding:"required"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// AddMultipleKeys handles creating new keys from a text block within a specific group.
|
// AddMultipleKeys handles creating new keys from a text block within a specific group.
|
||||||
func (s *Server) AddMultipleKeys(c *gin.Context) {
|
func (s *Server) AddMultipleKeys(c *gin.Context) {
|
||||||
var req KeyTextRequest
|
var req KeyTextRequest
|
||||||
@@ -258,12 +264,18 @@ func (s *Server) TestMultipleKeys(c *gin.Context) {
|
|||||||
|
|
||||||
// ValidateGroupKeys initiates a manual validation task for all keys in a group.
|
// ValidateGroupKeys initiates a manual validation task for all keys in a group.
|
||||||
func (s *Server) ValidateGroupKeys(c *gin.Context) {
|
func (s *Server) ValidateGroupKeys(c *gin.Context) {
|
||||||
var req GroupIDRequest
|
var req ValidateGroupKeysRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.Error(c, app_errors.NewAPIError(app_errors.ErrInvalidJSON, err.Error()))
|
response.Error(c, app_errors.NewAPIError(app_errors.ErrInvalidJSON, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate status if provided
|
||||||
|
if req.Status != "" && req.Status != models.KeyStatusActive && req.Status != models.KeyStatusInvalid {
|
||||||
|
response.Error(c, app_errors.NewAPIError(app_errors.ErrValidation, "Invalid status value"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
groupDB, ok := s.findGroupByID(c, req.GroupID)
|
groupDB, ok := s.findGroupByID(c, req.GroupID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
@@ -275,7 +287,7 @@ func (s *Server) ValidateGroupKeys(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
taskStatus, err := s.KeyManualValidationService.StartValidationTask(group)
|
taskStatus, err := s.KeyManualValidationService.StartValidationTask(group, req.Status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, app_errors.NewAPIError(app_errors.ErrTaskInProgress, err.Error()))
|
response.Error(c, app_errors.NewAPIError(app_errors.ErrTaskInProgress, err.Error()))
|
||||||
return
|
return
|
||||||
|
@@ -41,10 +41,14 @@ func NewKeyManualValidationService(db *gorm.DB, validator *keypool.KeyValidator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StartValidationTask starts a new manual validation task for a given group.
|
// StartValidationTask starts a new manual validation task for a given group.
|
||||||
func (s *KeyManualValidationService) StartValidationTask(group *models.Group) (*TaskStatus, error) {
|
func (s *KeyManualValidationService) StartValidationTask(group *models.Group, status string) (*TaskStatus, error) {
|
||||||
var keys []models.APIKey
|
var keys []models.APIKey
|
||||||
if err := s.DB.Where("group_id = ?", group.ID).Find(&keys).Error; err != nil {
|
query := s.DB.Where("group_id = ?", group.ID)
|
||||||
return nil, fmt.Errorf("failed to get keys for group %s: %w", group.Name, err)
|
if status != "" {
|
||||||
|
query = query.Where("status = ?", status)
|
||||||
|
}
|
||||||
|
if err := query.Find(&keys).Error; err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get keys for group %s with status '%s': %w", group.Name, status, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
@@ -59,13 +63,20 @@ func (s *KeyManualValidationService) StartValidationTask(group *models.Group) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run the validation in a separate goroutine
|
// Run the validation in a separate goroutine
|
||||||
go s.runValidation(group, keys)
|
go s.runValidation(group, keys, status)
|
||||||
|
|
||||||
return taskStatus, nil
|
return taskStatus, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *KeyManualValidationService) runValidation(group *models.Group, keys []models.APIKey) {
|
func (s *KeyManualValidationService) runValidation(group *models.Group, keys []models.APIKey, status string) {
|
||||||
logrus.Infof("Starting manual validation for group %s", group.Name)
|
logFields := logrus.Fields{
|
||||||
|
"group": group.Name,
|
||||||
|
"status": status,
|
||||||
|
}
|
||||||
|
if status == "" {
|
||||||
|
logFields["status"] = "all"
|
||||||
|
}
|
||||||
|
logrus.WithFields(logFields).Info("Starting manual validation")
|
||||||
|
|
||||||
jobs := make(chan models.APIKey, len(keys))
|
jobs := make(chan models.APIKey, len(keys))
|
||||||
results := make(chan bool, len(keys))
|
results := make(chan bool, len(keys))
|
||||||
|
@@ -175,14 +175,21 @@ export const keysApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 验证分组密钥
|
// 验证分组密钥
|
||||||
async validateGroupKeys(groupId: number): Promise<{
|
async validateGroupKeys(
|
||||||
|
groupId: number,
|
||||||
|
status?: "active" | "invalid"
|
||||||
|
): Promise<{
|
||||||
is_running: boolean;
|
is_running: boolean;
|
||||||
group_name: string;
|
group_name: string;
|
||||||
processed: number;
|
processed: number;
|
||||||
total: number;
|
total: number;
|
||||||
started_at: string;
|
started_at: string;
|
||||||
}> {
|
}> {
|
||||||
const res = await http.post("/keys/validate-group", { group_id: groupId });
|
const payload: { group_id: number; status?: string } = { group_id: groupId };
|
||||||
|
if (status) {
|
||||||
|
payload.status = status;
|
||||||
|
}
|
||||||
|
const res = await http.post("/keys/validate-group", payload);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ async function pollOnce() {
|
|||||||
let msg = "任务已完成。";
|
let msg = "任务已完成。";
|
||||||
if (task.task_type === "KEY_VALIDATION") {
|
if (task.task_type === "KEY_VALIDATION") {
|
||||||
const result = task.result as import("@/types/models").KeyValidationResult;
|
const result = task.result as import("@/types/models").KeyValidationResult;
|
||||||
msg = `密钥验证完成,处理了 ${result.total_keys} 个密钥,其中 ${result.valid_keys} 个有效,${result.invalid_keys} 个无效。`;
|
msg = `密钥验证完成,处理了 ${result.total_keys} 个密钥,其中 ${result.valid_keys} 个成功,${result.invalid_keys} 个失败。请注意:验证失败并不一定拉黑该密钥,需要失败次数达到阈值才会拉黑。`;
|
||||||
} else if (task.task_type === "KEY_IMPORT") {
|
} else if (task.task_type === "KEY_IMPORT") {
|
||||||
const result = task.result as import("@/types/models").KeyImportResult;
|
const result = task.result as import("@/types/models").KeyImportResult;
|
||||||
msg = `密钥导入完成,成功添加 ${result.added_count} 个密钥,忽略了 ${result.ignored_count} 个。`;
|
msg = `密钥导入完成,成功添加 ${result.added_count} 个密钥,忽略了 ${result.ignored_count} 个。`;
|
||||||
|
@@ -67,6 +67,8 @@ const moreOptions = [
|
|||||||
{ label: "清空所有无效密钥", key: "clearInvalid", props: { style: { color: "#d03050" } } },
|
{ label: "清空所有无效密钥", key: "clearInvalid", props: { style: { color: "#d03050" } } },
|
||||||
{ type: "divider" },
|
{ type: "divider" },
|
||||||
{ label: "验证所有密钥", key: "validateAll" },
|
{ label: "验证所有密钥", key: "validateAll" },
|
||||||
|
{ label: "验证有效密钥", key: "validateActive" },
|
||||||
|
{ label: "验证无效密钥", key: "validateInvalid" },
|
||||||
];
|
];
|
||||||
|
|
||||||
let testingMsg: MessageReactive | null = null;
|
let testingMsg: MessageReactive | null = null;
|
||||||
@@ -150,7 +152,13 @@ function handleMoreAction(key: string) {
|
|||||||
restoreAllInvalid();
|
restoreAllInvalid();
|
||||||
break;
|
break;
|
||||||
case "validateAll":
|
case "validateAll":
|
||||||
validateAllKeys();
|
validateKeys("all");
|
||||||
|
break;
|
||||||
|
case "validateActive":
|
||||||
|
validateKeys("active");
|
||||||
|
break;
|
||||||
|
case "validateInvalid":
|
||||||
|
validateKeys("invalid");
|
||||||
break;
|
break;
|
||||||
case "clearInvalid":
|
case "clearInvalid":
|
||||||
clearAllInvalid();
|
clearAllInvalid();
|
||||||
@@ -395,17 +403,24 @@ async function restoreAllInvalid() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateAllKeys() {
|
async function validateKeys(status: "all" | "active" | "invalid") {
|
||||||
if (!props.selectedGroup?.id || testingMsg) {
|
if (!props.selectedGroup?.id || testingMsg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
testingMsg = window.$message.info("正在验证密钥...", {
|
let statusText = "所有";
|
||||||
|
if (status === "active") {
|
||||||
|
statusText = "有效";
|
||||||
|
} else if (status === "invalid") {
|
||||||
|
statusText = "无效";
|
||||||
|
}
|
||||||
|
|
||||||
|
testingMsg = window.$message.info(`正在验证${statusText}密钥...`, {
|
||||||
duration: 0,
|
duration: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await keysApi.validateGroupKeys(props.selectedGroup.id);
|
await keysApi.validateGroupKeys(props.selectedGroup.id, status === "all" ? undefined : status);
|
||||||
localStorage.removeItem("last_closed_task");
|
localStorage.removeItem("last_closed_task");
|
||||||
appState.taskPollingTrigger++;
|
appState.taskPollingTrigger++;
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
|
Reference in New Issue
Block a user