Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 45 additions & 18 deletions source/dns/server_for_name.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,12 @@ function serverForName(
const staticData = staticDataInDomain[resourceName];
return callback(req, res, dns.getRecords(staticData, reqName));
}

if (! checkAndConstraints.isLegalUsername(resourceName)) {
logger.warn(`DNS: ${util.inspect(resourceName)} is no legal username.`);
return callback(req, res, nullRecord);
}

// assert: resourceName fulfills the character level constraints for a username.
const uid = resourceName;

// 0 to 4 char length are reserved
if (uid.length < 5) {
// nothing found
return callback(req, res, nullRecord);
}


db.getServer(uid, function (error, result) {
//console.log('*** FOUND :'+ result);
if (error || ! result) { return callback(req, res, nullRecord); }
getEntryFromDB(resourceName, function (error, dyn) {
if (error || ! dyn) { return callback(req, res, nullRecord); }

var dyn: DnsData = {
'alias': [ { name: result } ]};

// add Authority or Nameservers
switch (req.q[0].typeName) {
Expand All @@ -169,6 +153,49 @@ function serverForName(
return callback(req, res, rec); // ndns-warper.sendresponse
});
}

function getEntryFromDB(resourceName, callback) {

getEntryFromKey(resourceName, function (err, dbEntry) {
if (err) return callback(err, null);
if (dbEntry) return callback(null, dbEntry);

getAliasForuser(resourceName, callback);
});
}

function getEntryFromKey(resourceName, callback) {
db.getNSEntry(resourceName, callback);
}

function getAliasForuser(resourceName, callback) {
// username
if (! checkAndConstraints.isLegalUsername(resourceName)) {
logger.warn(`DNS: ${util.inspect(resourceName)} is no legal username.`);
return callback(null, null);
}

// assert: resourceName fulfills the character level constraints for a username.
const uid = resourceName;

// 0 to 4 char length are reserved
if (uid.length < 5) {
// nothing found
return callback(null, null);
}


db.getServer(uid, function (error, result) {
if (error || ! result) { return callback(error, null); }

var dyn: DnsData = {
'alias': [ { name: result } ]
};
callback(null, dyn);
});
}


module.exports = {
serverForName: serverForName,
logger: logger
Expand Down
27 changes: 27 additions & 0 deletions source/routes/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,38 @@ const users = require('../storage/users');
const messages = require('../utils/messages');
const invitations = require('../storage/invitations');
const requireRoles = require('../middleware/requireRoles');
const db = require('../storage/database');

/**
* Routes for admin to manage users
*/
module.exports = function (app: any) {

app.post('/admin/nsentries', requireRoles('admin'), function (req, res, next) { 
const body = req.body;
if (! body.key || typeof key !== 'string') return next(messages.e(422, 'INVALID_DATA', "invalid or missing key parameter"));

db.setNSEntry(body.key, body.value, function(err) {
if (err) {
return next(err);
}
res.send({entry: {key: body.key, value: body.value}});
return next();
});
});

app.get('/admin/nsentries', requireRoles('admin'), function (req, res, next) { 
const result = [];

db.getNSEntries(function(err, entries) {
if (err) {
return next(err);
}
res.send({nsentries: entries});
return next();
});
});

// GET /admin/users: get the user list
app.get('/admin/users', requireRoles('admin'), function (req, res, next) {
const headers = {
Expand Down
28 changes: 27 additions & 1 deletion source/storage/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,32 @@ exports.getAccessState = function (key: string, callback: GenericCallback<Access
getJSON(key + ':access', mixedCallback);
};

exports.setNSEntry = function (key: string, value: DnsData, callback) {
redis.set(ns(key,'nsentry'), JSON.stringify(value), callback);
}

exports.getNSEntry = function (key: string, callback) {
getJSON(ns(key,'nsentry'), callback);
}

exports.getNSEntries = function (callback) {
const mask = '*:nsentry';
const maskLength = mask.length - 1;
const result = {};
doOnKeysValuesMatching(mask, '*', function(key, value) { 
const k = key.slice(0, - maskLength);
let v;
try {
v = JSON.parse(value);
} catch (e) {
v = {error: e.message}
}
result[k] = v;
}, function() {
callback(null, result);
});
}

//----------------- Reserved words --------------//

var RESERVED_WORDS_VERSION = 'reservedwords:version';
Expand Down Expand Up @@ -976,7 +1002,7 @@ exports.reservedWordExists = function (word: string, callback: GenericCallback<b
/// Given a value (`a`) and a namespace kind (`b`): Assembles and returns the
/// redis namespace for accessing that value.
///
type NamespaceKind = 'users' | 'server' | 'email';
type NamespaceKind = 'users' | 'server' | 'email' | 'nsentry';
function ns(a: string, b: NamespaceKind): string {
return `${a}:${b}`;
}
Expand Down
69 changes: 69 additions & 0 deletions test/acceptance/admin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const Server = require('../../source/server.js');
const dataValidation = require('../support/data-validation');
const schema = require('../support/schema.responses');
const db = require('../../source/storage/database');
const async = require('async');
const { assert } = require('chai');

require('readyness/wait/mocha');

Expand Down Expand Up @@ -120,6 +122,9 @@ describe('GET /admin/servers/:srcServerName/rename/:dstServerName', function ()
});
});




describe('GET /admin/servers', function () {
let server;

Expand All @@ -143,6 +148,70 @@ describe('GET /admin/servers', function () {
});
});


describe('/admin/nsentries', function () {
let server;

before(async function () {
server = new Server();
await server.start();
});

after(async function () {
await server.stop();
});

describe('GET ', function () {
const entries = [
{key: '_testip', value: {ip: '120.120.120.120'}},
{key: '_testtxt', value: {description: 'asjdshahgdsahgdghasdhgas'}},
];

before((done) => { 
async.mapSeries(entries, function(item, callback) {
db.setNSEntry(item.key, item.value, callback);
}, done);
});


it('should send a list of nsentries', function (done) {
request.get(server.url + '/admin/nsentries' + '?auth=' + authAdminKey)
.end((err, res) => {
assert.exists(res.body.nsentries);
for (let entry of entries) {
assert.deepEqual(res.body.nsentries[entry.key], entry.value)
}
done();
});
});
});


describe('POST ', function () {

it('should store an entry', function (done) {
const entry = {
key: '_testrrandom',
value: {
description: 'asjdshahgdsahgdghasdhgas' + Math.round(Math.random() * 100000)
}
};
request.post(server.url + '/admin/nsentries' + '?auth=' + authAdminKey).send(entry).end((errRequest, resRequest) => {
assert.notExists(errRequest);
assert.exists(resRequest.body.entry);
assert.deepEqual(resRequest.body.entry, entry);
db.getNSEntry(entry.key, function(err, res) { 
assert.notExists(err);
assert.deepEqual(entry.value, res);
done();
})
});
});
});

});


describe('/admin/invitations', function () {
let server;

Expand Down
34 changes: 34 additions & 0 deletions test/acceptance/dns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ var db = require('../../source/storage/database');
const ndns = require('../../source/dns/ndns');
const Client = ndns.Client;

const async = require('async');

require('../../source/app-dns');

require('readyness/wait/mocha');
Expand Down Expand Up @@ -118,6 +120,38 @@ describe('DNS', function () {
});


describe('NS entries in DB', () => {
const entries = [
{key: '_testip', value: {ip: '120.120.120.120'}},
{key: '_testtxt', value: {description: 'asjdshahgdsahgdghasdhgas'}},
];

before((done) => { 
async.mapSeries(entries, function(item, callback) {
db.setNSEntry(item.key, item.value, callback);
}, done);
});

it('DNS answers to A NSentry in DB', (done) => { 
const entry = entries[0];
dig('A', entry.key + '.' + config.get('dns:domain'), function (error, result) {
if (error) { return done(error); }
assert.strictEqual(result, entry.value.ip);
done();
});
});

it('DNS answers to TXT NSentry in DB', (done) => { 
const entry = entries[1];
dig('TXT', entry.key + '.' + config.get('dns:domain'), function (error, result) {
if (error) { return done(error); }
assert.strictEqual(result, '"' + entry.value.description + '"' );
done();
});
});

});

describe('CAA records', () => {
it('work', (done) => {
dig('CAA', config.get('dns:domain'), function (error, result) {
Expand Down