0
Fork 0
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:
Katharina Irrgang 2017-03-08 15:31:22 +01:00 committed by Hannah Wolfe
parent 345003a16f
commit 27f17c973d
4 changed files with 40 additions and 23 deletions

View file

@ -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);

View file

@ -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},

View file

@ -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();

View file

@ -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,