69 lines
3.0 KiB
Bash
69 lines
3.0 KiB
Bash
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
SECTION_JS="$ROOT_DIR/luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/section.js"
|
|
|
|
node - "$SECTION_JS" <<'NODE'
|
|
const fs = require("fs");
|
|
const source = fs.readFileSync(process.argv[2], "utf8");
|
|
|
|
function fail(message) {
|
|
console.error(`FAIL: ${message}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
function requiredIndex(needle, from = 0) {
|
|
const index = source.indexOf(needle, from);
|
|
if (index < 0) fail(`missing source contract: ${needle}`);
|
|
return index;
|
|
}
|
|
|
|
const domains = requiredIndex('key: "domain_suffix"');
|
|
const ips = requiredIndex('const ipConditionOption = addTextConditionField(section, {', domains);
|
|
const builtIns = requiredIndex('const builtInRulesetOption = section.taboption(', ips);
|
|
if (source.slice(domains, ips).includes("dependsOnRoutingAction")) {
|
|
fail("DNS action must keep the Domains field visible");
|
|
}
|
|
if (!source.slice(ips, builtIns).includes("dependsOnRoutingAction(ipConditionOption)")) {
|
|
fail("DNS action must hide the IPs field");
|
|
}
|
|
|
|
const sectionContent = requiredIndex("function createSectionContent(section)");
|
|
const protocol = requiredIndex('"dns_type"', sectionContent);
|
|
const server = requiredIndex('"dns_server"', protocol);
|
|
if (server <= protocol || !source.slice(protocol, server).includes('_("DNS protocol")')) {
|
|
fail("DNS protocol must be rendered before DNS server");
|
|
}
|
|
if (source.slice(server, requiredIndex('"dns_detour_enabled"', server)).includes('placeholder = "1.1.1.1"')) {
|
|
fail("DNS server must not render the 1.1.1.1 placeholder");
|
|
}
|
|
|
|
for (const expected of [
|
|
'_("DNS server used by the resolver")',
|
|
'_("DNS requests through section")',
|
|
'"Add URLs or local paths to .srs / .json lists. Subnets are ignored by default."',
|
|
'"Add URLs or local paths to .lst lists containing domains. IP entries are ignored."',
|
|
]) {
|
|
requiredIndex(expected);
|
|
}
|
|
|
|
const ruleSetOption = requiredIndex("const ruleSetOption = section.taboption(");
|
|
const dnsRuleSetOption = requiredIndex("const dnsRuleSetOption = section.taboption(", ruleSetOption);
|
|
const domainLists = requiredIndex("const domainIpListsOption", dnsRuleSetOption);
|
|
if (!source.slice(ruleSetOption, dnsRuleSetOption).includes("SettingsDynamicList") ||
|
|
!source.slice(ruleSetOption, dnsRuleSetOption).includes("dependsOnRoutingAction(ruleSetOption)") ||
|
|
!source.slice(ruleSetOption, dnsRuleSetOption).includes("ruleSetOption.retain = true")) {
|
|
fail("routing rule sets must keep their retained settings DynamicList");
|
|
}
|
|
if (!source.slice(dnsRuleSetOption, domainLists).includes("form.DynamicList") ||
|
|
!source.slice(dnsRuleSetOption, domainLists).includes('"_dns_rule_set"') ||
|
|
!source.slice(dnsRuleSetOption, domainLists).includes('dnsRuleSetOption.depends("action", "dns")') ||
|
|
!source.slice(dnsRuleSetOption, domainLists).includes("dnsRuleSetOption.retain = true") ||
|
|
!source.slice(dnsRuleSetOption, domainLists).includes("writeDnsRulesetReferences")) {
|
|
fail("DNS rule sets must use a retained classic DynamicList");
|
|
}
|
|
NODE
|
|
|
|
printf 'DNS action UI checks passed\n'
|