mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-23 03:42:27 +03:00
Added "verified" status to session
refs ENG-1622 Currently unused by the API, this session variable will be used to confirm whether the user has authenticated their session with an email OTP. The verified status is not removed on logout, so sessions are now retained instead of being destroyed.
This commit is contained in:
parent
698e42433c
commit
8f7c81ac84
@ -61,8 +61,8 @@ const controller = {
|
||||
});
|
||||
},
|
||||
delete() {
|
||||
return Promise.resolve(function destroySessionMw(req, res, next) {
|
||||
auth.session.destroySession(req, res, next);
|
||||
return Promise.resolve(function logoutSessionMw(req, res, next) {
|
||||
auth.session.logout(req, res, next);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -8,9 +8,9 @@ function SessionMiddleware({sessionService}) {
|
||||
}
|
||||
}
|
||||
|
||||
async function destroySession(req, res, next) {
|
||||
async function logout(req, res, next) {
|
||||
try {
|
||||
await sessionService.destroyCurrentSession(req);
|
||||
await sessionService.removeUserForSession(req, res);
|
||||
res.sendStatus(204);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
@ -33,7 +33,7 @@ function SessionMiddleware({sessionService}) {
|
||||
|
||||
return {
|
||||
createSession: createSession,
|
||||
destroySession: destroySession,
|
||||
logout: logout,
|
||||
authenticate: authenticate
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
const {
|
||||
BadRequestError,
|
||||
InternalServerError
|
||||
BadRequestError
|
||||
} = require('@tryghost/errors');
|
||||
|
||||
/**
|
||||
@ -15,6 +14,7 @@ const {
|
||||
* @prop {string} origin
|
||||
* @prop {string} user_agent
|
||||
* @prop {string} ip
|
||||
* @prop {boolean} verified
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -25,8 +25,9 @@ const {
|
||||
/**
|
||||
* @typedef {object} SessionService
|
||||
* @prop {(req: Req, res: Res) => Promise<User | null>} getUserForSession
|
||||
* @prop {(req: Req, res: Res) => Promise<void>} destroyCurrentSession
|
||||
* @prop {(req: Req, res: Res) => Promise<void>} removeUserForSession
|
||||
* @prop {(req: Req, res: Res, user: User) => Promise<void>} createSessionForUser
|
||||
* @prop {(req: Req, res: Res) => Promise<void>} verifySession
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -86,22 +87,26 @@ module.exports = function createSessionService({getSession, findUserById, getOri
|
||||
}
|
||||
|
||||
/**
|
||||
* destroyCurrentSession
|
||||
* verifySession
|
||||
*
|
||||
* @param {Req} req
|
||||
* @param {Res} res
|
||||
*/
|
||||
async function verifySession(req, res) {
|
||||
const session = await getSession(req, res);
|
||||
session.verified = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* removeUserForSession
|
||||
*
|
||||
* @param {Req} req
|
||||
* @param {Res} res
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function destroyCurrentSession(req, res) {
|
||||
async function removeUserForSession(req, res) {
|
||||
const session = await getSession(req, res);
|
||||
return new Promise((resolve, reject) => {
|
||||
session.destroy((err) => {
|
||||
if (err) {
|
||||
return reject(new InternalServerError({err}));
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
session.user_id = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,7 +144,7 @@ module.exports = function createSessionService({getSession, findUserById, getOri
|
||||
return {
|
||||
getUserForSession,
|
||||
createSessionForUser,
|
||||
destroyCurrentSession
|
||||
removeUserForSession,
|
||||
verifySession
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -49,8 +49,11 @@ describe('SessionService', function () {
|
||||
const expectedUser = await findUserById.returnValues[0];
|
||||
should.equal(actualUser, expectedUser);
|
||||
|
||||
await sessionService.destroyCurrentSession(req, res);
|
||||
should.ok(req.session.destroy.calledOnce);
|
||||
await sessionService.removeUserForSession(req, res);
|
||||
should.equal(req.session.user_id, undefined);
|
||||
|
||||
const removedUser = await sessionService.getUserForSession(req, res);
|
||||
should.equal(removedUser, null);
|
||||
});
|
||||
|
||||
it('Throws an error when the csrf verification fails', async function () {
|
||||
@ -131,4 +134,55 @@ describe('SessionService', function () {
|
||||
|
||||
await sessionService.getUserForSession(req, res).should.be.fulfilled();
|
||||
});
|
||||
|
||||
it('Can verify a user session', async function () {
|
||||
const getSession = async (req) => {
|
||||
if (req.session) {
|
||||
return req.session;
|
||||
}
|
||||
req.session = {
|
||||
destroy: sinon.spy(cb => cb())
|
||||
};
|
||||
return req.session;
|
||||
};
|
||||
const findUserById = sinon.spy(async ({id}) => ({id}));
|
||||
const getOriginOfRequest = sinon.stub().returns('origin');
|
||||
|
||||
const sessionService = SessionService({
|
||||
getSession,
|
||||
findUserById,
|
||||
getOriginOfRequest
|
||||
});
|
||||
|
||||
const req = Object.create(express.request, {
|
||||
ip: {
|
||||
value: '0.0.0.0'
|
||||
},
|
||||
headers: {
|
||||
value: {
|
||||
cookie: 'thing'
|
||||
}
|
||||
},
|
||||
get: {
|
||||
value: () => 'Fake'
|
||||
}
|
||||
});
|
||||
const res = Object.create(express.response);
|
||||
const user = {id: 'egg'};
|
||||
|
||||
await sessionService.createSessionForUser(req, res, user);
|
||||
should.equal(req.session.user_id, 'egg');
|
||||
should.equal(req.session.verified, undefined);
|
||||
|
||||
await sessionService.verifySession(req, res);
|
||||
should.equal(req.session.verified, true);
|
||||
|
||||
await sessionService.removeUserForSession(req, res);
|
||||
should.equal(req.session.user_id, undefined);
|
||||
should.equal(req.session.verified, true);
|
||||
|
||||
await sessionService.createSessionForUser(req, res, user);
|
||||
should.equal(req.session.user_id, 'egg');
|
||||
should.equal(req.session.verified, true);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user