70 lines
1.8 KiB
JavaScript
70 lines
1.8 KiB
JavaScript
|
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;
|
||
|
}
|