diff --git a/core/frontend/services/routing/ParentRouter.js b/core/frontend/services/routing/ParentRouter.js index 51c4918a11..82d2cee629 100644 --- a/core/frontend/services/routing/ParentRouter.js +++ b/core/frontend/services/routing/ParentRouter.js @@ -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'); diff --git a/core/frontend/services/routing/controllers/channel.js b/core/frontend/services/routing/controllers/channel.js index b88dd8be7f..06dfe85154 100644 --- a/core/frontend/services/routing/controllers/channel.js +++ b/core/frontend/services/routing/controllers/channel.js @@ -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'); diff --git a/core/frontend/services/routing/controllers/collection.js b/core/frontend/services/routing/controllers/collection.js index 852efb72d9..b2a38a3914 100644 --- a/core/frontend/services/routing/controllers/collection.js +++ b/core/frontend/services/routing/controllers/collection.js @@ -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'); diff --git a/core/frontend/services/routing/controllers/rss.js b/core/frontend/services/routing/controllers/rss.js index 0bfec1f0dd..5d329c9ca1 100644 --- a/core/frontend/services/routing/controllers/rss.js +++ b/core/frontend/services/routing/controllers/rss.js @@ -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'); diff --git a/core/frontend/services/themes/ThemeStorage.js b/core/frontend/services/themes/ThemeStorage.js index 8992427aac..c9b0ff1a80 100644 --- a/core/frontend/services/themes/ThemeStorage.js +++ b/core/frontend/services/themes/ThemeStorage.js @@ -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'); diff --git a/core/server/api/canary/invites.js b/core/server/api/canary/invites.js index 19911af69e..685ac99896 100644 --- a/core/server/api/canary/invites.js +++ b/core/server/api/canary/invites.js @@ -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'); diff --git a/core/server/api/v2/invites.js b/core/server/api/v2/invites.js index 19911af69e..685ac99896 100644 --- a/core/server/api/v2/invites.js +++ b/core/server/api/v2/invites.js @@ -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'); diff --git a/core/server/data/exporter/index.js b/core/server/data/exporter/index.js index 7059c2b1d1..893519f60f 100644 --- a/core/server/data/exporter/index.js +++ b/core/server/data/exporter/index.js @@ -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']; diff --git a/core/server/lib/security/identifier.js b/core/server/lib/security/identifier.js deleted file mode 100644 index 31f0c7a558..0000000000 --- a/core/server/lib/security/identifier.js +++ /dev/null @@ -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(''); -}; diff --git a/core/server/lib/security/index.js b/core/server/lib/security/index.js deleted file mode 100644 index 7242972586..0000000000 --- a/core/server/lib/security/index.js +++ /dev/null @@ -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'); - } -}; diff --git a/core/server/lib/security/password.js b/core/server/lib/security/password.js deleted file mode 100644 index 697e0be986..0000000000 --- a/core/server/lib/security/password.js +++ /dev/null @@ -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); -}; diff --git a/core/server/lib/security/string.js b/core/server/lib/security/string.js deleted file mode 100644 index b2d1367ad8..0000000000 --- a/core/server/lib/security/string.js +++ /dev/null @@ -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); -}; diff --git a/core/server/lib/security/tokens.js b/core/server/lib/security/tokens.js deleted file mode 100644 index 973c853d80..0000000000 --- a/core/server/lib/security/tokens.js +++ /dev/null @@ -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; - } -}; diff --git a/core/server/lib/security/url.js b/core/server/lib/security/url.js deleted file mode 100644 index 400403740e..0000000000 --- a/core/server/lib/security/url.js +++ /dev/null @@ -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; -}; diff --git a/core/server/models/base/index.js b/core/server/models/base/index.js index c8d425836b..9a448eed0b 100644 --- a/core/server/models/base/index.js +++ b/core/server/models/base/index.js @@ -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'); diff --git a/core/server/models/invite.js b/core/server/models/invite.js index 9f235ae11b..ed315045c8 100644 --- a/core/server/models/invite.js +++ b/core/server/models/invite.js @@ -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'); diff --git a/core/server/models/user.js b/core/server/models/user.js index 6c374f58ee..491f554639 100644 --- a/core/server/models/user.js +++ b/core/server/models/user.js @@ -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'); diff --git a/core/server/services/auth/passwordreset.js b/core/server/services/auth/passwordreset.js index e9d435343d..fa9796c995 100644 --- a/core/server/services/auth/passwordreset.js +++ b/core/server/services/auth/passwordreset.js @@ -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'); diff --git a/core/server/services/invitations/accept.js b/core/server/services/invitations/accept.js index 52cbe5098e..8c6d691cef 100644 --- a/core/server/services/invitations/accept.js +++ b/core/server/services/invitations/accept.js @@ -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]; diff --git a/package.json b/package.json index a5c072515e..da48ff72b4 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/test/regression/api/canary/admin/authentication_spec.js b/test/regression/api/canary/admin/authentication_spec.js index 4073465336..410fa2718d 100644 --- a/test/regression/api/canary/admin/authentication_spec.js +++ b/test/regression/api/canary/admin/authentication_spec.js @@ -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'); diff --git a/test/regression/api/v2/admin/authentication_spec.js b/test/regression/api/v2/admin/authentication_spec.js index f617c0a6df..7163776eda 100644 --- a/test/regression/api/v2/admin/authentication_spec.js +++ b/test/regression/api/v2/admin/authentication_spec.js @@ -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'); diff --git a/test/regression/api/v3/admin/authentication_spec.js b/test/regression/api/v3/admin/authentication_spec.js index 4073465336..410fa2718d 100644 --- a/test/regression/api/v3/admin/authentication_spec.js +++ b/test/regression/api/v3/admin/authentication_spec.js @@ -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'); diff --git a/test/unit/lib/security/password_spec.js b/test/unit/lib/security/password_spec.js deleted file mode 100644 index 9b66e8d275..0000000000 --- a/test/unit/lib/security/password_spec.js +++ /dev/null @@ -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; - }); - }); -}); diff --git a/test/unit/lib/security/string_spec.js b/test/unit/lib/security/string_spec.js deleted file mode 100644 index 2d50e115b1..0000000000 --- a/test/unit/lib/security/string_spec.js +++ /dev/null @@ -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%su|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'); - }); - }); -}); diff --git a/test/unit/lib/security/tokens_spec.js b/test/unit/lib/security/tokens_spec.js deleted file mode 100644 index e075c93eb5..0000000000 --- a/test/unit/lib/security/tokens_spec.js +++ /dev/null @@ -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); - }); -}); - diff --git a/test/unit/models/base/index_spec.js b/test/unit/models/base/index_spec.js index f530e80795..34beb1942e 100644 --- a/test/unit/models/base/index_spec.js +++ b/test/unit/models/base/index_spec.js @@ -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'); diff --git a/test/unit/models/post_spec.js b/test/unit/models/post_spec.js index 928854c04e..03effa0c0c 100644 --- a/test/unit/models/post_spec.js +++ b/test/unit/models/post_spec.js @@ -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'); diff --git a/test/unit/models/user_spec.js b/test/unit/models/user_spec.js index a2a83c6e34..5ebdb570ad 100644 --- a/test/unit/models/user_spec.js +++ b/test/unit/models/user_spec.js @@ -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 () { diff --git a/test/unit/services/routing/controllers/channel_spec.js b/test/unit/services/routing/controllers/channel_spec.js index 1ce4963e58..1cf8911dd2 100644 --- a/test/unit/services/routing/controllers/channel_spec.js +++ b/test/unit/services/routing/controllers/channel_spec.js @@ -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'); diff --git a/test/unit/services/routing/controllers/collection_spec.js b/test/unit/services/routing/controllers/collection_spec.js index cae541514b..f6da2213b2 100644 --- a/test/unit/services/routing/controllers/collection_spec.js +++ b/test/unit/services/routing/controllers/collection_spec.js @@ -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'); diff --git a/test/unit/services/routing/controllers/rss_spec.js b/test/unit/services/routing/controllers/rss_spec.js index f908768393..5bc31b8750 100644 --- a/test/unit/services/routing/controllers/rss_spec.js +++ b/test/unit/services/routing/controllers/rss_spec.js @@ -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'); diff --git a/yarn.lock b/yarn.lock index 20ee982a75..303cb35423 100644 --- a/yarn.lock +++ b/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"