diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 91e352f7f..6fa576b6f 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -4318,7 +4318,6 @@ const message = { 'Set one port allowed by the firewall. Manage the listening port in the service settings.', whitelistSourcesHelper: 'Enter IP addresses or CIDR ranges, separated by commas or new lines. Leave blank to allow all IPv4 and IPv6 sources.', - systemAccessSourceError: 'Enter at least one valid {0} address or CIDR range.', destinationPortPlaceholder: 'e.g. 80, 80,443, or 8080-8089', deleteRuleConfirm: 'Will delete {0} rules. Continue?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 4c1d7fc27..1b5e70d3f 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -4371,7 +4371,6 @@ const message = { 'Configure un único puerto permitido por el cortafuegos. El puerto de escucha se gestiona en la configuración del servicio.', whitelistSourcesHelper: 'Introduzca direcciones IP o rangos CIDR separados por comas o saltos de línea. Déjelo en blanco para permitir todos los orígenes IPv4 e IPv6.', - systemAccessSourceError: 'Introduzca al menos una dirección o red CIDR {0} válida.', destinationPortPlaceholder: 'p. ej. 80, 80,443 o 8080-8089', deleteRuleConfirm: 'Se eliminarán {0} reglas. ¿Continuar?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/fa.ts b/frontend/src/lang/modules/fa.ts index 6011fc198..2f04b029b 100644 --- a/frontend/src/lang/modules/fa.ts +++ b/frontend/src/lang/modules/fa.ts @@ -4275,7 +4275,6 @@ const message = { 'یک درگاه مجاز برای دیواره آتش تنظیم کنید. درگاه شنود را در تنظیمات سرویس تغییر دهید.', whitelistSourcesHelper: 'آدرس‌های IP یا محدوده‌های CIDR را با ویرگول یا خط جدید جدا کنید. برای مجاز کردن همه مبدأهای IPv4 و IPv6، این قسمت را خالی بگذارید.', - systemAccessSourceError: 'حداقل یک نشانی {0} یا بازه CIDR معتبر وارد کنید.', destinationPortPlaceholder: 'مثلاً: 80، 80,443 یا 8080-8089', deleteRuleConfirm: '{0} قانون حذف خواهند شد. ادامه می‌دهید؟', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 6ba350513..0fb1a727c 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -4301,7 +4301,6 @@ const message = { 'ファイアウォールで許可するポートを1つ設定します。待ち受けポートは各サービスの設定で変更してください。', whitelistSourcesHelper: 'IP アドレスまたは CIDR をカンマか改行で区切って入力してください。 空欄の場合、すべての IPv4 および IPv6 の接続元を許可します。', - systemAccessSourceError: '有効な {0} アドレスまたは CIDR を1つ以上入力してください。', destinationPortPlaceholder: '例: 80、80,443、8080-8089', deleteRuleConfirm: '{0} 個のルールを削除します。続行しますか?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 191df95a7..c788730aa 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -4222,7 +4222,6 @@ const message = { '방화벽에서 허용할 포트 하나를 설정합니다. 수신 포트는 해당 서비스 설정에서 변경하세요.', whitelistSourcesHelper: 'IP 주소 또는 CIDR 대역을 쉼표나 줄바꿈으로 구분하세요. 비워 두면 모든 IPv4 및 IPv6 출발지를 허용합니다.', - systemAccessSourceError: '유효한 {0} 주소 또는 CIDR 대역을 하나 이상 입력하세요.', destinationPortPlaceholder: '예: 80, 80,443 또는 8080-8089', deleteRuleConfirm: '{0}개의 규칙을 삭제합니다. 계속하시겠습니까?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/lo.ts b/frontend/src/lang/modules/lo.ts index 41367e9da..0767684e4 100644 --- a/frontend/src/lang/modules/lo.ts +++ b/frontend/src/lang/modules/lo.ts @@ -4185,7 +4185,6 @@ const message = { whitelistServicePortsHelper: 'ຕັ້ງຄ່າໜຶ່ງພອດທີ່ໄຟວໍອະນຸຍາດ. ປ່ຽນພອດຮັບຟັງໃນການຕັ້ງຄ່າບໍລິການ.', whitelistSourcesHelper: 'ປ້ອນທີ່ຢູ່ IP ຫຼື CIDR ໂດຍແຍກດ້ວຍຈຸດຈ້ຳ ຫຼື ຂຶ້ນແຖວໃໝ່. ຖ້າປະໄວ້ຫວ່າງ ຈະອະນຸຍາດທຸກແຫຼ່ງທີ່ມາ IPv4 ແລະ IPv6.', - systemAccessSourceError: 'ປ້ອນທີ່ຢູ່ {0} ຫຼື CIDR ທີ່ຖືກຕ້ອງຢ່າງໜ້ອຍໜຶ່ງລາຍການ.', destinationPortPlaceholder: 'ຕົວຢ່າງ: 80, 80,443 ຫຼື 8080-8089', deleteRuleConfirm: 'ຈະລຶບ {0} ກົດລະບຽບ. ຕ້ອງການຕໍ່ຫຼືບໍ່?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 887fb7ba3..ea34bb52a 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -4385,7 +4385,6 @@ const message = { 'Tetapkan satu port yang dibenarkan oleh tembok api. Urus port pendengar dalam tetapan perkhidmatan.', whitelistSourcesHelper: 'Masukkan alamat IP atau julat CIDR, dipisahkan dengan koma atau baris baharu. Biarkan kosong untuk membenarkan semua sumber IPv4 dan IPv6.', - systemAccessSourceError: 'Masukkan sekurang-kurangnya satu alamat {0} atau julat CIDR yang sah.', destinationPortPlaceholder: 'contoh: 80, 80,443 atau 8080-8089', deleteRuleConfirm: 'Akan memadam {0} peraturan. Teruskan?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 8ada6d596..5019dab38 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -4407,7 +4407,6 @@ const message = { 'Defina uma única porta permitida pelo firewall. Gerencie a porta de escuta nas configurações do serviço.', whitelistSourcesHelper: 'Insira endereços IP ou intervalos CIDR separados por vírgulas ou quebras de linha. Deixe em branco para permitir todas as origens IPv4 e IPv6.', - systemAccessSourceError: 'Informe pelo menos um endereço {0} ou intervalo CIDR válido.', destinationPortPlaceholder: 'por exemplo: 80, 80,443 ou 8080-8089', deleteRuleConfirm: 'Excluirá {0} regras. Continuar?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index eea318f93..3f276ddbb 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -4373,7 +4373,6 @@ const message = { 'Укажите один порт, разрешённый брандмауэром. Порт прослушивания меняется в настройках службы.', whitelistSourcesHelper: 'Введите IP-адреса или подсети CIDR через запятую или с новой строки. Оставьте поле пустым, чтобы разрешить все источники IPv4 и IPv6.', - systemAccessSourceError: 'Укажите хотя бы один допустимый адрес {0} или диапазон CIDR.', destinationPortPlaceholder: 'например: 80, 80,443 или 8080-8089', deleteRuleConfirm: 'Удалит {0} правил. Продолжить?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index ce961cc4f..d84c86080 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -4389,7 +4389,6 @@ const message = { 'Güvenlik duvarının izin verdiği tek bir port ayarlayın. Dinleme portunu hizmet ayarlarından yönetin.', whitelistSourcesHelper: 'IP adreslerini veya CIDR aralıklarını virgül ya da yeni satırla ayırın. Tüm IPv4 ve IPv6 kaynaklarına izin vermek için boş bırakın.', - systemAccessSourceError: 'En az bir geçerli {0} adresi veya CIDR aralığı girin.', destinationPortPlaceholder: 'örn. 80, 80,443 veya 8080-8089', deleteRuleConfirm: '{0} kural silinecek. Devam etmek istiyor musunuz?', deleteUsedRuleConfirm: diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index a1508be93..904579372 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -4022,7 +4022,6 @@ const message = { systemAccessChangeConfirm: '對 {0} 白名單規則執行此操作後,可能無法透過該服務遠端存取。是否繼續?', whitelistServicePortsHelper: '設定一個防火牆放行連接埠,服務監聽連接埠請在對應服務設定中修改。', whitelistSourcesHelper: '支援 IP 或 CIDR,多個以逗號或換行分隔。留空預設允許所有 IPv4 和 IPv6 來源。', - systemAccessSourceError: '請至少填寫一個有效的 {0} 位址或 CIDR 網段。', destinationPortPlaceholder: '例如:80、80,443 或 8080-8089', deleteRuleConfirm: '將刪除 {0} 條規則,是否繼續?', deleteUsedRuleConfirm: '該規則涵蓋由 {0} 提供的監聽服務。刪除後可能導致相關服務無法存取,是否繼續?', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index b20247999..81aa2c857 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -4070,7 +4070,6 @@ const message = { systemAccessChangeConfirm: '对 {0} 白名单规则执行此操作后,可能无法通过该服务远程访问。是否继续?', whitelistServicePortsHelper: '设置一个防火墙放行端口,服务监听端口请在对应服务设置中修改。', whitelistSourcesHelper: '支持 IP 或 CIDR,多个以逗号或换行分隔。留空默认允许所有 IPv4 和 IPv6 来源。', - systemAccessSourceError: '请至少填写一个有效的 {0} 地址或 CIDR 网段。', destinationPortPlaceholder: '例如:80、80,443 或 8080-8089', deleteRuleConfirm: '将删除 {0} 条规则,是否继续?', deleteUsedRuleConfirm: '该规则覆盖了由 {0} 提供的监听服务。删除后可能导致相关服务无法访问,是否继续?', diff --git a/frontend/src/views/host/firewall/setting/white-list/index.vue b/frontend/src/views/host/firewall/setting/white-list/index.vue index dbd18e204..a66f3dddd 100644 --- a/frontend/src/views/host/firewall/setting/white-list/index.vue +++ b/frontend/src/views/host/firewall/setting/white-list/index.vue @@ -46,7 +46,14 @@ :title="$t(editingRule ? 'commons.button.edit' : 'commons.button.create')" :show-close="!saving" > - + @@ -65,16 +72,16 @@ - + {{ $t('firewall.whitelistServicePortsHelper') }} - + props.loading || saving.value); const disabled = computed(() => busy.value || !props.rules); const data = computed(() => props.rules || []); const editingRule = ref(); +const formRef = ref(); const form = ref({ type: 'custom' as WhiteListType | 'custom', protocol: 'tcp' as WhiteListProtocol, port: '', sourceInput: '', }); +const rules: FormRules = { + port: [ + { + required: true, + validator: (_rule, value: string, callback) => { + if (!value) { + callback(new Error(i18n.global.t('commons.rule.requiredInput'))); + return; + } + if (!isValidPortRange(value) || (form.value.type !== 'custom' && !/^\d+$/.test(value))) { + const message = form.value.type === 'custom' ? 'firewall.portFormatError' : 'commons.rule.port'; + callback(new Error(i18n.global.t(message))); + return; + } + callback(); + }, + trigger: ['blur', 'change'], + }, + ], + sourceInput: [ + { + validator: (_rule, value: string, callback) => { + if (splitTagValues([value]).some((source) => !isValidIPOrCIDR(source))) { + callback(new Error(i18n.global.t('commons.rule.ip'))); + return; + } + callback(); + }, + trigger: ['blur', 'change'], + }, + ], +}; const serviceTypes: WhiteListType[] = ['ssh', 'panel']; const serviceLabel = (type: WhiteListType) => (type === 'panel' ? '1Panel' : 'SSH'); const servicePortLabel = (type: WhiteListType) => @@ -145,19 +190,18 @@ const openEditor = (rule?: WhiteListRule) => { port: rule?.port || '', sourceInput: formatHostAddressList(rule ? rule.sources || [] : ['0.0.0.0/0', '::/0']), }; + formRef.value?.clearValidate(); dialogVisible.value = true; }; const saveRule = async () => { - if (disabled.value) return; + if (disabled.value || !formRef.value) return; + const valid = await formRef.value.validate().catch(() => false); + if (!valid) return; const sources = splitTagValues([form.value.sourceInput]); if (!sources.length) { sources.push('0.0.0.0/0', '::/0'); } - if (sources.some((source) => !isValidIPOrCIDR(source))) { - MsgError(i18n.global.t('firewall.systemAccessSourceError', ['IPv4 / IPv6'])); - return; - } let rule: WhiteListRule; try { rule = normalizeWhiteListRule({