0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-18 02:21:47 -05:00

Stored cached member data in separate cookie

no-issue

This allows for simple trusted caching. We can still use the primary
cookie to determine whether or not a session exists, the cached cookie
can safely be deleted or ignored. This is an "progressive enhancement"
on top of the existing solution.
This commit is contained in:
Fabien O'Carroll 2019-09-09 13:46:18 +08:00
parent d741cd9fba
commit 458bcf41fa

View file

@ -8,6 +8,7 @@ const {
const EMPTY = {};
const SIX_MONTHS_MS = 1000 * 60 * 60 * 24 * 184;
const ONE_DAY_MS = 1000 * 60 * 60 * 24;
const withCookies = (fn, cookieConfig) => (req, res) => {
return new Promise((resolve) => {
@ -40,6 +41,8 @@ module.exports = function create(options = EMPTY) {
cookieMaxAge = SIX_MONTHS_MS,
cookieSecure = true,
cookieName = 'members-ssr',
cookieCacheName = 'members-ssr-cache',
cookieCacheMaxAge = ONE_DAY_MS,
cookiePath = '/',
cookieKeys,
membersApi
@ -76,6 +79,13 @@ module.exports = function create(options = EMPTY) {
maxAge: cookieMaxAge,
path: cookiePath
});
cookies.set(cookieCacheName, JSON.stringify(member), {
signed: true,
httpOnly: true,
sameSite: 'lax',
maxAge: cookieCacheMaxAge,
path: cookiePath
});
}, cookieConfig);
const deleteSession = withCookies((_req, _res, {cookies}) => {
@ -86,19 +96,56 @@ module.exports = function create(options = EMPTY) {
maxAge: cookieMaxAge,
path: cookiePath
});
cookies.set(cookieCacheName, {
signed: true,
httpOnly: true,
sameSite: 'lax',
maxAge: cookieCacheMaxAge,
path: cookiePath
});
}, cookieConfig);
const getMemberDataFromSession = withCookies(async (_req, _res, {cookies}) => {
try {
const email = cookies.get(cookieName, {
signed: true
});
return get(membersApi).getMemberIdentityData(email);
} catch (e) {
const email = cookies.get(cookieName, {
signed: true
});
if (!email) {
throw new BadRequestError({
message: `Cookie ${cookieName} not found`
});
}
const cachedMember = cookies.get(cookieCacheName, {
signed: true
});
if (cachedMember) {
try {
return JSON.parse(cachedMember);
} catch (e) {
cookies.set(cookieCacheName, {
signed: true,
httpOnly: true,
sameSite: 'lax',
maxAge: cookieCacheMaxAge,
path: cookiePath
});
throw new BadRequestError({
message: `Invalid JSON found in cookie ${cookieCacheName}`
});
}
}
const member = await get(membersApi).getMemberIdentityData(email);
cookies.set(cookieCacheName, JSON.stringify(member), {
signed: true,
httpOnly: true,
sameSite: 'lax',
maxAge: cookieCacheMaxAge,
path: cookiePath
});
return member;
}, cookieConfig);
const getIdentityTokenForMemberFromSession = withCookies(async (_req, _res, {cookies}) => {