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
|
||||||
logs
|
logs
|
||||||
*.log
|
*.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
|
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