ghost/mw-session-from-token/lib/session-from-token.js
module.exports = SessionFromToken;
/**
* @typedef {object} User
* @prop {string} id
*/
/**
* @typedef {import('express').Request} Req
* @typedef {import('express').Response} Res
* @typedef {import('express').NextFunction} Next
* @typedef {import('express').RequestHandler} RequestHandler
*/
/**
* Returns a connect middleware function which exchanges a token for a session
*
* @template Token
* @template Lookup
*
* @param { object } deps
* @param { (req: Req) => Promise<Token> } deps.getTokenFromRequest
* @param { (token: Token) => Promise<Lookup> } deps.getLookupFromToken
* @param { (lookup: Lookup) => Promise<User> } deps.findUserByLookup
* @param { (req: Req, res: Res, user: User) => Promise<void> } deps.createSession
* @param { boolean } deps.callNextWithError - Whether next should be call with an error or just pass through
*
* @returns {RequestHandler}
*/
function SessionFromToken({
getTokenFromRequest,
getLookupFromToken,
findUserByLookup,
createSession,
callNextWithError
}) {
/**
* @param {Req} req
* @param {Res} res
* @param {Next} next
* @returns {Promise<void>}
*/
async function handler(req, res, next) {
try {
const token = await getTokenFromRequest(req);
if (!token) {
return next();
}
const email = await getLookupFromToken(token);
if (!email) {
return next();
}
const user = await findUserByLookup(email);
if (!user) {
return next();
}
await createSession(req, res, user);
next();
} catch (err) {
if (callNextWithError) {
next(err);
} else {
next();
}
}
}
return handler;
}