'use strict'; var request = require('@root/request'); request = require('util').promisify(request); var defaults = { baseUrl: 'https://api.digitalocean.com' }; module.exports.create = function(config) { // config = { baseUrl, token } var baseUrl = config.baseUrl || defaults.baseUrl; var authtoken = config.token; return { set: function(data) { var ch = data.challenge; var domainname = ch.identifier.value; // PROBLEM: zone != domain // example.com, foo.example.com, and bar.foo.example.com are all in the example.com zone!! // Need to get list of "domains" (zones) and *then* set "subdomains" (domain records) // https://developers.digitalocean.com/documentation/v2/#domains var zone = domainname; // PROBLEM: dnsPrefix != dnsHost.split('.')[0] // _greenlock-dryrun-2277.bar.foo.example.com => _greenlock-dryrun-2277.bar.foo var dnsPrefix = ch.dnsHost.replace(new RegExp('.' + zone + '$'), ''); var txt = ch.dnsAuthorization; // If the domain to be verified is var url = baseUrl + '/v2/domains/' + zone + '/records'; console.log('adding txt', data); return request({ method: 'POST', url: url, headers: { Authorization: 'Bearer ' + authtoken, 'Content-Type': 'application/json' }, json: { type: 'TXT', name: dnsPrefix, data: txt, // PROBLEM (fixed) set a LOW ttl so that responses are not cached so long ttl: 300 } }).then(function(resp) { resp = resp.body; console.log(resp); if (resp && resp.domain_record && resp.domain_record.data === txt) { return true; } throw new Error('record did not set. check subdomain, api key, etc'); }); }, remove: function(data) { var domainname = data.challenge.altname; var zone = domainname; // PROBLEM: domainname != zone var url = baseUrl + '/v2/domains/' + zone + '/records'; // Digital ocean provides the api to remove records by ID. Since we do not have id, we fetch all the records, // filter the required TXT record and pass its id to remove API return request({ method: 'GET', url: url, // PROBLEM (fixed): Remember to set json: true (not need to JSON.parse) json: true, headers: { Authorization: 'Bearer ' + authtoken, 'Content-Type': 'application/json' } }) .then(function(resp) { resp = resp.body; var entries = resp && resp.domain_records && resp.domain_records.filter(function(x) { return x.type === 'TXT'; }); // PROBLEM entry[0] !== our entry // (see solution for other entries, down below) if (entries.length > 0) { return entries[0].id; } else { throw new Error( 'Couldnt remove record. check subdomain, api key, etc' ); } }) .then(function(recordId) { var domainname = data.challenge.altname; var zone = domainname; var url = baseUrl + '/v2/domains/' + zone + '/records/' + recordId; return request({ method: 'DELETE', url: url, headers: { Authorization: 'Bearer ' + authtoken, 'Content-Type': 'application/json' } }).then(function(resp) { resp = resp.body; console.log(resp); return true; }); }); }, get: function(data) { var ch = data.challenge; var domainname = data.challenge.altname; var zone = domainname; // PROBLEM: domainname != zone var url = baseUrl + '/v2/domains/' + zone + '/records'; console.log('getting txt', data); // Digital ocean provides the api to fetch records by ID. Since we do not have id, we fetch all the records, // filter the required TXT record return request({ method: 'GET', url: url, json: true, headers: { Authorization: 'Bearer ' + authtoken, 'Content-Type': 'application/json' } }).then(function(resp) { resp = resp.body; var entries = resp && resp.domain_records && resp.domain_records.filter(function(x) { // PROBLEM should also check for prefix return x.type === 'TXT'; }); // PROBLEM (fixed): entries[0] !== our entry var entry = entries.filter(function(x) { console.log('data', x.data); console.log('dnsAuth', ch.dnsAuthorization, ch); return x.data === ch.dnsAuthorization; })[0]; if (entry) { return { dnsAuthorization: entry.data }; } else { return null; } }); } }; };