diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 8168602f..b6b48cb0 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -22,6 +22,8 @@ sidebar: false ### 修复 +- 修复代理路由详情认证配置 Tab:移除 PoW 配置(PoW 仅在 WAF 规则组中设置);保留 Basic Auth 保存能力;移除页头重复的「保存当前分区」按钮。 + - 修复 Pages 路由发布失败并报 `pages module is not available`:配置快照发布流程补齐 Pages 项目激活部署解析与 `pages_deployment` 写入。 - 修复仪表盘与节点详情「24 小时网络趋势」误按速率展示:改为 OpenResty 入/出站小时流量与近 24 小时总量摘要,Y 轴与 tooltip 自动换算 B/KB/MB/GB。 diff --git a/frontend/app/(main)/proxy-routes/components/helpers.ts b/frontend/app/(main)/proxy-routes/components/helpers.ts index 70e3d2ba..b0184434 100644 --- a/frontend/app/(main)/proxy-routes/components/helpers.ts +++ b/frontend/app/(main)/proxy-routes/components/helpers.ts @@ -312,8 +312,6 @@ export function buildPayloadFromRoute( cache_rules: route.cache_rule_list, custom_headers: route.custom_header_list, remark: route.remark || '', - pow_enabled: route.pow_enabled, - pow_config: JSON.stringify(route.pow_config), basic_auth_enabled: route.basic_auth_enabled, basic_auth_username: route.basic_auth_username, basic_auth_password: route.basic_auth_password, diff --git a/frontend/app/(main)/proxy-routes/components/proxy-route-create-sheet.tsx b/frontend/app/(main)/proxy-routes/components/proxy-route-create-sheet.tsx index 41ece47c..2b157a4d 100644 --- a/frontend/app/(main)/proxy-routes/components/proxy-route-create-sheet.tsx +++ b/frontend/app/(main)/proxy-routes/components/proxy-route-create-sheet.tsx @@ -114,8 +114,6 @@ export function ProxyRouteCreateSheet({ cache_policy: 'url', cache_rules: [], custom_headers: [], - pow_enabled: false, - pow_config: '{}', basic_auth_enabled: false, remark: values.remark.trim(), upstream_type: 'direct', diff --git a/frontend/app/(main)/proxy-routes/detail/components/auth-section.tsx b/frontend/app/(main)/proxy-routes/detail/components/auth-section.tsx index 67f3103c..86e75241 100644 --- a/frontend/app/(main)/proxy-routes/detail/components/auth-section.tsx +++ b/frontend/app/(main)/proxy-routes/detail/components/auth-section.tsx @@ -1,31 +1,15 @@ 'use client'; -import {useEffect, useState} from 'react'; +import {useEffect} from 'react'; import {zodResolver} from '@hookform/resolvers/zod'; import {useForm} from 'react-hook-form'; +import {toast} from 'sonner'; import {z} from 'zod'; -import { - Form, - FormControl, - FormDescription, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components/ui/form'; +import {Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage,} from '@/components/ui/form'; import {Input} from '@/components/ui/input'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select'; -import type {ProxyRouteItem, ProxyRoutePoWConfig} from '@/lib/services/openflare'; - -import {defaultPowConfig} from '@/app/(main)/waf/components/helpers'; -import {PowConfigPanel} from '@/app/(main)/waf/components/pow-config-panel'; +import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from '@/components/ui/select'; +import type {ProxyRouteItem} from '@/lib/services/openflare'; import {proxyRouteFormIds} from '../helpers'; import {useRouteSectionSave} from '../hooks/use-route-section-save'; @@ -33,83 +17,34 @@ import {SectionShell} from './section-shell'; const authSchema = z .object({ - auth_mode: z.enum(['none', 'basic', 'pow']), + auth_mode: z.enum(['none', 'basic']), basic_auth_username: z.string(), basic_auth_password: z.string(), - pow_enabled: z.boolean(), - pow_difficulty: z.string(), - pow_algorithm: z.enum(['fast', 'slow']), - pow_session_ttl: z.string(), - pow_challenge_ttl: z.string(), }) .superRefine((value, context) => { - if (value.auth_mode === 'pow') { - const difficulty = Number(value.pow_difficulty); - if (!Number.isFinite(difficulty) || difficulty < 1 || difficulty > 16) { - context.addIssue({ - code: z.ZodIssueCode.custom, - path: ['pow_difficulty'], - message: '难度需为 1-16 的整数', - }); - } - - const sessionTtl = Number(value.pow_session_ttl); - if (!Number.isFinite(sessionTtl) || sessionTtl < 60) { - context.addIssue({ - code: z.ZodIssueCode.custom, - path: ['pow_session_ttl'], - message: '会话 TTL 需大于等于 60 秒', - }); - } - - const challengeTtl = Number(value.pow_challenge_ttl); - if (!Number.isFinite(challengeTtl) || challengeTtl < 30) { - context.addIssue({ - code: z.ZodIssueCode.custom, - path: ['pow_challenge_ttl'], - message: '挑战 TTL 需大于等于 30 秒', - }); - } + if (value.auth_mode !== 'basic') { + return; } - - if (value.auth_mode === 'basic') { - if (!value.basic_auth_username.trim()) { - context.addIssue({ - code: z.ZodIssueCode.custom, - path: ['basic_auth_username'], - message: '请输入账号', - }); - } - if (!value.basic_auth_password.trim()) { - context.addIssue({ - code: z.ZodIssueCode.custom, - path: ['basic_auth_password'], - message: '请输入密码', - }); - } + if (!value.basic_auth_username.trim()) { + context.addIssue({ + code: z.ZodIssueCode.custom, + path: ['basic_auth_username'], + message: '请输入账号', + }); + } + if (!value.basic_auth_password.trim()) { + context.addIssue({ + code: z.ZodIssueCode.custom, + path: ['basic_auth_password'], + message: '请输入密码', + }); } }); type AuthValues = z.infer; function resolveAuthMode(route: ProxyRouteItem): AuthValues['auth_mode'] { - if (route.basic_auth_enabled) { - return 'basic'; - } - if (route.pow_enabled) { - return 'pow'; - } - return 'none'; -} - -function syncPowFormValues( - setValue: ReturnType>['setValue'], - config: ProxyRoutePoWConfig, -) { - setValue('pow_difficulty', String(config.difficulty)); - setValue('pow_algorithm', config.algorithm); - setValue('pow_session_ttl', String(config.session_ttl)); - setValue('pow_challenge_ttl', String(config.challenge_ttl)); + return route.basic_auth_enabled ? 'basic' : 'none'; } interface AuthSectionProps { @@ -120,9 +55,6 @@ interface AuthSectionProps { export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectionProps) { const { saving, save } = useRouteSectionSave(route, onRouteUpdate, onSavingChange); - const [powConfig, setPowConfig] = useState( - route.pow_config ?? defaultPowConfig, - ); const form = useForm({ resolver: zodResolver(authSchema), @@ -130,26 +62,14 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio auth_mode: resolveAuthMode(route), basic_auth_username: route.basic_auth_username || '', basic_auth_password: route.basic_auth_password || '', - pow_enabled: route.pow_enabled, - pow_difficulty: String(route.pow_config?.difficulty ?? defaultPowConfig.difficulty), - pow_algorithm: route.pow_config?.algorithm ?? defaultPowConfig.algorithm, - pow_session_ttl: String(route.pow_config?.session_ttl ?? defaultPowConfig.session_ttl), - pow_challenge_ttl: String(route.pow_config?.challenge_ttl ?? defaultPowConfig.challenge_ttl), }, }); useEffect(() => { - const nextPowConfig = route.pow_config ?? defaultPowConfig; - setPowConfig(nextPowConfig); form.reset({ auth_mode: resolveAuthMode(route), basic_auth_username: route.basic_auth_username || '', basic_auth_password: route.basic_auth_password || '', - pow_enabled: route.pow_enabled, - pow_difficulty: String(nextPowConfig.difficulty), - pow_algorithm: nextPowConfig.algorithm, - pow_session_ttl: String(nextPowConfig.session_ttl), - pow_challenge_ttl: String(nextPowConfig.challenge_ttl), }); }, [form, route]); @@ -158,7 +78,7 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio return ( @@ -166,26 +86,23 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
{ - const nextPowConfig = - values.auth_mode === 'pow' ? powConfig : route.pow_config ?? defaultPowConfig; - const powEnabled = values.auth_mode === 'pow' || values.pow_enabled; - - await save( - { - basic_auth_enabled: values.auth_mode === 'basic', - basic_auth_username: - values.auth_mode === 'basic' ? values.basic_auth_username.trim() : '', - basic_auth_password: - values.auth_mode === 'basic' ? values.basic_auth_password.trim() : '', - pow_enabled: powEnabled, - pow_config: JSON.stringify( - values.auth_mode === 'pow' ? nextPowConfig : route.pow_config ?? defaultPowConfig, - ), - }, - '认证配置已保存', - ); - })} + onSubmit={form.handleSubmit( + async (values) => { + await save( + { + basic_auth_enabled: values.auth_mode === 'basic', + basic_auth_username: + values.auth_mode === 'basic' ? values.basic_auth_username.trim() : '', + basic_auth_password: + values.auth_mode === 'basic' ? values.basic_auth_password.trim() : '', + }, + '认证配置已保存', + ); + }, + () => { + toast.error('请检查认证配置表单'); + }, + )} > ( 认证模式 - { + field.onChange(mode); + if (mode !== 'basic') { + form.setValue('basic_auth_username', ''); + form.setValue('basic_auth_password', ''); + } + }} + > @@ -202,10 +128,9 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio 无认证 Basic Auth - PoW 防护 - 同一站点仅启用一种认证模式。 + PoW 防护仅支持在 WAF 规则组中启用并绑定站点。 )} @@ -242,20 +167,8 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio /> ) : null} - - {authMode === 'pow' ? ( - { - form.setValue('pow_enabled', enabled); - setPowConfig(config); - syncPowFormValues(form.setValue, config); - }} - /> - ) : null}
); -} \ No newline at end of file +} diff --git a/frontend/app/(main)/proxy-routes/detail/components/route-header.tsx b/frontend/app/(main)/proxy-routes/detail/components/route-header.tsx index 1d8b0780..7c9e3f0c 100644 --- a/frontend/app/(main)/proxy-routes/detail/components/route-header.tsx +++ b/frontend/app/(main)/proxy-routes/detail/components/route-header.tsx @@ -2,7 +2,7 @@ import Link from 'next/link'; import {useCallback, useState} from 'react'; -import {ArrowLeft, Loader2, Route, Save, Upload} from 'lucide-react'; +import {ArrowLeft, Loader2, Route, Upload} from 'lucide-react'; import {toast} from 'sonner'; import { @@ -17,11 +17,10 @@ import { import {Badge} from '@/components/ui/badge'; import {Button} from '@/components/ui/button'; import {DiffDialog} from '@/app/(main)/config-versions/components/diff-dialog'; -import type {ConfigDiffResult, ProxyRouteConfigSection, ProxyRouteItem} from '@/lib/services/openflare'; +import type {ConfigDiffResult, ProxyRouteItem} from '@/lib/services/openflare'; import {ConfigVersionService} from '@/lib/services/openflare'; import {getErrorMessage} from '../../components/helpers'; -import {submitProxyRouteSectionForm} from '../helpers'; function hasConfigDiff(diff: ConfigDiffResult) { return ( @@ -37,11 +36,9 @@ function hasConfigDiff(diff: ConfigDiffResult) { interface RouteHeaderProps { route: ProxyRouteItem; - activeSection: ProxyRouteConfigSection; - saving?: boolean; } -export function RouteHeader({ route, activeSection, saving = false }: RouteHeaderProps) { +export function RouteHeader({ route }: RouteHeaderProps) { const [diffOpen, setDiffOpen] = useState(false); const [publishConfirmOpen, setPublishConfirmOpen] = useState(false); const [diff, setDiff] = useState(null); @@ -49,13 +46,6 @@ export function RouteHeader({ route, activeSection, saving = false }: RouteHeade const [diffError, setDiffError] = useState(null); const [publishing, setPublishing] = useState(false); - const handleSave = useCallback(() => { - const submitted = submitProxyRouteSectionForm(activeSection); - if (!submitted) { - toast.error('当前分区无法保存'); - } - }, [activeSection]); - const loadDiff = useCallback(async () => { setDiffLoading(true); setDiffError(null); @@ -122,16 +112,6 @@ export function RouteHeader({ route, activeSection, saving = false }: RouteHeade
-