2016-09-30 14:45:59 +03:00
|
|
|
var models = require('../models'),
|
|
|
|
utils = require('../utils'),
|
|
|
|
i18n = require('../i18n'),
|
|
|
|
errors = require('../errors'),
|
|
|
|
_ = require('lodash'),
|
|
|
|
strategies;
|
|
|
|
|
|
|
|
strategies = {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ClientPasswordStrategy
|
|
|
|
*
|
|
|
|
* This strategy is used to authenticate registered OAuth clients. It is
|
|
|
|
* employed to protect the `token` endpoint, which consumers use to obtain
|
|
|
|
* access tokens. The OAuth 2.0 specification suggests that clients use the
|
|
|
|
* HTTP Basic scheme to authenticate (not implemented yet).
|
|
|
|
* Use of the client password strategy is implemented to support ember-simple-auth.
|
|
|
|
*/
|
|
|
|
clientPasswordStrategy: function clientPasswordStrategy(clientId, clientSecret, done) {
|
|
|
|
return models.Client.findOne({slug: clientId}, {withRelated: ['trustedDomains']})
|
|
|
|
.then(function then(model) {
|
|
|
|
if (model) {
|
|
|
|
var client = model.toJSON({include: ['trustedDomains']});
|
|
|
|
if (client.status === 'enabled' && client.secret === clientSecret) {
|
|
|
|
return done(null, client);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return done(null, false);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* BearerStrategy
|
|
|
|
*
|
|
|
|
* This strategy is used to authenticate users based on an access token (aka a
|
|
|
|
* bearer token). The user must have previously authorized a client
|
|
|
|
* application, which is issued an access token to make requests on behalf of
|
|
|
|
* the authorizing user.
|
|
|
|
*/
|
|
|
|
bearerStrategy: function bearerStrategy(accessToken, done) {
|
|
|
|
return models.Accesstoken.findOne({token: accessToken})
|
|
|
|
.then(function then(model) {
|
|
|
|
if (model) {
|
|
|
|
var token = model.toJSON();
|
|
|
|
if (token.expires > Date.now()) {
|
|
|
|
return models.User.findOne({id: token.user_id})
|
|
|
|
.then(function then(model) {
|
|
|
|
if (model) {
|
|
|
|
var user = model.toJSON(),
|
|
|
|
info = {scope: '*'};
|
|
|
|
return done(null, {id: user.id}, info);
|
|
|
|
}
|
|
|
|
return done(null, false);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return done(null, false);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return done(null, false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ghost Strategy
|
2016-10-03 17:11:43 +03:00
|
|
|
* ghostAuthRefreshToken: will be null for now, because we don't need it right now
|
2016-09-30 14:45:59 +03:00
|
|
|
*
|
|
|
|
* CASES:
|
|
|
|
* - via invite token
|
|
|
|
* - via normal auth
|
|
|
|
* - via setup
|
|
|
|
*
|
2016-10-03 17:11:43 +03:00
|
|
|
* @TODO: validate GhostAuth profile?
|
2016-09-30 14:45:59 +03:00
|
|
|
*/
|
2016-10-03 17:11:43 +03:00
|
|
|
ghostStrategy: function ghostStrategy(req, ghostAuthAccessToken, ghostAuthRefreshToken, profile, done) {
|
2016-09-30 14:45:59 +03:00
|
|
|
var inviteToken = req.body.inviteToken,
|
|
|
|
options = {context: {internal: true}},
|
|
|
|
handleInviteToken, handleSetup;
|
|
|
|
|
|
|
|
handleInviteToken = function handleInviteToken() {
|
|
|
|
var user, invite;
|
|
|
|
inviteToken = utils.decodeBase64URLsafe(inviteToken);
|
|
|
|
|
|
|
|
return models.Invite.findOne({token: inviteToken}, options)
|
|
|
|
.then(function addInviteUser(_invite) {
|
|
|
|
invite = _invite;
|
|
|
|
|
|
|
|
if (!invite) {
|
2016-10-06 15:27:35 +03:00
|
|
|
throw new errors.NotFoundError({message: i18n.t('errors.api.invites.inviteNotFound')});
|
2016-09-30 14:45:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (invite.get('expires') < Date.now()) {
|
2016-10-06 15:27:35 +03:00
|
|
|
throw new errors.NotFoundError({message: i18n.t('errors.api.invites.inviteExpired')});
|
2016-09-30 14:45:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return models.User.add({
|
2016-11-08 17:21:25 +03:00
|
|
|
email: profile.email,
|
|
|
|
name: profile.email,
|
2016-09-30 14:45:59 +03:00
|
|
|
password: utils.uid(50),
|
|
|
|
roles: invite.toJSON().roles
|
|
|
|
}, options);
|
|
|
|
})
|
|
|
|
.then(function destroyInvite(_user) {
|
|
|
|
user = _user;
|
|
|
|
return invite.destroy(options);
|
|
|
|
})
|
|
|
|
.then(function () {
|
|
|
|
return user;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
handleSetup = function handleSetup() {
|
|
|
|
return models.User.findOne({slug: 'ghost-owner', status: 'all'}, options)
|
|
|
|
.then(function fetchedOwner(owner) {
|
|
|
|
if (!owner) {
|
2016-10-06 15:27:35 +03:00
|
|
|
throw new errors.NotFoundError({message: i18n.t('errors.models.user.userNotFound')});
|
2016-09-30 14:45:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return models.User.edit({
|
2016-11-08 17:21:25 +03:00
|
|
|
email: profile.email,
|
2016-09-30 14:45:59 +03:00
|
|
|
status: 'active'
|
|
|
|
}, _.merge({id: owner.id}, options));
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-11-08 17:21:25 +03:00
|
|
|
models.User.getByEmail(profile.email, options)
|
2016-09-30 14:45:59 +03:00
|
|
|
.then(function fetchedUser(user) {
|
|
|
|
if (user) {
|
|
|
|
return user;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inviteToken) {
|
|
|
|
return handleInviteToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
return handleSetup();
|
|
|
|
})
|
2016-10-03 17:11:43 +03:00
|
|
|
.then(function updateGhostAuthToken(user) {
|
2016-09-30 14:45:59 +03:00
|
|
|
options.id = user.id;
|
2016-10-03 17:11:43 +03:00
|
|
|
return models.User.edit({ghost_auth_access_token: ghostAuthAccessToken}, options);
|
2016-09-30 14:45:59 +03:00
|
|
|
})
|
|
|
|
.then(function returnResponse(user) {
|
|
|
|
done(null, user, profile);
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = strategies;
|