diff --git a/src/domaindb.js b/src/domaindb.js new file mode 100644 index 000000000..9f238064b --- /dev/null +++ b/src/domaindb.js @@ -0,0 +1,95 @@ +/* jslint node:true */ + +'use strict'; + +exports = module.exports = { + add: add, + get: get, + getAll: getAll, + update: update, + del: del, + + _clear: clear +}; + +var assert = require('assert'), + database = require('./database.js'), + DatabaseError = require('./databaseerror'), + safe = require('safetydance'); + +function postProcess(data) { + data.config = safe.JSON.parse(data.configJson); + + return data; +} + +function get(domain, callback) { + assert.strictEqual(typeof domain, 'string'); + assert.strictEqual(typeof callback, 'function'); + + database.query('SELECT * FROM domains WHERE domain=?', [ domain ], function (error, result) { + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + + postProcess(result[0]); + + callback(null, result[0]); + }); +} + +function getAll(callback) { + database.query('SELECT * FROM domains ORDER BY domain', function (error, results) { + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + + results.forEach(postProcess); + + callback(null, results); + }); +} + +function add(domain, zoneName, config, callback) { + assert.strictEqual(typeof domain, 'string'); + assert.strictEqual(typeof zoneName, 'string'); + assert.strictEqual(typeof config, 'object'); + assert.strictEqual(typeof callback, 'function'); + + database.query('INSERT INTO domains (domain, zoneName, configJson) VALUES (?, ?, ?)', [ domain, zoneName, JSON.stringify(config) ], function (error) { + if (error && error.code === 'ER_DUP_ENTRY') return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS, error)); + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + + callback(null); + }); +} + +function update(domain, config, callback) { + assert.strictEqual(typeof domain, 'string'); + assert.strictEqual(typeof config, 'object'); + assert.strictEqual(typeof callback, 'function'); + + database.query('UPDATE domains SET configJson=? WHERE domain=?', [ JSON.stringify(config), domain ], function (error) { + if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + + callback(null); + }); +} + +function del(domain, callback) { + assert.strictEqual(typeof domain, 'string'); + assert.strictEqual(typeof callback, 'function'); + + database.query('DELETE FROM domains WHERE domain=?', [ domain ], function (error, result) { + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + if (result.affectedRows !== 1) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + + callback(null); + }); +} + +function clear(callback) { + database.query('DELETE FROM domains', function (error) { + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + + callback(error); + }); +} diff --git a/src/test/database-test.js b/src/test/database-test.js index fb77e6bbe..d407251e6 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -12,6 +12,7 @@ var appdb = require('../appdb.js'), clientdb = require('../clientdb.js'), database = require('../database'), DatabaseError = require('../databaseerror.js'), + domaindb = require('../domaindb'), eventlogdb = require('../eventlogdb.js'), expect = require('expect.js'), groupdb = require('../groupdb.js'), @@ -70,6 +71,122 @@ describe('database', function () { database._clear(done); }); + describe('domains', function () { + const DOMAIN_0 = { + domain: 'foobar.com', + zoneName: 'foobar.com', + config: { provider: 'digitalocean', token: 'abcd' } + }; + + const DOMAIN_1 = { + domain: 'foo.example.com', + zoneName: 'example.com', + config: null + }; + + it('can add domain', function (done) { + domaindb.add(DOMAIN_0.domain, DOMAIN_0.zoneName, DOMAIN_0.config, done); + }); + + it('can add another domain', function (done) { + domaindb.add(DOMAIN_1.domain, DOMAIN_1.zoneName, DOMAIN_1.config, done); + }); + + it('cannot add same domain twice', function (done) { + domaindb.add(DOMAIN_0.domain, DOMAIN_0.zoneName, DOMAIN_0.config, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS); + done(); + }); + }); + + it('can get domain', function (done) { + domaindb.get(DOMAIN_0.domain, function (error, result) { + expect(error).to.equal(null); + expect(result).to.be.an('object'); + expect(result.domain).to.equal(DOMAIN_0.domain); + expect(result.zoneName).to.equal(DOMAIN_0.zoneName); + expect(result.config).to.eql(DOMAIN_0.config); + + done(); + }); + }); + + it('can get domain without provider set', function (done) { + domaindb.get(DOMAIN_1.domain, function (error, result) { + expect(error).to.equal(null); + expect(result).to.be.an('object'); + expect(result.domain).to.equal(DOMAIN_1.domain); + expect(result.zoneName).to.equal(DOMAIN_1.zoneName); + expect(result.config).to.eql(DOMAIN_1.config); + + done(); + }); + }); + + it('can update domain', function (done) { + const newConfig = { provider: 'manual' }; + + domaindb.update(DOMAIN_1.domain, newConfig, function (error) { + console.log(error) + expect(error).to.equal(null); + + domaindb.get(DOMAIN_1.domain, function (error, result) { + expect(error).to.equal(null); + expect(result).to.be.an('object'); + expect(result.domain).to.equal(DOMAIN_1.domain); + expect(result.zoneName).to.equal(DOMAIN_1.zoneName); + expect(result.config).to.eql(newConfig); + + DOMAIN_1.config = newConfig; + + done(); + }); + }); + }); + + it('can get all domains', function (done) { + domaindb.getAll(function (error, result) { + expect(error).to.equal(null); + expect(result).to.be.an('array'); + expect(result.length).to.equal(2); + + // sorted by domain + expect(result[0].domain).to.equal(DOMAIN_1.domain); + expect(result[0].zoneName).to.equal(DOMAIN_1.zoneName); + expect(result[0].config).to.eql(DOMAIN_1.config); + + expect(result[1].domain).to.equal(DOMAIN_0.domain); + expect(result[1].zoneName).to.equal(DOMAIN_0.zoneName); + expect(result[1].config).to.eql(DOMAIN_0.config); + + done(); + }); + }); + + it('cannot delete non-existing domain', function (done) { + domaindb.del('not.exists', function (error) { + expect(error).to.be.a(DatabaseError); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + + done(); + }); + }); + + it('can delete existing domain', function (done) { + domaindb.del(DOMAIN_0.domain, function (error) { + expect(error).to.be(null); + + domaindb.get(DOMAIN_0.domain, function (error) { + expect(error).to.be.a(DatabaseError); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + + done(); + }); + }); + }); + }); + describe('user', function () { it('can add user', function (done) { userdb.add(USER_0.id, USER_0, done);