mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 05:37:34 +03:00
Removed defunct Ghost OAuth code (#9014)
closes #8342 - no need to add a migration, because when we'released 1.0, OAuth was never an option - it was disabled in April, 1.0-beta was released in June - remove all remote authentication code
This commit is contained in:
parent
1868285bed
commit
7b4c3fc085
@ -46,8 +46,6 @@ function getBaseConfig() {
|
||||
* ## Configuration API Methods
|
||||
*
|
||||
* We need to load the client credentials dynamically.
|
||||
* For example: on bootstrap ghost-auth get's created and if we load them here in parallel,
|
||||
* it can happen that we won't get any client credentials or wrong credentials.
|
||||
*
|
||||
* **See:** [API Methods](index.js.html#api%20methods)
|
||||
*/
|
||||
@ -61,26 +59,14 @@ configuration = {
|
||||
*/
|
||||
read: function read(options) {
|
||||
options = options || {};
|
||||
var ops = {};
|
||||
|
||||
if (!options.key) {
|
||||
ops.ghostAdmin = models.Client.findOne({slug: 'ghost-admin'});
|
||||
|
||||
if (config.get('auth:type') === 'ghost') {
|
||||
ops.ghostAuth = models.Client.findOne({slug: 'ghost-auth'});
|
||||
}
|
||||
|
||||
return Promise.props(ops)
|
||||
.then(function (result) {
|
||||
return models.Client.findOne({slug: 'ghost-admin'})
|
||||
.then(function (ghostAdmin) {
|
||||
var configuration = getBaseConfig();
|
||||
|
||||
configuration.clientId = result.ghostAdmin.get('slug');
|
||||
configuration.clientSecret = result.ghostAdmin.get('secret');
|
||||
|
||||
if (config.get('auth:type') === 'ghost') {
|
||||
configuration.ghostAuthId = result.ghostAuth && result.ghostAuth.get('uuid') || 'not-available';
|
||||
configuration.ghostAuthUrl = config.get('auth:url');
|
||||
}
|
||||
configuration.clientId = ghostAdmin.get('slug');
|
||||
configuration.clientSecret = ghostAdmin.get('secret');
|
||||
|
||||
return {configuration: [configuration]};
|
||||
});
|
||||
|
@ -1,19 +0,0 @@
|
||||
var passport = require('passport'),
|
||||
Promise = require('bluebird');
|
||||
|
||||
module.exports.getUser = function getUser(options) {
|
||||
options = options || {};
|
||||
|
||||
var id = options.id,
|
||||
ghostOAuth2Strategy = passport._strategies.ghost;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
ghostOAuth2Strategy.userProfileByIdentityId(id, function (err, profile) {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
resolve(profile);
|
||||
});
|
||||
});
|
||||
};
|
@ -1,23 +1,13 @@
|
||||
var passport = require('./passport'),
|
||||
authorize = require('./authorize'),
|
||||
authenticate = require('./authenticate'),
|
||||
sync = require('./sync'),
|
||||
oauth = require('./oauth'),
|
||||
validation = require('./validation'),
|
||||
ghostAuth = require('./ghost-auth');
|
||||
oauth = require('./oauth');
|
||||
|
||||
exports.init = function (options) {
|
||||
oauth.init(options);
|
||||
sync.init(options);
|
||||
|
||||
return passport.init(options)
|
||||
.then(function (response) {
|
||||
return {auth: response.passport};
|
||||
});
|
||||
return passport.init(options);
|
||||
};
|
||||
|
||||
exports.validation = validation;
|
||||
exports.oauth = oauth;
|
||||
exports.authorize = authorize;
|
||||
exports.authenticate = authenticate;
|
||||
exports.ghostAuth = ghostAuth;
|
||||
|
@ -1,221 +1,15 @@
|
||||
var ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
|
||||
BearerStrategy = require('passport-http-bearer').Strategy,
|
||||
GhostOAuth2Strategy = require('passport-ghost').Strategy,
|
||||
passport = require('passport'),
|
||||
_ = require('lodash'),
|
||||
debug = require('ghost-ignition').debug('auth'),
|
||||
Promise = require('bluebird'),
|
||||
authStrategies = require('./auth-strategies'),
|
||||
errors = require('../errors'),
|
||||
events = require('../events'),
|
||||
logging = require('../logging'),
|
||||
models = require('../models'),
|
||||
_private = {};
|
||||
|
||||
/**
|
||||
* Update client name and description if changes in the blog settings
|
||||
*/
|
||||
_private.registerEvents = function registerEvents() {
|
||||
events.on('settings.edited', function onSettingsChanged(settingModel) {
|
||||
var titleHasChanged = settingModel.attributes.key === 'title' && settingModel.attributes.value !== settingModel._updatedAttributes.value,
|
||||
descriptionHasChanged = settingModel.attributes.key === 'description' && settingModel.attributes.value !== settingModel._updatedAttributes.value,
|
||||
options = {
|
||||
ghostOAuth2Strategy: passport._strategies.ghost
|
||||
};
|
||||
|
||||
if (!titleHasChanged && !descriptionHasChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (titleHasChanged) {
|
||||
options.clientName = settingModel.attributes.value;
|
||||
debug('Ghost Auth Client title has changed: ' + options.clientName);
|
||||
}
|
||||
|
||||
if (descriptionHasChanged) {
|
||||
options.clientDescription = settingModel.attributes.value;
|
||||
debug('Ghost AuthClient description has changed: ' + options.clientDescription);
|
||||
}
|
||||
|
||||
_private.updateClient(options).catch(function onUpdatedClientError(err) {
|
||||
// @TODO: see https://github.com/TryGhost/Ghost/issues/7627
|
||||
if (_.isArray(err)) {
|
||||
err = err[0];
|
||||
}
|
||||
|
||||
logging.error(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* smart function
|
||||
*/
|
||||
_private.updateClient = function updateClient(options) {
|
||||
var ghostOAuth2Strategy = options.ghostOAuth2Strategy,
|
||||
redirectUri = options.redirectUri,
|
||||
clientUri = options.clientUri,
|
||||
clientName = options.clientName,
|
||||
clientDescription = options.clientDescription;
|
||||
|
||||
return models.Client.findOne({slug: 'ghost-auth'}, {context: {internal: true}})
|
||||
.then(function (client) {
|
||||
// CASE: we have to create the client
|
||||
if (!client) {
|
||||
debug('Client does not exist');
|
||||
|
||||
return ghostOAuth2Strategy.registerClient({
|
||||
name: clientName,
|
||||
description: clientDescription
|
||||
}).then(function registeredRemoteClient(credentials) {
|
||||
debug('Registered remote client: ' + JSON.stringify(credentials));
|
||||
logging.info('Registered remote client successfully.');
|
||||
|
||||
return models.Client.add({
|
||||
name: credentials.name,
|
||||
description: credentials.description,
|
||||
slug: 'ghost-auth',
|
||||
uuid: credentials.client_id,
|
||||
secret: credentials.client_secret,
|
||||
redirection_uri: credentials.redirect_uri,
|
||||
client_uri: credentials.blog_uri,
|
||||
auth_uri: ghostOAuth2Strategy.url
|
||||
}, {context: {internal: true}});
|
||||
}).then(function addedLocalClient(client) {
|
||||
debug('Added local client: ' + JSON.stringify(client.toJSON()));
|
||||
|
||||
return {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// CASE: auth url has changed, create client
|
||||
if (client.get('auth_uri') !== ghostOAuth2Strategy.url) {
|
||||
return models.Client.destroy({id: client.id})
|
||||
.then(function () {
|
||||
return _private.updateClient(options);
|
||||
});
|
||||
}
|
||||
|
||||
// CASE: nothing changed
|
||||
if (client.get('redirection_uri') === redirectUri &&
|
||||
client.get('name') === clientName &&
|
||||
client.get('description') === clientDescription &&
|
||||
client.get('client_uri') === clientUri) {
|
||||
debug('Client did not change');
|
||||
|
||||
return {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
};
|
||||
}
|
||||
|
||||
debug('Update client...');
|
||||
return ghostOAuth2Strategy.updateClient(_.omit({
|
||||
clientId: client.get('uuid'),
|
||||
clientSecret: client.get('secret'),
|
||||
redirectUri: redirectUri,
|
||||
blogUri: clientUri,
|
||||
name: clientName,
|
||||
description: clientDescription
|
||||
}, _.isUndefined)).then(function updatedRemoteClient(updatedRemoteClient) {
|
||||
debug('Update remote client: ' + JSON.stringify(updatedRemoteClient));
|
||||
|
||||
client.set('auth_uri', ghostOAuth2Strategy.url);
|
||||
client.set('redirection_uri', updatedRemoteClient.redirect_uri);
|
||||
client.set('client_uri', updatedRemoteClient.blog_uri);
|
||||
client.set('name', updatedRemoteClient.name);
|
||||
client.set('description', updatedRemoteClient.description);
|
||||
|
||||
return client.save(null, {context: {internal: true}});
|
||||
}).then(function updatedLocalClient() {
|
||||
logging.info('Updated remote client successfully.');
|
||||
|
||||
return {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
authStrategies = require('./auth-strategies');
|
||||
|
||||
/**
|
||||
* auth types:
|
||||
* - password: local login
|
||||
* - ghost: remote login at Ghost.org
|
||||
*/
|
||||
exports.init = function initPassport(options) {
|
||||
var authType = options.authType,
|
||||
clientName = options.clientName,
|
||||
clientDescription = options.clientDescription,
|
||||
ghostAuthUrl = options.ghostAuthUrl,
|
||||
redirectUri = options.redirectUri,
|
||||
clientUri = options.clientUri;
|
||||
exports.init = function initPassport() {
|
||||
passport.use(new ClientPasswordStrategy(authStrategies.clientPasswordStrategy));
|
||||
passport.use(new BearerStrategy(authStrategies.bearerStrategy));
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
passport.use(new ClientPasswordStrategy(authStrategies.clientPasswordStrategy));
|
||||
passport.use(new BearerStrategy(authStrategies.bearerStrategy));
|
||||
|
||||
// CASE: use switches from password to ghost and back
|
||||
// If we don't clean up the database, it can happen that the auth switch validation fails
|
||||
if (authType !== 'ghost') {
|
||||
return models.Client.findOne({slug: 'ghost-auth'})
|
||||
.then(function (client) {
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
return models.Client.destroy({id: client.id});
|
||||
})
|
||||
.then(function () {
|
||||
resolve({passport: passport.initialize()});
|
||||
})
|
||||
.catch(reject);
|
||||
}
|
||||
|
||||
var ghostOAuth2Strategy = new GhostOAuth2Strategy({
|
||||
redirectUri: redirectUri,
|
||||
blogUri: clientUri,
|
||||
url: ghostAuthUrl,
|
||||
passReqToCallback: true,
|
||||
retryHook: function retryHook(err) {
|
||||
logging.error(err);
|
||||
}
|
||||
}, authStrategies.ghostStrategy);
|
||||
|
||||
_private.updateClient({
|
||||
ghostOAuth2Strategy: ghostOAuth2Strategy,
|
||||
clientName: clientName,
|
||||
clientDescription: clientDescription,
|
||||
redirectUri: redirectUri,
|
||||
clientUri: clientUri
|
||||
}).then(function setClient(client) {
|
||||
ghostOAuth2Strategy.setClient(client);
|
||||
passport.use(ghostOAuth2Strategy);
|
||||
_private.registerEvents();
|
||||
return resolve({passport: passport.initialize()});
|
||||
}).catch(function onError(err) {
|
||||
debug('Public registration failed:' + err.message);
|
||||
|
||||
// @TODO: see https://github.com/TryGhost/Ghost/issues/7627
|
||||
// CASE: can happen if database query fails
|
||||
if (_.isArray(err)) {
|
||||
err = err[0];
|
||||
}
|
||||
|
||||
if (!errors.utils.isIgnitionError(err)) {
|
||||
err = new errors.GhostError({
|
||||
err: err
|
||||
});
|
||||
}
|
||||
|
||||
err.level = 'critical';
|
||||
err.context = err.context || 'Public client registration failed';
|
||||
err.help = err.help || 'Please verify the configured url: ' + ghostOAuth2Strategy.url;
|
||||
|
||||
return reject(err);
|
||||
});
|
||||
});
|
||||
return passport.initialize();
|
||||
};
|
||||
|
@ -1,63 +0,0 @@
|
||||
var debug = require('ghost-ignition').debug('sync'),
|
||||
models = require('../models'),
|
||||
ghostAuth = require('./ghost-auth'),
|
||||
logging = require('../logging'),
|
||||
errors = require('../errors'),
|
||||
events = require('../events'),
|
||||
knex = require('../data/db').knex,
|
||||
_private = {
|
||||
syncIntervalInMs: 1000 * 60 * 60,
|
||||
lastSync: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @TODO: support long polling in the ghost auth service
|
||||
*/
|
||||
_private.syncUser = function syncUser(loggedInUserModel) {
|
||||
debug('syncUser');
|
||||
|
||||
// CASE: sync every hour for now
|
||||
if (_private.lastSync[loggedInUserModel.id]) {
|
||||
if ((_private.lastSync[loggedInUserModel.id] + _private.syncIntervalInMs) > Date.now()) {
|
||||
debug('too early too sync');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return ghostAuth.getUser({
|
||||
id: loggedInUserModel.get('ghost_auth_id')
|
||||
}).then(function (ghostUser) {
|
||||
debug('ghost_email', ghostUser.email);
|
||||
debug('user_email', loggedInUserModel.get('email'));
|
||||
|
||||
if (ghostUser.email === loggedInUserModel.get('email')) {
|
||||
debug('email has not changed');
|
||||
return;
|
||||
}
|
||||
|
||||
debug('sync email');
|
||||
|
||||
// CASE: we update the user in a transaction to avoid collisions
|
||||
return knex.transaction(function onTransaction(transaction) {
|
||||
return models.User.edit({
|
||||
email: ghostUser.email
|
||||
}, {id: loggedInUserModel.id, transacting: transaction});
|
||||
});
|
||||
}).then(function () {
|
||||
debug('update lastSync');
|
||||
_private.lastSync[loggedInUserModel.id] = Date.now();
|
||||
}).catch(function onError(err) {
|
||||
logging.error(new errors.InternalServerError({
|
||||
message: 'ghost-auth: sync failed',
|
||||
err: err
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.init = function init(options) {
|
||||
var authType = options.authType;
|
||||
|
||||
if (authType === 'ghost') {
|
||||
events.on('read:users:me', _private.syncUser);
|
||||
}
|
||||
};
|
@ -1,42 +0,0 @@
|
||||
var Promise = require('bluebird'),
|
||||
models = require('../models'),
|
||||
errors = require('../errors');
|
||||
|
||||
/**
|
||||
* If the setup is completed and...
|
||||
* 1. the public client does exist, deny to switch to local
|
||||
* 2. the public client does not exist, deny to switch to remote
|
||||
*
|
||||
* See https://github.com/TryGhost/Ghost/issues/8342
|
||||
* Remote authentication is disabled right now.
|
||||
*/
|
||||
exports.validate = function validate(options) {
|
||||
var authType = options.authType;
|
||||
|
||||
if (authType === 'ghost') {
|
||||
return Promise.reject(new errors.InternalServerError({
|
||||
code: 'AUTH_TYPE',
|
||||
message: 'Ghost doesn\'t support remote authentication at the moment.',
|
||||
help: 'Set `auth.type` to "password".'
|
||||
}));
|
||||
}
|
||||
|
||||
return models.User.isSetup()
|
||||
.then(function (isSetup) {
|
||||
if (!isSetup) {
|
||||
return;
|
||||
}
|
||||
|
||||
return models.Client.findOne({slug: 'ghost-auth'}, {columns: 'id'})
|
||||
.then(function (client) {
|
||||
if ((client && authType === 'password') || !client && authType === 'ghost') {
|
||||
return Promise.reject(new errors.InternalServerError({
|
||||
code: 'AUTH_SWITCH',
|
||||
message: 'Switching the auth strategy is not allowed.',
|
||||
context: 'Please reset your database and start from scratch.',
|
||||
help: 'NODE_ENV=production|development knex-migrator reset && NODE_ENV=production|development knex-migrator init\n'
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
@ -7,9 +7,6 @@
|
||||
},
|
||||
"debug": false
|
||||
},
|
||||
"auth": {
|
||||
"type": "password"
|
||||
},
|
||||
"paths": {
|
||||
"contentPath": "content/"
|
||||
},
|
||||
|
@ -8,9 +8,6 @@
|
||||
"database" : "ghost"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"type": "password"
|
||||
},
|
||||
"paths": {
|
||||
"contentPath": "content/"
|
||||
},
|
||||
|
@ -12,9 +12,6 @@
|
||||
"database" : "ghost_testing"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"type": "password"
|
||||
},
|
||||
"logging": {
|
||||
"level": "fatal"
|
||||
},
|
||||
|
3
core/server/config/env/config.testing.json
vendored
3
core/server/config/env/config.testing.json
vendored
@ -11,9 +11,6 @@
|
||||
"server": {
|
||||
"port": 2369
|
||||
},
|
||||
"auth": {
|
||||
"type": "password"
|
||||
},
|
||||
"logging": {
|
||||
"level": "fatal"
|
||||
},
|
||||
|
@ -17,7 +17,6 @@ var debug = require('ghost-ignition').debug('boot:init'),
|
||||
// Config should be first require, as it triggers the initial load of the config files
|
||||
config = require('./config'),
|
||||
Promise = require('bluebird'),
|
||||
logging = require('./logging'),
|
||||
i18n = require('./i18n'),
|
||||
models = require('./models'),
|
||||
permissions = require('./permissions'),
|
||||
@ -29,7 +28,6 @@ var debug = require('ghost-ignition').debug('boot:init'),
|
||||
GhostServer = require('./ghost-server'),
|
||||
scheduling = require('./adapters/scheduling'),
|
||||
settings = require('./settings'),
|
||||
settingsCache = require('./settings/cache'),
|
||||
themes = require('./themes'),
|
||||
utils = require('./utils');
|
||||
|
||||
@ -78,25 +76,9 @@ function init() {
|
||||
|
||||
debug('Express Apps done');
|
||||
}).then(function () {
|
||||
return auth.validation.validate({
|
||||
authType: config.get('auth:type')
|
||||
});
|
||||
}).then(function () {
|
||||
// runs asynchronous
|
||||
auth.init({
|
||||
authType: config.get('auth:type'),
|
||||
ghostAuthUrl: config.get('auth:url'),
|
||||
redirectUri: utils.url.urlFor('admin', true),
|
||||
clientUri: utils.url.urlFor('home', true),
|
||||
clientName: settingsCache.get('title'),
|
||||
clientDescription: settingsCache.get('description')
|
||||
}).then(function (response) {
|
||||
parentApp.use(response.auth);
|
||||
}).catch(function onAuthError(err) {
|
||||
logging.error(err);
|
||||
});
|
||||
}).then(function () {
|
||||
parentApp.use(auth.init());
|
||||
debug('Auth done');
|
||||
|
||||
return new GhostServer(parentApp);
|
||||
}).then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
|
@ -18,9 +18,6 @@ describe('Configuration API', function () {
|
||||
should.exist(ConfigurationAPI);
|
||||
|
||||
it('can read basic config and get all expected properties', function (done) {
|
||||
configUtils.set('auth:type', 'ghost');
|
||||
configUtils.set('auth:url', 'https://auth.ghost.com');
|
||||
|
||||
ConfigurationAPI.read().then(function (response) {
|
||||
var props;
|
||||
|
||||
@ -45,14 +42,9 @@ describe('Configuration API', function () {
|
||||
props.publicAPI.should.eql(false);
|
||||
props.clientId.should.eql('ghost-admin');
|
||||
props.clientSecret.should.eql('not_available');
|
||||
props.ghostAuthUrl.should.eql('https://auth.ghost.com');
|
||||
|
||||
// value not available, because settings API was not called yet
|
||||
props.hasOwnProperty('blogTitle').should.eql(true);
|
||||
|
||||
// uuid
|
||||
props.hasOwnProperty('ghostAuthId').should.eql(true);
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
@ -1,258 +1,23 @@
|
||||
var should = require('should'), // jshint ignore:line
|
||||
sinon = require('sinon'),
|
||||
passport = require('passport'),
|
||||
Promise = require('bluebird'),
|
||||
rewire = require('rewire'),
|
||||
|
||||
testUtils = require('../../utils'),
|
||||
GhostPassport = rewire('../../../server/auth/passport'),
|
||||
models = require('../../../server/models'),
|
||||
utils = require('../../../server/utils'),
|
||||
errors = require('../../../server/errors'),
|
||||
|
||||
ghostPassport = require('../../../server/auth/passport'),
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
describe('Ghost Passport', function () {
|
||||
var client, events, registeredEvents = {};
|
||||
|
||||
function FakeGhostOAuth2Strategy(options) {
|
||||
this.name = 'ghost';
|
||||
|
||||
should.exist(options.blogUri);
|
||||
should.exist(options.url);
|
||||
should.exist(options.redirectUri);
|
||||
options.passReqToCallback.should.eql(true);
|
||||
|
||||
this.blogUri = options.blogUri;
|
||||
this.redirectUri = options.redirectUri;
|
||||
}
|
||||
|
||||
before(function () {
|
||||
models.init();
|
||||
|
||||
events = {
|
||||
on: function (name, onEvent) {
|
||||
registeredEvents[name] = onEvent;
|
||||
}
|
||||
};
|
||||
|
||||
GhostPassport.__set__('events', events);
|
||||
GhostPassport.__set__('GhostOAuth2Strategy', FakeGhostOAuth2Strategy);
|
||||
GhostPassport.__set__('_private.retryTimeout', 50);
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox.spy(passport, 'use');
|
||||
|
||||
sandbox.stub(models.Client, 'findOne', function () {
|
||||
if (client) {
|
||||
client.save = sandbox.stub();
|
||||
}
|
||||
|
||||
return Promise.resolve(client);
|
||||
});
|
||||
|
||||
sandbox.stub(models.Client, 'destroy').returns(Promise.resolve());
|
||||
|
||||
sandbox.stub(models.Client, 'add', function () {
|
||||
client = new models.Client(testUtils.DataGenerator.forKnex.createClient());
|
||||
return Promise.resolve(client);
|
||||
});
|
||||
|
||||
FakeGhostOAuth2Strategy.prototype.setClient = sandbox.stub();
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient = function () {
|
||||
};
|
||||
FakeGhostOAuth2Strategy.prototype.updateClient = function () {
|
||||
};
|
||||
|
||||
sandbox.stub(FakeGhostOAuth2Strategy.prototype, 'registerClient', function (options) {
|
||||
return Promise.resolve({
|
||||
redirect_uri: this.redirectUri,
|
||||
blog_uri: this.blogUri,
|
||||
name: options.name,
|
||||
description: options.description
|
||||
});
|
||||
});
|
||||
|
||||
sandbox.stub(FakeGhostOAuth2Strategy.prototype, 'updateClient', function () {
|
||||
return Promise.resolve({
|
||||
redirect_uri: client.get('redirection_uri'),
|
||||
blog_uri: client.get('blog_uri'),
|
||||
name: client.get('name'),
|
||||
description: client.get('description')
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe('auth_type: password', function () {
|
||||
describe('[default] local auth', function () {
|
||||
it('initialise passport with passport auth type', function () {
|
||||
return GhostPassport.init({
|
||||
authType: 'passport'
|
||||
}).then(function (response) {
|
||||
should.exist(response.passport);
|
||||
passport.use.callCount.should.eql(2);
|
||||
|
||||
models.Client.findOne.called.should.eql(true);
|
||||
models.Client.destroy.called.should.eql(false);
|
||||
models.Client.add.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.setClient.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.updateClient.called.should.eql(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('initialise passport with passport auth type [auth client exists]', function () {
|
||||
return models.Client.add({slug: 'ghost-auth'})
|
||||
.then(function () {
|
||||
models.Client.add.called.should.eql(true);
|
||||
models.Client.add.reset();
|
||||
|
||||
return GhostPassport.init({
|
||||
authType: 'passport'
|
||||
});
|
||||
})
|
||||
.then(function (response) {
|
||||
should.exist(response.passport);
|
||||
passport.use.callCount.should.eql(2);
|
||||
|
||||
models.Client.findOne.called.should.eql(true);
|
||||
models.Client.destroy.called.should.eql(true);
|
||||
models.Client.add.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.setClient.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.updateClient.called.should.eql(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('auth_type: ghost', function () {
|
||||
it('ghost client is already present in database and nothing has changed', function () {
|
||||
client = new models.Client(testUtils.DataGenerator.forKnex.createClient({
|
||||
name: 'Ghost',
|
||||
client_uri: 'http://my-blog.com',
|
||||
redirection_uri: utils.url.urlFor('home', true)
|
||||
}));
|
||||
|
||||
return GhostPassport.init({
|
||||
authType: 'ghost',
|
||||
clientUri: 'http://my-blog.com',
|
||||
ghostAuthUrl: 'http://devauth.ghost.org',
|
||||
redirectUri: utils.url.urlFor('home', true),
|
||||
clientName: 'Ghost'
|
||||
}).then(function (response) {
|
||||
should.exist(response.passport);
|
||||
passport.use.callCount.should.eql(3);
|
||||
|
||||
models.Client.findOne.called.should.eql(true);
|
||||
models.Client.add.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.setClient.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.updateClient.called.should.eql(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('ghost client is already present in database and redirect_uri has changed', function () {
|
||||
client = new models.Client(testUtils.DataGenerator.forKnex.createClient({
|
||||
name: 'Ghost',
|
||||
client_uri: 'http://my-blog.com',
|
||||
redirection_uri: 'URL-HAS-CHANGED'
|
||||
}));
|
||||
|
||||
return GhostPassport.init({
|
||||
authType: 'ghost',
|
||||
clientUri: 'http://my-blog.com',
|
||||
ghostAuthUrl: 'http://devauth.ghost.org',
|
||||
redirectUri: utils.url.urlFor('home', true),
|
||||
clientName: 'Ghost'
|
||||
}).then(function (response) {
|
||||
should.exist(response.passport);
|
||||
passport.use.callCount.should.eql(3);
|
||||
|
||||
models.Client.findOne.called.should.eql(true);
|
||||
models.Client.add.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.setClient.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(false);
|
||||
FakeGhostOAuth2Strategy.prototype.updateClient.called.should.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('ghost client is already present in database and title changes', function (done) {
|
||||
client = null;
|
||||
|
||||
GhostPassport.init({
|
||||
authType: 'ghost',
|
||||
clientUri: 'http://my-blog.com',
|
||||
ghostAuthUrl: 'http://devauth.ghost.org',
|
||||
redirectUri: utils.url.urlFor('home', true),
|
||||
clientName: 'Ghost'
|
||||
}).then(function () {
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.updateClient.called.should.eql(false);
|
||||
|
||||
registeredEvents['settings.edited']({
|
||||
attributes: {
|
||||
key: 'title',
|
||||
value: 'new-title'
|
||||
},
|
||||
_updatedAttributes: {
|
||||
value: 'old-title'
|
||||
}
|
||||
});
|
||||
|
||||
(function retry() {
|
||||
if (FakeGhostOAuth2Strategy.prototype.updateClient.called === true) {
|
||||
return done();
|
||||
}
|
||||
|
||||
setTimeout(retry, 100);
|
||||
})();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('ghost client does not exist', function () {
|
||||
client = null;
|
||||
|
||||
return GhostPassport.init({
|
||||
authType: 'ghost',
|
||||
clientUri: 'http://my-blog.com',
|
||||
ghostAuthUrl: 'http://devauth.ghost.org',
|
||||
redirectUri: utils.url.urlFor('home', true),
|
||||
clientName: 'custom client name'
|
||||
}).then(function (response) {
|
||||
should.exist(response.passport);
|
||||
passport.use.callCount.should.eql(3);
|
||||
|
||||
models.Client.findOne.called.should.eql(true);
|
||||
models.Client.add.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.setClient.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.calledWith({
|
||||
name: 'custom client name',
|
||||
description: undefined
|
||||
}).should.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('ghost client does not exist, ghost.org register client does not work', function () {
|
||||
client = null;
|
||||
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.restore();
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient = sandbox.stub();
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.returns(Promise.reject(new Error('cannot connect to ghost.org')));
|
||||
|
||||
return GhostPassport.init({
|
||||
authType: 'ghost',
|
||||
clientUri: 'http://my-blog.com',
|
||||
ghostAuthUrl: 'http://devauth.ghost.org',
|
||||
redirectUri: utils.url.urlFor('home', true)
|
||||
}).catch(function (err) {
|
||||
(err instanceof errors.GhostError).should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.callCount.should.eql(1);
|
||||
});
|
||||
var response = ghostPassport.init();
|
||||
should.exist(response);
|
||||
passport.use.callCount.should.eql(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,93 +0,0 @@
|
||||
var should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
Promise = require('bluebird'),
|
||||
auth = require('../../../server/auth'),
|
||||
models = require('../../../server/models'),
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
/**
|
||||
* See https://github.com/TryGhost/Ghost/issues/8342
|
||||
* We have disabled Ghost authentication temporary.
|
||||
* That's why some tests are skipped for now.
|
||||
*/
|
||||
describe('UNIT: auth validation', function () {
|
||||
before(function () {
|
||||
models.init();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe('ghost is enabled', function () {
|
||||
it('[failure]', function () {
|
||||
return auth.validation.validate({
|
||||
authType: 'ghost'
|
||||
}).catch(function (err) {
|
||||
should.exist(err);
|
||||
err.code.should.eql('AUTH_TYPE');
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('[success]', function () {
|
||||
sandbox.stub(models.User, 'isSetup').returns(Promise.resolve(false));
|
||||
|
||||
return auth.validation.validate({
|
||||
authType: 'ghost'
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('[success]', function () {
|
||||
sandbox.stub(models.User, 'isSetup').returns(Promise.resolve(true));
|
||||
sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(true));
|
||||
|
||||
return auth.validation.validate({
|
||||
authType: 'ghost'
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('[failure]', function () {
|
||||
sandbox.stub(models.User, 'isSetup').returns(Promise.resolve(true));
|
||||
sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(true));
|
||||
|
||||
return auth.validation.validate({
|
||||
authType: 'password'
|
||||
}).catch(function (err) {
|
||||
should.exist(err);
|
||||
err.code.should.eql('AUTH_SWITCH');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('password is enabled', function () {
|
||||
it('[success]', function () {
|
||||
sandbox.stub(models.User, 'isSetup').returns(Promise.resolve(false));
|
||||
|
||||
return auth.validation.validate({
|
||||
authType: 'password'
|
||||
});
|
||||
});
|
||||
|
||||
it('[success]', function () {
|
||||
sandbox.stub(models.User, 'isSetup').returns(Promise.resolve(true));
|
||||
sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(false));
|
||||
|
||||
return auth.validation.validate({
|
||||
authType: 'password'
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('[failure]', function () {
|
||||
sandbox.stub(models.User, 'isSetup').returns(Promise.resolve(true));
|
||||
sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(true));
|
||||
|
||||
return auth.validation.validate({
|
||||
authType: 'ghost'
|
||||
}).catch(function (err) {
|
||||
should.exist(err);
|
||||
err.code.should.eql('AUTH_SWITCH');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -78,7 +78,6 @@
|
||||
"nodemailer": "0.7.1",
|
||||
"oauth2orize": "1.8.0",
|
||||
"passport": "0.3.2",
|
||||
"passport-ghost": "2.3.1",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"path-match": "1.2.4",
|
||||
|
25
yarn.lock
25
yarn.lock
@ -322,7 +322,7 @@ bluebird@3.4.6:
|
||||
version "3.4.6"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f"
|
||||
|
||||
bluebird@3.5.0, bluebird@^3.0.5, bluebird@^3.4.1, bluebird@^3.4.3, bluebird@^3.4.6:
|
||||
bluebird@3.5.0, bluebird@^3.0.5, bluebird@^3.4.3, bluebird@^3.4.6:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
|
||||
|
||||
@ -3168,7 +3168,7 @@ lodash@4.16.3:
|
||||
version "4.16.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.3.tgz#0ba761439529127c7a38c439114ca153efa999a2"
|
||||
|
||||
lodash@4.17.4, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.4, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.6.0, lodash@^4.7.0, lodash@^4.8.0, lodash@~4.17.2:
|
||||
lodash@4.17.4, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.4, lodash@^4.17.4, lodash@^4.6.0, lodash@^4.7.0, lodash@^4.8.0, lodash@~4.17.2:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||
|
||||
@ -3773,10 +3773,6 @@ oauth2orize@1.8.0:
|
||||
uid2 "0.0.x"
|
||||
utils-merge "1.x.x"
|
||||
|
||||
oauth@0.9.x:
|
||||
version "0.9.15"
|
||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||
|
||||
object-assign@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
|
||||
@ -3892,15 +3888,6 @@ parseurl@~1.3.0, parseurl@~1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
|
||||
|
||||
passport-ghost@2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/passport-ghost/-/passport-ghost-2.3.1.tgz#0dfa63d725bb7c8902acf91219b34b053f7cea9a"
|
||||
dependencies:
|
||||
bluebird "^3.4.1"
|
||||
ghost-ignition "^2.8.7"
|
||||
lodash "^4.16.6"
|
||||
passport-oauth2 "1.1.2"
|
||||
|
||||
passport-http-bearer@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz#147469ea3669e2a84c6167ef99dbb77e1f0098a8"
|
||||
@ -3913,14 +3900,6 @@ passport-oauth2-client-password@0.1.2:
|
||||
dependencies:
|
||||
passport-strategy "1.x.x"
|
||||
|
||||
passport-oauth2@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.1.2.tgz#bd7163b1b6090371868dc4ef6f9f2e1e4cc4b948"
|
||||
dependencies:
|
||||
oauth "0.9.x"
|
||||
passport-strategy "1.x.x"
|
||||
uid2 "0.0.x"
|
||||
|
||||
passport-strategy@1.x.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
|
||||
|
Loading…
Reference in New Issue
Block a user