mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-07 16:16:37 +08:00
修复代理路由详情认证配置 Tab:移除 PoW 配置(PoW 仅在 WAF 规则组中设置);保留 Basic Auth 保存能力;移除页头重复的「保存当前分区」按钮。
This commit is contained in:
@@ -22,6 +22,8 @@ sidebar: false
|
|||||||
|
|
||||||
### 修复
|
### 修复
|
||||||
|
|
||||||
|
- 修复代理路由详情认证配置 Tab:移除 PoW 配置(PoW 仅在 WAF 规则组中设置);保留 Basic Auth 保存能力;移除页头重复的「保存当前分区」按钮。
|
||||||
|
|
||||||
- 修复 Pages 路由发布失败并报 `pages module is not available`:配置快照发布流程补齐 Pages 项目激活部署解析与 `pages_deployment` 写入。
|
- 修复 Pages 路由发布失败并报 `pages module is not available`:配置快照发布流程补齐 Pages 项目激活部署解析与 `pages_deployment` 写入。
|
||||||
|
|
||||||
- 修复仪表盘与节点详情「24 小时网络趋势」误按速率展示:改为 OpenResty 入/出站小时流量与近 24 小时总量摘要,Y 轴与 tooltip 自动换算 B/KB/MB/GB。
|
- 修复仪表盘与节点详情「24 小时网络趋势」误按速率展示:改为 OpenResty 入/出站小时流量与近 24 小时总量摘要,Y 轴与 tooltip 自动换算 B/KB/MB/GB。
|
||||||
|
|||||||
@@ -312,8 +312,6 @@ export function buildPayloadFromRoute(
|
|||||||
cache_rules: route.cache_rule_list,
|
cache_rules: route.cache_rule_list,
|
||||||
custom_headers: route.custom_header_list,
|
custom_headers: route.custom_header_list,
|
||||||
remark: route.remark || '',
|
remark: route.remark || '',
|
||||||
pow_enabled: route.pow_enabled,
|
|
||||||
pow_config: JSON.stringify(route.pow_config),
|
|
||||||
basic_auth_enabled: route.basic_auth_enabled,
|
basic_auth_enabled: route.basic_auth_enabled,
|
||||||
basic_auth_username: route.basic_auth_username,
|
basic_auth_username: route.basic_auth_username,
|
||||||
basic_auth_password: route.basic_auth_password,
|
basic_auth_password: route.basic_auth_password,
|
||||||
|
|||||||
@@ -114,8 +114,6 @@ export function ProxyRouteCreateSheet({
|
|||||||
cache_policy: 'url',
|
cache_policy: 'url',
|
||||||
cache_rules: [],
|
cache_rules: [],
|
||||||
custom_headers: [],
|
custom_headers: [],
|
||||||
pow_enabled: false,
|
|
||||||
pow_config: '{}',
|
|
||||||
basic_auth_enabled: false,
|
basic_auth_enabled: false,
|
||||||
remark: values.remark.trim(),
|
remark: values.remark.trim(),
|
||||||
upstream_type: 'direct',
|
upstream_type: 'direct',
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect} from 'react';
|
||||||
import {zodResolver} from '@hookform/resolvers/zod';
|
import {zodResolver} from '@hookform/resolvers/zod';
|
||||||
import {useForm} from 'react-hook-form';
|
import {useForm} from 'react-hook-form';
|
||||||
|
import {toast} from 'sonner';
|
||||||
import {z} from 'zod';
|
import {z} from 'zod';
|
||||||
|
|
||||||
import {
|
import {Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage,} from '@/components/ui/form';
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormDescription,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from '@/components/ui/form';
|
|
||||||
import {Input} from '@/components/ui/input';
|
import {Input} from '@/components/ui/input';
|
||||||
import {
|
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from '@/components/ui/select';
|
||||||
Select,
|
import type {ProxyRouteItem} from '@/lib/services/openflare';
|
||||||
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 {proxyRouteFormIds} from '../helpers';
|
import {proxyRouteFormIds} from '../helpers';
|
||||||
import {useRouteSectionSave} from '../hooks/use-route-section-save';
|
import {useRouteSectionSave} from '../hooks/use-route-section-save';
|
||||||
@@ -33,83 +17,34 @@ import {SectionShell} from './section-shell';
|
|||||||
|
|
||||||
const authSchema = z
|
const authSchema = z
|
||||||
.object({
|
.object({
|
||||||
auth_mode: z.enum(['none', 'basic', 'pow']),
|
auth_mode: z.enum(['none', 'basic']),
|
||||||
basic_auth_username: z.string(),
|
basic_auth_username: z.string(),
|
||||||
basic_auth_password: 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) => {
|
.superRefine((value, context) => {
|
||||||
if (value.auth_mode === 'pow') {
|
if (value.auth_mode !== 'basic') {
|
||||||
const difficulty = Number(value.pow_difficulty);
|
return;
|
||||||
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.basic_auth_username.trim()) {
|
||||||
if (value.auth_mode === 'basic') {
|
context.addIssue({
|
||||||
if (!value.basic_auth_username.trim()) {
|
code: z.ZodIssueCode.custom,
|
||||||
context.addIssue({
|
path: ['basic_auth_username'],
|
||||||
code: z.ZodIssueCode.custom,
|
message: '请输入账号',
|
||||||
path: ['basic_auth_username'],
|
});
|
||||||
message: '请输入账号',
|
}
|
||||||
});
|
if (!value.basic_auth_password.trim()) {
|
||||||
}
|
context.addIssue({
|
||||||
if (!value.basic_auth_password.trim()) {
|
code: z.ZodIssueCode.custom,
|
||||||
context.addIssue({
|
path: ['basic_auth_password'],
|
||||||
code: z.ZodIssueCode.custom,
|
message: '请输入密码',
|
||||||
path: ['basic_auth_password'],
|
});
|
||||||
message: '请输入密码',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
type AuthValues = z.infer<typeof authSchema>;
|
type AuthValues = z.infer<typeof authSchema>;
|
||||||
|
|
||||||
function resolveAuthMode(route: ProxyRouteItem): AuthValues['auth_mode'] {
|
function resolveAuthMode(route: ProxyRouteItem): AuthValues['auth_mode'] {
|
||||||
if (route.basic_auth_enabled) {
|
return route.basic_auth_enabled ? 'basic' : 'none';
|
||||||
return 'basic';
|
|
||||||
}
|
|
||||||
if (route.pow_enabled) {
|
|
||||||
return 'pow';
|
|
||||||
}
|
|
||||||
return 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncPowFormValues(
|
|
||||||
setValue: ReturnType<typeof useForm<AuthValues>>['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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AuthSectionProps {
|
interface AuthSectionProps {
|
||||||
@@ -120,9 +55,6 @@ interface AuthSectionProps {
|
|||||||
|
|
||||||
export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectionProps) {
|
export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectionProps) {
|
||||||
const { saving, save } = useRouteSectionSave(route, onRouteUpdate, onSavingChange);
|
const { saving, save } = useRouteSectionSave(route, onRouteUpdate, onSavingChange);
|
||||||
const [powConfig, setPowConfig] = useState<ProxyRoutePoWConfig>(
|
|
||||||
route.pow_config ?? defaultPowConfig,
|
|
||||||
);
|
|
||||||
|
|
||||||
const form = useForm<AuthValues>({
|
const form = useForm<AuthValues>({
|
||||||
resolver: zodResolver(authSchema),
|
resolver: zodResolver(authSchema),
|
||||||
@@ -130,26 +62,14 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
|
|||||||
auth_mode: resolveAuthMode(route),
|
auth_mode: resolveAuthMode(route),
|
||||||
basic_auth_username: route.basic_auth_username || '',
|
basic_auth_username: route.basic_auth_username || '',
|
||||||
basic_auth_password: route.basic_auth_password || '',
|
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(() => {
|
useEffect(() => {
|
||||||
const nextPowConfig = route.pow_config ?? defaultPowConfig;
|
|
||||||
setPowConfig(nextPowConfig);
|
|
||||||
form.reset({
|
form.reset({
|
||||||
auth_mode: resolveAuthMode(route),
|
auth_mode: resolveAuthMode(route),
|
||||||
basic_auth_username: route.basic_auth_username || '',
|
basic_auth_username: route.basic_auth_username || '',
|
||||||
basic_auth_password: route.basic_auth_password || '',
|
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]);
|
}, [form, route]);
|
||||||
|
|
||||||
@@ -158,7 +78,7 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
|
|||||||
return (
|
return (
|
||||||
<SectionShell
|
<SectionShell
|
||||||
title="认证配置"
|
title="认证配置"
|
||||||
description="配置基础鉴权或 PoW 防护,限制未授权访问。"
|
description="配置 Basic Auth 限制未授权访问。PoW 防护请在 WAF 规则组中配置。"
|
||||||
formId={proxyRouteFormIds.auth}
|
formId={proxyRouteFormIds.auth}
|
||||||
saving={saving}
|
saving={saving}
|
||||||
>
|
>
|
||||||
@@ -166,26 +86,23 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
|
|||||||
<form
|
<form
|
||||||
id={proxyRouteFormIds.auth}
|
id={proxyRouteFormIds.auth}
|
||||||
className="space-y-5"
|
className="space-y-5"
|
||||||
onSubmit={form.handleSubmit(async (values) => {
|
onSubmit={form.handleSubmit(
|
||||||
const nextPowConfig =
|
async (values) => {
|
||||||
values.auth_mode === 'pow' ? powConfig : route.pow_config ?? defaultPowConfig;
|
await save(
|
||||||
const powEnabled = values.auth_mode === 'pow' || values.pow_enabled;
|
{
|
||||||
|
basic_auth_enabled: values.auth_mode === 'basic',
|
||||||
await save(
|
basic_auth_username:
|
||||||
{
|
values.auth_mode === 'basic' ? values.basic_auth_username.trim() : '',
|
||||||
basic_auth_enabled: values.auth_mode === 'basic',
|
basic_auth_password:
|
||||||
basic_auth_username:
|
values.auth_mode === 'basic' ? values.basic_auth_password.trim() : '',
|
||||||
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,
|
toast.error('请检查认证配置表单');
|
||||||
),
|
},
|
||||||
},
|
)}
|
||||||
'认证配置已保存',
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -193,7 +110,16 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>认证模式</FormLabel>
|
<FormLabel>认证模式</FormLabel>
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={(mode) => {
|
||||||
|
field.onChange(mode);
|
||||||
|
if (mode !== 'basic') {
|
||||||
|
form.setValue('basic_auth_username', '');
|
||||||
|
form.setValue('basic_auth_password', '');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
@@ -202,10 +128,9 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
|
|||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="none">无认证</SelectItem>
|
<SelectItem value="none">无认证</SelectItem>
|
||||||
<SelectItem value="basic">Basic Auth</SelectItem>
|
<SelectItem value="basic">Basic Auth</SelectItem>
|
||||||
<SelectItem value="pow">PoW 防护</SelectItem>
|
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormDescription>同一站点仅启用一种认证模式。</FormDescription>
|
<FormDescription>PoW 防护仅支持在 WAF 规则组中启用并绑定站点。</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
@@ -242,20 +167,8 @@ export function AuthSection({ route, onRouteUpdate, onSavingChange }: AuthSectio
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{authMode === 'pow' ? (
|
|
||||||
<PowConfigPanel
|
|
||||||
enabled={form.watch('pow_enabled')}
|
|
||||||
config={powConfig}
|
|
||||||
onChange={(enabled, config) => {
|
|
||||||
form.setValue('pow_enabled', enabled);
|
|
||||||
setPowConfig(config);
|
|
||||||
syncPowFormValues(form.setValue, config);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</SectionShell>
|
</SectionShell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import {useCallback, useState} from 'react';
|
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 {toast} from 'sonner';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -17,11 +17,10 @@ import {
|
|||||||
import {Badge} from '@/components/ui/badge';
|
import {Badge} from '@/components/ui/badge';
|
||||||
import {Button} from '@/components/ui/button';
|
import {Button} from '@/components/ui/button';
|
||||||
import {DiffDialog} from '@/app/(main)/config-versions/components/diff-dialog';
|
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 {ConfigVersionService} from '@/lib/services/openflare';
|
||||||
|
|
||||||
import {getErrorMessage} from '../../components/helpers';
|
import {getErrorMessage} from '../../components/helpers';
|
||||||
import {submitProxyRouteSectionForm} from '../helpers';
|
|
||||||
|
|
||||||
function hasConfigDiff(diff: ConfigDiffResult) {
|
function hasConfigDiff(diff: ConfigDiffResult) {
|
||||||
return (
|
return (
|
||||||
@@ -37,11 +36,9 @@ function hasConfigDiff(diff: ConfigDiffResult) {
|
|||||||
|
|
||||||
interface RouteHeaderProps {
|
interface RouteHeaderProps {
|
||||||
route: ProxyRouteItem;
|
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 [diffOpen, setDiffOpen] = useState(false);
|
||||||
const [publishConfirmOpen, setPublishConfirmOpen] = useState(false);
|
const [publishConfirmOpen, setPublishConfirmOpen] = useState(false);
|
||||||
const [diff, setDiff] = useState<ConfigDiffResult | null>(null);
|
const [diff, setDiff] = useState<ConfigDiffResult | null>(null);
|
||||||
@@ -49,13 +46,6 @@ export function RouteHeader({ route, activeSection, saving = false }: RouteHeade
|
|||||||
const [diffError, setDiffError] = useState<string | null>(null);
|
const [diffError, setDiffError] = useState<string | null>(null);
|
||||||
const [publishing, setPublishing] = useState(false);
|
const [publishing, setPublishing] = useState(false);
|
||||||
|
|
||||||
const handleSave = useCallback(() => {
|
|
||||||
const submitted = submitProxyRouteSectionForm(activeSection);
|
|
||||||
if (!submitted) {
|
|
||||||
toast.error('当前分区无法保存');
|
|
||||||
}
|
|
||||||
}, [activeSection]);
|
|
||||||
|
|
||||||
const loadDiff = useCallback(async () => {
|
const loadDiff = useCallback(async () => {
|
||||||
setDiffLoading(true);
|
setDiffLoading(true);
|
||||||
setDiffError(null);
|
setDiffError(null);
|
||||||
@@ -122,16 +112,6 @@ export function RouteHeader({ route, activeSection, saving = false }: RouteHeade
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="secondary"
|
|
||||||
className="h-8 gap-1.5 text-xs"
|
|
||||||
disabled={saving}
|
|
||||||
onClick={handleSave}
|
|
||||||
>
|
|
||||||
{saving ? <Loader2 className="size-3.5 animate-spin" /> : <Save className="size-3.5" />}
|
|
||||||
{saving ? '保存中...' : '保存当前分区'}
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
className="h-8 gap-1.5 text-xs"
|
className="h-8 gap-1.5 text-xs"
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export function ProxyRouteDetailPageClient() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="py-6 px-1 space-y-6">
|
<div className="py-6 px-1 space-y-6">
|
||||||
<RouteHeader route={route} activeSection={activeSection} saving={sectionSaving} />
|
<RouteHeader route={route} />
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
value={activeSection}
|
value={activeSection}
|
||||||
|
|||||||
@@ -255,8 +255,6 @@ export interface ProxyRouteItem {
|
|||||||
cache_rule_list: string[];
|
cache_rule_list: string[];
|
||||||
custom_headers: string;
|
custom_headers: string;
|
||||||
custom_header_list: ProxyRouteCustomHeader[];
|
custom_header_list: ProxyRouteCustomHeader[];
|
||||||
pow_enabled: boolean;
|
|
||||||
pow_config: ProxyRoutePoWConfig;
|
|
||||||
basic_auth_enabled: boolean;
|
basic_auth_enabled: boolean;
|
||||||
basic_auth_username: string;
|
basic_auth_username: string;
|
||||||
basic_auth_password: string;
|
basic_auth_password: string;
|
||||||
@@ -296,8 +294,6 @@ export interface ProxyRouteMutationPayload {
|
|||||||
cache_policy: string;
|
cache_policy: string;
|
||||||
cache_rules: string[];
|
cache_rules: string[];
|
||||||
custom_headers: ProxyRouteCustomHeader[];
|
custom_headers: ProxyRouteCustomHeader[];
|
||||||
pow_enabled: boolean;
|
|
||||||
pow_config: string;
|
|
||||||
basic_auth_enabled: boolean;
|
basic_auth_enabled: boolean;
|
||||||
basic_auth_username?: string;
|
basic_auth_username?: string;
|
||||||
basic_auth_password?: string;
|
basic_auth_password?: string;
|
||||||
|
|||||||
@@ -115,3 +115,32 @@ func TestValidateProxyRouteIdentityUniquenessUsesDecodedPrimaryDomain(t *testing
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "site_name already exists")
|
assert.Contains(t, err.Error(), "site_name already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdateProxyRouteAuthConfig(t *testing.T) {
|
||||||
|
cleanup := setupProxyRouteTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
created, err := CreateProxyRoute(ctx, Input{
|
||||||
|
SiteName: "auth-site",
|
||||||
|
Domain: "auth.example.com",
|
||||||
|
OriginURL: "http://origin.example.com:8080",
|
||||||
|
Enabled: true,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
updated, err := UpdateProxyRoute(ctx, created.ID, Input{
|
||||||
|
SiteName: created.SiteName,
|
||||||
|
Domain: created.Domain,
|
||||||
|
Domains: created.Domains,
|
||||||
|
OriginURL: created.OriginURL,
|
||||||
|
Enabled: created.Enabled,
|
||||||
|
BasicAuthEnabled: true,
|
||||||
|
BasicAuthUsername: "admin",
|
||||||
|
BasicAuthPassword: "secret",
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.True(t, updated.BasicAuthEnabled)
|
||||||
|
assert.Equal(t, "admin", updated.BasicAuthUsername)
|
||||||
|
assert.Equal(t, "secret", updated.BasicAuthPassword)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user