fix(nodes): agent 主控地址预填 origin+基础路径,地址为空时不生成安装命令并提示
This commit is contained in:
@@ -20,6 +20,7 @@ import type { Msg } from '@/utils';
|
||||
import { NodeFormSchema, type NodeFormValues, type ProbeResult } from '@/schemas/node';
|
||||
import { FormField, rhfZodValidate } from '@/components/form/rhf';
|
||||
import { useOutboundTagGroups } from '@/api/queries/useOutboundTags';
|
||||
import { currentPanelMasterUrl } from './agentMasterUrl';
|
||||
import './NodeFormModal.css';
|
||||
|
||||
type Mode = 'add' | 'edit';
|
||||
@@ -248,8 +249,10 @@ export default function NodeFormModal({
|
||||
if (agentMode && mode === 'add' && obj?.agentToken) {
|
||||
setAgentToken(obj.agentToken);
|
||||
setAgentNodeName(result.data.name.trim());
|
||||
// Default master URL to the current panel origin; user can edit it.
|
||||
setAgentMasterUrl(window.location.origin);
|
||||
// Default the master URL to the address this panel is being
|
||||
// viewed through — origin AND base path. Dropping the base
|
||||
// path made the agent's registration 404. User can edit it.
|
||||
setAgentMasterUrl(currentPanelMasterUrl());
|
||||
// Keep the modal open state; the token dialog shows on top.
|
||||
} else {
|
||||
onOpenChange(false);
|
||||
@@ -264,6 +267,13 @@ export default function NodeFormModal({
|
||||
if (!submitting) onOpenChange(false);
|
||||
}
|
||||
|
||||
// The install command is only meaningful with a master URL; an empty
|
||||
// one would produce a command that can never register, so withhold it
|
||||
// (and say why) instead of letting the user copy a dead command.
|
||||
const installCmd = agentMasterUrl
|
||||
? `bash <(curl -fL https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-agent.sh) --master ${agentMasterUrl} --token ${agentToken ?? ''} --name ${agentNodeName}`
|
||||
: '';
|
||||
|
||||
return (
|
||||
<>
|
||||
{messageContextHolder}
|
||||
@@ -560,9 +570,9 @@ export default function NodeFormModal({
|
||||
<Button
|
||||
key="copy"
|
||||
type="primary"
|
||||
disabled={!installCmd}
|
||||
onClick={() => {
|
||||
const cmd = `bash <(curl -fL https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-agent.sh) --master ${agentMasterUrl} --token ${agentToken} --name ${agentNodeName}`;
|
||||
navigator.clipboard.writeText(cmd).then(
|
||||
navigator.clipboard.writeText(installCmd).then(
|
||||
() => messageApi.success(t('pages.nodes.agentTokenCopied')),
|
||||
() => messageApi.error(t('pages.nodes.agentTokenCopyFailed')),
|
||||
);
|
||||
@@ -597,9 +607,18 @@ export default function NodeFormModal({
|
||||
onChange={(e) => setAgentMasterUrl(e.target.value.trim())}
|
||||
style={{ marginBottom: 12, fontFamily: 'monospace' }}
|
||||
/>
|
||||
{!agentMasterUrl && (
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
style={{ marginBottom: 12 }}
|
||||
title={t('pages.nodes.agentMasterUrlRequired')}
|
||||
/>
|
||||
)}
|
||||
<p>{t('pages.nodes.agentTokenHint')}</p>
|
||||
<Input.TextArea
|
||||
value={`bash <(curl -fL https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-agent.sh) --master ${agentMasterUrl} --token ${agentToken} --name ${agentNodeName}`}
|
||||
value={installCmd}
|
||||
placeholder={t('pages.nodes.agentMasterUrlRequired')}
|
||||
readOnly
|
||||
rows={4}
|
||||
style={{ fontFamily: 'monospace' }}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Default master URL offered in the agent install command.
|
||||
//
|
||||
// The agent registers against {master_url}/panel/api/agent/register, and
|
||||
// the panel itself is usually served under a base path (webBasePath, e.g.
|
||||
// "/rogue"). Prefilling the bare origin — as the form used to — produced
|
||||
// an install command whose registration 404'd, leaving the node stuck at
|
||||
// "unknown" on the panel. The address the operator is viewing the panel
|
||||
// through already contains the base path, so derive the default from it:
|
||||
// origin + window.X_UI_BASE_PATH (injected by the panel server). The
|
||||
// operator can still override it (e.g. a public address instead of a LAN
|
||||
// or tunnel one).
|
||||
export function computeDefaultMasterUrl(origin: string, basePath: string | undefined): string {
|
||||
const trimmed = (basePath || '/').replace(/\/+$/, '');
|
||||
return origin + trimmed;
|
||||
}
|
||||
|
||||
export function currentPanelMasterUrl(): string {
|
||||
if (typeof window === 'undefined') return '';
|
||||
return computeDefaultMasterUrl(window.location.origin, window.X_UI_BASE_PATH);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { computeDefaultMasterUrl } from '@/pages/nodes/agentMasterUrl';
|
||||
|
||||
// The install command's --master must be the address agents can register
|
||||
// against: origin + panel base path. Dropping the base path was the
|
||||
// production bug — registration 404'd and the node stayed "unknown".
|
||||
describe('computeDefaultMasterUrl', () => {
|
||||
it('keeps a base path with trailing slash', () => {
|
||||
expect(computeDefaultMasterUrl('https://amb.example.com', '/rogue/')).toBe(
|
||||
'https://amb.example.com/rogue',
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps a base path without trailing slash', () => {
|
||||
expect(computeDefaultMasterUrl('https://amb.example.com', '/rogue')).toBe(
|
||||
'https://amb.example.com/rogue',
|
||||
);
|
||||
});
|
||||
|
||||
it('root base path yields the bare origin', () => {
|
||||
expect(computeDefaultMasterUrl('http://192.168.0.1:55889', '/')).toBe('http://192.168.0.1:55889');
|
||||
});
|
||||
|
||||
it('undefined or empty base path yields the bare origin', () => {
|
||||
expect(computeDefaultMasterUrl('http://10.0.0.2:2053', undefined)).toBe('http://10.0.0.2:2053');
|
||||
expect(computeDefaultMasterUrl('http://10.0.0.2:2053', '')).toBe('http://10.0.0.2:2053');
|
||||
});
|
||||
|
||||
it('nested base paths survive', () => {
|
||||
expect(computeDefaultMasterUrl('https://example.com', '/a/b/')).toBe('https://example.com/a/b');
|
||||
});
|
||||
});
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "افتراضي",
|
||||
|
||||
@@ -1061,7 +1061,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Default",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Predeterminado",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "پیشفرض",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Bawaan",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "デフォルト",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Padrão",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "По умолчанию",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Varsayılan",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Типово",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "Mặc định",
|
||||
|
||||
@@ -943,7 +943,8 @@
|
||||
"agentTokenCopied": "安装命令已复制",
|
||||
"agentTokenCopyFailed": "复制失败,请手动复制",
|
||||
"copyToken": "复制安装命令",
|
||||
"agentMasterUrlHint": "主控地址(agent 用来连接主控,如有域名或反代请改成对外地址):"
|
||||
"agentMasterUrlHint": "主控地址(agent 用来连接主控,如有域名或反代请改成对外地址):",
|
||||
"agentMasterUrlRequired": "主控地址为空——请先填入主控地址,之后才会生成安装命令。"
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "默认",
|
||||
|
||||
@@ -921,7 +921,8 @@
|
||||
"agentTokenCopied": "Install command copied",
|
||||
"agentTokenCopyFailed": "Copy failed, please copy manually",
|
||||
"copyToken": "Copy Install Command",
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):"
|
||||
"agentMasterUrlHint": "Master URL (used by agent to reach the master; change to public address if behind proxy):",
|
||||
"agentMasterUrlRequired": "Master URL is empty — enter the master address first; the install command is generated only then."
|
||||
},
|
||||
"settings": {
|
||||
"defaultTag": "預設",
|
||||
|
||||
Reference in New Issue
Block a user