mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-09 04:56:51 +03:00
feat: migrate validatePath to modular
This commit is contained in:
@@ -1,70 +1,76 @@
|
|||||||
export const STATUS_COLORS = {
|
export const STATUS_COLORS = {
|
||||||
SUCCESS: '#4caf50',
|
SUCCESS: '#4caf50',
|
||||||
ERROR: '#f44336',
|
ERROR: '#f44336',
|
||||||
WARNING: '#ff9800'
|
WARNING: '#ff9800',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi';
|
export const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi';
|
||||||
export const IP_CHECK_DOMAIN = 'ip.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 = [
|
export const ALLOWED_WITH_RUSSIA_INSIDE = [
|
||||||
'russia_inside',
|
'russia_inside',
|
||||||
'meta',
|
'meta',
|
||||||
'twitter',
|
'twitter',
|
||||||
'discord',
|
'discord',
|
||||||
'telegram',
|
'telegram',
|
||||||
'cloudflare',
|
'cloudflare',
|
||||||
'google_ai',
|
'google_ai',
|
||||||
'google_play',
|
'google_play',
|
||||||
'hetzner',
|
'hetzner',
|
||||||
'ovh',
|
'ovh',
|
||||||
'hodca',
|
'hodca',
|
||||||
'digitalocean',
|
'digitalocean',
|
||||||
'cloudfront'
|
'cloudfront',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DOMAIN_LIST_OPTIONS = {
|
export const DOMAIN_LIST_OPTIONS = {
|
||||||
russia_inside: 'Russia inside',
|
russia_inside: 'Russia inside',
|
||||||
russia_outside: 'Russia outside',
|
russia_outside: 'Russia outside',
|
||||||
ukraine_inside: 'Ukraine',
|
ukraine_inside: 'Ukraine',
|
||||||
geoblock: 'Geo Block',
|
geoblock: 'Geo Block',
|
||||||
block: 'Block',
|
block: 'Block',
|
||||||
porn: 'Porn',
|
porn: 'Porn',
|
||||||
news: 'News',
|
news: 'News',
|
||||||
anime: 'Anime',
|
anime: 'Anime',
|
||||||
youtube: 'Youtube',
|
youtube: 'Youtube',
|
||||||
discord: 'Discord',
|
discord: 'Discord',
|
||||||
meta: 'Meta',
|
meta: 'Meta',
|
||||||
twitter: 'Twitter (X)',
|
twitter: 'Twitter (X)',
|
||||||
hdrezka: 'HDRezka',
|
hdrezka: 'HDRezka',
|
||||||
tiktok: 'Tik-Tok',
|
tiktok: 'Tik-Tok',
|
||||||
telegram: 'Telegram',
|
telegram: 'Telegram',
|
||||||
cloudflare: 'Cloudflare',
|
cloudflare: 'Cloudflare',
|
||||||
google_ai: 'Google AI',
|
google_ai: 'Google AI',
|
||||||
google_play: 'Google Play',
|
google_play: 'Google Play',
|
||||||
hodca: 'H.O.D.C.A',
|
hodca: 'H.O.D.C.A',
|
||||||
hetzner: 'Hetzner ASN',
|
hetzner: 'Hetzner ASN',
|
||||||
ovh: 'OVH ASN',
|
ovh: 'OVH ASN',
|
||||||
digitalocean: 'Digital Ocean ASN',
|
digitalocean: 'Digital Ocean ASN',
|
||||||
cloudfront: 'CloudFront ASN'
|
cloudfront: 'CloudFront ASN',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UPDATE_INTERVAL_OPTIONS = {
|
export const UPDATE_INTERVAL_OPTIONS = {
|
||||||
'1h': 'Every hour',
|
'1h': 'Every hour',
|
||||||
'3h': 'Every 3 hours',
|
'3h': 'Every 3 hours',
|
||||||
'12h': 'Every 12 hours',
|
'12h': 'Every 12 hours',
|
||||||
'1d': 'Every day',
|
'1d': 'Every day',
|
||||||
'3d': 'Every 3 days'
|
'3d': 'Every 3 days',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DNS_SERVER_OPTIONS = {
|
export const DNS_SERVER_OPTIONS = {
|
||||||
'1.1.1.1': '1.1.1.1 (Cloudflare)',
|
'1.1.1.1': '1.1.1.1 (Cloudflare)',
|
||||||
'8.8.8.8': '8.8.8.8 (Google)',
|
'8.8.8.8': '8.8.8.8 (Google)',
|
||||||
'9.9.9.9': '9.9.9.9 (Quad9)',
|
'9.9.9.9': '9.9.9.9 (Quad9)',
|
||||||
'dns.adguard-dns.com': 'dns.adguard-dns.com (AdGuard Default)',
|
'dns.adguard-dns.com': 'dns.adguard-dns.com (AdGuard Default)',
|
||||||
'unfiltered.adguard-dns.com': 'unfiltered.adguard-dns.com (AdGuard Unfiltered)',
|
'unfiltered.adguard-dns.com':
|
||||||
'family.adguard-dns.com': 'family.adguard-dns.com (AdGuard Family)'
|
'unfiltered.adguard-dns.com (AdGuard Unfiltered)',
|
||||||
|
'family.adguard-dns.com': 'family.adguard-dns.com (AdGuard Family)',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DIAGNOSTICS_UPDATE_INTERVAL = 10000; // 10 seconds
|
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)
|
// Command scheduling intervals in diagnostics (in milliseconds)
|
||||||
export const COMMAND_SCHEDULING = {
|
export const COMMAND_SCHEDULING = {
|
||||||
P0_PRIORITY: 0, // Highest priority (no delay)
|
P0_PRIORITY: 0, // Highest priority (no delay)
|
||||||
P1_PRIORITY: 100, // Very high priority
|
P1_PRIORITY: 100, // Very high priority
|
||||||
P2_PRIORITY: 300, // High priority
|
P2_PRIORITY: 300, // High priority
|
||||||
P3_PRIORITY: 500, // Above average
|
P3_PRIORITY: 500, // Above average
|
||||||
P4_PRIORITY: 700, // Standard priority
|
P4_PRIORITY: 700, // Standard priority
|
||||||
P5_PRIORITY: 900, // Below average
|
P5_PRIORITY: 900, // Below average
|
||||||
P6_PRIORITY: 1100, // Low priority
|
P6_PRIORITY: 1100, // Low priority
|
||||||
P7_PRIORITY: 1300, // Very low priority
|
P7_PRIORITY: 1300, // Very low priority
|
||||||
P8_PRIORITY: 1500, // Background execution
|
P8_PRIORITY: 1500, // Background execution
|
||||||
P9_PRIORITY: 1700, // Idle mode execution
|
P9_PRIORITY: 1700, // Idle mode execution
|
||||||
P10_PRIORITY: 1900 // Lowest priority
|
P10_PRIORITY: 1900, // Lowest priority
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
'require baseclass';
|
'require baseclass';
|
||||||
|
|
||||||
export * from './validators';
|
export * from './validators';
|
||||||
export * from './constants'
|
export * from './constants';
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ export * from './validateIp';
|
|||||||
export * from './validateDomain';
|
export * from './validateDomain';
|
||||||
export * from './validateDns';
|
export * from './validateDns';
|
||||||
export * from './validateUrl';
|
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.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
if (!value || value.length === 0) return true;
|
// Optional
|
||||||
const pathRegex = /^\/[a-zA-Z0-9_\-\/\.]+$/;
|
if (!value || value.length === 0) {
|
||||||
if (!pathRegex.test(value)) {
|
return true
|
||||||
return _('Invalid path format. Path must start with "/" and contain valid characters');
|
|
||||||
}
|
}
|
||||||
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'));
|
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.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
if (!value || value.length === 0) return true;
|
// Optional
|
||||||
const pathRegex = /^\/[a-zA-Z0-9_\-\/\.]+$/;
|
if (!value || value.length === 0) {
|
||||||
if (!pathRegex.test(value)) {
|
return true
|
||||||
return _('Invalid path format. Path must start with "/" and contain valid characters');
|
|
||||||
}
|
}
|
||||||
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'));
|
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
|
// src/constants.ts
|
||||||
var STATUS_COLORS = {
|
var STATUS_COLORS = {
|
||||||
SUCCESS: "#4caf50",
|
SUCCESS: "#4caf50",
|
||||||
@@ -67,7 +88,11 @@ var STATUS_COLORS = {
|
|||||||
};
|
};
|
||||||
var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi";
|
var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi";
|
||||||
var IP_CHECK_DOMAIN = "ip.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 = [
|
var ALLOWED_WITH_RUSSIA_INSIDE = [
|
||||||
"russia_inside",
|
"russia_inside",
|
||||||
"meta",
|
"meta",
|
||||||
@@ -174,5 +199,6 @@ return baseclass.extend({
|
|||||||
validateDNS,
|
validateDNS,
|
||||||
validateDomain,
|
validateDomain,
|
||||||
validateIPV4,
|
validateIPV4,
|
||||||
|
validatePath,
|
||||||
validateUrl
|
validateUrl
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user