porkbun: cleanup implementation
This commit is contained in:
@@ -29,6 +29,7 @@ function injectPrivateFields(newConfig, currentConfig) {
|
||||
// in-place injection of tokens and api keys which came in with constants.SECRET_PLACEHOLDER
|
||||
}
|
||||
|
||||
// replaces any existing records or creates new records of subdomain+type with values
|
||||
async function upsert(domainObject, subdomain, type, values) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof subdomain, 'string');
|
||||
@@ -40,6 +41,7 @@ async function upsert(domainObject, subdomain, type, values) {
|
||||
throw new BoxError(BoxError.NOT_IMPLEMENTED, 'upsert is not implemented');
|
||||
}
|
||||
|
||||
// NOTE: returns empty array when there are no records
|
||||
async function get(domainObject, subdomain, type) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof subdomain, 'string');
|
||||
@@ -50,6 +52,7 @@ async function get(domainObject, subdomain, type) {
|
||||
throw new BoxError(BoxError.NOT_IMPLEMENTED, 'get is not implemented');
|
||||
}
|
||||
|
||||
// must only delete records that match values
|
||||
async function del(domainObject, subdomain, type, values) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof subdomain, 'string');
|
||||
|
||||
+102
-68
@@ -35,66 +35,11 @@ function injectPrivateFields(newConfig, currentConfig) {
|
||||
if (newConfig.secretapikey === constants.SECRET_PLACEHOLDER) newConfig.secretapikey = currentConfig.secretapikey;
|
||||
}
|
||||
|
||||
async function upsert(domainObject, location, type, values) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof location, 'string');
|
||||
async function getDnsRecords(domainConfig, zoneName, name, type) {
|
||||
assert.strictEqual(typeof domainConfig, 'object');
|
||||
assert.strictEqual(typeof zoneName, 'string');
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof type, 'string');
|
||||
assert(Array.isArray(values));
|
||||
|
||||
const domainConfig = domainObject.config,
|
||||
zoneName = domainObject.zoneName,
|
||||
name = dns.getName(domainObject, location, type) || '';
|
||||
|
||||
debug(`upsert: ${name} in zone ${zoneName} of type ${type} with values ${JSON.stringify(values)}`);
|
||||
|
||||
const records = await get(domainObject, location, type);
|
||||
|
||||
const data = {
|
||||
secretapikey: domainConfig.secretapikey,
|
||||
apikey: domainConfig.apikey,
|
||||
ttl: 10, // min seems to be 600 anyway
|
||||
content: values[0] // for mx records, value is already of the '<priority> <server>' format
|
||||
};
|
||||
|
||||
let url;
|
||||
if (records.length) {
|
||||
url = `${PORKBUN_API}/editByNameType/${zoneName}/${type}/${name}`;
|
||||
} else { // create
|
||||
url = `${PORKBUN_API}/create/${zoneName}`;
|
||||
data.type = type;
|
||||
data.name = name;
|
||||
}
|
||||
|
||||
if (type === 'MX') {
|
||||
data.prio = values[0].split(' ')[0]; // string
|
||||
data.content = values[0].split(' ')[1];
|
||||
} else if (type === 'TXT') {
|
||||
data.content = values[0].startsWith('"') && values[0].endsWith('"') ? values[0].slice(1, values[0].length-1) : values[0];
|
||||
} else {
|
||||
data.content = values[0];
|
||||
}
|
||||
|
||||
const [error, response] = await safe(superagent.post(url)
|
||||
.timeout(30 * 1000)
|
||||
.send(data)
|
||||
.ok(() => true));
|
||||
|
||||
if (error) throw new BoxError(BoxError.NETWORK_ERROR, error.message);
|
||||
if (response.statusCode !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, formatError(response));
|
||||
if (response.body.status !== 'SUCCESS') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid status in response: ${JSON.stringify(response.body)}`);
|
||||
if (records.length === 0 && !response.body.id) throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid id in response: ${JSON.stringify(response.body)}`); // only for create
|
||||
|
||||
debug(`upsert: created record with id ${response.body.id}`);
|
||||
}
|
||||
|
||||
async function get(domainObject, location, type) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof location, 'string');
|
||||
assert.strictEqual(typeof type, 'string');
|
||||
|
||||
const domainConfig = domainObject.config,
|
||||
zoneName = domainObject.zoneName,
|
||||
name = dns.getName(domainObject, location, type) || '';
|
||||
|
||||
debug(`get: ${name} in zone ${zoneName} of type ${type}`);
|
||||
|
||||
@@ -113,7 +58,90 @@ async function get(domainObject, location, type) {
|
||||
if (response.body.status !== 'SUCCESS') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid status in response: ${JSON.stringify(response.body)}`);
|
||||
if (!Array.isArray(response.body.records)) throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid records in response: ${JSON.stringify(response.body)}`);
|
||||
|
||||
return response.body.records.map(r => r.content);
|
||||
// TXT records are returned without quoting. When no records match, it returns empty records array
|
||||
return response.body.records;
|
||||
}
|
||||
|
||||
async function delDnsRecords(domainConfig, zoneName, name, type) {
|
||||
assert.strictEqual(typeof domainConfig, 'object');
|
||||
assert.strictEqual(typeof zoneName, 'string');
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof type, 'string');
|
||||
|
||||
const data = {
|
||||
secretapikey: domainConfig.secretapikey,
|
||||
apikey: domainConfig.apikey,
|
||||
};
|
||||
|
||||
// deletes all the records matching type+name
|
||||
const [error, response] = await safe(superagent.post(`${PORKBUN_API}/deleteByNameType/${zoneName}/${type}/${name}`)
|
||||
.send(data)
|
||||
.timeout(30 * 1000)
|
||||
.ok(() => true));
|
||||
|
||||
if (error) throw new BoxError(BoxError.NETWORK_ERROR, error.message);
|
||||
if (response.statusCode === 400) return; // not found, "Could not delete record."
|
||||
if (response.statusCode !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, formatError(response));
|
||||
if (response.body.status !== 'SUCCESS') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid status in response: ${JSON.stringify(response.body)}`);
|
||||
}
|
||||
|
||||
async function upsert(domainObject, location, type, values) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof location, 'string');
|
||||
assert.strictEqual(typeof type, 'string');
|
||||
assert(Array.isArray(values));
|
||||
|
||||
const domainConfig = domainObject.config,
|
||||
zoneName = domainObject.zoneName,
|
||||
name = dns.getName(domainObject, location, type) || '';
|
||||
|
||||
debug(`upsert: ${name} in zone ${zoneName} of type ${type} with values ${JSON.stringify(values)}`);
|
||||
|
||||
await delDnsRecords(domainConfig, zoneName, name, type);
|
||||
|
||||
for (const value of values) {
|
||||
const data = {
|
||||
secretapikey: domainConfig.secretapikey,
|
||||
apikey: domainConfig.apikey,
|
||||
ttl: '10', // 600 seems to be minimum anyway
|
||||
type,
|
||||
name
|
||||
};
|
||||
|
||||
if (type === 'MX') {
|
||||
data.prio = value.split(' ')[0]; // string
|
||||
data.content = value.split(' ')[1];
|
||||
} else if (type === 'TXT') { // strip quotes
|
||||
data.content = value.startsWith('"') && value.endsWith('"') ? value.slice(1, value.length-1) : value;
|
||||
} else {
|
||||
data.content = value;
|
||||
}
|
||||
|
||||
const [error, response] = await safe(superagent.post(`${PORKBUN_API}/create/${zoneName}`)
|
||||
.timeout(30 * 1000)
|
||||
.send(data)
|
||||
.ok(() => true));
|
||||
|
||||
if (error) throw new BoxError(BoxError.NETWORK_ERROR, error.message);
|
||||
if (response.statusCode !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, formatError(response));
|
||||
if (response.body.status !== 'SUCCESS') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid status in response: ${JSON.stringify(response.body)}`);
|
||||
if (!response.body.id) throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid id in response: ${JSON.stringify(response.body)}`);
|
||||
|
||||
debug(`upsert: created record with id ${response.body.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function get(domainObject, location, type) {
|
||||
assert.strictEqual(typeof domainObject, 'object');
|
||||
assert.strictEqual(typeof location, 'string');
|
||||
assert.strictEqual(typeof type, 'string');
|
||||
|
||||
const domainConfig = domainObject.config,
|
||||
zoneName = domainObject.zoneName,
|
||||
name = dns.getName(domainObject, location, type) || '';
|
||||
|
||||
const records = await getDnsRecords(domainConfig, zoneName, name, type);
|
||||
return records.map(r => r.content);
|
||||
}
|
||||
|
||||
async function del(domainObject, location, type, values) {
|
||||
@@ -133,15 +161,21 @@ async function del(domainObject, location, type, values) {
|
||||
apikey: domainConfig.apikey,
|
||||
};
|
||||
|
||||
const [error, response] = await safe(superagent.post(`${PORKBUN_API}/deleteByNameType/${zoneName}/${type}/${name}`)
|
||||
.send(data)
|
||||
.timeout(30 * 1000)
|
||||
.ok(() => true));
|
||||
// note that deleteByNameType deletes all the records matching type+name. we only want to delete records matching values
|
||||
const records = await getDnsRecords(domainConfig, zoneName, name, type);
|
||||
const ids = records.filter(r => values.includes(r.content)).map(r => r.id);
|
||||
|
||||
if (error) throw new BoxError(BoxError.NETWORK_ERROR, error.message);
|
||||
if (response.statusCode === 400) return; // not found!
|
||||
if (response.statusCode !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, formatError(response));
|
||||
if (response.body.status !== 'SUCCESS') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid status in response: ${JSON.stringify(response.body)}`);
|
||||
for (const id of ids) {
|
||||
const [error, response] = await safe(superagent.post(`${PORKBUN_API}/delete/${zoneName}/${id}`)
|
||||
.send(data)
|
||||
.timeout(30 * 1000)
|
||||
.ok(() => true));
|
||||
|
||||
if (error) throw new BoxError(BoxError.NETWORK_ERROR, error.message);
|
||||
if (response.statusCode === 400) continue; // not found! "Invalid record id."
|
||||
if (response.statusCode !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, formatError(response));
|
||||
if (response.body.status !== 'SUCCESS') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid status in response: ${JSON.stringify(response.body)}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function wait(domainObject, subdomain, type, value, options) {
|
||||
|
||||
Reference in New Issue
Block a user