Configurable user cache population in auth middleware

This commit is contained in:
Rory Powell 2021-09-13 17:38:12 +01:00
parent d919c44185
commit fb01a66936
2 changed files with 35 additions and 4 deletions

View File

@ -3,7 +3,27 @@ const { getTenantId, lookupTenantId, getGlobalDB } = require("../tenancy")
const EXPIRY_SECONDS = 3600 const EXPIRY_SECONDS = 3600
exports.getUser = async (userId, tenantId = null) => { /**
* The default populate user function
*/
const populateFromDB = (userId, tenantId) => {
return getGlobalDB(tenantId).get(userId)
}
/**
* Get the requested user by id.
* Use redis cache to first read the user.
* If not present fallback to loading the user directly and re-caching.
* @param {*} userId the id of the user to get
* @param {*} tenantId the tenant of the user to get
* @param {*} loadUser function to provide the user for re-caching. default to couch db
* @returns
*/
exports.getUser = async (
userId,
tenantId = null,
populateUser = populateFromDB
) => {
if (!tenantId) { if (!tenantId) {
try { try {
tenantId = getTenantId() tenantId = getTenantId()
@ -15,7 +35,7 @@ exports.getUser = async (userId, tenantId = null) => {
// try cache // try cache
let user = await client.get(userId) let user = await client.get(userId)
if (!user) { if (!user) {
user = await getGlobalDB(tenantId).get(userId) user = await populateUser(userId, tenantId)
client.store(userId, user, EXPIRY_SECONDS) client.store(userId, user, EXPIRY_SECONDS)
} }
if (user && !user.tenantId && tenantId) { if (user && !user.tenantId && tenantId) {

View File

@ -21,7 +21,10 @@ function finalise(
* The tenancy modules should not be used here and it should be assumed that the tenancy context * The tenancy modules should not be used here and it should be assumed that the tenancy context
* has not yet been populated. * has not yet been populated.
*/ */
module.exports = (noAuthPatterns = [], opts = { publicAllowed: false }) => { module.exports = (
noAuthPatterns = [],
opts = { publicAllowed: false, populateUser: null }
) => {
const noAuthOptions = noAuthPatterns ? buildMatcherRegex(noAuthPatterns) : [] const noAuthOptions = noAuthPatterns ? buildMatcherRegex(noAuthPatterns) : []
return async (ctx, next) => { return async (ctx, next) => {
let publicEndpoint = false let publicEndpoint = false
@ -46,7 +49,15 @@ module.exports = (noAuthPatterns = [], opts = { publicAllowed: false }) => {
error = "No session found" error = "No session found"
} else { } else {
try { try {
user = await getUser(userId, session.tenantId) if (opts && opts.populateUser) {
user = await getUser(
userId,
session.tenantId,
opts.populateUser(ctx)
)
} else {
user = await getUser(userId, session.tenantId)
}
delete user.password delete user.password
authenticated = true authenticated = true
} catch (err) { } catch (err) {