mirror of
https://github.com/tiennm99/is-a-dev.git
synced 2026-08-21 00:24:54 +00:00
prettier + move some stuff
This commit is contained in:
@@ -12,10 +12,7 @@ t("Nested subdomains should not exist without a parent subdomain", (t) => {
|
||||
if (subdomain.split(".").length > 1) {
|
||||
const parentSubdomain = subdomain.split(".").pop();
|
||||
|
||||
t.true(
|
||||
files.includes(`${parentSubdomain}.json`),
|
||||
`${file}: Parent subdomain does not exist`
|
||||
);
|
||||
t.true(files.includes(`${parentSubdomain}.json`), `${file}: Parent subdomain does not exist`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+9
-18
@@ -4,25 +4,24 @@ const path = require("path");
|
||||
|
||||
const requiredFields = {
|
||||
owner: "object",
|
||||
record: "object",
|
||||
record: "object"
|
||||
};
|
||||
|
||||
const optionalFields = {
|
||||
proxied: "boolean",
|
||||
reserved: "boolean",
|
||||
reserved: "boolean"
|
||||
};
|
||||
|
||||
const requiredOwnerFields = {
|
||||
username: "string",
|
||||
username: "string"
|
||||
};
|
||||
|
||||
const optionalOwnerFields = {
|
||||
email: "string",
|
||||
email: "string"
|
||||
};
|
||||
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
const hostnameRegex =
|
||||
/^(?=.{1,253}$)(?:(?:[_a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)\.)+[a-zA-Z]{2,63}$/;
|
||||
const hostnameRegex = /^(?=.{1,253}$)(?:(?:[_a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)\.)+[a-zA-Z]{2,63}$/;
|
||||
|
||||
const domainsPath = path.resolve("domains");
|
||||
const files = fs.readdirSync(domainsPath);
|
||||
@@ -30,13 +29,9 @@ const files = fs.readdirSync(domainsPath);
|
||||
function validateRequiredFields(t, obj, requiredFields, file) {
|
||||
Object.keys(requiredFields).forEach((key) => {
|
||||
t.true(obj.hasOwnProperty(key), `${file}: Missing required field: ${key}`);
|
||||
t.is(
|
||||
typeof obj[key],
|
||||
requiredFields[key],
|
||||
`${file}: Field ${key} should be of type ${requiredFields[key]}`
|
||||
);
|
||||
t.is(typeof obj[key], requiredFields[key], `${file}: Field ${key} should be of type ${requiredFields[key]}`);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function validateOptionalFields(t, obj, optionalFields, file) {
|
||||
Object.keys(optionalFields).forEach((key) => {
|
||||
@@ -48,7 +43,7 @@ function validateOptionalFields(t, obj, optionalFields, file) {
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
t("All files should be valid JSON", (t) => {
|
||||
files.forEach((file) => {
|
||||
@@ -94,11 +89,7 @@ t("All files should have valid optional fields", (t) => {
|
||||
validateOptionalFields(t, data.owner, optionalOwnerFields, file);
|
||||
|
||||
if (data.owner.email) {
|
||||
t.regex(
|
||||
data.owner.email,
|
||||
emailRegex,
|
||||
`${file}: Owner email should be a valid email address`
|
||||
);
|
||||
t.regex(data.owner.email, emailRegex, `${file}: Owner email should be a valid email address`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+4
-7
@@ -2,11 +2,8 @@ const t = require("ava");
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
|
||||
const requiredRecordsToProxy = [
|
||||
"A",
|
||||
"AAAA",
|
||||
"CNAME"
|
||||
];
|
||||
const requiredRecordsToProxy = ["A", "AAAA", "CNAME"];
|
||||
// URL records are not listed here because they are proxied by default, so they don't need the proxied flag
|
||||
|
||||
function validateProxiedRecords(t, data, file) {
|
||||
if (data.proxied) {
|
||||
@@ -14,7 +11,7 @@ function validateProxiedRecords(t, data, file) {
|
||||
|
||||
t.true(hasProxiedRecord, `${file}: Proxied is true but there are no records that can be proxied`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const domainsPath = path.resolve("domains");
|
||||
const files = fs.readdirSync(domainsPath);
|
||||
@@ -24,5 +21,5 @@ t("Domains with proxy enabled should have have at least one record that can be p
|
||||
const domain = fs.readJsonSync(path.join(domainsPath, file));
|
||||
|
||||
validateProxiedRecords(t, domain, file);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,6 +14,80 @@ const ipv6Regex =
|
||||
const domainsPath = path.resolve("domains");
|
||||
const files = fs.readdirSync(domainsPath);
|
||||
|
||||
function expandIPv6(ip) {
|
||||
// Split into segments by ":"
|
||||
let segments = ip.split(":");
|
||||
|
||||
// Count the number of segments that are empty due to "::" shorthand
|
||||
const emptyIndex = segments.indexOf("");
|
||||
if (emptyIndex !== -1) {
|
||||
// Calculate how many "0000" segments are missing
|
||||
const nonEmptySegments = segments.filter((seg) => seg !== "");
|
||||
const missingSegments = 8 - nonEmptySegments.length;
|
||||
|
||||
// Insert the missing "0000" segments into the position of the empty segment
|
||||
segments = [
|
||||
...nonEmptySegments.slice(0, emptyIndex),
|
||||
...Array(missingSegments).fill("0000"),
|
||||
...nonEmptySegments.slice(emptyIndex)
|
||||
];
|
||||
}
|
||||
|
||||
// Expand each segment to 4 characters, padding with leading zeros
|
||||
const expandedSegments = segments.map((segment) => segment.padStart(4, "0"));
|
||||
|
||||
// Join the segments back together
|
||||
return expandedSegments.join(":");
|
||||
}
|
||||
|
||||
function isPublicIPv4(ip, proxied) {
|
||||
const parts = ip.split(".").map(Number);
|
||||
|
||||
// Validate IPv4 address format
|
||||
if (parts.length !== 4 || parts.some((part) => isNaN(part) || part < 0 || part > 255)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exception for 192.0.2.1, assuming the domain is proxied
|
||||
if (ip === "192.0.2.1" && proxied) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for private and reserved IPv4 ranges
|
||||
return !(
|
||||
// Private ranges
|
||||
(
|
||||
parts[0] === 10 ||
|
||||
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||
|
||||
(parts[0] === 192 && parts[1] === 168) ||
|
||||
// Reserved or special-use ranges
|
||||
(parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127) || // Carrier-grade NAT
|
||||
(parts[0] === 169 && parts[1] === 254) || // Link-local
|
||||
(parts[0] === 192 && parts[1] === 0 && parts[2] === 0) || // IETF Protocol Assignments
|
||||
(parts[0] === 192 && parts[1] === 0 && parts[2] === 2) || // Documentation (TEST-NET-1)
|
||||
(parts[0] === 198 && parts[1] === 18) || // Network Interconnect Devices
|
||||
(parts[0] === 198 && parts[1] === 51 && parts[2] === 100) || // Documentation (TEST-NET-2)
|
||||
(parts[0] === 203 && parts[1] === 0 && parts[2] === 113) || // Documentation (TEST-NET-3)
|
||||
parts[0] >= 224
|
||||
) // Multicast and reserved ranges
|
||||
);
|
||||
}
|
||||
|
||||
function isPublicIPv6(ip) {
|
||||
const normalizedIP = ip.toLowerCase();
|
||||
|
||||
// Check for private or special-use IPv6 ranges
|
||||
return !(
|
||||
(
|
||||
normalizedIP.startsWith("fc") || // Unique Local Address (ULA)
|
||||
normalizedIP.startsWith("fd") || // Unique Local Address (ULA)
|
||||
normalizedIP.startsWith("fe80") || // Link-local
|
||||
normalizedIP.startsWith("::1") || // Loopback address (::1)
|
||||
normalizedIP.startsWith("2001:db8")
|
||||
) // Documentation range
|
||||
);
|
||||
}
|
||||
|
||||
t("All files should have valid record types", (t) => {
|
||||
files.forEach((file) => {
|
||||
const data = fs.readJsonSync(path.join(domainsPath, file));
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
module.exports.expandIPv6 = function (ip) {
|
||||
// Split into segments by ":"
|
||||
let segments = ip.split(":");
|
||||
|
||||
// Count the number of segments that are empty due to "::" shorthand
|
||||
const emptyIndex = segments.indexOf("");
|
||||
if (emptyIndex !== -1) {
|
||||
// Calculate how many "0000" segments are missing
|
||||
const nonEmptySegments = segments.filter((seg) => seg !== "");
|
||||
const missingSegments = 8 - nonEmptySegments.length;
|
||||
|
||||
// Insert the missing "0000" segments into the position of the empty segment
|
||||
segments = [...nonEmptySegments.slice(0, emptyIndex), ...Array(missingSegments).fill("0000"), ...nonEmptySegments.slice(emptyIndex)];
|
||||
}
|
||||
|
||||
// Expand each segment to 4 characters, padding with leading zeros
|
||||
const expandedSegments = segments.map((segment) => segment.padStart(4, "0"));
|
||||
|
||||
// Join the segments back together
|
||||
return expandedSegments.join(":");
|
||||
};
|
||||
|
||||
module.exports.isPublicIPv4 = function (ip, proxied) {
|
||||
const parts = ip.split('.').map(Number);
|
||||
|
||||
// Validate IPv4 address format
|
||||
if (parts.length !== 4 || parts.some(part => isNaN(part) || part < 0 || part > 255)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exception for 192.0.2.1, assuming the domain is proxied
|
||||
if (ip === "192.0.2.1" && proxied) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for private and reserved IPv4 ranges
|
||||
return !(
|
||||
// Private ranges
|
||||
parts[0] === 10 ||
|
||||
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||
|
||||
(parts[0] === 192 && parts[1] === 168) ||
|
||||
|
||||
// Reserved or special-use ranges
|
||||
(parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127) || // Carrier-grade NAT
|
||||
(parts[0] === 169 && parts[1] === 254) || // Link-local
|
||||
(parts[0] === 192 && parts[1] === 0 && parts[2] === 0) || // IETF Protocol Assignments
|
||||
(parts[0] === 192 && parts[1] === 0 && parts[2] === 2) || // Documentation (TEST-NET-1)
|
||||
(parts[0] === 198 && parts[1] === 18) || // Network Interconnect Devices
|
||||
(parts[0] === 198 && parts[1] === 51 && parts[2] === 100) || // Documentation (TEST-NET-2)
|
||||
(parts[0] === 203 && parts[1] === 0 && parts[2] === 113) || // Documentation (TEST-NET-3)
|
||||
(parts[0] >= 224) // Multicast and reserved ranges
|
||||
);
|
||||
};
|
||||
|
||||
module.exports.isPublicIPv6 = function (ip) {
|
||||
const normalizedIP = ip.toLowerCase();
|
||||
|
||||
// Check for private or special-use IPv6 ranges
|
||||
return !(
|
||||
normalizedIP.startsWith("fc") || // Unique Local Address (ULA)
|
||||
normalizedIP.startsWith("fd") || // Unique Local Address (ULA)
|
||||
normalizedIP.startsWith("fe80") || // Link-local
|
||||
normalizedIP.startsWith("::1") || // Loopback address (::1)
|
||||
normalizedIP.startsWith("2001:db8") // Documentation range
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user