🎨 Ghost OAuth improvements (#7550)
refs #7452 - 🎨 logging.debug for public client registration - 🎨 add tests for passport ghost - improve readability for passport file - add basic tests
This commit is contained in:
parent
06151ef5ac
commit
22589e8b91
@ -8,73 +8,77 @@ var ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy
|
||||
errors = require('../errors'),
|
||||
logging = require('../logging'),
|
||||
models = require('../models'),
|
||||
_private = {};
|
||||
_private = {
|
||||
retryTimeout: 3000,
|
||||
retries: 10
|
||||
};
|
||||
|
||||
/**
|
||||
* Public client registration at Ghost.org
|
||||
*/
|
||||
_private.registerClient = function registerClient(options) {
|
||||
_private.registerClient = function (options) {
|
||||
var ghostOAuth2Strategy = options.ghostOAuth2Strategy,
|
||||
url = options.url;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var retry = function retry(retryCount, done) {
|
||||
models.Client.findOne({slug: 'ghost-auth'}, {context: {internal: true}})
|
||||
.then(function (client) {
|
||||
// CASE: Ghost Auth client is already registered
|
||||
if (client) {
|
||||
return done(null, {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
});
|
||||
}
|
||||
|
||||
return ghostOAuth2Strategy.registerClient({clientName: url})
|
||||
.then(function addClient(credentials) {
|
||||
return models.Client.add({
|
||||
name: 'Ghost Auth',
|
||||
slug: 'ghost-auth',
|
||||
uuid: credentials.client_id,
|
||||
secret: credentials.client_secret
|
||||
}, {context: {internal: true}});
|
||||
})
|
||||
.then(function returnClient(client) {
|
||||
return done(null, {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
});
|
||||
})
|
||||
.catch(function publicClientRegistrationError(err) {
|
||||
logging.error(err);
|
||||
|
||||
if (retryCount < 0) {
|
||||
return done(new errors.IncorrectUsageError({
|
||||
message: 'Public client registration failed: ' + err.code || err.message,
|
||||
context: 'Please verify that the url is reachable: ' + ghostOAuth2Strategy.url
|
||||
}));
|
||||
}
|
||||
|
||||
console.log('RETRY: Public Client Registration...');
|
||||
var timeout = setTimeout(function () {
|
||||
clearTimeout(timeout);
|
||||
retryCount = retryCount - 1;
|
||||
retry(retryCount, done);
|
||||
}, 3000);
|
||||
});
|
||||
})
|
||||
.catch(reject);
|
||||
};
|
||||
|
||||
retry(10, function retryPublicClientRegistration(err, client) {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
return models.Client.findOne({slug: 'ghost-auth'}, {context: {internal: true}})
|
||||
.then(function fetchedClient(client) {
|
||||
// CASE: Ghost Auth client is already registered
|
||||
if (client) {
|
||||
return {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
};
|
||||
}
|
||||
|
||||
resolve(client);
|
||||
return ghostOAuth2Strategy.registerClient({clientName: url})
|
||||
.then(function addClient(credentials) {
|
||||
return models.Client.add({
|
||||
name: 'Ghost Auth',
|
||||
slug: 'ghost-auth',
|
||||
uuid: credentials.client_id,
|
||||
secret: credentials.client_secret
|
||||
}, {context: {internal: true}});
|
||||
})
|
||||
.then(function returnClient(client) {
|
||||
return {
|
||||
client_id: client.get('uuid'),
|
||||
client_secret: client.get('secret')
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
_private.startPublicClientRegistration = function startPublicClientRegistration(options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
(function retry(retries) {
|
||||
options.retryCount = retries;
|
||||
|
||||
_private.registerClient(options)
|
||||
.then(resolve)
|
||||
.catch(function publicClientRegistrationError(err) {
|
||||
logging.error(err);
|
||||
|
||||
if (options.retryCount < 0) {
|
||||
return reject(new errors.IncorrectUsageError({
|
||||
message: 'Public client registration failed: ' + err.code || err.message,
|
||||
context: 'Please verify that the url can be reached: ' + options.ghostOAuth2Strategy.url
|
||||
}));
|
||||
}
|
||||
|
||||
logging.debug('Trying to register Public Client...');
|
||||
var timeout = setTimeout(function () {
|
||||
clearTimeout(timeout);
|
||||
|
||||
options.retryCount = options.retryCount - 1;
|
||||
retry(options.retryCount);
|
||||
}, _private.retryTimeout);
|
||||
});
|
||||
})(_private.retries);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* auth types:
|
||||
* - password: local login
|
||||
* - ghost: remote login at Ghost.org
|
||||
*/
|
||||
exports.init = function initPassport(options) {
|
||||
var type = options.type,
|
||||
url = options.url;
|
||||
@ -93,14 +97,15 @@ exports.init = function initPassport(options) {
|
||||
passReqToCallback: true
|
||||
}, authStrategies.ghostStrategy);
|
||||
|
||||
_private.registerClient({ghostOAuth2Strategy: ghostOAuth2Strategy, url: utils.url.getBaseUrl()})
|
||||
.then(function setClient(client) {
|
||||
console.log('SUCCESS: Public Client Registration');
|
||||
_private.startPublicClientRegistration({
|
||||
ghostOAuth2Strategy: ghostOAuth2Strategy,
|
||||
url: utils.url.getBaseUrl()
|
||||
}).then(function setClient(client) {
|
||||
logging.debug('Public Client Registration was successful');
|
||||
|
||||
ghostOAuth2Strategy.setClient(client);
|
||||
passport.use(ghostOAuth2Strategy);
|
||||
return resolve({passport: passport.initialize()});
|
||||
})
|
||||
.catch(reject);
|
||||
ghostOAuth2Strategy.setClient(client);
|
||||
passport.use(ghostOAuth2Strategy);
|
||||
return resolve({passport: passport.initialize()});
|
||||
}).catch(reject);
|
||||
});
|
||||
};
|
||||
|
106
core/test/unit/auth/passport_spec.js
Normal file
106
core/test/unit/auth/passport_spec.js
Normal file
@ -0,0 +1,106 @@
|
||||
var passport = require('passport'),
|
||||
sinon = require('sinon'),
|
||||
Promise = require('bluebird'),
|
||||
rewire = require('rewire'),
|
||||
should = require('should'),
|
||||
sandbox = sinon.sandbox.create(),
|
||||
testUtils = require('../../utils'),
|
||||
GhostPassport = rewire('../../../server/auth/passport'),
|
||||
models = require('../../../server/models'),
|
||||
errors = require('../../../server/errors');
|
||||
|
||||
should.equal(true, true);
|
||||
|
||||
describe('Ghost Passport', function () {
|
||||
var client;
|
||||
|
||||
function FakeGhostOAuth2Strategy() {
|
||||
this.name = 'FakeGhostOAuth2Strategy';
|
||||
}
|
||||
|
||||
before(function () {
|
||||
models.init();
|
||||
GhostPassport.__set__('GhostOAuth2Strategy', FakeGhostOAuth2Strategy);
|
||||
GhostPassport.__set__('_private.retryTimeout', 50);
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox.spy(passport, 'use');
|
||||
|
||||
sandbox.stub(models.Client, 'findOne', function () {
|
||||
return Promise.resolve(client);
|
||||
});
|
||||
|
||||
sandbox.stub(models.Client, 'add').returns(Promise.resolve(new models.Client(testUtils.DataGenerator.forKnex.createClient())));
|
||||
|
||||
FakeGhostOAuth2Strategy.prototype.setClient = sandbox.stub();
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient = sandbox.stub().returns(Promise.resolve({}));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe('auth_type: password', function () {
|
||||
it('initialise passport with passport auth type', function () {
|
||||
return GhostPassport.init({
|
||||
type: 'passport'
|
||||
}).then(function (response) {
|
||||
should.exist(response.passport);
|
||||
passport.use.callCount.should.eql(2);
|
||||
|
||||
models.Client.findOne.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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('auth_type: ghost', function () {
|
||||
it('ghost client is already present in database', function () {
|
||||
client = new models.Client(testUtils.DataGenerator.forKnex.createClient());
|
||||
|
||||
return GhostPassport.init({
|
||||
type: '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);
|
||||
});
|
||||
});
|
||||
|
||||
it('ghost client does not exist', function () {
|
||||
client = null;
|
||||
|
||||
return GhostPassport.init({
|
||||
type: '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(true);
|
||||
FakeGhostOAuth2Strategy.prototype.setClient.called.should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('ghost client does not exist, ghost.org register client does not work', function () {
|
||||
client = null;
|
||||
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.returns(Promise.reject(new Error('cannot connect to ghost.org')));
|
||||
|
||||
return GhostPassport.init({
|
||||
type: 'ghost'
|
||||
}).catch(function (err) {
|
||||
(err instanceof errors.IncorrectUsageError).should.eql(true);
|
||||
FakeGhostOAuth2Strategy.prototype.registerClient.callCount.should.eql(12);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user