mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-08 20:46:50 +03:00
feat: migrate validatePath to modular
This commit is contained in:
@@ -1,70 +1,76 @@
|
||||
export const STATUS_COLORS = {
|
||||
SUCCESS: '#4caf50',
|
||||
ERROR: '#f44336',
|
||||
WARNING: '#ff9800'
|
||||
SUCCESS: '#4caf50',
|
||||
ERROR: '#f44336',
|
||||
WARNING: '#ff9800',
|
||||
};
|
||||
|
||||
export const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi';
|
||||
export const IP_CHECK_DOMAIN = 'ip.podkop.fyi';
|
||||
|
||||
export const REGIONAL_OPTIONS = ['russia_inside', 'russia_outside', 'ukraine_inside'];
|
||||
export const REGIONAL_OPTIONS = [
|
||||
'russia_inside',
|
||||
'russia_outside',
|
||||
'ukraine_inside',
|
||||
];
|
||||
|
||||
export const ALLOWED_WITH_RUSSIA_INSIDE = [
|
||||
'russia_inside',
|
||||
'meta',
|
||||
'twitter',
|
||||
'discord',
|
||||
'telegram',
|
||||
'cloudflare',
|
||||
'google_ai',
|
||||
'google_play',
|
||||
'hetzner',
|
||||
'ovh',
|
||||
'hodca',
|
||||
'digitalocean',
|
||||
'cloudfront'
|
||||
'russia_inside',
|
||||
'meta',
|
||||
'twitter',
|
||||
'discord',
|
||||
'telegram',
|
||||
'cloudflare',
|
||||
'google_ai',
|
||||
'google_play',
|
||||
'hetzner',
|
||||
'ovh',
|
||||
'hodca',
|
||||
'digitalocean',
|
||||
'cloudfront',
|
||||
];
|
||||
|
||||
export const DOMAIN_LIST_OPTIONS = {
|
||||
russia_inside: 'Russia inside',
|
||||
russia_outside: 'Russia outside',
|
||||
ukraine_inside: 'Ukraine',
|
||||
geoblock: 'Geo Block',
|
||||
block: 'Block',
|
||||
porn: 'Porn',
|
||||
news: 'News',
|
||||
anime: 'Anime',
|
||||
youtube: 'Youtube',
|
||||
discord: 'Discord',
|
||||
meta: 'Meta',
|
||||
twitter: 'Twitter (X)',
|
||||
hdrezka: 'HDRezka',
|
||||
tiktok: 'Tik-Tok',
|
||||
telegram: 'Telegram',
|
||||
cloudflare: 'Cloudflare',
|
||||
google_ai: 'Google AI',
|
||||
google_play: 'Google Play',
|
||||
hodca: 'H.O.D.C.A',
|
||||
hetzner: 'Hetzner ASN',
|
||||
ovh: 'OVH ASN',
|
||||
digitalocean: 'Digital Ocean ASN',
|
||||
cloudfront: 'CloudFront ASN'
|
||||
russia_inside: 'Russia inside',
|
||||
russia_outside: 'Russia outside',
|
||||
ukraine_inside: 'Ukraine',
|
||||
geoblock: 'Geo Block',
|
||||
block: 'Block',
|
||||
porn: 'Porn',
|
||||
news: 'News',
|
||||
anime: 'Anime',
|
||||
youtube: 'Youtube',
|
||||
discord: 'Discord',
|
||||
meta: 'Meta',
|
||||
twitter: 'Twitter (X)',
|
||||
hdrezka: 'HDRezka',
|
||||
tiktok: 'Tik-Tok',
|
||||
telegram: 'Telegram',
|
||||
cloudflare: 'Cloudflare',
|
||||
google_ai: 'Google AI',
|
||||
google_play: 'Google Play',
|
||||
hodca: 'H.O.D.C.A',
|
||||
hetzner: 'Hetzner ASN',
|
||||
ovh: 'OVH ASN',
|
||||
digitalocean: 'Digital Ocean ASN',
|
||||
cloudfront: 'CloudFront ASN',
|
||||
};
|
||||
|
||||
export const UPDATE_INTERVAL_OPTIONS = {
|
||||
'1h': 'Every hour',
|
||||
'3h': 'Every 3 hours',
|
||||
'12h': 'Every 12 hours',
|
||||
'1d': 'Every day',
|
||||
'3d': 'Every 3 days'
|
||||
'1h': 'Every hour',
|
||||
'3h': 'Every 3 hours',
|
||||
'12h': 'Every 12 hours',
|
||||
'1d': 'Every day',
|
||||
'3d': 'Every 3 days',
|
||||
};
|
||||
|
||||
export const DNS_SERVER_OPTIONS = {
|
||||
'1.1.1.1': '1.1.1.1 (Cloudflare)',
|
||||
'8.8.8.8': '8.8.8.8 (Google)',
|
||||
'9.9.9.9': '9.9.9.9 (Quad9)',
|
||||
'dns.adguard-dns.com': 'dns.adguard-dns.com (AdGuard Default)',
|
||||
'unfiltered.adguard-dns.com': 'unfiltered.adguard-dns.com (AdGuard Unfiltered)',
|
||||
'family.adguard-dns.com': 'family.adguard-dns.com (AdGuard Family)'
|
||||
'1.1.1.1': '1.1.1.1 (Cloudflare)',
|
||||
'8.8.8.8': '8.8.8.8 (Google)',
|
||||
'9.9.9.9': '9.9.9.9 (Quad9)',
|
||||
'dns.adguard-dns.com': 'dns.adguard-dns.com (AdGuard Default)',
|
||||
'unfiltered.adguard-dns.com':
|
||||
'unfiltered.adguard-dns.com (AdGuard Unfiltered)',
|
||||
'family.adguard-dns.com': 'family.adguard-dns.com (AdGuard Family)',
|
||||
};
|
||||
|
||||
export const DIAGNOSTICS_UPDATE_INTERVAL = 10000; // 10 seconds
|
||||
@@ -77,15 +83,15 @@ export const DIAGNOSTICS_INITIAL_DELAY = 100; // 100 milliseconds
|
||||
|
||||
// Command scheduling intervals in diagnostics (in milliseconds)
|
||||
export const COMMAND_SCHEDULING = {
|
||||
P0_PRIORITY: 0, // Highest priority (no delay)
|
||||
P1_PRIORITY: 100, // Very high priority
|
||||
P2_PRIORITY: 300, // High priority
|
||||
P3_PRIORITY: 500, // Above average
|
||||
P4_PRIORITY: 700, // Standard priority
|
||||
P5_PRIORITY: 900, // Below average
|
||||
P6_PRIORITY: 1100, // Low priority
|
||||
P7_PRIORITY: 1300, // Very low priority
|
||||
P8_PRIORITY: 1500, // Background execution
|
||||
P9_PRIORITY: 1700, // Idle mode execution
|
||||
P10_PRIORITY: 1900 // Lowest priority
|
||||
P0_PRIORITY: 0, // Highest priority (no delay)
|
||||
P1_PRIORITY: 100, // Very high priority
|
||||
P2_PRIORITY: 300, // High priority
|
||||
P3_PRIORITY: 500, // Above average
|
||||
P4_PRIORITY: 700, // Standard priority
|
||||
P5_PRIORITY: 900, // Below average
|
||||
P6_PRIORITY: 1100, // Low priority
|
||||
P7_PRIORITY: 1300, // Very low priority
|
||||
P8_PRIORITY: 1500, // Background execution
|
||||
P9_PRIORITY: 1700, // Idle mode execution
|
||||
P10_PRIORITY: 1900, // Lowest priority
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
'require baseclass';
|
||||
|
||||
export * from './validators';
|
||||
export * from './constants'
|
||||
export * from './constants';
|
||||
|
||||
@@ -2,3 +2,4 @@ export * from './validateIp';
|
||||
export * from './validateDomain';
|
||||
export * from './validateDns';
|
||||
export * from './validateUrl';
|
||||
export * from './validatePath';
|
||||
|
||||
39
fe-app-podkop/src/validators/tests/validatePath.test.js
Normal file
39
fe-app-podkop/src/validators/tests/validatePath.test.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { validatePath } from '../validatePath';
|
||||
|
||||
export const validPaths = [
|
||||
['Single level', '/etc'],
|
||||
['Nested path', '/usr/local/bin'],
|
||||
['With dash', '/var/log/nginx-access'],
|
||||
['With underscore', '/opt/my_app/config'],
|
||||
['With numbers', '/data123/files'],
|
||||
['With dots', '/home/user/.config'],
|
||||
['Deep nested', '/a/b/c/d/e/f/g'],
|
||||
];
|
||||
|
||||
export const invalidPaths = [
|
||||
['Empty string', ''],
|
||||
['Missing starting slash', 'usr/local'],
|
||||
['Only dot', '.'],
|
||||
['Space inside', '/path with space'],
|
||||
['Illegal char', '/path$'],
|
||||
['Backslash not allowed', '\\windows\\path'],
|
||||
['Relative path ./', './relative'],
|
||||
['Relative path ../', '../parent'],
|
||||
];
|
||||
|
||||
describe('validatePath', () => {
|
||||
describe.each(validPaths)('Valid path: %s', (_desc, path) => {
|
||||
it(`returns valid=true for "${path}"`, () => {
|
||||
const res = validatePath(path);
|
||||
expect(res.valid).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(invalidPaths)('Invalid path: %s', (_desc, path) => {
|
||||
it(`returns valid=false for "${path}"`, () => {
|
||||
const res = validatePath(path);
|
||||
expect(res.valid).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
25
fe-app-podkop/src/validators/validatePath.ts
Normal file
25
fe-app-podkop/src/validators/validatePath.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ValidationResult } from './types';
|
||||
|
||||
export function validatePath(value: string): ValidationResult {
|
||||
if (!value) {
|
||||
return {
|
||||
valid: false,
|
||||
message: 'Path cannot be empty',
|
||||
};
|
||||
}
|
||||
|
||||
const pathRegex = /^\/[a-zA-Z0-9_\-/.]+$/;
|
||||
|
||||
if (pathRegex.test(value)) {
|
||||
return {
|
||||
valid: true,
|
||||
message: 'Valid',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
valid: false,
|
||||
message:
|
||||
'Invalid path format. Path must start with "/" and contain valid characters',
|
||||
};
|
||||
}
|
||||
@@ -409,12 +409,18 @@ function createConfigSection(section, map, network) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
o.validate = function (section_id, value) {
|
||||
if (!value || value.length === 0) return true;
|
||||
const pathRegex = /^\/[a-zA-Z0-9_\-\/\.]+$/;
|
||||
if (!pathRegex.test(value)) {
|
||||
return _('Invalid path format. Path must start with "/" and contain valid characters');
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
}
|
||||
return true;
|
||||
|
||||
const validation = main.validatePath(value);
|
||||
|
||||
if (validation.valid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'remote_domain_lists_enabled', _('Remote Domain Lists'), _('Download and use domain lists from remote URLs'));
|
||||
@@ -453,12 +459,18 @@ function createConfigSection(section, map, network) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
o.validate = function (section_id, value) {
|
||||
if (!value || value.length === 0) return true;
|
||||
const pathRegex = /^\/[a-zA-Z0-9_\-\/\.]+$/;
|
||||
if (!pathRegex.test(value)) {
|
||||
return _('Invalid path format. Path must start with "/" and contain valid characters');
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
}
|
||||
return true;
|
||||
|
||||
const validation = main.validatePath(value);
|
||||
|
||||
if (validation.valid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'user_subnet_list_type', _('User Subnet List Type'), _('Select how to add your custom subnets'));
|
||||
|
||||
@@ -59,6 +59,27 @@ function validateUrl(url, protocols = ["http:", "https:"]) {
|
||||
}
|
||||
}
|
||||
|
||||
// src/validators/validatePath.ts
|
||||
function validatePath(value) {
|
||||
if (!value) {
|
||||
return {
|
||||
valid: false,
|
||||
message: "Path cannot be empty"
|
||||
};
|
||||
}
|
||||
const pathRegex = /^\/[a-zA-Z0-9_\-/.]+$/;
|
||||
if (pathRegex.test(value)) {
|
||||
return {
|
||||
valid: true,
|
||||
message: "Valid"
|
||||
};
|
||||
}
|
||||
return {
|
||||
valid: false,
|
||||
message: 'Invalid path format. Path must start with "/" and contain valid characters'
|
||||
};
|
||||
}
|
||||
|
||||
// src/constants.ts
|
||||
var STATUS_COLORS = {
|
||||
SUCCESS: "#4caf50",
|
||||
@@ -67,7 +88,11 @@ var STATUS_COLORS = {
|
||||
};
|
||||
var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi";
|
||||
var IP_CHECK_DOMAIN = "ip.podkop.fyi";
|
||||
var REGIONAL_OPTIONS = ["russia_inside", "russia_outside", "ukraine_inside"];
|
||||
var REGIONAL_OPTIONS = [
|
||||
"russia_inside",
|
||||
"russia_outside",
|
||||
"ukraine_inside"
|
||||
];
|
||||
var ALLOWED_WITH_RUSSIA_INSIDE = [
|
||||
"russia_inside",
|
||||
"meta",
|
||||
@@ -174,5 +199,6 @@ return baseclass.extend({
|
||||
validateDNS,
|
||||
validateDomain,
|
||||
validateIPV4,
|
||||
validatePath,
|
||||
validateUrl
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user