Merge branch 'main' into main

This commit is contained in:
areen-c
2024-01-08 14:06:09 +07:00
committed by GitHub
19 changed files with 152 additions and 33 deletions
+5 -4
View File
@@ -5,17 +5,18 @@ RUN ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime
RUN apt-get -y update
RUN apt-get install -y nodejs npm curl wget dnsutils certbot --fix-missing
RUN apt-get install -y unzip
RUN npm i -g n yarn && n 15.11
RUN bash -c "curl -fsSL https://bun.sh/install | bash -s 'bun-v1.0.15'"
RUN node -v
RUN ~/.bun/bin/bun -v
WORKDIR /opt/app
COPY yarn.lock .
COPY bun.lockb .
COPY package.json .
RUN yarn install
RUN ~/.bun/bin/bun install
CMD ["sh", "-c", "cp -r node_modules code; cd code; tail -f /dev/null"]
+3 -1
View File
@@ -6,6 +6,8 @@
"email": "phenax5@gmail.com"
},
"record": {
"URL": "http://www.is-a.dev"
"URL": "http://www.is-a.dev",
"MX": ["mail.is-a.dev"],
"TXT": ["v=spf1 ip4:51.161.54.164 include:mail.is-a.dev ~all"]
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"owner": {
"username": "jirafey",
"email": "jirafey@tuta.io"
},
"record": {
"TXT": "dh=3c80d94ed181b223255b5fbf35f8fda6a402058f"
}
}
@@ -0,0 +1,10 @@
{
"owner": {
"username": "is-a-dev",
"email": "phenax5@gmail.com"
},
"record": {
"TXT": "2c9dfbe7c8"
}
}
@@ -0,0 +1,10 @@
{
"owner": {
"username": "is-a-dev",
"email": "phenax5@gmail.com"
},
"record": {
"TXT": "c551c059fb167540ec0498d9011556"
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"owner": {
"username": "alijafari-gd",
"email": "ali.jafari.sn@gmail.com"
},
"record": {
"URL": "https://alijafari.is-a.dev"
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"owner": {
"username": "aayank13",
"email": "aayank1306@gmail.com"
},
"record": {
"A": [
"217.174.245.249",
"51.161.54.161"
],
"MX": ["mail.is-a.dev"],
"TXT": "v=spf1 mx a:mail.is-a.dev ~all"
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"owner": {
"username": "alijafari-gd",
"email": "ali.jafari.sn@gmail.com"
},
"record": {
"A": [
"217.174.245.249",
"51.161.54.161"
],
"MX": ["mail.is-a.dev"],
"TXT": "v=spf1 mx a:mail.is-a.dev ~all"
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"description": "blek is a dev",
"owner": {
"username": "b1ek",
"email": "me@blek.codes"
},
"record": {
"A": [ "185.130.226.115" ],
"AAAA": [ "2a05:b40:0:570:4563:92af:9a56:7fc8" ]
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"owner": {
"username": "DarindaDraX",
"email": "123kishanvish@gmail.com"
},
"record": {
"A": ["69.30.249.53"]
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"owner": {
"username": "vuthanhtrung2010",
"email": "vuthanhtrungsuper@gmail.com"
},
"record": {
"A": ["69.30.249.53"]
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"owner": {
"username": "Nikhil",
"username": "nikxso",
"email": "nikhilsoniya123@gmail.com",
"discord": "nikxso#0000"
},
+1 -1
View File
@@ -12,7 +12,7 @@
"mail.is-a.dev"
],
"TXT": [
" v=spf1 mx a:mail.is-a.dev ip4:217.174.245.249 ~all"
"v=spf1 mx a:mail.is-a.dev ip4:217.174.245.249 ~all"
]
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
export ENV=production
export NODE_ENV=production
DRY_RUN=0
if_dry_run() { [[ $DRY_RUN == 1 ]] && echo "$1" || echo "$2"; }
@@ -32,7 +32,7 @@ update_record() {
local name="$3";
local address="$4";
local ttl=${5:-"1"};
echo "
bun -e "
const { domainService } = require('./utils/domain-service');
const { ENV, DOMAIN_DOMAIN } = require('./utils/constants');
const method = '$method';
@@ -57,7 +57,7 @@ update_record() {
}
main().catch(console.error);
" | node -
"
}
update_acme_txt_record() {
@@ -68,6 +68,7 @@ reset_acme() {
sleep 1;
update_record remove TXT '_acme-challenge' '';
update_record remove TXT '_acme-challenge' '';
# update_record add CNAME 'www' "is-a-dev.github.io";
}
get_acme() { dig +noall +answer _acme-challenge.is-a.dev TXT | awk '{print $5}'; }
@@ -84,7 +85,6 @@ esac
### STEPS ###
# Run ./scripts/certbot.sh cert
# Run ./scripts/certbot.sh acme_txt "<key>"
# cp -r /tmp/is-a-dev-whatever /opt/app/code/is-a-dev-cert
# Upload cert.pem and privkey.pem (from config/live/is-a.dev/) contents to SSL > Manage SSL Sites
# Run ./scripts/certbot.sh reset
+1 -1
View File
@@ -15,7 +15,7 @@ const toHostList = R.chain(data => {
// URL redirection must contain explicit A record
// Wildcard A record breaks when used with MX
// Ref: https://github.com/is-a-dev/register/issues/2365
if (data.record.URL && data.record.MX) {
if ((data.record.URL && data.record.MX) || data.name === '@') {
data.record.A = [ DOMAIN_HOST_IP ]
}
+2 -2
View File
@@ -12,7 +12,7 @@ describe('Cpanel client', () => {
describe('fetchzonerecords', () => {
it('should make the correct request', async () => {
const fetch = mockFetch((url, request) => {
expect(url).toBe('https://example.com:2000/json-api/cpanel?customonly=1&domain=a.b&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&cpanel_jsonapi_apiversion=2');
expect(url).toBe('https://example.com:2000/json-api/cpanel?customonly=0&domain=a.b&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&cpanel_jsonapi_apiversion=2');
expect(request).toEqual({
headers: {
Authorization: 'cpanel boy:boybyebye',
@@ -35,7 +35,7 @@ describe('Cpanel client', () => {
it('should make the correct request with query', async () => {
const fetch = mockFetch((url, request) => {
expect(url).toBe('https://example.com:2000/json-api/cpanel?customonly=1&domain=foobar.boeey&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&cpanel_jsonapi_apiversion=2');
expect(url).toBe('https://example.com:2000/json-api/cpanel?customonly=0&domain=foobar.boeey&cpanel_jsonapi_user=boy&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&cpanel_jsonapi_apiversion=2');
expect(request).toEqual({
headers: {
Authorization: 'cpanel boy:boybyebye',
+9 -3
View File
@@ -263,8 +263,8 @@ describe('Domain service', () => {
]);
expect(removeZone).toHaveBeenCalledTimes(2);
expect(getRecordCalls(removeZone)).toEqual([
{ line: 2 },
{ line: 3 },
{ line: 2 },
]);
});
@@ -277,6 +277,9 @@ describe('Domain service', () => {
{ line: 5, name: 'c', type: 'MX', address: 'mx1.hello.com', priority: 20 },
{ line: 6, name: 'c', type: 'MX', address: 'mx2.hello.com', priority: 21 },
{ line: 7, name: 'b', type: 'MX', address: 'foo.bar', priority: 20 },
{ line: 101, name: 'x', type: 'A', address: '1' },
{ line: 99, name: 'y', type: 'A', address: '2' },
{ line: 100, name: 'z', type: 'A', address: '3' },
];
const redirections = [
{ domain: `b.${DOMAIN_DOMAIN}`, destination: 'https://foobar.com' },
@@ -306,8 +309,11 @@ describe('Domain service', () => {
{ name: 'b', type: 'A', address: '3' },
{ name: 'd', type: 'CNAME', address: 'helo.com' },
]);
expect(removeZone).toHaveBeenCalledTimes(1);
expect(removeZone).toHaveBeenCalledTimes(4);
expect(getRecordCalls(removeZone)).toEqual([
{ line: 101 },
{ line: 100 },
{ line: 99 },
{ line: 1 },
]);
@@ -317,8 +323,8 @@ describe('Domain service', () => {
]);
expect(removeEmail).toHaveBeenCalledTimes(2);
expect(getRecordCalls(removeEmail)).toEqual([
{ domain: 'c.is-a.dev', exchanger: 'mx1.hello.com', priority: 20 },
{ domain: 'b.is-a.dev', exchanger: 'foo.bar', priority: 20 },
{ domain: 'c.is-a.dev', exchanger: 'mx1.hello.com', priority: 20 },
]);
expect(addRedir).toHaveBeenCalledTimes(3);
+30 -15
View File
@@ -1,6 +1,6 @@
const R = require('ramda');
const { cpanel } = require('./lib/cpanel');
const { DOMAIN_DOMAIN } = require('./constants');
const { DOMAIN_DOMAIN, VALID_RECORD_TYPES } = require('./constants');
const { then, log, print, lazyTask, batchLazyTasks } = require('./helpers');
const BATCH_SIZE = 1;
@@ -23,7 +23,7 @@ const recordToZone = ({ name, type, address, id, priority }) => ({
});
const cleanName = name =>
name === DOMAIN_DOMAIN ? '@' : `${name}`.replace(new RegExp(`\\.${DOMAIN_DOMAIN}\\.?$`), '').toLowerCase();
[DOMAIN_DOMAIN, `${DOMAIN_DOMAIN}.`].includes(name) ? '@' : `${name}`.replace(new RegExp(`\\.${DOMAIN_DOMAIN}\\.?$`), '').toLowerCase();
const zoneToRecord = ({
name,
@@ -63,8 +63,7 @@ const diffRecords = (oldRecords, newRecords) => {
const isMatchingRecord = (a, b) => getHostKey(a) === getHostKey(b);
const remove = R.differenceWith(isMatchingRecord, oldRecords, newRecords);
const add = R.differenceWith(isMatchingRecord, newRecords, oldRecords)
.filter(r => !['www'].includes(r.name));
const add = R.differenceWith(isMatchingRecord, newRecords, oldRecords);
return { add, remove };
};
@@ -85,9 +84,20 @@ const executeBatch = (batches) => batches.reduce((promise, batch, index) => {
});
}, Promise.resolve());
const isReserved = (domain) =>
domain.name.startsWith('*') ||
!VALID_RECORD_TYPES.includes(domain.type)
const getDomainService = ({ cpanel }) => {
const fetchZoneRecords = R.compose(then(R.map(zoneToRecord)), cpanel.zone.fetch);
const fetchRedirections = R.compose(then(R.map(redirectionToRecord)), cpanel.redirection.fetch);
const fetchZoneRecords = R.compose(
then(R.filter(R.complement(isReserved))),
then(R.map(zoneToRecord)),
cpanel.zone.fetch
);
const fetchRedirections = R.compose(
then(R.map(redirectionToRecord)),
cpanel.redirection.fetch
);
const addZoneRecord = lazyTask(R.compose(
R.ifElse(R.propEq('type', 'MX'),
@@ -120,15 +130,20 @@ const getDomainService = ({ cpanel }) => {
const getHosts = () =>
Promise.all([fetchZoneRecords(), fetchRedirections()]).then(R.flatten);
const addRecords = R.compose(batchLazyTasks(BATCH_SIZE), R.filter(Boolean), R.map(R.cond([
[R.propEq('name', 'www'), R.always(null)], // Ignore www
[R.propEq('type', 'URL'), addRedirection],
[R.T, addZoneRecord],
])));
const removeRecords = R.compose(batchLazyTasks(BATCH_SIZE), R.map(R.cond([
[R.propEq('type', 'URL'), removeRedirection],
[R.T, removeZoneRecord],
])));
const addRecords = R.compose(
batchLazyTasks(BATCH_SIZE),
R.filter(Boolean),
R.map(R.cond([
// [R.propEq('name', 'www'), R.always(null)], // Ignore www
[R.propEq('type', 'URL'), addRedirection],
[R.T, addZoneRecord],
])),
);
const removeRecords = R.compose(
batchLazyTasks(BATCH_SIZE),
R.map(R.cond([ [ R.propEq('type', 'URL'), removeRedirection ], [ R.T, removeZoneRecord ] ])),
R.sort((a, b) => b.id - a.id)
);
const updateHosts = async hosts => {
const remoteHostList = await getHosts();
+1 -1
View File
@@ -37,7 +37,7 @@ const CpanelClient = (options) => {
// -> [{ class, ttl, name, line, Line, cname, type, record }]
fetch: R.compose(
p => p.then(R.pathOr([], ['cpanelresult', 'data'])),
api2('ZoneEdit', 'fetchzone_records', { customonly: 1, domain: options.domain })
api2('ZoneEdit', 'fetchzone_records', { customonly: 0, domain: options.domain })
),
// { name, type(A|CNAME), cname, address, ttl }