mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(tool-guard): friendly duplicate rule-id rejection and client-side name/pattern validation (#88)
This commit is contained in:
parent
aed559d1cf
commit
2bca55f5b4
@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import vip.mate.approval.ApprovalWorkflowService;
|
||||
import vip.mate.common.result.R;
|
||||
@ -97,8 +98,12 @@ public class SecurityController {
|
||||
public R<ToolGuardRuleEntity> createRule(@RequestBody ToolGuardRuleEntity rule) {
|
||||
try {
|
||||
return R.ok(ruleService.createRule(rule));
|
||||
} catch (Exception e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
return R.fail(e.getMessage());
|
||||
} catch (DuplicateKeyException e) {
|
||||
// Race fallback: pre-check passed but a concurrent insert took the slot.
|
||||
String ruleId = rule != null && rule.getRuleId() != null ? rule.getRuleId().trim() : "";
|
||||
return R.fail("Rule ID already exists: " + ruleId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -74,6 +74,12 @@ public class ToolGuardRuleService {
|
||||
rule.setName(rule.getName().trim());
|
||||
rule.setPattern(rule.getPattern().trim());
|
||||
rule.setBuiltin(false);
|
||||
// Pre-check uniqueness so the API returns a friendly message instead of
|
||||
// surfacing the raw JDBC UNIQUE-constraint violation through the global
|
||||
// exception handler. The DB constraint still guards against races.
|
||||
if (getByRuleId(rule.getRuleId()) != null) {
|
||||
throw new IllegalArgumentException("Rule ID already exists: " + rule.getRuleId());
|
||||
}
|
||||
ruleMapper.insert(rule);
|
||||
ruleRegistry.reload();
|
||||
return rule;
|
||||
|
||||
@ -1368,6 +1368,9 @@ export default {
|
||||
},
|
||||
messages: {
|
||||
ruleIdRequired: 'Rule ID is required',
|
||||
nameRequired: 'Name is required',
|
||||
patternRequired: 'Regex pattern is required',
|
||||
ruleIdDuplicate: 'Rule ID already exists',
|
||||
saveFailed: 'Failed to save rule',
|
||||
},
|
||||
},
|
||||
|
||||
@ -1266,6 +1266,9 @@ export default {
|
||||
},
|
||||
messages: {
|
||||
ruleIdRequired: '规则 ID 不能为空',
|
||||
nameRequired: '名称不能为空',
|
||||
patternRequired: '正则模式不能为空',
|
||||
ruleIdDuplicate: '规则 ID 已存在',
|
||||
saveFailed: '保存规则失败',
|
||||
},
|
||||
},
|
||||
|
||||
@ -155,12 +155,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ t('security.toolGuard.fields.name') }}</label>
|
||||
<input v-model="ruleForm.name" class="form-input" />
|
||||
<label>{{ t('security.toolGuard.fields.name') }} <span class="required">*</span></label>
|
||||
<input v-model="ruleForm.name" class="form-input" required />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ t('security.toolGuard.fields.pattern') }}</label>
|
||||
<input v-model="ruleForm.pattern" class="form-input mono" placeholder="regex pattern" />
|
||||
<label>{{ t('security.toolGuard.fields.pattern') }} <span class="required">*</span></label>
|
||||
<input v-model="ruleForm.pattern" class="form-input mono" placeholder="regex pattern" required />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ t('security.toolGuard.fields.severity') }}</label>
|
||||
@ -360,6 +360,14 @@ async function saveRule() {
|
||||
ElMessage.error(t('security.toolGuard.messages.ruleIdRequired'))
|
||||
return
|
||||
}
|
||||
if (!ruleForm.name.trim()) {
|
||||
ElMessage.error(t('security.toolGuard.messages.nameRequired'))
|
||||
return
|
||||
}
|
||||
if (!ruleForm.pattern.trim()) {
|
||||
ElMessage.error(t('security.toolGuard.messages.patternRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (editingRule.value) {
|
||||
@ -370,7 +378,12 @@ async function saveRule() {
|
||||
showRuleModal.value = false
|
||||
loadRules()
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.msg || e?.message || t('security.toolGuard.messages.saveFailed'))
|
||||
const raw = e?.msg || e?.message || ''
|
||||
if (typeof raw === 'string' && raw.toLowerCase().includes('already exists')) {
|
||||
ElMessage.error(t('security.toolGuard.messages.ruleIdDuplicate'))
|
||||
} else {
|
||||
ElMessage.error(raw || t('security.toolGuard.messages.saveFailed'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user