mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-28 13:22:39 +03:00
Extracted core/server/lib/security to @tryghost/security package
- code and tests were extracted out to this package - deletes these files - replaces all local requires, and adds it as a dependency
This commit is contained in:
parent
beabc62c45
commit
c9a5b28669
@ -13,7 +13,7 @@ const EventEmitter = require('events').EventEmitter;
|
||||
const express = require('../../../shared/express');
|
||||
const _ = require('lodash');
|
||||
const url = require('url');
|
||||
const security = require('../../../server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const registry = require('./registry');
|
||||
|
||||
|
@ -2,7 +2,7 @@ const _ = require('lodash');
|
||||
const debug = require('ghost-ignition').debug('services:routing:controllers:channel');
|
||||
const {i18n} = require('../../../../server/lib/common');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../../../../server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const themes = require('../../themes');
|
||||
const helpers = require('../helpers');
|
||||
|
||||
|
@ -2,7 +2,7 @@ const _ = require('lodash');
|
||||
const debug = require('ghost-ignition').debug('services:routing:controllers:collection');
|
||||
const {i18n} = require('../../../../server/lib/common');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../../../../server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const urlService = require('../../url');
|
||||
const themes = require('../../themes');
|
||||
const helpers = require('../helpers');
|
||||
|
@ -1,7 +1,7 @@
|
||||
const _ = require('lodash');
|
||||
const debug = require('ghost-ignition').debug('services:routing:controllers:rss');
|
||||
const url = require('url');
|
||||
const security = require('../../../../server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../../../../server/services/settings/cache');
|
||||
const rssService = require('../../rss');
|
||||
const helpers = require('../helpers');
|
||||
|
@ -2,7 +2,7 @@ const fs = require('fs-extra');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const config = require('../../../shared/config');
|
||||
const security = require('../../../server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const {compress} = require('@tryghost/zip');
|
||||
const LocalFileStorage = require('../../../server/adapters/storage/LocalFileStorage');
|
||||
|
||||
|
@ -2,7 +2,7 @@ const Promise = require('bluebird');
|
||||
const {i18n} = require('../../lib/common');
|
||||
const logging = require('../../../shared/logging');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const mailService = require('../../services/mail');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const settingsCache = require('../../services/settings/cache');
|
||||
|
@ -2,7 +2,7 @@ const Promise = require('bluebird');
|
||||
const {i18n} = require('../../lib/common');
|
||||
const logging = require('../../../shared/logging');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const mailService = require('../../services/mail');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const settingsCache = require('../../services/settings/cache');
|
||||
|
@ -6,7 +6,7 @@ const ghostVersion = require('../../lib/ghost-version');
|
||||
const {i18n} = require('../../lib/common');
|
||||
const logging = require('../../../shared/logging');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const models = require('../../models');
|
||||
const EXCLUDED_TABLES = ['sessions', 'mobiledoc_revisions'];
|
||||
|
||||
|
@ -1,26 +0,0 @@
|
||||
let _private = {};
|
||||
|
||||
// @TODO: replace with crypto.randomBytes
|
||||
_private.getRandomInt = function (min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a unique identifier with the given `len`.
|
||||
*
|
||||
* @param {Number} maxLength
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
module.exports.uid = function uid(maxLength) {
|
||||
const buf = [];
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charLength = chars.length;
|
||||
let i;
|
||||
|
||||
for (i = 0; i < maxLength; i = i + 1) {
|
||||
buf.push(chars[_private.getRandomInt(0, charLength - 1)]);
|
||||
}
|
||||
|
||||
return buf.join('');
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
module.exports = {
|
||||
get url() {
|
||||
return require('./url');
|
||||
},
|
||||
|
||||
get tokens() {
|
||||
return require('./tokens');
|
||||
},
|
||||
|
||||
get string() {
|
||||
return require('./string');
|
||||
},
|
||||
|
||||
get identifier() {
|
||||
return require('./identifier');
|
||||
},
|
||||
|
||||
get password() {
|
||||
return require('./password');
|
||||
}
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
const Promise = require('bluebird');
|
||||
|
||||
module.exports.hash = function hash(plainPassword) {
|
||||
const bcrypt = require('bcryptjs');
|
||||
const bcryptGenSalt = Promise.promisify(bcrypt.genSalt);
|
||||
const bcryptHash = Promise.promisify(bcrypt.hash);
|
||||
|
||||
return bcryptGenSalt().then(function (salt) {
|
||||
return bcryptHash(plainPassword, salt);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.compare = function compare(plainPassword, hashedPassword) {
|
||||
const bcrypt = require('bcryptjs');
|
||||
const bcryptCompare = Promise.promisify(bcrypt.compare);
|
||||
|
||||
return bcryptCompare(plainPassword, hashedPassword);
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
const _ = require('lodash');
|
||||
const slugify = require('@tryghost/string').slugify;
|
||||
|
||||
module.exports.safe = function safe(string, options) {
|
||||
options = options || {};
|
||||
let opts = {requiredChangesOnly: true};
|
||||
if (!_.has(options, 'importing') || !options.importing) {
|
||||
opts.requiredChangesOnly = false;
|
||||
}
|
||||
return slugify(string, opts);
|
||||
};
|
@ -1,115 +0,0 @@
|
||||
const crypto = require('crypto');
|
||||
|
||||
module.exports.generateFromContent = function generateFromContent(options) {
|
||||
options = options || {};
|
||||
|
||||
const hash = crypto.createHash('sha256');
|
||||
const content = options.content;
|
||||
|
||||
let text = '';
|
||||
|
||||
hash.update(content);
|
||||
|
||||
text += [content, hash.digest('base64')].join('|');
|
||||
return Buffer.from(text).toString('base64');
|
||||
};
|
||||
|
||||
module.exports.generateFromEmail = function generateFromEmail(options) {
|
||||
options = options || {};
|
||||
|
||||
const hash = crypto.createHash('sha256');
|
||||
const expires = options.expires;
|
||||
const email = options.email;
|
||||
const secret = options.secret;
|
||||
|
||||
let text = '';
|
||||
|
||||
hash.update(String(expires));
|
||||
hash.update(email.toLocaleLowerCase());
|
||||
hash.update(String(secret));
|
||||
|
||||
text += [expires, email, hash.digest('base64')].join('|');
|
||||
return Buffer.from(text).toString('base64');
|
||||
};
|
||||
|
||||
module.exports.resetToken = {
|
||||
generateHash: function generateHash(options) {
|
||||
options = options || {};
|
||||
|
||||
const hash = crypto.createHash('sha256');
|
||||
const expires = options.expires;
|
||||
const email = options.email;
|
||||
const dbHash = options.dbHash;
|
||||
const password = options.password;
|
||||
let text = '';
|
||||
|
||||
hash.update(String(expires));
|
||||
hash.update(email.toLocaleLowerCase());
|
||||
hash.update(password);
|
||||
hash.update(String(dbHash));
|
||||
|
||||
text += [expires, email, hash.digest('base64')].join('|');
|
||||
return Buffer.from(text).toString('base64');
|
||||
},
|
||||
extract: function extract(options) {
|
||||
options = options || {};
|
||||
|
||||
const token = options.token;
|
||||
const tokenText = Buffer.from(token, 'base64').toString('ascii');
|
||||
let parts;
|
||||
let expires;
|
||||
let email;
|
||||
|
||||
parts = tokenText.split('|');
|
||||
|
||||
// Check if invalid structure
|
||||
if (!parts || parts.length !== 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
expires = parseInt(parts[0], 10);
|
||||
email = parts[1];
|
||||
|
||||
return {
|
||||
expires: expires,
|
||||
email: email
|
||||
};
|
||||
},
|
||||
compare: function compare(options) {
|
||||
options = options || {};
|
||||
|
||||
const tokenToCompare = options.token;
|
||||
const parts = exports.resetToken.extract({token: tokenToCompare});
|
||||
const dbHash = options.dbHash;
|
||||
const password = options.password;
|
||||
let generatedToken;
|
||||
let diff = 0;
|
||||
let i;
|
||||
|
||||
if (isNaN(parts.expires)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if token is expired to prevent replay attacks
|
||||
if (parts.expires < Date.now()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
generatedToken = exports.resetToken.generateHash({
|
||||
email: parts.email,
|
||||
expires: parts.expires,
|
||||
dbHash: dbHash,
|
||||
password: password
|
||||
});
|
||||
|
||||
if (tokenToCompare.length !== generatedToken.length) {
|
||||
diff = 1;
|
||||
}
|
||||
|
||||
for (i = tokenToCompare.length - 1; i >= 0; i = i - 1) {
|
||||
diff |= tokenToCompare.charCodeAt(i) ^ generatedToken.charCodeAt(i);
|
||||
}
|
||||
|
||||
return diff === 0;
|
||||
}
|
||||
};
|
@ -1,14 +0,0 @@
|
||||
// The token is encoded URL safe by replacing '+' with '-', '\' with '_' and removing '='
|
||||
// NOTE: the token is not encoded using valid base64 anymore
|
||||
module.exports.encodeBase64 = function encodeBase64(base64String) {
|
||||
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||
};
|
||||
|
||||
// Decode url safe base64 encoding and add padding ('=')
|
||||
module.exports.decodeBase64 = function decodeBase64(base64String) {
|
||||
base64String = base64String.replace(/-/g, '+').replace(/_/g, '/');
|
||||
while (base64String.length % 4) {
|
||||
base64String += '=';
|
||||
}
|
||||
return base64String;
|
||||
};
|
@ -18,7 +18,7 @@ const db = require('../../data/db');
|
||||
const {events, i18n} = require('../../lib/common');
|
||||
const logging = require('../../../shared/logging');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const schema = require('../../data/schema');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const validation = require('../../data/validation');
|
||||
|
@ -3,7 +3,7 @@ const _ = require('lodash');
|
||||
const {i18n} = require('../lib/common');
|
||||
const errors = require('@tryghost/errors');
|
||||
const constants = require('@tryghost/constants');
|
||||
const security = require('../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../services/settings/cache');
|
||||
const ghostBookshelf = require('./base');
|
||||
|
||||
|
@ -6,7 +6,7 @@ const ghostBookshelf = require('./base');
|
||||
const baseUtils = require('./base/utils');
|
||||
const {i18n} = require('../lib/common');
|
||||
const errors = require('@tryghost/errors');
|
||||
const security = require('../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const {gravatar} = require('../lib/image');
|
||||
const pipeline = require('../lib/promise/pipeline');
|
||||
const validation = require('../data/validation');
|
||||
|
@ -1,5 +1,5 @@
|
||||
const _ = require('lodash');
|
||||
const security = require('../../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const constants = require('@tryghost/constants');
|
||||
const errors = require('@tryghost/errors');
|
||||
const {i18n} = require('../../lib/common');
|
||||
|
@ -1,7 +1,7 @@
|
||||
const errors = require('@tryghost/errors');
|
||||
const {i18n} = require('../../lib/common');
|
||||
const models = require('../../models');
|
||||
const security = require('../../lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
|
||||
async function accept(invitation) {
|
||||
const data = invitation.invitation[0];
|
||||
|
@ -58,6 +58,7 @@
|
||||
"@tryghost/members-csv": "0.2.1",
|
||||
"@tryghost/members-ssr": "0.8.5",
|
||||
"@tryghost/mw-session-from-token": "0.1.6",
|
||||
"@tryghost/security": "0.1.0",
|
||||
"@tryghost/session-service": "0.1.7",
|
||||
"@tryghost/social-urls": "0.1.11",
|
||||
"@tryghost/string": "0.1.10",
|
||||
|
@ -4,7 +4,7 @@ const supertest = require('supertest');
|
||||
const localUtils = require('./utils');
|
||||
const testUtils = require('../../../../utils/index');
|
||||
const models = require('../../../../../core/server/models/index');
|
||||
const security = require('../../../../../core/server/lib/security/index');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../../../../../core/server/services/settings/cache');
|
||||
const config = require('../../../../../core/shared/config/index');
|
||||
const mailService = require('../../../../../core/server/services/mail/index');
|
||||
|
@ -4,7 +4,7 @@ const supertest = require('supertest');
|
||||
const localUtils = require('./utils');
|
||||
const testUtils = require('../../../../utils/index');
|
||||
const models = require('../../../../../core/server/models/index');
|
||||
const security = require('../../../../../core/server/lib/security/index');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../../../../../core/server/services/settings/cache');
|
||||
const config = require('../../../../../core/shared/config/index');
|
||||
const mailService = require('../../../../../core/server/services/mail/index');
|
||||
|
@ -4,7 +4,7 @@ const supertest = require('supertest');
|
||||
const localUtils = require('./utils');
|
||||
const testUtils = require('../../../../utils/index');
|
||||
const models = require('../../../../../core/server/models/index');
|
||||
const security = require('../../../../../core/server/lib/security/index');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../../../../../core/server/services/settings/cache');
|
||||
const config = require('../../../../../core/shared/config/index');
|
||||
const mailService = require('../../../../../core/server/services/mail/index');
|
||||
|
@ -1,18 +0,0 @@
|
||||
const should = require('should');
|
||||
const security = require('../../../../core/server/lib/security');
|
||||
|
||||
describe('Lib: Security - Password', function () {
|
||||
it('hash plain password', function () {
|
||||
return security.password.hash('test')
|
||||
.then(function (hash) {
|
||||
hash.should.match(/^\$2[ayb]\$.{56}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('compare password', function () {
|
||||
return security.password.compare('test', '$2a$10$we16f8rpbrFZ34xWj0/ZC.LTPUux8ler7bcdTs5qIleN6srRHhilG')
|
||||
.then(function (valid) {
|
||||
valid.should.be.true;
|
||||
});
|
||||
});
|
||||
});
|
@ -1,94 +0,0 @@
|
||||
const should = require('should');
|
||||
const security = require('../../../../core/server/lib/security');
|
||||
|
||||
describe('Lib: Security - String', function () {
|
||||
describe('Safe String', function () {
|
||||
const options = {};
|
||||
|
||||
it('should remove beginning and ending whitespace', function () {
|
||||
const result = security.string.safe(' stringwithspace ', options);
|
||||
result.should.equal('stringwithspace');
|
||||
});
|
||||
|
||||
it('can handle null strings', function () {
|
||||
const result = security.string.safe(null);
|
||||
result.should.equal('');
|
||||
});
|
||||
|
||||
it('should remove non ascii characters', function () {
|
||||
const result = security.string.safe('howtowin✓', options);
|
||||
result.should.equal('howtowin');
|
||||
});
|
||||
|
||||
it('should replace spaces with dashes', function () {
|
||||
const result = security.string.safe('how to win', options);
|
||||
result.should.equal('how-to-win');
|
||||
});
|
||||
|
||||
it('should replace most special characters with dashes', function () {
|
||||
const result = security.string.safe('a:b/c?d#e[f]g!h$i&j(k)l*m+n,o;{p}=q\\r%s<t>u|v^w~x£y"z@1.2`3', options);
|
||||
result.should.equal('a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-1-2-3');
|
||||
});
|
||||
|
||||
it('should replace all of the html4 compat symbols in ascii except hyphen and underscore', function () {
|
||||
// note: This is missing the soft-hyphen char that isn't much-liked by linters/browsers/etc,
|
||||
// it passed the test before it was removed
|
||||
const result = security.string.safe('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿');
|
||||
result.should.equal('_-c-y-ss-c-a-r-deg-23up-1o-1-41-23-4');
|
||||
});
|
||||
|
||||
it('should replace all of the foreign chars in ascii', function () {
|
||||
const result = security.string.safe('ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ');
|
||||
result.should.equal('aaaaaaaeceeeeiiiidnoooooxouuuuuthssaaaaaaaeceeeeiiiidnooooo-ouuuuythy');
|
||||
});
|
||||
|
||||
it('should remove special characters at the beginning of a string', function () {
|
||||
const result = security.string.safe('.Not special', options);
|
||||
result.should.equal('not-special');
|
||||
});
|
||||
|
||||
it('should remove apostrophes ', function () {
|
||||
const result = security.string.safe('how we shouldn\'t be', options);
|
||||
result.should.equal('how-we-shouldnt-be');
|
||||
});
|
||||
|
||||
it('should convert to lowercase', function () {
|
||||
const result = security.string.safe('This has Upper Case', options);
|
||||
result.should.equal('this-has-upper-case');
|
||||
});
|
||||
|
||||
it('should convert multiple dashes into a single dash', function () {
|
||||
const result = security.string.safe('This :) means everything', options);
|
||||
result.should.equal('this-means-everything');
|
||||
});
|
||||
|
||||
it('should remove trailing dashes from the result', function () {
|
||||
const result = security.string.safe('This.', options);
|
||||
result.should.equal('this');
|
||||
});
|
||||
|
||||
it('should handle pound signs', function () {
|
||||
const result = security.string.safe('WHOOPS! I spent all my £ again!', options);
|
||||
result.should.equal('whoops-i-spent-all-my-again');
|
||||
});
|
||||
|
||||
it('should properly handle unicode punctuation conversion', function () {
|
||||
const result = security.string.safe('に間違いがないか、再度確認してください。再読み込みしてください。', options);
|
||||
result.should.equal('nijian-wei-iganaika-zai-du-que-ren-sitekudasai-zai-du-miip-misitekudasai');
|
||||
});
|
||||
|
||||
it('should not lose or convert dashes if options are passed with truthy importing flag', function () {
|
||||
let result;
|
||||
const options = {importing: true};
|
||||
result = security.string.safe('-slug-with-starting-ending-and---multiple-dashes-', options);
|
||||
result.should.equal('-slug-with-starting-ending-and---multiple-dashes-');
|
||||
});
|
||||
|
||||
it('should still remove/convert invalid characters when passed options with truthy importing flag', function () {
|
||||
let result;
|
||||
const options = {importing: true};
|
||||
result = security.string.safe('-slug-&with-✓-invalid-characters-に\'', options);
|
||||
result.should.equal('-slug--with--invalid-characters-ni');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,150 +0,0 @@
|
||||
const should = require('should');
|
||||
const uuid = require('uuid');
|
||||
const security = require('../../../../core/server/lib/security');
|
||||
|
||||
describe('Utils: tokens', function () {
|
||||
it('generate', function () {
|
||||
const expires = Date.now() + 60 * 1000;
|
||||
const dbHash = uuid.v4();
|
||||
let token;
|
||||
|
||||
token = security.tokens.resetToken.generateHash({
|
||||
email: 'test1@ghost.org',
|
||||
expires: expires,
|
||||
password: 'password',
|
||||
dbHash: dbHash
|
||||
});
|
||||
|
||||
should.exist(token);
|
||||
token.length.should.be.above(0);
|
||||
});
|
||||
|
||||
it('compare: success', function () {
|
||||
const expires = Date.now() + 60 * 1000;
|
||||
const dbHash = uuid.v4();
|
||||
let token;
|
||||
let tokenIsCorrect;
|
||||
|
||||
token = security.tokens.resetToken.generateHash({
|
||||
email: 'test1@ghost.org',
|
||||
expires: expires,
|
||||
password: '12345678',
|
||||
dbHash: dbHash
|
||||
});
|
||||
|
||||
tokenIsCorrect = security.tokens.resetToken.compare({
|
||||
token: token,
|
||||
dbHash: dbHash,
|
||||
password: '12345678'
|
||||
});
|
||||
|
||||
tokenIsCorrect.should.eql(true);
|
||||
});
|
||||
|
||||
it('compare: error', function () {
|
||||
const expires = Date.now() + 60 * 1000;
|
||||
const dbHash = uuid.v4();
|
||||
let token;
|
||||
let tokenIsCorrect;
|
||||
|
||||
token = security.tokens.resetToken.generateHash({
|
||||
email: 'test1@ghost.org',
|
||||
expires: expires,
|
||||
password: '12345678',
|
||||
dbHash: dbHash
|
||||
});
|
||||
|
||||
tokenIsCorrect = security.tokens.resetToken.compare({
|
||||
token: token,
|
||||
dbHash: dbHash,
|
||||
password: '123456'
|
||||
});
|
||||
|
||||
tokenIsCorrect.should.eql(false);
|
||||
});
|
||||
|
||||
it('extract', function () {
|
||||
const expires = Date.now() + 60 * 1000;
|
||||
const dbHash = uuid.v4();
|
||||
let token;
|
||||
let parts;
|
||||
const email = 'test1@ghost.org';
|
||||
|
||||
token = security.tokens.resetToken.generateHash({
|
||||
email: email,
|
||||
expires: expires,
|
||||
password: '12345678',
|
||||
dbHash: dbHash
|
||||
});
|
||||
|
||||
parts = security.tokens.resetToken.extract({
|
||||
token: token
|
||||
});
|
||||
|
||||
parts.email.should.eql(email);
|
||||
parts.expires.should.eql(expires);
|
||||
should.not.exist(parts.password);
|
||||
should.not.exist(parts.dbHash);
|
||||
});
|
||||
|
||||
it('extract', function () {
|
||||
const expires = Date.now() + 60 * 1000;
|
||||
const dbHash = uuid.v4();
|
||||
let token;
|
||||
let parts;
|
||||
const email = 'test3@ghost.org';
|
||||
|
||||
token = security.tokens.resetToken.generateHash({
|
||||
email: email,
|
||||
expires: expires,
|
||||
password: '$2a$10$t5dY1uRRdjvqfNlXhae3uuc0nuhi.Rd7/K/9JaHHwSkLm6UUa3NsW',
|
||||
dbHash: dbHash
|
||||
});
|
||||
|
||||
parts = security.tokens.resetToken.extract({
|
||||
token: token
|
||||
});
|
||||
|
||||
parts.email.should.eql(email);
|
||||
parts.expires.should.eql(expires);
|
||||
should.not.exist(parts.password);
|
||||
should.not.exist(parts.dbHash);
|
||||
});
|
||||
|
||||
it('can validate an URI encoded reset token', function () {
|
||||
const expires = Date.now() + 60 * 1000;
|
||||
const email = 'test1@ghost.org';
|
||||
const dbHash = uuid.v4();
|
||||
let token;
|
||||
let tokenIsCorrect;
|
||||
let parts;
|
||||
|
||||
token = security.tokens.resetToken.generateHash({
|
||||
email: email,
|
||||
expires: expires,
|
||||
password: '12345678',
|
||||
dbHash: dbHash
|
||||
});
|
||||
|
||||
token = security.url.encodeBase64(token);
|
||||
token = encodeURIComponent(token);
|
||||
token = decodeURIComponent(token);
|
||||
token = security.url.decodeBase64(token);
|
||||
|
||||
parts = security.tokens.resetToken.extract({
|
||||
token: token
|
||||
});
|
||||
|
||||
parts.email.should.eql(email);
|
||||
parts.expires.should.eql(expires);
|
||||
|
||||
tokenIsCorrect = security.tokens.resetToken.compare({
|
||||
token: token,
|
||||
dbHash: dbHash,
|
||||
password: '12345678'
|
||||
});
|
||||
|
||||
tokenIsCorrect.should.eql(true);
|
||||
});
|
||||
});
|
||||
|
@ -3,7 +3,7 @@ const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const _ = require('lodash');
|
||||
const Promise = require('bluebird');
|
||||
const security = require('../../../../core/server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const models = require('../../../../core/server/models');
|
||||
const urlUtils = require('../../../../core/shared/url-utils');
|
||||
const testUtils = require('../../../utils');
|
||||
|
@ -6,7 +6,7 @@ const testUtils = require('../../utils');
|
||||
const knex = require('../../../core/server/data/db').knex;
|
||||
const urlService = require('../../../core/frontend/services/url');
|
||||
const models = require('../../../core/server/models');
|
||||
const security = require('../../../core/server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
|
||||
describe('Unit: models/post', function () {
|
||||
const mockDb = require('mock-knex');
|
||||
|
@ -5,7 +5,7 @@ const errors = require('@tryghost/errors');
|
||||
const models = require('../../../core/server/models');
|
||||
const permissions = require('../../../core/server/services/permissions');
|
||||
const validation = require('../../../core/server/data/validation');
|
||||
const security = require('../../../core/server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const testUtils = require('../../utils');
|
||||
|
||||
describe('Unit: models/user', function () {
|
||||
|
@ -2,7 +2,7 @@ const errors = require('@tryghost/errors');
|
||||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const testUtils = require('../../../../utils');
|
||||
const security = require('../../../../../core/server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const themeService = require('../../../../../core/frontend/services/themes');
|
||||
const controllers = require('../../../../../core/frontend/services/routing/controllers');
|
||||
const helpers = require('../../../../../core/frontend/services/routing/helpers');
|
||||
|
@ -2,7 +2,7 @@ const errors = require('@tryghost/errors');
|
||||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const testUtils = require('../../../../utils');
|
||||
const security = require('../../../../../core/server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const themeService = require('../../../../../core/frontend/services/themes');
|
||||
const urlService = require('../../../../../core/frontend/services/url');
|
||||
const controllers = require('../../../../../core/frontend/services/routing/controllers');
|
||||
|
@ -1,6 +1,6 @@
|
||||
const sinon = require('sinon');
|
||||
const testUtils = require('../../../../utils');
|
||||
const security = require('../../../../../core/server/lib/security');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../../../../../core/server/services/settings/cache');
|
||||
const controllers = require('../../../../../core/frontend/services/routing/controllers');
|
||||
const helpers = require('../../../../../core/frontend/services/routing/helpers');
|
||||
|
10
yarn.lock
10
yarn.lock
@ -475,6 +475,16 @@
|
||||
chalk "4.1.0"
|
||||
sywac "1.3.0"
|
||||
|
||||
"@tryghost/security@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/security/-/security-0.1.0.tgz#ce78111dd6febb7705cf62d6838b0d8cdfb7df9f"
|
||||
integrity sha512-jDiLbsN9zCAZhGIibCb92Ym30BBWzVSZx2DBPL+Ige8b95pefEx6d8humbCjXhMIcJS5dlaMw4Pk70mXLCXCvQ==
|
||||
dependencies:
|
||||
"@tryghost/string" "0.1.10"
|
||||
bcryptjs "2.4.3"
|
||||
bluebird "3.7.2"
|
||||
lodash "4.17.19"
|
||||
|
||||
"@tryghost/session-service@0.1.7":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/session-service/-/session-service-0.1.7.tgz#9af4adca4bd301e95e47b9065cbc6b8e396ae20d"
|
||||
|
Loading…
Reference in New Issue
Block a user