Implement MongoDB client
This commit is contained in:
parent
7f629aec13
commit
ce2b24d83d
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
.DS_Store
|
||||
credentials.json
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
4
.jscsrc
Normal file
4
.jscsrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"disallowTrailingWhitespace": true,
|
||||
"validateIndentation": 2
|
||||
}
|
25
.jshintrc
Normal file
25
.jshintrc
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"strict": true,
|
||||
"node": true,
|
||||
"nonew": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"newcap": true,
|
||||
"regexp": true,
|
||||
"evil": true,
|
||||
"eqnull": true,
|
||||
"expr": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"esnext": true,
|
||||
|
||||
"globals": {
|
||||
"describe" : true,
|
||||
"it" : true,
|
||||
"before" : true,
|
||||
"beforeEach" : true,
|
||||
"after" : true,
|
||||
"afterEach" : true
|
||||
}
|
||||
}
|
17
.travis.yml
Normal file
17
.travis.yml
Normal file
@ -0,0 +1,17 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
- "5"
|
||||
- "6"
|
||||
before_script:
|
||||
- npm install -g grunt-cli
|
||||
- sleep 15
|
||||
- mongo test_db --eval 'db.addUser("travis", "test");'
|
||||
notifications:
|
||||
email:
|
||||
- build@mailvelope.com
|
||||
services:
|
||||
- mongodb
|
||||
env:
|
||||
- MONGO_URI=127.0.0.1:27017/test_db MONGO_USER=travis MONGO_PASS=test
|
43
Gruntfile.js
Normal file
43
Gruntfile.js
Normal file
@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.initConfig({
|
||||
jshint: {
|
||||
all: ['*.js', 'src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
}
|
||||
},
|
||||
|
||||
jscs: {
|
||||
src: ['*.js', 'src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
config: ".jscsrc",
|
||||
esnext: true, // If you use ES6 http://jscs.info/overview.html#esnext
|
||||
verbose: true, // If you need output with rule names http://jscs.info/overview.html#verbose
|
||||
}
|
||||
},
|
||||
|
||||
mochaTest: {
|
||||
test: {
|
||||
options: {
|
||||
reporter: 'spec'
|
||||
},
|
||||
src: [
|
||||
'test/unit/*.js',
|
||||
'test/integration/*.js',
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Load the plugin(s)
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-jscs');
|
||||
grunt.loadNpmTasks('grunt-mocha-test');
|
||||
|
||||
// Default task(s).
|
||||
grunt.registerTask('test', ['jshint', 'jscs', 'mochaTest']);
|
||||
|
||||
};
|
@ -1,2 +1,4 @@
|
||||
# keyserver
|
||||
Mailvelope Keyserver [![Build Status](https://travis-ci.org/mailvelope/keyserver.svg?branch=master)](https://travis-ci.org/mailvelope/keyserver)
|
||||
==============
|
||||
|
||||
A simple OpenPGP public key server
|
||||
|
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "mailvelope-keyserver",
|
||||
"version": "0.0.1",
|
||||
"license": "AGPL-3.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mailvelope/keyserver.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt test"
|
||||
},
|
||||
"dependencies": {
|
||||
"mongodb": "^2.1.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^3.5.0",
|
||||
"co-mocha": "^1.1.2",
|
||||
"grunt": "^1.0.1",
|
||||
"grunt-contrib-jshint": "^1.0.0",
|
||||
"grunt-jscs": "^2.8.0",
|
||||
"grunt-mocha-test": "^0.12.7",
|
||||
"mocha": "^2.5.3",
|
||||
"sinon": "^1.17.4"
|
||||
}
|
||||
}
|
124
src/dao/mongo.js
Normal file
124
src/dao/mongo.js
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Mailvelope - secure email with OpenPGP encryption for Webmail
|
||||
* Copyright (C) 2016 Mailvelope GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License version 3
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const MongoClient = require('mongodb').MongoClient;
|
||||
|
||||
/**
|
||||
* A simple wrapper around the official MongoDB client.
|
||||
*/
|
||||
class Mongo {
|
||||
|
||||
/**
|
||||
* Create an instance of the MongoDB client.
|
||||
* @param {String} options.uri The mongodb uri
|
||||
* @param {String} options.user The databse user
|
||||
* @param {String} options.password The database user's password
|
||||
* @param {String} options.type (optional) The default collection type to use e.g. 'publickey'
|
||||
* @return {undefined}
|
||||
*/
|
||||
constructor(options) {
|
||||
this._uri = 'mongodb://' + options.user + ':' + options.password + '@' + options.uri;
|
||||
this._type = options.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the database client by connecting to the MongoDB.
|
||||
* @return {undefined}
|
||||
*/
|
||||
*connect() {
|
||||
this._db = yield MongoClient.connect(this._uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup by closing the connection to the database.
|
||||
* @return {undefined}
|
||||
*/
|
||||
disconnect() {
|
||||
return this._db.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a single document.
|
||||
* @param {Object} document Inserts a single documents
|
||||
* @param {String} type (optional) The collection to use e.g. 'publickey'
|
||||
* @return {Object} The operation result
|
||||
*/
|
||||
create(document, type) {
|
||||
let col = this._db.collection(type || this._type);
|
||||
return col.insertOne(document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single document.
|
||||
* @param {Object} query The query e.g. { _id:'0' }
|
||||
* @param {Object} diff The attributes to change/set e.g. { foo:'bar' }
|
||||
* @param {String} type (optional) The collection to use e.g. 'publickey'
|
||||
* @return {Object} The operation result
|
||||
*/
|
||||
update(query, diff, type) {
|
||||
let col = this._db.collection(type || this._type);
|
||||
return col.updateOne(query, { $set:diff });
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single document.
|
||||
* @param {Object} query The query e.g. { _id:'0' }
|
||||
* @param {String} type (optional) The collection to use e.g. 'publickey'
|
||||
* @return {Object} The document object
|
||||
*/
|
||||
get(query, type) {
|
||||
let col = this._db.collection(type || this._type);
|
||||
return col.findOne(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read multiple documents at once.
|
||||
* @param {Object} query The query e.g. { foo:'bar' }
|
||||
* @param {String} type (optional) The collection to use e.g. 'publickey'
|
||||
* @return {Array} An array of document objects
|
||||
*/
|
||||
list(query, type) {
|
||||
let col = this._db.collection(type || this._type);
|
||||
return col.find(query).toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single document.
|
||||
* @param {Object} query The query e.g. { _id:'0' }
|
||||
* @param {String} type (optional) The collection to use e.g. 'publickey'
|
||||
* @return {Object} The document object
|
||||
*/
|
||||
remove(query, type) {
|
||||
let col = this._db.collection(type || this._type);
|
||||
return col.deleteOne(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all documents of a collection.
|
||||
* @param {String} type (optional) The collection to use e.g. 'publickey'
|
||||
* @return {Object} The operation result
|
||||
*/
|
||||
clear(type) {
|
||||
let col = this._db.collection(type || this._type);
|
||||
return col.deleteMany({});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Mongo;
|
131
test/integration/mongo-test.js
Normal file
131
test/integration/mongo-test.js
Normal file
@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
|
||||
require('co-mocha')(require('mocha')); // monkey patch mocha for generators
|
||||
|
||||
const Mongo = require('../../src/dao/mongo'),
|
||||
expect = require('chai').expect,
|
||||
fs = require('fs');
|
||||
|
||||
describe('Mongo Integration Tests', function() {
|
||||
this.timeout(20000);
|
||||
|
||||
const defaultType = 'apple';
|
||||
const secondaryType = 'orange';
|
||||
let mongo;
|
||||
|
||||
before(function *() {
|
||||
let credentials;
|
||||
try {
|
||||
credentials = JSON.parse(fs.readFileSync(__dirname + '/../../credentials.json'));
|
||||
} catch(e) {}
|
||||
mongo = new Mongo({
|
||||
uri: process.env.MONGO_URI || credentials.mongoUri,
|
||||
user: process.env.MONGO_USER || credentials.mongoUser,
|
||||
password: process.env.MONGO_PASS || credentials.mongoPass,
|
||||
type: defaultType
|
||||
});
|
||||
yield mongo.connect();
|
||||
});
|
||||
|
||||
beforeEach(function *() {
|
||||
yield mongo.clear();
|
||||
yield mongo.clear(secondaryType);
|
||||
});
|
||||
|
||||
afterEach(function() {});
|
||||
|
||||
after(function *() {
|
||||
yield mongo.clear();
|
||||
yield mongo.clear(secondaryType);
|
||||
yield mongo.disconnect();
|
||||
});
|
||||
|
||||
describe("create", function() {
|
||||
it('should insert a document', function *() {
|
||||
let r = yield mongo.create({ _id:'0' });
|
||||
expect(r.insertedCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should insert a document with a type', function *() {
|
||||
let r = yield mongo.create({ _id:'0' });
|
||||
expect(r.insertedCount).to.equal(1);
|
||||
r = yield mongo.create({ _id:'0' }, secondaryType);
|
||||
expect(r.insertedCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should fail if two with the same ID are inserted', function *() {
|
||||
let r = yield mongo.create({ _id:'0' });
|
||||
expect(r.insertedCount).to.equal(1);
|
||||
try {
|
||||
r = yield mongo.create({ _id:'0' });
|
||||
} catch(e) {
|
||||
expect(e.message).to.match(/duplicate/);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("update", function() {
|
||||
it('should update a document', function *() {
|
||||
let r = yield mongo.create({ _id:'0' });
|
||||
r = yield mongo.update({ _id:'0' }, { foo:'bar' });
|
||||
expect(r.modifiedCount).to.equal(1);
|
||||
r = yield mongo.get({ _id:'0' });
|
||||
expect(r.foo).to.equal('bar');
|
||||
});
|
||||
|
||||
it('should update a document with a type', function *() {
|
||||
let r = yield mongo.create({ _id:'0' }, secondaryType);
|
||||
r = yield mongo.update({ _id:'0' }, { foo:'bar' }, secondaryType);
|
||||
expect(r.modifiedCount).to.equal(1);
|
||||
r = yield mongo.get({ _id:'0' }, secondaryType);
|
||||
expect(r.foo).to.equal('bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe("get", function() {
|
||||
it('should get a document', function *() {
|
||||
let r = yield mongo.create({ _id:'0' });
|
||||
r = yield mongo.get({ _id:'0' });
|
||||
expect(r).to.exist;
|
||||
});
|
||||
|
||||
it('should get a document with a type', function *() {
|
||||
let r = yield mongo.create({ _id:'0' }, secondaryType);
|
||||
r = yield mongo.get({ _id:'0' }, secondaryType);
|
||||
expect(r).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe("list", function() {
|
||||
it('should list documents', function *() {
|
||||
let r = yield mongo.create({ _id:'0', foo:'bar' });
|
||||
r = yield mongo.create({ _id:'1', foo:'bar' });
|
||||
r = yield mongo.list({ foo:'bar' });
|
||||
expect(r).to.deep.equal([{ _id:'0', foo:'bar' }, { _id:'1', foo:'bar' }]);
|
||||
});
|
||||
|
||||
it('should list documents with a type', function *() {
|
||||
let r = yield mongo.create({ _id:'0', foo:'bar' }, secondaryType);
|
||||
r = yield mongo.create({ _id:'1', foo:'bar' }, secondaryType);
|
||||
r = yield mongo.list({ foo:'bar' }, secondaryType);
|
||||
expect(r).to.deep.equal([{ _id:'0', foo:'bar' }, { _id:'1', foo:'bar' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("remove", function() {
|
||||
it('should remove a document', function *() {
|
||||
let r = yield mongo.create({ _id:'0' });
|
||||
r = yield mongo.remove({ _id:'0' });
|
||||
r = yield mongo.get({ _id:'0' });
|
||||
expect(r).to.not.exist;
|
||||
});
|
||||
|
||||
it('should remove a document with a type', function *() {
|
||||
let r = yield mongo.create({ _id:'0' }, secondaryType);
|
||||
r = yield mongo.remove({ _id:'0' }, secondaryType);
|
||||
r = yield mongo.get({ _id:'0' }, secondaryType);
|
||||
expect(r).to.not.exist;
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue
Block a user