This commit is contained in:
Baobhan Sith
2025-05-12 00:35:04 +08:00
parent e0bc12dcc3
commit f217eecde4
4 changed files with 2 additions and 132 deletions
@@ -1,49 +0,0 @@
import { Request, Response } from 'express';
import { captchaService } from '../services/captcha.service';
interface VerifyCaptchaCredentialsBody {
provider: 'hcaptcha' | 'recaptcha';
siteKey?: string;
secretKey?: string;
}
export class CaptchaController {
async verifyCredentials(
request: Request<{}, {}, VerifyCaptchaCredentialsBody>, // Express Request type
reply: Response // Express Response type
): Promise<void> {
const { provider, siteKey, secretKey } = request.body;
if (!provider || (provider !== 'hcaptcha' && provider !== 'recaptcha')) {
reply.status(400).json({ message: '无效的 CAPTCHA 提供商。' }); // Use .json for Express
return;
}
if (!siteKey || !secretKey) {
let missingKeyMessage = `缺少 ${provider} 的 Site Key 或 Secret Key。`;
if (!siteKey && !secretKey) {
missingKeyMessage = `缺少 ${provider} 的 Site Key 和 Secret Key。`;
} else if (!siteKey) {
missingKeyMessage = `缺少 ${provider} 的 Site Key。`;
} else if (!secretKey) {
missingKeyMessage = `缺少 ${provider} 的 Secret Key。`;
}
reply.status(400).json({ message: missingKeyMessage }); // Use .json
return;
}
try {
const isValid = await captchaService.verifyCredentials(provider, siteKey, secretKey);
if (isValid) {
reply.status(200).json({ message: 'CAPTCHA 凭据验证成功。' }); // Use .json
} else {
reply.status(400).json({ message: 'CAPTCHA 凭据验证失败。请检查您的 Site Key 和 Secret Key 是否正确,并确保服务器可以访问 CAPTCHA 服务提供商。' }); // Use .json
}
} catch (error: any) {
console.error(`[CaptchaController] 凭据验证时发生意外错误: ${error.message}`);
reply.status(500).json({ message: error.message || 'CAPTCHA 凭据验证时发生服务器内部错误。' }); // Use .json
}
}
}
export const captchaController = new CaptchaController();
@@ -1,11 +0,0 @@
import express, { Router } from 'express';
import { captchaController } from './captcha.controller';
// import { requireAuth } from '../auth/auth.middleware'; // 假设的认证中间件
const router: Router = express.Router();
// POST /api/v1/settings/captcha/verify (路径将由 index.ts 中的 app.use 指定)
// 如果需要认证,可以在这里添加中间件: router.post('/verify', requireAuth, captchaController.verifyCredentials);
router.post('/verify', captchaController.verifyCredentials);
export default router;
-2
View File
@@ -44,7 +44,6 @@ import sftpRouter from './sftp/sftp.routes';
import proxyRoutes from './proxies/proxies.routes'; import proxyRoutes from './proxies/proxies.routes';
import tagsRouter from './tags/tags.routes'; import tagsRouter from './tags/tags.routes';
import settingsRoutes from './settings/settings.routes'; import settingsRoutes from './settings/settings.routes';
import captchaRoutes from './captcha/captcha.routes'; // +++ Import CAPTCHA routes +++
import notificationRoutes from './notifications/notification.routes'; import notificationRoutes from './notifications/notification.routes';
import auditRoutes from './audit/audit.routes'; import auditRoutes from './audit/audit.routes';
import commandHistoryRoutes from './command-history/command-history.routes'; import commandHistoryRoutes from './command-history/command-history.routes';
@@ -265,7 +264,6 @@ const startServer = () => {
app.use('/api/v1/proxies', proxyRoutes); app.use('/api/v1/proxies', proxyRoutes);
app.use('/api/v1/tags', tagsRouter); app.use('/api/v1/tags', tagsRouter);
app.use('/api/v1/settings', settingsRoutes); app.use('/api/v1/settings', settingsRoutes);
app.use('/api/v1/settings/captcha', captchaRoutes); // +++ Register CAPTCHA routes under settings +++
app.use('/api/v1/notifications', notificationRoutes); app.use('/api/v1/notifications', notificationRoutes);
app.use('/api/v1/audit-logs', auditRoutes); app.use('/api/v1/audit-logs', auditRoutes);
app.use('/api/v1/command-history', commandHistoryRoutes); app.use('/api/v1/command-history', commandHistoryRoutes);
@@ -59,77 +59,9 @@ export function useCaptchaSettings() {
captchaMessage.value = ''; captchaMessage.value = '';
captchaSuccess.value = false; captchaSuccess.value = false;
try { try {
let needsVerification = false; // Verification steps removed
let providerForVerification: CaptchaProvider | null = null;
let siteKeyForVerification: string | undefined = undefined;
let secretKeyForVerification: string | undefined = undefined;
// Step 1: Determine if verification is needed // Prepare DTO for saving
if (captchaForm.enabled && captchaForm.provider && captchaForm.provider !== 'none') {
const originalSettings = captchaSettings.value; // Persisted settings from store
if (captchaForm.provider === 'hcaptcha') {
const originalSiteKeyValue = originalSettings?.hcaptchaSiteKey || '';
const currentSiteKeyValue = captchaForm.hcaptchaSiteKey || '';
const currentSecretKeyValue = captchaForm.hcaptchaSecretKey || '';
if (currentSiteKeyValue !== originalSiteKeyValue) {
if (!currentSiteKeyValue || !currentSecretKeyValue) {
throw new Error(t('settings.captcha.error.hcaptchaKeysRequired'));
}
needsVerification = true;
providerForVerification = 'hcaptcha';
siteKeyForVerification = currentSiteKeyValue;
secretKeyForVerification = currentSecretKeyValue;
} else if (currentSecretKeyValue) {
if (!currentSiteKeyValue) {
throw new Error(t('settings.captcha.error.hcaptchaKeysRequired'));
}
needsVerification = true;
providerForVerification = 'hcaptcha';
siteKeyForVerification = currentSiteKeyValue;
secretKeyForVerification = currentSecretKeyValue;
}
} else if (captchaForm.provider === 'recaptcha') {
const originalSiteKeyValue = originalSettings?.recaptchaSiteKey || '';
const currentSiteKeyValue = captchaForm.recaptchaSiteKey || '';
const currentSecretKeyValue = captchaForm.recaptchaSecretKey || '';
if (currentSiteKeyValue !== originalSiteKeyValue) {
if (!currentSiteKeyValue || !currentSecretKeyValue) {
throw new Error(t('settings.captcha.error.recaptchaKeysRequired'));
}
needsVerification = true;
providerForVerification = 'recaptcha';
siteKeyForVerification = currentSiteKeyValue;
secretKeyForVerification = currentSecretKeyValue;
} else if (currentSecretKeyValue) {
if (!currentSiteKeyValue) {
throw new Error(t('settings.captcha.error.recaptchaKeysRequired'));
}
needsVerification = true;
providerForVerification = 'recaptcha';
siteKeyForVerification = currentSiteKeyValue;
secretKeyForVerification = currentSecretKeyValue;
}
}
}
// Step 2: Perform verification if needed
if (needsVerification && providerForVerification && siteKeyForVerification && secretKeyForVerification) {
try {
await apiClient.post('/settings/captcha/verify', {
provider: providerForVerification,
siteKey: siteKeyForVerification,
secretKey: secretKeyForVerification,
});
} catch (verifyError: any) {
console.error('CAPTCHA verification failed:', verifyError);
throw new Error(verifyError.response?.data?.message || verifyError.message || t('settings.captcha.error.verificationFailed'));
}
}
// Step 3: Prepare DTO for saving
const dtoToSave: UpdateCaptchaSettingsDto = { const dtoToSave: UpdateCaptchaSettingsDto = {
enabled: captchaForm.enabled, enabled: captchaForm.enabled,
provider: captchaForm.provider, provider: captchaForm.provider,