'use strict'; module.exports = function () { const User = require('../model/user'), ObjectId = require('mongodb').ObjectId, moment = require('moment'), { Errors, DEFAULT_LANG } = require('./constants'), { AppParamError, AppAuthError } = require('./app_error'); return { _cache: {}, get: function (key) { return this._cache[key] ? { id: key, ...this._cache[key] } : null; }, set: function (key, val) { this._cache[key] = val; }, delete: function (key) { delete this._cache[key]; }, isExpired: function (key, seconds) { const userInfo = this._cache[key]; if (!userInfo) return false; return (!userInfo.ts || (moment.utc().unix() - userInfo.ts) >= seconds); }, clear: function () { this._cache = {}; }, loadUser: async function (uid) { try { if (!ObjectId.isValid(uid)) throw AppParamError.throw(); // Project migratedDate to be used in the cache const updatedRes = await User.aggregate([ { $match: { _id: ObjectId(uid) } }, { $addFields: { 'parentUser': { $ifNull: ['$parent', '$_id'] } } }, { $lookup: { from: 'users', let: { parentUser: '$parentUser' }, pipeline: [{ $match: { $expr: { $eq: ['$_id', '$$parentUser'] } } }], as: 'applicator' } }, { $unwind: { path: '$applicator', 'preserveNullAndEmptyArrays': true } }, { $project: { puid: '$parentUser', kind: 1, premium: { $ifNull: ['$applicator.premium', 0] }, membership: '$applicator.membership', // Also load the user's membership info (applicator's) when fetching user data from DB markedDelete: 1, lang: 1, migratedDate: { $ifNull: ['$migratedDate', '$applicator.migratedDate'] } } } ]); if (!updatedRes || !updatedRes.length) AppAuthError.throw(); const userInfo = updatedRes[0]; this.set(uid, { kind: userInfo.kind, puid: userInfo.puid.toHexString(), premium: userInfo.premium, membership: userInfo.membership, lang: userInfo.lang || DEFAULT_LANG, markedDelete: userInfo.markedDelete || false, ts: moment.utc().unix(), migratedDate: userInfo.migratedDate } ); return userInfo; } catch (err) { throw err; } }, /** * Filter cache entries by parent user and kind * @param { string } pUser required * @param { number } kind user type * @returns [[key, value ]] array of logged in user and session info object */ filterByKind: function (pUser, kind) { const all = Object.entries(this._cache) || []; if (kind === undefined) { return all.filter(it => { return Object.values(it).length > 1 && Object.values(it)[1]['puid'] === pUser; }); } else { return all.filter(it => Object.values(it).length > 1 && (Object.values(it)[1]['puid'] === pUser && Object.values(it)[1]['type'] === kind)); } } } }();