mirror of
https://github.com/tiennm99/is-a-dev.git
synced 2026-10-13 10:15:47 +00:00
support new services key
This commit is contained in:
1 parent
d792791995
commit
229d821881
8 files changed
+148
-31
No files matched your search
@@ -133,6 +133,19 @@ for (var subdomain in domains) {
|
||||
if (data.records.URL) {
|
||||
records.push(A(subdomainName, IP("192.0.2.1"), CF_PROXY_ON));
|
||||
}
|
||||
|
||||
// Manage service records
|
||||
|
||||
// Discord TXT verification
|
||||
if (data.services.discord) {
|
||||
if (Array.isArray(data.services.discord)) {
|
||||
for (var txt in data.services.discord) {
|
||||
records.push(TXT("_discord." + subdomainName, data.services.discord[txt]));
|
||||
}
|
||||
} else {
|
||||
records.push(TXT("_discord." + subdomainName, data.services.discord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var reserved = require("./util/reserved.json");
|
||||
|
||||
@@ -11,5 +11,8 @@
|
||||
"/github": "https://github.com/wdhdev"
|
||||
},
|
||||
"redirect_paths": true
|
||||
},
|
||||
"services": {
|
||||
"discord": "dh=4e444050c7f0e742327d027ebdf50a39f1203acd"
|
||||
}
|
||||
}
|
||||
@@ -105,3 +105,16 @@ t("Users are limited to one single character subdomain", (t) => {
|
||||
|
||||
t.pass();
|
||||
});
|
||||
|
||||
t("Disallow nested subdomains when parent has specific service records", (t) => {
|
||||
files.forEach((file) => {
|
||||
const subdomain = file.replace(/\.json$/, "");
|
||||
const data = getDomainData(subdomain);
|
||||
|
||||
if(data?.services?.discord) {
|
||||
t.false(files.includes(`_discord.${file}`), `${file}: Nested subdomain "_discord.${subdomain}" should not exist when services.discord is present`);
|
||||
}
|
||||
});
|
||||
|
||||
t.pass();
|
||||
});
|
||||
+13
-11
@@ -11,7 +11,8 @@ const requiredFields = {
|
||||
|
||||
const optionalFields = {
|
||||
proxied: "boolean",
|
||||
redirect_config: "object"
|
||||
redirect_config: "object",
|
||||
services: "object"
|
||||
};
|
||||
|
||||
const requiredOwnerFields = {
|
||||
@@ -27,12 +28,7 @@ const optionalRedirectConfigFields = {
|
||||
redirect_paths: "boolean"
|
||||
};
|
||||
|
||||
const blockedFields = [
|
||||
"domain",
|
||||
"internal",
|
||||
"reserved",
|
||||
"subdomain"
|
||||
];
|
||||
const blockedFields = ["domain", "internal", "reserved", "subdomain"];
|
||||
|
||||
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}$/;
|
||||
@@ -117,10 +113,7 @@ async function validateFileName(t, file) {
|
||||
!internalDomains.some((i) => subdomain.endsWith(`.${i}`)),
|
||||
`${file}: Subdomain name is registered internally`
|
||||
);
|
||||
t.true(
|
||||
!reservedDomains.some((r) => subdomain.endsWith(`.${r}`)),
|
||||
`${file}: Subdomain name is reserved`
|
||||
);
|
||||
t.true(!reservedDomains.some((r) => subdomain.endsWith(`.${r}`)), `${file}: Subdomain name is reserved`);
|
||||
|
||||
const rootSubdomain = subdomain.split(".").pop();
|
||||
t.false(rootSubdomain.startsWith("_"), `${file}: Root subdomains should not start with an underscore`);
|
||||
@@ -157,6 +150,15 @@ async function processFile(file, t) {
|
||||
validateFields(t, data.redirect_config, optionalRedirectConfigFields, file, "redirect_config");
|
||||
}
|
||||
|
||||
if (data.services) {
|
||||
if (data.services.discord) {
|
||||
t.true(
|
||||
Array.isArray(data.services.discord) || typeof data.services.discord === "string",
|
||||
`${file}: Discord service should be an array or string`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const field of blockedFields) {
|
||||
t.true(!data.hasOwnProperty(field), `${file}: Disallowed field: ${field}`);
|
||||
}
|
||||
|
||||
+27
-10
@@ -3,7 +3,10 @@ const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
|
||||
const requiredEnvVars = ["PR_AUTHOR", "PR_AUTHOR_ID"];
|
||||
const trustedUsers = require("../util/trusted.json").map((u) => u.id.toString());
|
||||
const trustedUsers = require("../util/trusted.json");
|
||||
|
||||
const trusted = trustedUsers.map((u) => u.id.toString());
|
||||
const admins = trustedUsers.filter((u) => u.admin).map((u) => u.id.toString());
|
||||
|
||||
function getDomainData(subdomain) {
|
||||
try {
|
||||
@@ -28,17 +31,24 @@ t("Users can only update their own subdomains", (t) => {
|
||||
.filter((file) => file.name.startsWith("domains/"))
|
||||
.map((file) => path.basename(file.name));
|
||||
|
||||
if ((!changedJSONFiles && !deletedFiles) || trustedUsers.includes(prAuthorId)) return t.pass();
|
||||
if (!changedJSONFiles && !deletedFiles) return t.pass();
|
||||
if (process.env.PR_LABELS && process.env.PR_LABELS.includes("ci: bypass-owner-check")) return t.pass();
|
||||
|
||||
changedJSONFiles.forEach((file) => {
|
||||
const subdomain = file.replace(/\.json$/, "");
|
||||
const data = getDomainData(subdomain);
|
||||
|
||||
t.true(
|
||||
data.owner.username.toLowerCase() === prAuthor,
|
||||
`${subdomain}: ${prAuthor} is not authorized to update ${subdomain}.is-a.dev`
|
||||
);
|
||||
if (data.owner.username === "is-a-dev") {
|
||||
t.true(
|
||||
admins.includes(prAuthorId),
|
||||
`${subdomain}: ${prAuthor} is not authorized to update ${subdomain}.is-a.dev`
|
||||
);
|
||||
} else {
|
||||
t.true(
|
||||
data.owner.username.toLowerCase() === prAuthor || trusted.includes(prAuthorId),
|
||||
`${file}: ${prAuthor} is not authorized to update ${subdomain}.is-a.dev`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
deletedJSONFiles.forEach((file) => {
|
||||
@@ -52,10 +62,17 @@ t("Users can only update their own subdomains", (t) => {
|
||||
.join("\n")
|
||||
);
|
||||
|
||||
t.true(
|
||||
data.owner.username.toLowerCase() === prAuthor,
|
||||
`${file}: ${prAuthor} is not authorized to delete ${subdomain}.is-a.dev`
|
||||
);
|
||||
if (data.owner.username === "is-a-dev") {
|
||||
t.true(
|
||||
admins.includes(prAuthorId),
|
||||
`${subdomain}: ${prAuthor} is not authorized to delete ${subdomain}.is-a.dev`
|
||||
);
|
||||
} else {
|
||||
t.true(
|
||||
data.owner.username.toLowerCase() === prAuthor || trusted.includes(prAuthorId),
|
||||
`${file}: ${prAuthor} is not authorized to delete ${subdomain}.is-a.dev`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+24
-1
@@ -268,7 +268,7 @@ function validateRecordValues(t, data, file) {
|
||||
}
|
||||
}
|
||||
|
||||
t("All files should have valid record types", (t) => {
|
||||
t("All files should have valid records", (t) => {
|
||||
files.forEach((file) => {
|
||||
const data = getDomainData(file);
|
||||
const recordKeys = Object.keys(data.records);
|
||||
@@ -328,3 +328,26 @@ t("Root subdomains should have at least one usable record", (t) => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
t("All files should have valid service records", (t) => {
|
||||
files.forEach((file) => {
|
||||
const data = getDomainData(file);
|
||||
|
||||
if (data?.services?.discord) {
|
||||
const discord = Array.isArray(data.services.discord) ? data.services.discord : [data.services.discord];
|
||||
|
||||
discord.forEach((value) => {
|
||||
const token = value.split("=")[1];
|
||||
|
||||
t.true(value.startsWith("dh="), `${file}: Discord service record should start with "dh="`);
|
||||
t.true(token.length === 40, `${file}: Discord service token should be 40 characters long`);
|
||||
t.true(
|
||||
isValidHexadecimal(token),
|
||||
`${file}: Discord service token should be a valid hexadecimal string`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
t.pass();
|
||||
});
|
||||
@@ -110,6 +110,32 @@ fs.readdir(directoryPath, function (err, files) {
|
||||
v1.push(itemV1);
|
||||
v2.push(itemV2);
|
||||
|
||||
if (item.services) {
|
||||
if (item.services.discord) {
|
||||
const discord = Array.isArray(item.services.discord)
|
||||
? item.services.discord
|
||||
: [item.services.discord];
|
||||
|
||||
v1.push({
|
||||
domain: `_discord.${item.domain}`,
|
||||
subdomain: `_discord.${item.subdomain}`,
|
||||
owner: item.owner,
|
||||
record: {
|
||||
TXT: discord
|
||||
}
|
||||
});
|
||||
|
||||
v2.push({
|
||||
domain: `_discord.${item.domain}`,
|
||||
subdomain: `_discord.${item.subdomain}`,
|
||||
owner: item.owner,
|
||||
records: {
|
||||
TXT: discord
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
if (processedCount === files.length) {
|
||||
fs.writeFile("raw-api/index.json", JSON.stringify(v1), (err) => {
|
||||
|
||||
+29
-9
@@ -1,11 +1,31 @@
|
||||
[
|
||||
{ "username": "21Z", "id": 69188068 },
|
||||
{ "username": "DEV-DIBSTER", "id": 76603072 },
|
||||
{ "username": "iostpa", "id": 69630113 },
|
||||
{ "username": "is-a-dev-bot", "id": 106927495 },
|
||||
{ "username": "orangci", "id": 90866414 },
|
||||
{ "username": "Stef-00012", "id": 81536172 },
|
||||
{ "username": "SX-9", "id": 90962949 },
|
||||
{ "username": "WDH-2", "id": 115670568 },
|
||||
{ "username": "wdhdev", "id": 87287585 }
|
||||
{
|
||||
"username": "21Z",
|
||||
"id": 69188068
|
||||
},
|
||||
{
|
||||
"username": "DEV-DIBSTER",
|
||||
"id": 76603072
|
||||
},
|
||||
{
|
||||
"username": "iostpa",
|
||||
"id": 69630113
|
||||
},
|
||||
{
|
||||
"username": "orangci",
|
||||
"id": 90866414
|
||||
},
|
||||
{
|
||||
"username": "Stef-00012",
|
||||
"id": 81536172
|
||||
},
|
||||
{
|
||||
"username": "SX-9",
|
||||
"id": 90962949
|
||||
},
|
||||
{
|
||||
"username": "wdhdev",
|
||||
"id": 87287585,
|
||||
"admin": true
|
||||
}
|
||||
]
|
||||
Reference in new issue
Block a user