commit
158a7418d0
59
.eslintrc
Normal file
59
.eslintrc
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"strict": ["error", "global"],
|
||||||
|
/* possible errors */
|
||||||
|
"no-console": 0,
|
||||||
|
"no-empty": ["error", { "allowEmptyCatch": true }], // disallow empty block statements
|
||||||
|
/* best practices */
|
||||||
|
"curly": 2, // enforce consistent brace style for all control statements
|
||||||
|
"no-eval": 2, // disallow the use of eval()
|
||||||
|
"no-extend-native": 2, // disallow extending native types
|
||||||
|
"no-global-assign": 2, // disallow assignments to native objects or read-only global variables
|
||||||
|
"no-implicit-coercion": 2, // disallow shorthand type conversions
|
||||||
|
"no-implicit-globals": 2, // disallow var and named function declarations in the global scope
|
||||||
|
"no-implied-eval": 2, // disallow the use of eval()-like methods
|
||||||
|
"no-lone-blocks": 2, // disallow unnecessary nested blocks
|
||||||
|
"no-useless-escape": 0, // disallow unnecessary escape characters
|
||||||
|
/* Stylistic Issues */
|
||||||
|
"array-bracket-spacing": 1, // enforce consistent spacing inside array brackets
|
||||||
|
"block-spacing": 1, // enforce consistent spacing inside single-line blocks
|
||||||
|
"comma-spacing": 1, // enforce consistent spacing before and after commas
|
||||||
|
"computed-property-spacing": 1, // enforce consistent spacing inside computed property brackets
|
||||||
|
"eol-last": 1, // enforce at least one newline at the end of files
|
||||||
|
"func-call-spacing": 1, // require or disallow spacing between function identifiers and their invocations
|
||||||
|
"indent": ["warn", 2, {"MemberExpression": 0, "SwitchCase": 1}], // enforce consistent indentation
|
||||||
|
"key-spacing": ["warn", { "mode": "minimum" }], // enforce consistent spacing before and after keywords
|
||||||
|
"keyword-spacing": 1, // enforce consistent spacing between keys and values in object literal properties
|
||||||
|
"linebreak-style": 1, // enforce consistent linebreak style
|
||||||
|
"no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines
|
||||||
|
"no-var": 1, // require let or const instead of var
|
||||||
|
"object-curly-spacing": ["warn", "never"], // enforce consistent spacing inside braces
|
||||||
|
"one-var": ["warn", "never"], // enforce variables to be declared either together or separately in functions
|
||||||
|
"padded-blocks": ["warn", "never"], // require or disallow padding within blocks
|
||||||
|
"semi": ["warn", "always"], // require or disallow semicolons instead of ASI
|
||||||
|
"semi-spacing": 1, // enforce consistent spacing before and after semicolons
|
||||||
|
"space-before-blocks": 1, // enforce consistent spacing before blocks
|
||||||
|
"space-before-function-paren": ["warn", "never"], // enforce consistent spacing before function definition opening parenthesis
|
||||||
|
"space-in-parens": ["warn", "never"], // enforce consistent spacing inside parentheses
|
||||||
|
"space-infix-ops": 1, // require spacing around operators
|
||||||
|
/* ES6 */
|
||||||
|
"arrow-body-style": ["warn", "as-needed"], // require braces around arrow function bodies
|
||||||
|
"arrow-parens": ["warn", "as-needed"], // require parentheses around arrow function arguments
|
||||||
|
"arrow-spacing": 1, // enforce consistent spacing before and after the arrow in arrow functions
|
||||||
|
"no-useless-constructor": 1, // disallow unnecessary constructors
|
||||||
|
"object-shorthand": ["warn", "always", {"avoidQuotes": true}], // require or disallow method and property shorthand syntax for object literals
|
||||||
|
"prefer-arrow-callback": ["warn", {"allowNamedFunctions": true}], // require arrow functions as callbacks
|
||||||
|
"prefer-const": 1, // require const declarations for variables that are never reassigned after declared
|
||||||
|
"prefer-template": 1, // require template literals instead of string concatenation
|
||||||
|
"template-curly-spacing": ["warn", "never"] // require or disallow spacing around embedded expressions of template strings
|
||||||
|
},
|
||||||
|
"root": true
|
||||||
|
}
|
28
.jshintrc
28
.jshintrc
@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"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": {
|
|
||||||
"expect": true,
|
|
||||||
"sinon": true,
|
|
||||||
"describe" : true,
|
|
||||||
"it" : true,
|
|
||||||
"before" : true,
|
|
||||||
"beforeEach" : true,
|
|
||||||
"after" : true,
|
|
||||||
"afterEach" : true,
|
|
||||||
"jQuery" : true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
log: {
|
log: {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
mongo: {
|
mongo: {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
log: {
|
log: {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
log: {
|
log: {
|
||||||
|
@ -11,9 +11,8 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": ": ${NODE_ENV=development} && node index.js",
|
"start": ": ${NODE_ENV=development} && node index.js",
|
||||||
"test": ": ${NODE_ENV=development} && npm run test:jshint && npm run test:jscs && npm run test:unit && npm run test:integration",
|
"test": ": ${NODE_ENV=development} && npm run test:lint && npm run test:unit && npm run test:integration",
|
||||||
"test:jshint": "jshint *.js src/**/*.js test/**/*.js",
|
"test:lint": "eslint config src test *.js",
|
||||||
"test:jscs": "jscs *.js src/**/*.js test/**/*.js",
|
|
||||||
"test:unit": "mocha --opts test/mocha.opts ./test/unit/",
|
"test:unit": "mocha --opts test/mocha.opts ./test/unit/",
|
||||||
"test:integration": "mocha --opts test/mocha.opts ./test/integration",
|
"test:integration": "mocha --opts test/mocha.opts ./test/integration",
|
||||||
"release": "npm run release:install && npm run release:archive",
|
"release": "npm run release:install && npm run release:archive",
|
||||||
@ -37,8 +36,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.1.1",
|
"chai": "^4.1.1",
|
||||||
"co-mocha": "^1.1.2",
|
"co-mocha": "^1.1.2",
|
||||||
"jscs": "^3.0.7",
|
"eslint": "^4.4.1",
|
||||||
"jshint": "^2.9.4",
|
|
||||||
"mocha": "^3.2.0",
|
"mocha": "^3.2.0",
|
||||||
"sinon": "^1.17.4",
|
"sinon": "^1.17.4",
|
||||||
"supertest": "^3.0.0"
|
"supertest": "^3.0.0"
|
||||||
|
17
src/app.js
17
src/app.js
@ -31,7 +31,12 @@ const PublicKey = require('./service/public-key');
|
|||||||
const HKP = require('./route/hkp');
|
const HKP = require('./route/hkp');
|
||||||
const REST = require('./route/rest');
|
const REST = require('./route/rest');
|
||||||
|
|
||||||
let mongo, email, pgp, publicKey, hkp, rest;
|
let mongo;
|
||||||
|
let email;
|
||||||
|
let pgp;
|
||||||
|
let publicKey;
|
||||||
|
let hkp;
|
||||||
|
let rest;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Configure koa HTTP server
|
// Configure koa HTTP server
|
||||||
@ -59,7 +64,7 @@ router.del('/api/v1/key', function *() {
|
|||||||
// Redirect all http traffic to https
|
// Redirect all http traffic to https
|
||||||
app.use(function *(next) {
|
app.use(function *(next) {
|
||||||
if (util.isTrue(config.server.httpsUpgrade) && util.checkHTTP(this)) {
|
if (util.isTrue(config.server.httpsUpgrade) && util.checkHTTP(this)) {
|
||||||
this.redirect('https://' + this.hostname + this.url);
|
this.redirect(`https://${this.hostname}${this.url}`);
|
||||||
} else {
|
} else {
|
||||||
yield next;
|
yield next;
|
||||||
}
|
}
|
||||||
@ -73,7 +78,7 @@ app.use(function *(next) {
|
|||||||
}
|
}
|
||||||
// HPKP
|
// HPKP
|
||||||
if (config.server.httpsKeyPin && config.server.httpsKeyPinBackup) {
|
if (config.server.httpsKeyPin && config.server.httpsKeyPinBackup) {
|
||||||
this.set('Public-Key-Pins', 'pin-sha256="' + config.server.httpsKeyPin + '"; pin-sha256="' + config.server.httpsKeyPinBackup + '"; max-age=16070400');
|
this.set('Public-Key-Pins', `pin-sha256="${config.server.httpsKeyPin}"; pin-sha256="${config.server.httpsKeyPinBackup}"; max-age=16070400`);
|
||||||
}
|
}
|
||||||
// CSP
|
// CSP
|
||||||
this.set('Content-Security-Policy', "default-src 'self'; object-src 'none'; script-src 'self' code.jquery.com; style-src 'self' maxcdn.bootstrapcdn.com; font-src 'self' maxcdn.bootstrapcdn.com");
|
this.set('Content-Security-Policy', "default-src 'self'; object-src 'none'; script-src 'self' code.jquery.com; style-src 'self' maxcdn.bootstrapcdn.com; font-src 'self' maxcdn.bootstrapcdn.com");
|
||||||
@ -91,7 +96,7 @@ app.use(router.routes());
|
|||||||
app.use(router.allowedMethods());
|
app.use(router.allowedMethods());
|
||||||
|
|
||||||
// serve static files
|
// serve static files
|
||||||
app.use(serve(__dirname + '/static'));
|
app.use(serve(`${__dirname}/static`));
|
||||||
|
|
||||||
app.on('error', (error, ctx) => {
|
app.on('error', (error, ctx) => {
|
||||||
if (error.status) {
|
if (error.status) {
|
||||||
@ -120,9 +125,9 @@ function injectDependencies() {
|
|||||||
|
|
||||||
if (!global.testing) { // don't automatically start server in tests
|
if (!global.testing) { // don't automatically start server in tests
|
||||||
co(function *() {
|
co(function *() {
|
||||||
let app = yield init();
|
const app = yield init();
|
||||||
app.listen(config.server.port);
|
app.listen(config.server.port);
|
||||||
log.info('app', 'Ready to rock! Listening on http://localhost:' + config.server.port);
|
log.info('app', `Ready to rock! Listening on http://localhost:${config.server.port}`);
|
||||||
}).catch(err => log.error('app', 'Initialization failed!', err));
|
}).catch(err => log.error('app', 'Initialization failed!', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ const MongoClient = require('mongodb').MongoClient;
|
|||||||
* A simple wrapper around the official MongoDB client.
|
* A simple wrapper around the official MongoDB client.
|
||||||
*/
|
*/
|
||||||
class Mongo {
|
class Mongo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the database client by connecting to the MongoDB.
|
* Initializes the database client by connecting to the MongoDB.
|
||||||
* @param {String} uri The mongodb uri
|
* @param {String} uri The mongodb uri
|
||||||
@ -32,7 +31,7 @@ class Mongo {
|
|||||||
* @yield {undefined}
|
* @yield {undefined}
|
||||||
*/
|
*/
|
||||||
*init({uri, user, pass}) {
|
*init({uri, user, pass}) {
|
||||||
let url = 'mongodb://' + user + ':' + pass + '@' + uri;
|
const url = `mongodb://${user}:${pass}@${uri}`;
|
||||||
this._db = yield MongoClient.connect(url);
|
this._db = yield MongoClient.connect(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ class Mongo {
|
|||||||
* @yield {Object} The operation result
|
* @yield {Object} The operation result
|
||||||
*/
|
*/
|
||||||
create(document, type) {
|
create(document, type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.insertOne(document);
|
return col.insertOne(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +61,7 @@ class Mongo {
|
|||||||
* @yield {Object} The operation result
|
* @yield {Object} The operation result
|
||||||
*/
|
*/
|
||||||
batch(documents, type) {
|
batch(documents, type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.insertMany(documents);
|
return col.insertMany(documents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +73,7 @@ class Mongo {
|
|||||||
* @yield {Object} The operation result
|
* @yield {Object} The operation result
|
||||||
*/
|
*/
|
||||||
update(query, diff, type) {
|
update(query, diff, type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.updateOne(query, {$set: diff});
|
return col.updateOne(query, {$set: diff});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +84,7 @@ class Mongo {
|
|||||||
* @yield {Object} The document object
|
* @yield {Object} The document object
|
||||||
*/
|
*/
|
||||||
get(query, type) {
|
get(query, type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.findOne(query);
|
return col.findOne(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +95,7 @@ class Mongo {
|
|||||||
* @yield {Array} An array of document objects
|
* @yield {Array} An array of document objects
|
||||||
*/
|
*/
|
||||||
list(query, type) {
|
list(query, type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.find(query).toArray();
|
return col.find(query).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +106,7 @@ class Mongo {
|
|||||||
* @yield {Object} The operation result
|
* @yield {Object} The operation result
|
||||||
*/
|
*/
|
||||||
remove(query, type) {
|
remove(query, type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.deleteMany(query);
|
return col.deleteMany(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +116,9 @@ class Mongo {
|
|||||||
* @yield {Object} The operation result
|
* @yield {Object} The operation result
|
||||||
*/
|
*/
|
||||||
clear(type) {
|
clear(type) {
|
||||||
let col = this._db.collection(type);
|
const col = this._db.collection(type);
|
||||||
return col.deleteMany({});
|
return col.deleteMany({});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Mongo;
|
module.exports = Mongo;
|
@ -26,7 +26,6 @@ const openpgpEncrypt = require('nodemailer-openpgp').openpgpEncrypt;
|
|||||||
* A simple wrapper around Nodemailer to send verification emails
|
* A simple wrapper around Nodemailer to send verification emails
|
||||||
*/
|
*/
|
||||||
class Email {
|
class Email {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of the reusable nodemailer SMTP transport.
|
* Create an instance of the reusable nodemailer SMTP transport.
|
||||||
* @param {string} host SMTP server's hostname: 'smtp.gmail.com'
|
* @param {string} host SMTP server's hostname: 'smtp.gmail.com'
|
||||||
@ -60,7 +59,7 @@ class Email {
|
|||||||
* @yield {Object} send response from the SMTP server
|
* @yield {Object} send response from the SMTP server
|
||||||
*/
|
*/
|
||||||
*send({template, userId, keyId, origin}) {
|
*send({template, userId, keyId, origin}) {
|
||||||
let message = {
|
const message = {
|
||||||
from: this._sender,
|
from: this._sender,
|
||||||
to: userId,
|
to: userId,
|
||||||
subject: template.subject,
|
subject: template.subject,
|
||||||
@ -69,7 +68,7 @@ class Email {
|
|||||||
params: {
|
params: {
|
||||||
name: userId.name,
|
name: userId.name,
|
||||||
baseUrl: util.url(origin),
|
baseUrl: util.url(origin),
|
||||||
keyId: keyId,
|
keyId,
|
||||||
nonce: userId.nonce
|
nonce: userId.nonce
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -87,19 +86,19 @@ class Email {
|
|||||||
* @yield {Object} reponse object containing SMTP info
|
* @yield {Object} reponse object containing SMTP info
|
||||||
*/
|
*/
|
||||||
*_sendHelper({from, to, subject, text, html, params = {}}) {
|
*_sendHelper({from, to, subject, text, html, params = {}}) {
|
||||||
let template = {
|
const template = {
|
||||||
subject,
|
subject,
|
||||||
text,
|
text,
|
||||||
html,
|
html,
|
||||||
encryptionKeys: [to.publicKeyArmored]
|
encryptionKeys: [to.publicKeyArmored]
|
||||||
};
|
};
|
||||||
let sender = {
|
const sender = {
|
||||||
from: {
|
from: {
|
||||||
name: from.name,
|
name: from.name,
|
||||||
address: from.email
|
address: from.email
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let recipient = {
|
const recipient = {
|
||||||
to: {
|
to: {
|
||||||
name: to.name,
|
name: to.name,
|
||||||
address: to.email
|
address: to.email
|
||||||
@ -107,8 +106,8 @@ class Email {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let sendFn = this._transport.templateSender(template, sender);
|
const sendFn = this._transport.templateSender(template, sender);
|
||||||
let info = yield sendFn(recipient, params);
|
const info = yield sendFn(recipient, params);
|
||||||
if (!this._checkResponse(info)) {
|
if (!this._checkResponse(info)) {
|
||||||
log.warn('email', 'Message may not have been received.', info);
|
log.warn('email', 'Message may not have been received.', info);
|
||||||
}
|
}
|
||||||
@ -128,7 +127,6 @@ class Email {
|
|||||||
_checkResponse(info) {
|
_checkResponse(info) {
|
||||||
return /^2/.test(info.response);
|
return /^2/.test(info.response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Email;
|
module.exports = Email;
|
@ -25,7 +25,6 @@ const util = require('../service/util');
|
|||||||
* See https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00
|
* See https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00
|
||||||
*/
|
*/
|
||||||
class HKP {
|
class HKP {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of the HKP server
|
* Create an instance of the HKP server
|
||||||
* @param {Object} publicKey An instance of the public key service
|
* @param {Object} publicKey An instance of the public key service
|
||||||
@ -39,12 +38,11 @@ class HKP {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*add(ctx) {
|
*add(ctx) {
|
||||||
let body = yield parse.form(ctx, { limit: '1mb' });
|
const {keytext: publicKeyArmored} = yield parse.form(ctx, {limit: '1mb'});
|
||||||
let publicKeyArmored = body.keytext;
|
|
||||||
if (!publicKeyArmored) {
|
if (!publicKeyArmored) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
let origin = util.origin(ctx);
|
const origin = util.origin(ctx);
|
||||||
yield this._publicKey.put({publicKeyArmored, origin});
|
yield this._publicKey.put({publicKeyArmored, origin});
|
||||||
ctx.body = 'Upload successful. Check your inbox to verify your email address.';
|
ctx.body = 'Upload successful. Check your inbox to verify your email address.';
|
||||||
ctx.status = 201;
|
ctx.status = 201;
|
||||||
@ -55,8 +53,8 @@ class HKP {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*lookup(ctx) {
|
*lookup(ctx) {
|
||||||
let params = this.parseQueryString(ctx);
|
const params = this.parseQueryString(ctx);
|
||||||
let key = yield this._publicKey.get(params);
|
const key = yield this._publicKey.get(params);
|
||||||
this.setGetHeaders(ctx, params);
|
this.setGetHeaders(ctx, params);
|
||||||
this.setGetBody(ctx, params, key);
|
this.setGetBody(ctx, params, key);
|
||||||
}
|
}
|
||||||
@ -68,12 +66,12 @@ class HKP {
|
|||||||
* @return {Object} The query parameters or undefined for an invalid request
|
* @return {Object} The query parameters or undefined for an invalid request
|
||||||
*/
|
*/
|
||||||
parseQueryString(ctx) {
|
parseQueryString(ctx) {
|
||||||
let params = {
|
const params = {
|
||||||
op: ctx.query.op, // operation ... only 'get' is supported
|
op: ctx.query.op, // operation ... only 'get' is supported
|
||||||
mr: ctx.query.options === 'mr' // machine readable
|
mr: ctx.query.options === 'mr' // machine readable
|
||||||
};
|
};
|
||||||
if (this.checkId(ctx.query.search)) {
|
if (this.checkId(ctx.query.search)) {
|
||||||
let id = ctx.query.search.replace(/^0x/, '');
|
const id = ctx.query.search.replace(/^0x/, '');
|
||||||
params.keyId = util.isKeyId(id) ? id : undefined;
|
params.keyId = util.isKeyId(id) ? id : undefined;
|
||||||
params.fingerprint = util.isFingerPrint(id) ? id : undefined;
|
params.fingerprint = util.isFingerPrint(id) ? id : undefined;
|
||||||
} else if (util.isEmail(ctx.query.search)) {
|
} else if (util.isEmail(ctx.query.search)) {
|
||||||
@ -125,20 +123,19 @@ class HKP {
|
|||||||
if (params.op === 'get') {
|
if (params.op === 'get') {
|
||||||
ctx.body = key.publicKeyArmored;
|
ctx.body = key.publicKeyArmored;
|
||||||
} else if (['index', 'vindex'].indexOf(params.op) !== -1) {
|
} else if (['index', 'vindex'].indexOf(params.op) !== -1) {
|
||||||
const VERSION = 1, COUNT = 1; // number of keys
|
const VERSION = 1;
|
||||||
let fp = key.fingerprint.toUpperCase();
|
const COUNT = 1; // number of keys
|
||||||
let algo = (key.algorithm.indexOf('rsa') !== -1) ? 1 : '';
|
const fp = key.fingerprint.toUpperCase();
|
||||||
let created = key.created ? (key.created.getTime() / 1000) : '';
|
const algo = (key.algorithm.indexOf('rsa') !== -1) ? 1 : '';
|
||||||
|
const created = key.created ? (key.created.getTime() / 1000) : '';
|
||||||
|
|
||||||
ctx.body = 'info:' + VERSION + ':' + COUNT + '\n' +
|
ctx.body = `info:${VERSION}:${COUNT}\npub:${fp}:${algo}:${key.keySize}:${created}::\n`;
|
||||||
'pub:' + fp + ':' + algo + ':' + key.keySize + ':' + created + '::\n';
|
|
||||||
|
|
||||||
for (let uid of key.userIds) {
|
for (const uid of key.userIds) {
|
||||||
ctx.body += 'uid:' + encodeURIComponent(uid.name + ' <' + uid.email + '>') + ':::\n';
|
ctx.body += `uid:${encodeURIComponent(`${uid.name} <${uid.email}>`)}:::\n`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = HKP;
|
module.exports = HKP;
|
@ -24,7 +24,6 @@ const util = require('../service/util');
|
|||||||
* The REST api to provide additional functionality on top of HKP
|
* The REST api to provide additional functionality on top of HKP
|
||||||
*/
|
*/
|
||||||
class REST {
|
class REST {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of the REST server
|
* Create an instance of the REST server
|
||||||
* @param {Object} publicKey An instance of the public key service
|
* @param {Object} publicKey An instance of the public key service
|
||||||
@ -39,12 +38,11 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*create(ctx) {
|
*create(ctx) {
|
||||||
let q = yield parse.json(ctx, { limit: '1mb' });
|
const {publicKeyArmored, primaryEmail} = yield parse.json(ctx, {limit: '1mb'});
|
||||||
let publicKeyArmored = q.publicKeyArmored, primaryEmail = q.primaryEmail;
|
|
||||||
if (!publicKeyArmored || (primaryEmail && !util.isEmail(primaryEmail))) {
|
if (!publicKeyArmored || (primaryEmail && !util.isEmail(primaryEmail))) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
let origin = util.origin(ctx);
|
const origin = util.origin(ctx);
|
||||||
yield this._publicKey.put({publicKeyArmored, primaryEmail, origin});
|
yield this._publicKey.put({publicKeyArmored, primaryEmail, origin});
|
||||||
ctx.body = 'Upload successful. Check your inbox to verify your email address.';
|
ctx.body = 'Upload successful. Check your inbox to verify your email address.';
|
||||||
ctx.status = 201;
|
ctx.status = 201;
|
||||||
@ -55,12 +53,12 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*query(ctx) {
|
*query(ctx) {
|
||||||
let op = ctx.query.op;
|
const op = ctx.query.op;
|
||||||
if (op === 'verify' || op === 'verifyRemove') {
|
if (op === 'verify' || op === 'verifyRemove') {
|
||||||
return yield this[op](ctx); // delegate operation
|
return yield this[op](ctx); // delegate operation
|
||||||
}
|
}
|
||||||
// do READ if no 'op' provided
|
// do READ if no 'op' provided
|
||||||
let q = { keyId:ctx.query.keyId, fingerprint:ctx.query.fingerprint, email:ctx.query.email };
|
const q = {keyId: ctx.query.keyId, fingerprint: ctx.query.fingerprint, email: ctx.query.email};
|
||||||
if (!util.isKeyId(q.keyId) && !util.isFingerPrint(q.fingerprint) && !util.isEmail(q.email)) {
|
if (!util.isKeyId(q.keyId) && !util.isFingerPrint(q.fingerprint) && !util.isEmail(q.email)) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
@ -72,13 +70,13 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*verify(ctx) {
|
*verify(ctx) {
|
||||||
let q = { keyId:ctx.query.keyId, nonce:ctx.query.nonce };
|
const q = {keyId: ctx.query.keyId, nonce: ctx.query.nonce};
|
||||||
if (!util.isKeyId(q.keyId) || !util.isString(q.nonce)) {
|
if (!util.isKeyId(q.keyId) || !util.isString(q.nonce)) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
yield this._publicKey.verify(q);
|
yield this._publicKey.verify(q);
|
||||||
// create link for sharing
|
// create link for sharing
|
||||||
let link = util.url(util.origin(ctx), '/pks/lookup?op=get&search=0x' + q.keyId.toUpperCase());
|
const link = util.url(util.origin(ctx), `/pks/lookup?op=get&search=0x${q.keyId.toUpperCase()}`);
|
||||||
ctx.body = `<p>Email address successfully verified!</p><p>Link to share your key: <a href="${link}" target="_blank">${link}</a></p>`;
|
ctx.body = `<p>Email address successfully verified!</p><p>Link to share your key: <a href="${link}" target="_blank">${link}</a></p>`;
|
||||||
ctx.set('Content-Type', 'text/html; charset=utf-8');
|
ctx.set('Content-Type', 'text/html; charset=utf-8');
|
||||||
}
|
}
|
||||||
@ -88,7 +86,7 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*remove(ctx) {
|
*remove(ctx) {
|
||||||
let q = { keyId:ctx.query.keyId, email:ctx.query.email, origin:util.origin(ctx) };
|
const q = {keyId: ctx.query.keyId, email: ctx.query.email, origin: util.origin(ctx)};
|
||||||
if (!util.isKeyId(q.keyId) && !util.isEmail(q.email)) {
|
if (!util.isKeyId(q.keyId) && !util.isEmail(q.email)) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
@ -102,14 +100,13 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*verifyRemove(ctx) {
|
*verifyRemove(ctx) {
|
||||||
let q = { keyId:ctx.query.keyId, nonce:ctx.query.nonce };
|
const q = {keyId: ctx.query.keyId, nonce: ctx.query.nonce};
|
||||||
if (!util.isKeyId(q.keyId) || !util.isString(q.nonce)) {
|
if (!util.isKeyId(q.keyId) || !util.isString(q.nonce)) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
yield this._publicKey.verifyRemove(q);
|
yield this._publicKey.verifyRemove(q);
|
||||||
ctx.body = 'Key successfully removed!';
|
ctx.body = 'Key successfully removed!';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = REST;
|
module.exports = REST;
|
@ -29,7 +29,6 @@ const KEY_END = '-----END PGP PUBLIC KEY BLOCK-----';
|
|||||||
* A simple wrapper around OpenPGP.js
|
* A simple wrapper around OpenPGP.js
|
||||||
*/
|
*/
|
||||||
class PGP {
|
class PGP {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an ascii armored pgp key block and get its parameters.
|
* Parse an ascii armored pgp key block and get its parameters.
|
||||||
* @param {String} publicKeyArmored ascii armored pgp key block
|
* @param {String} publicKeyArmored ascii armored pgp key block
|
||||||
@ -38,9 +37,9 @@ class PGP {
|
|||||||
parseKey(publicKeyArmored) {
|
parseKey(publicKeyArmored) {
|
||||||
publicKeyArmored = this.trimKey(publicKeyArmored);
|
publicKeyArmored = this.trimKey(publicKeyArmored);
|
||||||
|
|
||||||
let r = openpgp.key.readArmored(publicKeyArmored);
|
const r = openpgp.key.readArmored(publicKeyArmored);
|
||||||
if (r.err) {
|
if (r.err) {
|
||||||
let error = r.err[0];
|
const error = r.err[0];
|
||||||
log.error('pgp', 'Failed to parse PGP key:\n%s', publicKeyArmored, error);
|
log.error('pgp', 'Failed to parse PGP key:\n%s', publicKeyArmored, error);
|
||||||
util.throw(500, 'Failed to parse PGP key');
|
util.throw(500, 'Failed to parse PGP key');
|
||||||
} else if (!r.keys || r.keys.length !== 1 || !r.keys[0].primaryKey) {
|
} else if (!r.keys || r.keys.length !== 1 || !r.keys[0].primaryKey) {
|
||||||
@ -48,21 +47,21 @@ class PGP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verify primary key
|
// verify primary key
|
||||||
let key = r.keys[0];
|
const key = r.keys[0];
|
||||||
let primaryKey = key.primaryKey;
|
const primaryKey = key.primaryKey;
|
||||||
if (key.verifyPrimaryKey() !== openpgp.enums.keyStatus.valid) {
|
if (key.verifyPrimaryKey() !== openpgp.enums.keyStatus.valid) {
|
||||||
util.throw(400, 'Invalid PGP key: primary key verification failed');
|
util.throw(400, 'Invalid PGP key: primary key verification failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept version 4 keys only
|
// accept version 4 keys only
|
||||||
let keyId = primaryKey.getKeyId().toHex();
|
const keyId = primaryKey.getKeyId().toHex();
|
||||||
let fingerprint = primaryKey.fingerprint;
|
const fingerprint = primaryKey.fingerprint;
|
||||||
if (!util.isKeyId(keyId) || !util.isFingerPrint(fingerprint)) {
|
if (!util.isKeyId(keyId) || !util.isFingerPrint(fingerprint)) {
|
||||||
util.throw(400, 'Invalid PGP key: only v4 keys are accepted');
|
util.throw(400, 'Invalid PGP key: only v4 keys are accepted');
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for at least one valid user id
|
// check for at least one valid user id
|
||||||
let userIds = this.parseUserIds(key.users, primaryKey);
|
const userIds = this.parseUserIds(key.users, primaryKey);
|
||||||
if (!userIds.length) {
|
if (!userIds.length) {
|
||||||
util.throw(400, 'Invalid PGP key: invalid user ids');
|
util.throw(400, 'Invalid PGP key: invalid user ids');
|
||||||
}
|
}
|
||||||
@ -115,16 +114,16 @@ class PGP {
|
|||||||
util.throw(400, 'Invalid PGP key: no user id found');
|
util.throw(400, 'Invalid PGP key: no user id found');
|
||||||
}
|
}
|
||||||
// at least one user id signature must be valid
|
// at least one user id signature must be valid
|
||||||
let result = [];
|
const result = [];
|
||||||
for (let user of users) {
|
for (const user of users) {
|
||||||
let oneValid = false;
|
let oneValid = false;
|
||||||
for (let cert of user.selfCertifications) {
|
for (const cert of user.selfCertifications) {
|
||||||
if (user.isValidSelfCertificate(primaryKey, cert)) {
|
if (user.isValidSelfCertificate(primaryKey, cert)) {
|
||||||
oneValid = true;
|
oneValid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (oneValid && user.userId && user.userId.userid) {
|
if (oneValid && user.userId && user.userId.userid) {
|
||||||
let uid = addressparser(user.userId.userid)[0];
|
const uid = addressparser(user.userId.userid)[0];
|
||||||
if (util.isEmail(uid.address)) {
|
if (util.isEmail(uid.address)) {
|
||||||
result.push(uid);
|
result.push(uid);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@ const DB_TYPE = 'publickey';
|
|||||||
* A service that handlers PGP public keys queries to the database
|
* A service that handlers PGP public keys queries to the database
|
||||||
*/
|
*/
|
||||||
class PublicKey {
|
class PublicKey {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of the service
|
* Create an instance of the service
|
||||||
* @param {Object} pgp An instance of the OpenPGP.js wrapper
|
* @param {Object} pgp An instance of the OpenPGP.js wrapper
|
||||||
@ -68,9 +67,9 @@ class PublicKey {
|
|||||||
*/
|
*/
|
||||||
*put({publicKeyArmored, primaryEmail, origin}) {
|
*put({publicKeyArmored, primaryEmail, origin}) {
|
||||||
// parse key block
|
// parse key block
|
||||||
let key = this._pgp.parseKey(publicKeyArmored);
|
const key = this._pgp.parseKey(publicKeyArmored);
|
||||||
// check for existing verfied key by id or email addresses
|
// check for existing verfied key by id or email addresses
|
||||||
let verified = yield this.getVerified(key);
|
const verified = yield this.getVerified(key);
|
||||||
if (verified) {
|
if (verified) {
|
||||||
util.throw(304, 'Key for this user already exists');
|
util.throw(304, 'Key for this user already exists');
|
||||||
}
|
}
|
||||||
@ -89,11 +88,11 @@ class PublicKey {
|
|||||||
// delete old/unverified key
|
// delete old/unverified key
|
||||||
yield this._mongo.remove({keyId: key.keyId}, DB_TYPE);
|
yield this._mongo.remove({keyId: key.keyId}, DB_TYPE);
|
||||||
// generate nonces for verification
|
// generate nonces for verification
|
||||||
for (let uid of key.userIds) {
|
for (const uid of key.userIds) {
|
||||||
uid.nonce = util.random();
|
uid.nonce = util.random();
|
||||||
}
|
}
|
||||||
// persist new key
|
// persist new key
|
||||||
let r = yield this._mongo.create(key, DB_TYPE);
|
const r = yield this._mongo.create(key, DB_TYPE);
|
||||||
if (r.insertedCount !== 1) {
|
if (r.insertedCount !== 1) {
|
||||||
util.throw(500, 'Failed to persist key');
|
util.throw(500, 'Failed to persist key');
|
||||||
}
|
}
|
||||||
@ -107,16 +106,15 @@ class PublicKey {
|
|||||||
* @param {Object} origin the server's origin (required for email links)
|
* @param {Object} origin the server's origin (required for email links)
|
||||||
* @yield {undefined}
|
* @yield {undefined}
|
||||||
*/
|
*/
|
||||||
*_sendVerifyEmail(key, primaryEmail, origin) {
|
*_sendVerifyEmail({userIds, keyId, publicKeyArmored}, primaryEmail, origin) {
|
||||||
let userIds = key.userIds, keyId = key.keyId;
|
|
||||||
// check for primary email (send only one email)
|
// check for primary email (send only one email)
|
||||||
let primaryUserId = userIds.find(uid => uid.email === primaryEmail);
|
const primaryUserId = userIds.find(uid => uid.email === primaryEmail);
|
||||||
if (primaryUserId) {
|
if (primaryUserId) {
|
||||||
userIds = [primaryUserId];
|
userIds = [primaryUserId];
|
||||||
}
|
}
|
||||||
// send emails
|
// send emails
|
||||||
for (let userId of userIds) {
|
for (const userId of userIds) {
|
||||||
userId.publicKeyArmored = key.publicKeyArmored; // set key for encryption
|
userId.publicKeyArmored = publicKeyArmored; // set key for encryption
|
||||||
yield this._email.send({template: tpl.verifyKey, userId, keyId, origin});
|
yield this._email.send({template: tpl.verifyKey, userId, keyId, origin});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,13 +127,13 @@ class PublicKey {
|
|||||||
*/
|
*/
|
||||||
*verify({keyId, nonce}) {
|
*verify({keyId, nonce}) {
|
||||||
// look for verification nonce in database
|
// look for verification nonce in database
|
||||||
let query = { keyId, 'userIds.nonce':nonce };
|
const query = {keyId, 'userIds.nonce': nonce};
|
||||||
let key = yield this._mongo.get(query, DB_TYPE);
|
const key = yield this._mongo.get(query, DB_TYPE);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
util.throw(404, 'User id not found');
|
util.throw(404, 'User id not found');
|
||||||
}
|
}
|
||||||
// check if user ids of this key have already been verified in another key
|
// check if user ids of this key have already been verified in another key
|
||||||
let verified = yield this.getVerified(key);
|
const verified = yield this.getVerified(key);
|
||||||
if (verified && verified.keyId !== keyId) {
|
if (verified && verified.keyId !== keyId) {
|
||||||
util.throw(304, 'Key for this user already exists');
|
util.throw(304, 'Key for this user already exists');
|
||||||
}
|
}
|
||||||
@ -195,8 +193,8 @@ class PublicKey {
|
|||||||
*/
|
*/
|
||||||
*get({fingerprint, keyId, email}) {
|
*get({fingerprint, keyId, email}) {
|
||||||
// look for verified key
|
// look for verified key
|
||||||
let userIds = email ? [{ email:email }] : undefined;
|
const userIds = email ? [{email}] : undefined;
|
||||||
let key = yield this.getVerified({ keyId, fingerprint, userIds });
|
const key = yield this.getVerified({keyId, fingerprint, userIds});
|
||||||
if (!key) {
|
if (!key) {
|
||||||
util.throw(404, 'Key not found');
|
util.throw(404, 'Key not found');
|
||||||
}
|
}
|
||||||
@ -222,13 +220,13 @@ class PublicKey {
|
|||||||
*/
|
*/
|
||||||
*requestRemove({keyId, email, origin}) {
|
*requestRemove({keyId, email, origin}) {
|
||||||
// flag user ids for removal
|
// flag user ids for removal
|
||||||
let key = yield this._flagForRemove(keyId, email);
|
const key = yield this._flagForRemove(keyId, email);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
util.throw(404, 'User id not found');
|
util.throw(404, 'User id not found');
|
||||||
}
|
}
|
||||||
// send verification mails
|
// send verification mails
|
||||||
keyId = key.keyId; // get keyId in case request was by email
|
keyId = key.keyId; // get keyId in case request was by email
|
||||||
for (let userId of key.userIds) {
|
for (const userId of key.userIds) {
|
||||||
yield this._email.send({template: tpl.verifyRemove, userId, keyId, origin});
|
yield this._email.send({template: tpl.verifyRemove, userId, keyId, origin});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,23 +239,23 @@ class PublicKey {
|
|||||||
* @yield {Array} A list of user ids with nonces
|
* @yield {Array} A list of user ids with nonces
|
||||||
*/
|
*/
|
||||||
*_flagForRemove(keyId, email) {
|
*_flagForRemove(keyId, email) {
|
||||||
let query = email ? { 'userIds.email':email } : { keyId };
|
const query = email ? {'userIds.email': email} : {keyId};
|
||||||
let key = yield this._mongo.get(query, DB_TYPE);
|
const key = yield this._mongo.get(query, DB_TYPE);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// flag only the provided user id
|
// flag only the provided user id
|
||||||
if (email) {
|
if (email) {
|
||||||
let nonce = util.random();
|
const nonce = util.random();
|
||||||
yield this._mongo.update(query, {'userIds.$.nonce': nonce}, DB_TYPE);
|
yield this._mongo.update(query, {'userIds.$.nonce': nonce}, DB_TYPE);
|
||||||
let uid = key.userIds.find(u => u.email === email);
|
const uid = key.userIds.find(u => u.email === email);
|
||||||
uid.nonce = nonce;
|
uid.nonce = nonce;
|
||||||
return {userIds: [uid], keyId: key.keyId};
|
return {userIds: [uid], keyId: key.keyId};
|
||||||
}
|
}
|
||||||
// flag all key user ids
|
// flag all key user ids
|
||||||
if (keyId) {
|
if (keyId) {
|
||||||
for (let uid of key.userIds) {
|
for (const uid of key.userIds) {
|
||||||
let nonce = util.random();
|
const nonce = util.random();
|
||||||
yield this._mongo.update({'userIds.email': uid.email}, {'userIds.$.nonce': nonce}, DB_TYPE);
|
yield this._mongo.update({'userIds.email': uid.email}, {'userIds.$.nonce': nonce}, DB_TYPE);
|
||||||
uid.nonce = nonce;
|
uid.nonce = nonce;
|
||||||
}
|
}
|
||||||
@ -274,14 +272,13 @@ class PublicKey {
|
|||||||
*/
|
*/
|
||||||
*verifyRemove({keyId, nonce}) {
|
*verifyRemove({keyId, nonce}) {
|
||||||
// check if key exists in database
|
// check if key exists in database
|
||||||
let flagged = yield this._mongo.get({ keyId, 'userIds.nonce':nonce }, DB_TYPE);
|
const flagged = yield this._mongo.get({keyId, 'userIds.nonce': nonce}, DB_TYPE);
|
||||||
if (!flagged) {
|
if (!flagged) {
|
||||||
util.throw(404, 'User id not found');
|
util.throw(404, 'User id not found');
|
||||||
}
|
}
|
||||||
// delete the key
|
// delete the key
|
||||||
yield this._mongo.remove({keyId}, DB_TYPE);
|
yield this._mongo.remove({keyId}, DB_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = PublicKey;
|
module.exports = PublicKey;
|
@ -37,7 +37,7 @@ exports.isTrue = function(data) {
|
|||||||
if (this.isString(data)) {
|
if (this.isString(data)) {
|
||||||
return data === 'true';
|
return data === 'true';
|
||||||
} else {
|
} else {
|
||||||
return !!data;
|
return Boolean(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ exports.isEmail = function(data) {
|
|||||||
* @return {Error} The resulting error object
|
* @return {Error} The resulting error object
|
||||||
*/
|
*/
|
||||||
exports.throw = function(status, message) {
|
exports.throw = function(status, message) {
|
||||||
let err = new Error(message);
|
const err = new Error(message);
|
||||||
err.status = status;
|
err.status = status;
|
||||||
err.expose = true; // display message to the client
|
err.expose = true; // display message to the client
|
||||||
throw err;
|
throw err;
|
||||||
@ -143,7 +143,7 @@ exports.origin = function(ctx) {
|
|||||||
* @return {string} The complete url
|
* @return {string} The complete url
|
||||||
*/
|
*/
|
||||||
exports.url = function(origin, resource) {
|
exports.url = function(origin, resource) {
|
||||||
return origin.protocol + '://' + origin.host + (resource || '');
|
return `${origin.protocol}://${origin.host}${resource || ''}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
;(function($) {
|
;(function($) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
13
test/.eslintrc
Normal file
13
test/.eslintrc
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../.eslintrc",
|
||||||
|
"rules": {
|
||||||
|
"no-shadow": 1
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"expect": true,
|
||||||
|
"sinon": true
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"mocha": true
|
||||||
|
}
|
||||||
|
}
|
@ -5,12 +5,16 @@ const Mongo = require('../../src/dao/mongo');
|
|||||||
const nodemailer = require('nodemailer');
|
const nodemailer = require('nodemailer');
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const log = require('npmlog');
|
||||||
|
|
||||||
describe('Koa App (HTTP Server) Integration Tests', function() {
|
describe('Koa App (HTTP Server) Integration Tests', function() {
|
||||||
this.timeout(20000);
|
this.timeout(20000);
|
||||||
|
|
||||||
let app, mongo,
|
let app;
|
||||||
sendEmailStub, publicKeyArmored, emailParams;
|
let mongo;
|
||||||
|
let sendEmailStub;
|
||||||
|
let publicKeyArmored;
|
||||||
|
let emailParams;
|
||||||
|
|
||||||
const DB_TYPE_PUB_KEY = 'publickey';
|
const DB_TYPE_PUB_KEY = 'publickey';
|
||||||
const DB_TYPE_USER_ID = 'userid';
|
const DB_TYPE_USER_ID = 'userid';
|
||||||
@ -18,24 +22,24 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
const fingerprint = '4277257930867231CE393FB8DBC0B3D92B1B86E9';
|
const fingerprint = '4277257930867231CE393FB8DBC0B3D92B1B86E9';
|
||||||
|
|
||||||
before(function *() {
|
before(function *() {
|
||||||
publicKeyArmored = fs.readFileSync(__dirname + '/../key1.asc', 'utf8');
|
publicKeyArmored = fs.readFileSync(`${__dirname}/../key1.asc`, 'utf8');
|
||||||
mongo = new Mongo();
|
mongo = new Mongo();
|
||||||
yield mongo.init(config.mongo);
|
yield mongo.init(config.mongo);
|
||||||
|
|
||||||
sendEmailStub = sinon.stub().returns(Promise.resolve({response: '250'}));
|
sendEmailStub = sinon.stub().returns(Promise.resolve({response: '250'}));
|
||||||
sendEmailStub.withArgs(sinon.match(recipient => {
|
sendEmailStub.withArgs(sinon.match(recipient => recipient.to.address === primaryEmail), sinon.match(params => {
|
||||||
return recipient.to.address === primaryEmail;
|
|
||||||
}), sinon.match(params => {
|
|
||||||
emailParams = params;
|
emailParams = params;
|
||||||
return !!params.nonce;
|
return Boolean(params.nonce);
|
||||||
}));
|
}));
|
||||||
sinon.stub(nodemailer, 'createTransport').returns({
|
sinon.stub(nodemailer, 'createTransport').returns({
|
||||||
templateSender: () => { return sendEmailStub; },
|
templateSender: () => sendEmailStub,
|
||||||
use: function() {}
|
use() {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sinon.stub(log);
|
||||||
|
|
||||||
global.testing = true;
|
global.testing = true;
|
||||||
let init = require('../../src/app');
|
const init = require('../../src/app');
|
||||||
app = yield init();
|
app = yield init();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,6 +50,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
after(function *() {
|
after(function *() {
|
||||||
|
sinon.restore(log);
|
||||||
nodemailer.createTransport.restore();
|
nodemailer.createTransport.restore();
|
||||||
yield mongo.clear(DB_TYPE_PUB_KEY);
|
yield mongo.clear(DB_TYPE_PUB_KEY);
|
||||||
yield mongo.clear(DB_TYPE_USER_ID);
|
yield mongo.clear(DB_TYPE_USER_ID);
|
||||||
@ -104,21 +109,21 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 200 for valid params', done => {
|
it('should return 200 for valid params', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verify&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce)
|
.get(`/api/v1/key?op=verify&keyId=${emailParams.keyId}&nonce=${emailParams.nonce}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 400 for missing keyid and', done => {
|
it('should return 400 for missing keyid and', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verify&nonce=' + emailParams.nonce)
|
.get(`/api/v1/key?op=verify&nonce=${emailParams.nonce}`)
|
||||||
.expect(400)
|
.expect(400)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 400 for missing nonce', done => {
|
it('should return 400 for missing nonce', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verify&keyId=' + emailParams.keyId)
|
.get(`/api/v1/key?op=verify&keyId=${emailParams.keyId}`)
|
||||||
.expect(400)
|
.expect(400)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -136,7 +141,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
describe('Not yet verified', () => {
|
describe('Not yet verified', () => {
|
||||||
it('should return 404', done => {
|
it('should return 404', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?keyId=' + emailParams.keyId)
|
.get(`/api/v1/key?keyId=${emailParams.keyId}`)
|
||||||
.expect(404).end(done);
|
.expect(404).end(done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -144,21 +149,21 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
describe('Verified', () => {
|
describe('Verified', () => {
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verify&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce)
|
.get(`/api/v1/key?op=verify&keyId=${emailParams.keyId}&nonce=${emailParams.nonce}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 and get key by id', done => {
|
it('should return 200 and get key by id', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?keyId=' + emailParams.keyId)
|
.get(`/api/v1/key?keyId=${emailParams.keyId}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 and get key email address', done => {
|
it('should return 200 and get key email address', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?email=' + primaryEmail)
|
.get(`/api/v1/key?email=${primaryEmail}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -197,14 +202,14 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 202 for key id', done => {
|
it('should return 202 for key id', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.del('/api/v1/key?keyId=' + emailParams.keyId)
|
.del(`/api/v1/key?keyId=${emailParams.keyId}`)
|
||||||
.expect(202)
|
.expect(202)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 202 for email address', done => {
|
it('should return 202 for email address', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.del('/api/v1/key?email=' + primaryEmail)
|
.del(`/api/v1/key?email=${primaryEmail}`)
|
||||||
.expect(202)
|
.expect(202)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -230,9 +235,9 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
.post('/api/v1/key')
|
.post('/api/v1/key')
|
||||||
.send({publicKeyArmored, primaryEmail})
|
.send({publicKeyArmored, primaryEmail})
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.end(function() {
|
.end(() => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.del('/api/v1/key?keyId=' + emailParams.keyId)
|
.del(`/api/v1/key?keyId=${emailParams.keyId}`)
|
||||||
.expect(202)
|
.expect(202)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -240,7 +245,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 200 for key id', done => {
|
it('should return 200 for key id', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verifyRemove&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce)
|
.get(`/api/v1/key?op=verifyRemove&keyId=${emailParams.keyId}&nonce=${emailParams.nonce}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -254,7 +259,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 404 for unknown key id', done => {
|
it('should return 404 for unknown key id', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verifyRemove&keyId=0123456789ABCDEF&nonce=' + emailParams.nonce)
|
.get(`/api/v1/key?op=verifyRemove&keyId=0123456789ABCDEF&nonce=${emailParams.nonce}`)
|
||||||
.expect(404)
|
.expect(404)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -276,7 +281,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
request(app.listen())
|
request(app.listen())
|
||||||
.post('/pks/add')
|
.post('/pks/add')
|
||||||
.type('form')
|
.type('form')
|
||||||
.send('keytext=' + encodeURIComponent(publicKeyArmored))
|
.send(`keytext=${encodeURIComponent(publicKeyArmored)}`)
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -287,7 +292,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
request(app.listen())
|
request(app.listen())
|
||||||
.post('/pks/add')
|
.post('/pks/add')
|
||||||
.type('form')
|
.type('form')
|
||||||
.send('keytext=' + encodeURIComponent(publicKeyArmored))
|
.send(`keytext=${encodeURIComponent(publicKeyArmored)}`)
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -295,7 +300,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
describe('Not yet verified', () => {
|
describe('Not yet verified', () => {
|
||||||
it('should return 404', done => {
|
it('should return 404', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&search=0x' + emailParams.keyId)
|
.get(`/pks/lookup?op=get&search=0x${emailParams.keyId}`)
|
||||||
.expect(404)
|
.expect(404)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -304,35 +309,35 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
describe('Verified', () => {
|
describe('Verified', () => {
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?op=verify&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce)
|
.get(`/api/v1/key?op=verify&keyId=${emailParams.keyId}&nonce=${emailParams.nonce}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 for key id', done => {
|
it('should return 200 for key id', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&search=0x' + emailParams.keyId)
|
.get(`/pks/lookup?op=get&search=0x${emailParams.keyId}`)
|
||||||
.expect(200, publicKeyArmored)
|
.expect(200, publicKeyArmored)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 for fingerprint', done => {
|
it('should return 200 for fingerprint', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&search=0x' + fingerprint)
|
.get(`/pks/lookup?op=get&search=0x${fingerprint}`)
|
||||||
.expect(200, publicKeyArmored)
|
.expect(200, publicKeyArmored)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 for correct email address', done => {
|
it('should return 200 for correct email address', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&search=' + primaryEmail)
|
.get(`/pks/lookup?op=get&search=${primaryEmail}`)
|
||||||
.expect(200, publicKeyArmored)
|
.expect(200, publicKeyArmored)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 for "mr" option', done => {
|
it('should return 200 for "mr" option', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&options=mr&search=' + primaryEmail)
|
.get(`/pks/lookup?op=get&options=mr&search=${primaryEmail}`)
|
||||||
.expect('Content-Type', 'application/pgp-keys; charset=utf-8')
|
.expect('Content-Type', 'application/pgp-keys; charset=utf-8')
|
||||||
.expect('Content-Disposition', 'attachment; filename=openpgpkey.asc')
|
.expect('Content-Disposition', 'attachment; filename=openpgpkey.asc')
|
||||||
.expect(200, publicKeyArmored)
|
.expect(200, publicKeyArmored)
|
||||||
@ -341,14 +346,14 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 200 for "vindex" op', done => {
|
it('should return 200 for "vindex" op', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=vindex&search=0x' + emailParams.keyId)
|
.get(`/pks/lookup?op=vindex&search=0x${emailParams.keyId}`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 for "index" with "mr" option', done => {
|
it('should return 200 for "index" with "mr" option', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=index&options=mr&search=0x' + emailParams.keyId)
|
.get(`/pks/lookup?op=index&options=mr&search=0x${emailParams.keyId}`)
|
||||||
.expect('Content-Type', 'text/plain; charset=utf-8')
|
.expect('Content-Type', 'text/plain; charset=utf-8')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(done);
|
.end(done);
|
||||||
@ -377,7 +382,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 501 for a invalid key id format', done => {
|
it('should return 501 for a invalid key id format', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&search=' + emailParams.keyId)
|
.get(`/pks/lookup?op=get&search=${emailParams.keyId}`)
|
||||||
.expect(501)
|
.expect(501)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
@ -398,12 +403,11 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return 501 (Not implemented) for "x-email" op', done => {
|
it('should return 501 (Not implemented) for "x-email" op', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=x-email&search=0x' + emailParams.keyId)
|
.get(`/pks/lookup?op=x-email&search=0x${emailParams.keyId}`)
|
||||||
.expect(501)
|
.expect(501)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -7,15 +7,19 @@ const tpl = require('../../src/email/templates.json');
|
|||||||
describe('Email Integration Tests', function() {
|
describe('Email Integration Tests', function() {
|
||||||
this.timeout(20000);
|
this.timeout(20000);
|
||||||
|
|
||||||
let email, keyId, userId, origin, publicKeyArmored;
|
let email;
|
||||||
|
let keyId;
|
||||||
|
let userId;
|
||||||
|
let origin;
|
||||||
|
let publicKeyArmored;
|
||||||
|
|
||||||
const recipient = {name: 'Test User', email: 'safewithme.testuser@gmail.com'};
|
const recipient = {name: 'Test User', email: 'safewithme.testuser@gmail.com'};
|
||||||
|
|
||||||
before(function() {
|
before(() => {
|
||||||
publicKeyArmored = require('fs').readFileSync(__dirname + '/../key1.asc', 'utf8');
|
publicKeyArmored = require('fs').readFileSync(`${__dirname}/../key1.asc`, 'utf8');
|
||||||
origin = {
|
origin = {
|
||||||
protocol: 'http',
|
protocol: 'http',
|
||||||
host: 'localhost:' + config.server.port
|
host: `localhost:${config.server.port}`
|
||||||
};
|
};
|
||||||
email = new Email();
|
email = new Email();
|
||||||
email.init(config.email);
|
email.init(config.email);
|
||||||
@ -33,14 +37,14 @@ describe('Email Integration Tests', function() {
|
|||||||
|
|
||||||
describe("_sendHelper", () => {
|
describe("_sendHelper", () => {
|
||||||
it('should work', function *() {
|
it('should work', function *() {
|
||||||
let mailOptions = {
|
const mailOptions = {
|
||||||
from: email._sender,
|
from: email._sender,
|
||||||
to: recipient,
|
to: recipient,
|
||||||
subject: 'Hello ✔', // Subject line
|
subject: 'Hello ✔', // Subject line
|
||||||
text: 'Hello world 🐴', // plaintext body
|
text: 'Hello world 🐴', // plaintext body
|
||||||
html: '<b>Hello world 🐴</b>' // html body
|
html: '<b>Hello world 🐴</b>' // html body
|
||||||
};
|
};
|
||||||
let info = yield email._sendHelper(mailOptions);
|
const info = yield email._sendHelper(mailOptions);
|
||||||
expect(info).to.exist;
|
expect(info).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -66,5 +70,4 @@ describe('Email Integration Tests', function() {
|
|||||||
yield email.send({template: tpl.verifyRemove, userId, keyId, origin});
|
yield email.send({template: tpl.verifyRemove, userId, keyId, origin});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -25,7 +25,7 @@ describe('Mongo Integration Tests', function() {
|
|||||||
|
|
||||||
describe("create", () => {
|
describe("create", () => {
|
||||||
it('should insert a document', function *() {
|
it('should insert a document', function *() {
|
||||||
let r = yield mongo.create({ _id:'0' }, DB_TYPE);
|
const r = yield mongo.create({_id: '0'}, DB_TYPE);
|
||||||
expect(r.insertedCount).to.equal(1);
|
expect(r.insertedCount).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ describe('Mongo Integration Tests', function() {
|
|||||||
|
|
||||||
describe("batch", () => {
|
describe("batch", () => {
|
||||||
it('should insert a document', function *() {
|
it('should insert a document', function *() {
|
||||||
let r = yield mongo.batch([{ _id:'0' }, { _id:'1' }], DB_TYPE);
|
const r = yield mongo.batch([{_id: '0'}, {_id: '1'}], DB_TYPE);
|
||||||
expect(r.insertedCount).to.equal(2);
|
expect(r.insertedCount).to.equal(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,5 +91,4 @@ describe('Mongo Integration Tests', function() {
|
|||||||
expect(r).to.not.exist;
|
expect(r).to.not.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -10,8 +10,14 @@ const PublicKey = require('../../src/service/public-key');
|
|||||||
describe('Public Key Integration Tests', function() {
|
describe('Public Key Integration Tests', function() {
|
||||||
this.timeout(20000);
|
this.timeout(20000);
|
||||||
|
|
||||||
let publicKey, email, mongo, pgp,
|
let publicKey;
|
||||||
sendEmailStub, publicKeyArmored, publicKeyArmored2, mailsSent;
|
let email;
|
||||||
|
let mongo;
|
||||||
|
let pgp;
|
||||||
|
let sendEmailStub;
|
||||||
|
let publicKeyArmored;
|
||||||
|
let publicKeyArmored2;
|
||||||
|
let mailsSent;
|
||||||
|
|
||||||
const DB_TYPE = 'publickey';
|
const DB_TYPE = 'publickey';
|
||||||
const primaryEmail = 'test1@example.com';
|
const primaryEmail = 'test1@example.com';
|
||||||
@ -19,8 +25,8 @@ describe('Public Key Integration Tests', function() {
|
|||||||
const origin = {host: 'localhost', protocol: 'http'};
|
const origin = {host: 'localhost', protocol: 'http'};
|
||||||
|
|
||||||
before(function *() {
|
before(function *() {
|
||||||
publicKeyArmored = require('fs').readFileSync(__dirname + '/../key3.asc', 'utf8');
|
publicKeyArmored = require('fs').readFileSync(`${__dirname}/../key3.asc`, 'utf8');
|
||||||
publicKeyArmored2 = require('fs').readFileSync(__dirname + '/../key4.asc', 'utf8');
|
publicKeyArmored2 = require('fs').readFileSync(`${__dirname}/../key4.asc`, 'utf8');
|
||||||
mongo = new Mongo();
|
mongo = new Mongo();
|
||||||
yield mongo.init(config.mongo);
|
yield mongo.init(config.mongo);
|
||||||
});
|
});
|
||||||
@ -39,7 +45,7 @@ describe('Public Key Integration Tests', function() {
|
|||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
sinon.stub(nodemailer, 'createTransport').returns({
|
sinon.stub(nodemailer, 'createTransport').returns({
|
||||||
templateSender: () => { return sendEmailStub; }
|
templateSender: () => sendEmailStub
|
||||||
});
|
});
|
||||||
email = new Email(nodemailer);
|
email = new Email(nodemailer);
|
||||||
email.init({
|
email.init({
|
||||||
@ -95,9 +101,9 @@ describe('Public Key Integration Tests', function() {
|
|||||||
describe('verify', () => {
|
describe('verify', () => {
|
||||||
it('should update the document', function *() {
|
it('should update the document', function *() {
|
||||||
yield publicKey.put({publicKeyArmored, primaryEmail, origin});
|
yield publicKey.put({publicKeyArmored, primaryEmail, origin});
|
||||||
let emailParams = mailsSent[0].params;
|
const emailParams = mailsSent[0].params;
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let gotten = yield mongo.get({ keyId:emailParams.keyId }, DB_TYPE);
|
const gotten = yield mongo.get({keyId: emailParams.keyId}, DB_TYPE);
|
||||||
expect(gotten.userIds[0].verified).to.be.true;
|
expect(gotten.userIds[0].verified).to.be.true;
|
||||||
expect(gotten.userIds[0].nonce).to.be.null;
|
expect(gotten.userIds[0].nonce).to.be.null;
|
||||||
expect(gotten.userIds[1].verified).to.be.false;
|
expect(gotten.userIds[1].verified).to.be.false;
|
||||||
@ -106,14 +112,14 @@ describe('Public Key Integration Tests', function() {
|
|||||||
|
|
||||||
it('should not find the document', function *() {
|
it('should not find the document', function *() {
|
||||||
yield publicKey.put({publicKeyArmored, primaryEmail, origin});
|
yield publicKey.put({publicKeyArmored, primaryEmail, origin});
|
||||||
let emailParams = mailsSent[0].params;
|
const emailParams = mailsSent[0].params;
|
||||||
try {
|
try {
|
||||||
yield publicKey.verify({keyId: emailParams.keyId, nonce: 'fake_nonce'});
|
yield publicKey.verify({keyId: emailParams.keyId, nonce: 'fake_nonce'});
|
||||||
expect(true).to.be.false;
|
expect(true).to.be.false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.status).to.equal(404);
|
expect(e.status).to.equal(404);
|
||||||
}
|
}
|
||||||
let gotten = yield mongo.get({ keyId:emailParams.keyId }, DB_TYPE);
|
const gotten = yield mongo.get({keyId: emailParams.keyId}, DB_TYPE);
|
||||||
expect(gotten.userIds[0].verified).to.be.false;
|
expect(gotten.userIds[0].verified).to.be.false;
|
||||||
expect(gotten.userIds[0].nonce).to.equal(emailParams.nonce);
|
expect(gotten.userIds[0].nonce).to.equal(emailParams.nonce);
|
||||||
expect(gotten.userIds[1].verified).to.be.false;
|
expect(gotten.userIds[1].verified).to.be.false;
|
||||||
@ -133,7 +139,7 @@ describe('Public Key Integration Tests', function() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.status).to.equal(304);
|
expect(e.status).to.equal(304);
|
||||||
}
|
}
|
||||||
let gotten = yield mongo.get({ keyId:mailsSent[0].params.keyId }, DB_TYPE);
|
const gotten = yield mongo.get({keyId: mailsSent[0].params.keyId}, DB_TYPE);
|
||||||
expect(gotten.userIds[1].email).to.equal(primaryEmail2);
|
expect(gotten.userIds[1].email).to.equal(primaryEmail2);
|
||||||
expect(gotten.userIds[1].verified).to.be.false;
|
expect(gotten.userIds[1].verified).to.be.false;
|
||||||
expect(gotten.userIds[1].nonce).to.equal(mailsSent[0].params.nonce);
|
expect(gotten.userIds[1].nonce).to.equal(mailsSent[0].params.nonce);
|
||||||
@ -146,7 +152,7 @@ describe('Public Key Integration Tests', function() {
|
|||||||
yield publicKey.verify(mailsSent[1].params);
|
yield publicKey.verify(mailsSent[1].params);
|
||||||
yield publicKey.verify(mailsSent[2].params);
|
yield publicKey.verify(mailsSent[2].params);
|
||||||
yield publicKey.verify(mailsSent[3].params);
|
yield publicKey.verify(mailsSent[3].params);
|
||||||
let gotten = yield mongo.get({ keyId:mailsSent[0].params.keyId }, DB_TYPE);
|
const gotten = yield mongo.get({keyId: mailsSent[0].params.keyId}, DB_TYPE);
|
||||||
expect(gotten.userIds[0].verified).to.be.true;
|
expect(gotten.userIds[0].verified).to.be.true;
|
||||||
expect(gotten.userIds[1].verified).to.be.true;
|
expect(gotten.userIds[1].verified).to.be.true;
|
||||||
expect(gotten.userIds[2].verified).to.be.true;
|
expect(gotten.userIds[2].verified).to.be.true;
|
||||||
@ -165,32 +171,32 @@ describe('Public Key Integration Tests', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('by fingerprint', function *() {
|
it('by fingerprint', function *() {
|
||||||
let verified = yield publicKey.getVerified({ fingerprint:key.fingerprint });
|
const verified = yield publicKey.getVerified({fingerprint: key.fingerprint});
|
||||||
expect(verified).to.exist;
|
expect(verified).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by all userIds', function *() {
|
it('by all userIds', function *() {
|
||||||
let verified = yield publicKey.getVerified({ userIds:key.userIds });
|
const verified = yield publicKey.getVerified({userIds: key.userIds});
|
||||||
expect(verified).to.exist;
|
expect(verified).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by verified userId', function *() {
|
it('by verified userId', function *() {
|
||||||
let verified = yield publicKey.getVerified({ userIds:[key.userIds[0]] });
|
const verified = yield publicKey.getVerified({userIds: [key.userIds[0]]});
|
||||||
expect(verified).to.exist;
|
expect(verified).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by unverified userId', function *() {
|
it('by unverified userId', function *() {
|
||||||
let verified = yield publicKey.getVerified({ userIds:[key.userIds[1]] });
|
const verified = yield publicKey.getVerified({userIds: [key.userIds[1]]});
|
||||||
expect(verified).to.not.exist;
|
expect(verified).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by keyId', function *() {
|
it('by keyId', function *() {
|
||||||
let verified = yield publicKey.getVerified({ keyId:key.keyId });
|
const verified = yield publicKey.getVerified({keyId: key.keyId});
|
||||||
expect(verified).to.exist;
|
expect(verified).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by all params', function *() {
|
it('by all params', function *() {
|
||||||
let verified = yield publicKey.getVerified(key);
|
const verified = yield publicKey.getVerified(key);
|
||||||
expect(verified).to.exist;
|
expect(verified).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -203,22 +209,22 @@ describe('Public Key Integration Tests', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('by fingerprint', function *() {
|
it('by fingerprint', function *() {
|
||||||
let verified = yield publicKey.getVerified({ fingerprint:key.fingerprint });
|
const verified = yield publicKey.getVerified({fingerprint: key.fingerprint});
|
||||||
expect(verified).to.not.exist;
|
expect(verified).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by userIds', function *() {
|
it('by userIds', function *() {
|
||||||
let verified = yield publicKey.getVerified({ userIds:key.userIds });
|
const verified = yield publicKey.getVerified({userIds: key.userIds});
|
||||||
expect(verified).to.not.exist;
|
expect(verified).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by keyId', function *() {
|
it('by keyId', function *() {
|
||||||
let verified = yield publicKey.getVerified({ keyId:key.keyId });
|
const verified = yield publicKey.getVerified({keyId: key.keyId});
|
||||||
expect(verified).to.not.exist;
|
expect(verified).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('by all params', function *() {
|
it('by all params', function *() {
|
||||||
let verified = yield publicKey.getVerified(key);
|
const verified = yield publicKey.getVerified(key);
|
||||||
expect(verified).to.not.exist;
|
expect(verified).to.not.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -234,39 +240,39 @@ describe('Public Key Integration Tests', function() {
|
|||||||
|
|
||||||
it('should return verified key by key id', function *() {
|
it('should return verified key by key id', function *() {
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let key = yield publicKey.get({ keyId:emailParams.keyId });
|
const key = yield publicKey.get({keyId: emailParams.keyId});
|
||||||
expect(key.publicKeyArmored).to.exist;
|
expect(key.publicKeyArmored).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return verified key by key id (uppercase)', function *() {
|
it('should return verified key by key id (uppercase)', function *() {
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let key = yield publicKey.get({ keyId:emailParams.keyId.toUpperCase() });
|
const key = yield publicKey.get({keyId: emailParams.keyId.toUpperCase()});
|
||||||
expect(key.publicKeyArmored).to.exist;
|
expect(key.publicKeyArmored).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return verified key by fingerprint', function *() {
|
it('should return verified key by fingerprint', function *() {
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let fingerprint = pgp.parseKey(publicKeyArmored).fingerprint;
|
const fingerprint = pgp.parseKey(publicKeyArmored).fingerprint;
|
||||||
let key = yield publicKey.get({ fingerprint });
|
const key = yield publicKey.get({fingerprint});
|
||||||
expect(key.publicKeyArmored).to.exist;
|
expect(key.publicKeyArmored).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return verified key by fingerprint (uppercase)', function *() {
|
it('should return verified key by fingerprint (uppercase)', function *() {
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let fingerprint = pgp.parseKey(publicKeyArmored).fingerprint.toUpperCase();
|
const fingerprint = pgp.parseKey(publicKeyArmored).fingerprint.toUpperCase();
|
||||||
let key = yield publicKey.get({ fingerprint });
|
const key = yield publicKey.get({fingerprint});
|
||||||
expect(key.publicKeyArmored).to.exist;
|
expect(key.publicKeyArmored).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return verified key by email address', function *() {
|
it('should return verified key by email address', function *() {
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let key = yield publicKey.get({ email:primaryEmail });
|
const key = yield publicKey.get({email: primaryEmail});
|
||||||
expect(key.publicKeyArmored).to.exist;
|
expect(key.publicKeyArmored).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return verified key by email address (uppercase)', function *() {
|
it('should return verified key by email address (uppercase)', function *() {
|
||||||
yield publicKey.verify(emailParams);
|
yield publicKey.verify(emailParams);
|
||||||
let key = yield publicKey.get({ email:primaryEmail.toUpperCase() });
|
const key = yield publicKey.get({email: primaryEmail.toUpperCase()});
|
||||||
expect(key.publicKeyArmored).to.exist;
|
expect(key.publicKeyArmored).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -326,7 +332,7 @@ describe('Public Key Integration Tests', function() {
|
|||||||
|
|
||||||
it('should remove key', function *() {
|
it('should remove key', function *() {
|
||||||
yield publicKey.verifyRemove(mailsSent[1].params);
|
yield publicKey.verifyRemove(mailsSent[1].params);
|
||||||
let key = yield mongo.get({ keyId }, DB_TYPE);
|
const key = yield mongo.get({keyId}, DB_TYPE);
|
||||||
expect(key).to.not.exist;
|
expect(key).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -340,5 +346,4 @@ describe('Public Key Integration Tests', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -5,28 +5,29 @@ const Email = require('../../src/email/email');
|
|||||||
const nodemailer = require('nodemailer');
|
const nodemailer = require('nodemailer');
|
||||||
|
|
||||||
describe('Email Unit Tests', () => {
|
describe('Email Unit Tests', () => {
|
||||||
let email, sendFnStub;
|
let email;
|
||||||
|
let sendFnStub;
|
||||||
|
|
||||||
let template = {
|
const template = {
|
||||||
subject: 'foo',
|
subject: 'foo',
|
||||||
text: 'bar',
|
text: 'bar',
|
||||||
html: '<strong>bar</strong>'
|
html: '<strong>bar</strong>'
|
||||||
};
|
};
|
||||||
let sender = {
|
const sender = {
|
||||||
name: 'Foo Bar',
|
name: 'Foo Bar',
|
||||||
email: 'foo@bar.com'
|
email: 'foo@bar.com'
|
||||||
};
|
};
|
||||||
let userId1 = {
|
const userId1 = {
|
||||||
name: 'name1',
|
name: 'name1',
|
||||||
email: 'email1',
|
email: 'email1',
|
||||||
nonce: 'qwertzuioasdfghjkqwertzuio'
|
nonce: 'qwertzuioasdfghjkqwertzuio'
|
||||||
};
|
};
|
||||||
let keyId = '0123456789ABCDF0';
|
const keyId = '0123456789ABCDF0';
|
||||||
let origin = {
|
const origin = {
|
||||||
protocol: 'http',
|
protocol: 'http',
|
||||||
host: 'localhost:8888'
|
host: 'localhost:8888'
|
||||||
};
|
};
|
||||||
let mailOptions = {
|
const mailOptions = {
|
||||||
from: sender,
|
from: sender,
|
||||||
to: sender,
|
to: sender,
|
||||||
subject: 'Hello ✔', // Subject line
|
subject: 'Hello ✔', // Subject line
|
||||||
@ -37,7 +38,7 @@ describe('Email Unit Tests', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sendFnStub = sinon.stub();
|
sendFnStub = sinon.stub();
|
||||||
sinon.stub(nodemailer, 'createTransport').returns({
|
sinon.stub(nodemailer, 'createTransport').returns({
|
||||||
templateSender: () => { return sendFnStub; }
|
templateSender: () => sendFnStub
|
||||||
});
|
});
|
||||||
|
|
||||||
sinon.stub(log, 'warn');
|
sinon.stub(log, 'warn');
|
||||||
@ -47,7 +48,7 @@ describe('Email Unit Tests', () => {
|
|||||||
email.init({
|
email.init({
|
||||||
host: 'host',
|
host: 'host',
|
||||||
auth: {user: 'user', pass: 'pass'},
|
auth: {user: 'user', pass: 'pass'},
|
||||||
sender: sender
|
sender
|
||||||
});
|
});
|
||||||
expect(email._sender).to.equal(sender);
|
expect(email._sender).to.equal(sender);
|
||||||
});
|
});
|
||||||
@ -68,7 +69,7 @@ describe('Email Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should work', function *() {
|
it('should work', function *() {
|
||||||
let info = yield email.send({ template, userId:userId1, keyId, origin});
|
const info = yield email.send({template, userId: userId1, keyId, origin});
|
||||||
|
|
||||||
expect(info.response).to.match(/^250/);
|
expect(info.response).to.match(/^250/);
|
||||||
});
|
});
|
||||||
@ -78,7 +79,7 @@ describe('Email Unit Tests', () => {
|
|||||||
it('should work', function *() {
|
it('should work', function *() {
|
||||||
sendFnStub.returns(Promise.resolve({response: '250'}));
|
sendFnStub.returns(Promise.resolve({response: '250'}));
|
||||||
|
|
||||||
let info = yield email._sendHelper(mailOptions);
|
const info = yield email._sendHelper(mailOptions);
|
||||||
|
|
||||||
expect(info.response).to.match(/^250/);
|
expect(info.response).to.match(/^250/);
|
||||||
});
|
});
|
||||||
@ -86,7 +87,7 @@ describe('Email Unit Tests', () => {
|
|||||||
it('should log warning for reponse error', function *() {
|
it('should log warning for reponse error', function *() {
|
||||||
sendFnStub.returns(Promise.resolve({response: '554'}));
|
sendFnStub.returns(Promise.resolve({response: '554'}));
|
||||||
|
|
||||||
let info = yield email._sendHelper(mailOptions);
|
const info = yield email._sendHelper(mailOptions);
|
||||||
|
|
||||||
expect(info.response).to.match(/^554/);
|
expect(info.response).to.match(/^554/);
|
||||||
expect(log.warn.calledOnce).to.be.true;
|
expect(log.warn.calledOnce).to.be.true;
|
||||||
@ -104,5 +105,4 @@ describe('Email Unit Tests', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -6,18 +6,21 @@ const openpgp = require('openpgp');
|
|||||||
const PGP = require('../../src/service/pgp');
|
const PGP = require('../../src/service/pgp');
|
||||||
|
|
||||||
describe('PGP Unit Tests', () => {
|
describe('PGP Unit Tests', () => {
|
||||||
let pgp, key1Armored, key2Armored, key3Armored;
|
let pgp;
|
||||||
|
let key1Armored;
|
||||||
|
let key2Armored;
|
||||||
|
let key3Armored;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key1Armored = fs.readFileSync(__dirname + '/../key1.asc', 'utf8');
|
key1Armored = fs.readFileSync(`${__dirname}/../key1.asc`, 'utf8');
|
||||||
key2Armored = fs.readFileSync(__dirname + '/../key2.asc', 'utf8');
|
key2Armored = fs.readFileSync(`${__dirname}/../key2.asc`, 'utf8');
|
||||||
key3Armored = fs.readFileSync(__dirname + '/../key3.asc', 'utf8');
|
key3Armored = fs.readFileSync(`${__dirname}/../key3.asc`, 'utf8');
|
||||||
pgp = new PGP();
|
pgp = new PGP();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parseKey', () => {
|
describe('parseKey', () => {
|
||||||
it('should should throw error on key parsing', () => {
|
it('should should throw error on key parsing', () => {
|
||||||
let readStub = sinon.stub(openpgp.key, 'readArmored').returns({err:[new Error()]});
|
const readStub = sinon.stub(openpgp.key, 'readArmored').returns({err: [new Error()]});
|
||||||
sinon.stub(log, 'error');
|
sinon.stub(log, 'error');
|
||||||
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/Failed to parse/);
|
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/Failed to parse/);
|
||||||
expect(log.error.calledOnce).to.be.true;
|
expect(log.error.calledOnce).to.be.true;
|
||||||
@ -26,16 +29,16 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should should throw error when more than one key', () => {
|
it('should should throw error when more than one key', () => {
|
||||||
let readStub = sinon.stub(openpgp.key, 'readArmored').returns({keys:[{},{}]});
|
const readStub = sinon.stub(openpgp.key, 'readArmored').returns({keys: [{}, {}]});
|
||||||
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/only one key/);
|
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/only one key/);
|
||||||
readStub.restore();
|
readStub.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should should throw error when more than one key', () => {
|
it('should should throw error when more than one key', () => {
|
||||||
let readStub = sinon.stub(openpgp.key, 'readArmored').returns({
|
const readStub = sinon.stub(openpgp.key, 'readArmored').returns({
|
||||||
keys: [{
|
keys: [{
|
||||||
primaryKey: {},
|
primaryKey: {},
|
||||||
verifyPrimaryKey: function() { return false; }
|
verifyPrimaryKey() { return false; }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/primary key verification/);
|
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/primary key verification/);
|
||||||
@ -43,17 +46,17 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should only accept 16 char key id', () => {
|
it('should only accept 16 char key id', () => {
|
||||||
let readStub = sinon.stub(openpgp.key, 'readArmored').returns({
|
const readStub = sinon.stub(openpgp.key, 'readArmored').returns({
|
||||||
keys: [{
|
keys: [{
|
||||||
primaryKey: {
|
primaryKey: {
|
||||||
fingerprint: '4277257930867231ce393fb8dbc0b3d92b1b86e9',
|
fingerprint: '4277257930867231ce393fb8dbc0b3d92b1b86e9',
|
||||||
getKeyId: function() {
|
getKeyId() {
|
||||||
return {
|
return {
|
||||||
toHex:function() { return 'asdf'; }
|
toHex() { return 'asdf'; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
verifyPrimaryKey: function() { return openpgp.enums.keyStatus.valid; }
|
verifyPrimaryKey() { return openpgp.enums.keyStatus.valid; }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/only v4 keys/);
|
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/only v4 keys/);
|
||||||
@ -61,17 +64,17 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should only accept version 4 fingerprint', () => {
|
it('should only accept version 4 fingerprint', () => {
|
||||||
let readStub = sinon.stub(openpgp.key, 'readArmored').returns({
|
const readStub = sinon.stub(openpgp.key, 'readArmored').returns({
|
||||||
keys: [{
|
keys: [{
|
||||||
primaryKey: {
|
primaryKey: {
|
||||||
fingerprint: '4277257930867231ce393fb8dbc0b3d92b1b86e',
|
fingerprint: '4277257930867231ce393fb8dbc0b3d92b1b86e',
|
||||||
getKeyId: function() {
|
getKeyId() {
|
||||||
return {
|
return {
|
||||||
toHex:function() { return 'dbc0b3d92b1b86e9'; }
|
toHex() { return 'dbc0b3d92b1b86e9'; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
verifyPrimaryKey: function() { return openpgp.enums.keyStatus.valid; }
|
verifyPrimaryKey() { return openpgp.enums.keyStatus.valid; }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/only v4 keys/);
|
expect(pgp.parseKey.bind(pgp, key3Armored)).to.throw(/only v4 keys/);
|
||||||
@ -84,7 +87,7 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to parse RSA key', () => {
|
it('should be able to parse RSA key', () => {
|
||||||
let params = pgp.parseKey(key1Armored);
|
const params = pgp.parseKey(key1Armored);
|
||||||
expect(params.keyId).to.equal('dbc0b3d92b1b86e9');
|
expect(params.keyId).to.equal('dbc0b3d92b1b86e9');
|
||||||
expect(params.fingerprint).to.equal('4277257930867231ce393fb8dbc0b3d92b1b86e9');
|
expect(params.fingerprint).to.equal('4277257930867231ce393fb8dbc0b3d92b1b86e9');
|
||||||
expect(params.userIds[0].name).to.equal('safewithme testuser');
|
expect(params.userIds[0].name).to.equal('safewithme testuser');
|
||||||
@ -96,7 +99,7 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to parse RSA/ECC key', () => {
|
it('should be able to parse RSA/ECC key', () => {
|
||||||
let params = pgp.parseKey(key2Armored);
|
const params = pgp.parseKey(key2Armored);
|
||||||
expect(params.keyId).to.equal('b8e4105cc9dedc77');
|
expect(params.keyId).to.equal('b8e4105cc9dedc77');
|
||||||
expect(params.fingerprint).to.equal('e3317db04d3958fd5f662c37b8e4105cc9dedc77');
|
expect(params.fingerprint).to.equal('e3317db04d3958fd5f662c37b8e4105cc9dedc77');
|
||||||
expect(params.userIds.length).to.equal(1);
|
expect(params.userIds.length).to.equal(1);
|
||||||
@ -107,7 +110,7 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to parse komplex key', () => {
|
it('should be able to parse komplex key', () => {
|
||||||
let params = pgp.parseKey(key3Armored);
|
const params = pgp.parseKey(key3Armored);
|
||||||
expect(params.keyId).to.equal('4001a127a90de8e1');
|
expect(params.keyId).to.equal('4001a127a90de8e1');
|
||||||
expect(params.fingerprint).to.equal('04062c70b446e33016e219a74001a127a90de8e1');
|
expect(params.fingerprint).to.equal('04062c70b446e33016e219a74001a127a90de8e1');
|
||||||
expect(params.userIds.length).to.equal(4);
|
expect(params.userIds.length).to.equal(4);
|
||||||
@ -120,12 +123,12 @@ describe('PGP Unit Tests', () => {
|
|||||||
|
|
||||||
describe('trimKey', () => {
|
describe('trimKey', () => {
|
||||||
it('should be the same as key1', () => {
|
it('should be the same as key1', () => {
|
||||||
let trimmed = pgp.trimKey(key1Armored);
|
const trimmed = pgp.trimKey(key1Armored);
|
||||||
expect(trimmed).to.equal(key1Armored);
|
expect(trimmed).to.equal(key1Armored);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be the same as key2', () => {
|
it('should not be the same as key2', () => {
|
||||||
let trimmed = pgp.trimKey(key2Armored);
|
const trimmed = pgp.trimKey(key2Armored);
|
||||||
expect(trimmed).to.not.equal(key2Armored);
|
expect(trimmed).to.not.equal(key2Armored);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -135,22 +138,22 @@ describe('PGP Unit Tests', () => {
|
|||||||
const KEY_END = '-----END PGP PUBLIC KEY BLOCK-----';
|
const KEY_END = '-----END PGP PUBLIC KEY BLOCK-----';
|
||||||
|
|
||||||
it('should return true for valid key block', () => {
|
it('should return true for valid key block', () => {
|
||||||
let input = KEY_BEGIN + KEY_END;
|
const input = KEY_BEGIN + KEY_END;
|
||||||
expect(pgp.validateKeyBlock(input)).to.be.true;
|
expect(pgp.validateKeyBlock(input)).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false for invalid key block', () => {
|
it('should return false for invalid key block', () => {
|
||||||
let input = KEY_END + KEY_BEGIN;
|
const input = KEY_END + KEY_BEGIN;
|
||||||
expect(pgp.validateKeyBlock(input)).to.be.false;
|
expect(pgp.validateKeyBlock(input)).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false for invalid key block', () => {
|
it('should return false for invalid key block', () => {
|
||||||
let input = KEY_END;
|
const input = KEY_END;
|
||||||
expect(pgp.validateKeyBlock(input)).to.be.false;
|
expect(pgp.validateKeyBlock(input)).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false for invalid key block', () => {
|
it('should return false for invalid key block', () => {
|
||||||
let input = KEY_BEGIN;
|
const input = KEY_BEGIN;
|
||||||
expect(pgp.validateKeyBlock(input)).to.be.false;
|
expect(pgp.validateKeyBlock(input)).to.be.false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -163,7 +166,7 @@ describe('PGP Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should parse a valid user id', () => {
|
it('should parse a valid user id', () => {
|
||||||
let parsed = pgp.parseUserIds(key.users, key.primaryKey);
|
const parsed = pgp.parseUserIds(key.users, key.primaryKey);
|
||||||
expect(parsed[0].name).to.equal('safewithme testuser');
|
expect(parsed[0].name).to.equal('safewithme testuser');
|
||||||
expect(parsed[0].email).to.equal('safewithme.testuser@gmail.com');
|
expect(parsed[0].email).to.equal('safewithme.testuser@gmail.com');
|
||||||
});
|
});
|
||||||
@ -174,17 +177,16 @@ describe('PGP Unit Tests', () => {
|
|||||||
|
|
||||||
it('should return no user id for an invalid signature', () => {
|
it('should return no user id for an invalid signature', () => {
|
||||||
key.users[0].userId.userid = 'fake@example.com';
|
key.users[0].userId.userid = 'fake@example.com';
|
||||||
let parsed = pgp.parseUserIds(key.users, key.primaryKey);
|
const parsed = pgp.parseUserIds(key.users, key.primaryKey);
|
||||||
expect(parsed.length).to.equal(0);
|
expect(parsed.length).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw for a invalid email address', () => {
|
it('should throw for a invalid email address', () => {
|
||||||
let verifyStub = sinon.stub(key.users[0], 'isValidSelfCertificate').returns(true);
|
const verifyStub = sinon.stub(key.users[0], 'isValidSelfCertificate').returns(true);
|
||||||
key.users[0].userId.userid = 'safewithme testuser <safewithme.testusergmail.com>';
|
key.users[0].userId.userid = 'safewithme testuser <safewithme.testusergmail.com>';
|
||||||
let parsed = pgp.parseUserIds(key.users, key.primaryKey);
|
const parsed = pgp.parseUserIds(key.users, key.primaryKey);
|
||||||
expect(parsed.length).to.equal(0);
|
expect(parsed.length).to.equal(0);
|
||||||
verifyStub.restore();
|
verifyStub.restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -142,14 +142,13 @@ describe('Util Unit Tests', () => {
|
|||||||
|
|
||||||
describe('url', () => {
|
describe('url', () => {
|
||||||
it('should work with resource', () => {
|
it('should work with resource', () => {
|
||||||
let url = util.url({ host:'localhost', protocol:'http'}, '/foo');
|
const url = util.url({host: 'localhost', protocol: 'http'}, '/foo');
|
||||||
expect(url).to.equal('http://localhost/foo');
|
expect(url).to.equal('http://localhost/foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work without resource', () => {
|
it('should work without resource', () => {
|
||||||
let url = util.url({ host:'localhost', protocol:'http'});
|
const url = util.url({host: 'localhost', protocol: 'http'});
|
||||||
expect(url).to.equal('http://localhost');
|
expect(url).to.equal('http://localhost');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user