mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-08 02:52:39 -05:00
🎨 handle case: sync email after logout (#8097)
no issue If the user changes the email in the remote auth service and executes a logout directly afterwards, the user would lock himself out of his blog, because the email sync happens once per hour right now. For that case, we have to store the ghost auth id.
This commit is contained in:
parent
345003a16f
commit
27f17c973d
4 changed files with 40 additions and 23 deletions
|
@ -128,7 +128,7 @@ strategies = {
|
|||
});
|
||||
};
|
||||
|
||||
models.User.getByEmail(profile.email, options)
|
||||
models.User.findOne({ghost_auth_id: profile.id}, options)
|
||||
.then(function fetchedUser(user) {
|
||||
if (user) {
|
||||
return user;
|
||||
|
@ -142,7 +142,12 @@ strategies = {
|
|||
})
|
||||
.then(function updateGhostAuthToken(user) {
|
||||
options.id = user.id;
|
||||
return models.User.edit({ghost_auth_access_token: ghostAuthAccessToken}, options);
|
||||
|
||||
return models.User.edit({
|
||||
email: profile.email,
|
||||
ghost_auth_id: profile.id,
|
||||
ghost_auth_access_token: ghostAuthAccessToken
|
||||
}, options);
|
||||
})
|
||||
.then(function returnResponse(user) {
|
||||
done(null, user, profile);
|
||||
|
|
|
@ -29,6 +29,7 @@ module.exports = {
|
|||
name: {type: 'string', maxlength: 191, nullable: false},
|
||||
slug: {type: 'string', maxlength: 191, nullable: false, unique: true},
|
||||
ghost_auth_access_token: {type: 'string', maxlength: 32, nullable: true},
|
||||
ghost_auth_id: {type: 'string', maxlength: 24, nullable: true},
|
||||
password: {type: 'string', maxlength: 60, nullable: false},
|
||||
email: {type: 'string', maxlength: 191, nullable: false, unique: true, validations: {isEmail: true}},
|
||||
image: {type: 'string', maxlength: 2000, nullable: true},
|
||||
|
|
|
@ -201,10 +201,9 @@ describe('Auth Strategies', function () {
|
|||
});
|
||||
|
||||
describe('Ghost Strategy', function () {
|
||||
var userByEmailStub, inviteStub, userAddStub, userEditStub, userFindOneStub;
|
||||
var inviteStub, userAddStub, userEditStub, userFindOneStub;
|
||||
|
||||
beforeEach(function () {
|
||||
userByEmailStub = sandbox.stub(Models.User, 'getByEmail');
|
||||
userFindOneStub = sandbox.stub(Models.User, 'findOne');
|
||||
userAddStub = sandbox.stub(Models.User, 'add');
|
||||
userEditStub = sandbox.stub(Models.User, 'edit');
|
||||
|
@ -214,15 +213,15 @@ describe('Auth Strategies', function () {
|
|||
it('with invite, but with wrong invite token', function (done) {
|
||||
var ghostAuthAccessToken = '12345',
|
||||
req = {body: {inviteToken: 'wrong'}},
|
||||
profile = {email: 'test@example.com'};
|
||||
profile = {email: 'test@example.com', id: '1234'};
|
||||
|
||||
userByEmailStub.returns(Promise.resolve(null));
|
||||
userFindOneStub.returns(Promise.resolve(null));
|
||||
inviteStub.returns(Promise.reject(new errors.NotFoundError()));
|
||||
|
||||
authStrategies.ghostStrategy(req, ghostAuthAccessToken, null, profile, function (err) {
|
||||
should.exist(err);
|
||||
(err instanceof errors.NotFoundError).should.eql(true);
|
||||
userByEmailStub.calledOnce.should.be.true();
|
||||
userFindOneStub.calledOnce.should.be.true();
|
||||
inviteStub.calledOnce.should.be.true();
|
||||
done();
|
||||
});
|
||||
|
@ -231,9 +230,9 @@ describe('Auth Strategies', function () {
|
|||
it('with correct invite token, but expired', function (done) {
|
||||
var ghostAuthAccessToken = '12345',
|
||||
req = {body: {inviteToken: 'token'}},
|
||||
profile = {email: 'test@example.com'};
|
||||
profile = {email: 'test@example.com', id: '1234'};
|
||||
|
||||
userByEmailStub.returns(Promise.resolve(null));
|
||||
userFindOneStub.returns(Promise.resolve(null));
|
||||
inviteStub.returns(Promise.resolve(Models.Invite.forge({
|
||||
id: 1,
|
||||
token: 'token',
|
||||
|
@ -243,7 +242,7 @@ describe('Auth Strategies', function () {
|
|||
authStrategies.ghostStrategy(req, ghostAuthAccessToken, null, profile, function (err) {
|
||||
should.exist(err);
|
||||
(err instanceof errors.NotFoundError).should.eql(true);
|
||||
userByEmailStub.calledOnce.should.be.true();
|
||||
userFindOneStub.calledOnce.should.be.true();
|
||||
inviteStub.calledOnce.should.be.true();
|
||||
done();
|
||||
});
|
||||
|
@ -252,7 +251,7 @@ describe('Auth Strategies', function () {
|
|||
it('with correct invite token', function (done) {
|
||||
var ghostAuthAccessToken = '12345',
|
||||
req = {body: {inviteToken: 'token'}},
|
||||
invitedProfile = {email: 'test@example.com'},
|
||||
invitedProfile = {email: 'test@example.com', id: '1234'},
|
||||
invitedUser = {id: 2},
|
||||
inviteModel = Models.Invite.forge({
|
||||
id: 1,
|
||||
|
@ -260,7 +259,7 @@ describe('Auth Strategies', function () {
|
|||
expires: Date.now() + 1000
|
||||
});
|
||||
|
||||
userByEmailStub.returns(Promise.resolve(null));
|
||||
userFindOneStub.returns(Promise.resolve(null));
|
||||
userAddStub.returns(Promise.resolve(invitedUser));
|
||||
userEditStub.returns(Promise.resolve(invitedUser));
|
||||
inviteStub.returns(Promise.resolve(inviteModel));
|
||||
|
@ -273,7 +272,7 @@ describe('Auth Strategies', function () {
|
|||
user.should.eql(invitedUser);
|
||||
profile.should.eql(invitedProfile);
|
||||
|
||||
userByEmailStub.calledOnce.should.be.true();
|
||||
userFindOneStub.calledOnce.should.be.true();
|
||||
inviteStub.calledOnce.should.be.true();
|
||||
done();
|
||||
});
|
||||
|
@ -282,24 +281,32 @@ describe('Auth Strategies', function () {
|
|||
it('setup', function (done) {
|
||||
var ghostAuthAccessToken = '12345',
|
||||
req = {body: {}},
|
||||
ownerProfile = {email: 'test@example.com'},
|
||||
ownerProfile = {email: 'test@example.com', id: '1234'},
|
||||
owner = {id: 2};
|
||||
|
||||
userByEmailStub.returns(Promise.resolve(null));
|
||||
userFindOneStub.returns(Promise.resolve(_.merge({}, {status: 'inactive'}, owner)));
|
||||
userFindOneStub.withArgs({ghost_auth_id: ownerProfile.id})
|
||||
.returns(Promise.resolve(null));
|
||||
|
||||
userFindOneStub.withArgs({slug: 'ghost-owner', status: 'inactive'})
|
||||
.returns(Promise.resolve(_.merge({}, {status: 'inactive'}, owner)));
|
||||
|
||||
userEditStub.withArgs({status: 'active', email: 'test@example.com'}, {
|
||||
context: {internal: true},
|
||||
id: owner.id
|
||||
}).returns(Promise.resolve(owner));
|
||||
|
||||
userEditStub.withArgs({ghost_auth_access_token: ghostAuthAccessToken}, {
|
||||
userEditStub.withArgs({
|
||||
ghost_auth_access_token: ghostAuthAccessToken,
|
||||
ghost_auth_id: ownerProfile.id,
|
||||
email: ownerProfile.email
|
||||
}, {
|
||||
context: {internal: true},
|
||||
id: owner.id
|
||||
}).returns(Promise.resolve(owner));
|
||||
|
||||
authStrategies.ghostStrategy(req, ghostAuthAccessToken, null, ownerProfile, function (err, user, profile) {
|
||||
should.not.exist(err);
|
||||
userByEmailStub.calledOnce.should.be.true();
|
||||
userFindOneStub.calledTwice.should.be.true();
|
||||
inviteStub.calledOnce.should.be.false();
|
||||
|
||||
should.exist(user);
|
||||
|
@ -313,18 +320,22 @@ describe('Auth Strategies', function () {
|
|||
it('auth', function (done) {
|
||||
var ghostAuthAccessToken = '12345',
|
||||
req = {body: {}},
|
||||
ownerProfile = {email: 'test@example.com'},
|
||||
ownerProfile = {email: 'test@example.com', id: '12345'},
|
||||
owner = {id: 2};
|
||||
|
||||
userByEmailStub.returns(Promise.resolve(owner));
|
||||
userEditStub.withArgs({ghost_auth_access_token: ghostAuthAccessToken}, {
|
||||
userFindOneStub.returns(Promise.resolve(owner));
|
||||
userEditStub.withArgs({
|
||||
ghost_auth_access_token: ghostAuthAccessToken,
|
||||
ghost_auth_id: ownerProfile.id,
|
||||
email: ownerProfile.email
|
||||
}, {
|
||||
context: {internal: true},
|
||||
id: owner.id
|
||||
}).returns(Promise.resolve(owner));
|
||||
|
||||
authStrategies.ghostStrategy(req, ghostAuthAccessToken, null, ownerProfile, function (err, user, profile) {
|
||||
should.not.exist(err);
|
||||
userByEmailStub.calledOnce.should.be.true();
|
||||
userFindOneStub.calledOnce.should.be.true();
|
||||
userEditStub.calledOnce.should.be.true();
|
||||
inviteStub.calledOnce.should.be.false();
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ should.equal(true, true);
|
|||
// both of which are required for migrations to work properly.
|
||||
describe('DB version integrity', function () {
|
||||
// Only these variables should need updating
|
||||
var currentSchemaHash = 'e648a7d1f9b9c5eb19512999756cd4db',
|
||||
var currentSchemaHash = 'ae4ada98be2691b4d6e323eebcdb875f',
|
||||
currentFixturesHash = 'b9e684a87353c592df9b23948e364c05';
|
||||
|
||||
// If this test is failing, then it is likely a change has been made that requires a DB version bump,
|
||||
|
|
Loading…
Add table
Reference in a new issue