Oidc node mongodb adapter in normal functions
Vimal
Posted on March 1, 2024
const { MongoClient } = require('mongodb');
const snakeCase = require('lodash/snakeCase');
let DB;
const grantable = new Set([
'access_token',
'authorization_code',
'refresh_token',
'device_code',
'backchannel_authentication_request',
]);
const collections = new Set();
function addCollection(name) {
const nu = collections.has(name);
collections.add(name);
if (!nu) {
createIndexes(name);
}
}
function createIndexes(name) {
DB.collection(name).createIndexes([
...(grantable.has(name)
? [{
key: { 'payload.grantId': 1 },
}] : []),
...(name === 'device_code'
? [{
key: { 'payload.userCode': 1 },
unique: true,
}] : []),
...(name === 'session'
? [{
key: { 'payload.uid': 1 },
unique: true,
}] : []),
{
key: { expiresAt: 1 },
expireAfterSeconds: 0,
},
]).catch(console.error);
}
async function upsert(name, _id, payload, expiresIn) {
let expiresAt;
if (expiresIn) {
expiresAt = new Date(Date.now() + (expiresIn * 1000));
}
await updateOne(name, { _id }, { $set: { payload, ...(expiresAt ? { expiresAt } : undefined) } }, { upsert: true });
}
async function find(name, _id) {
const result = await findOne(name, { _id }, { payload: 1 });
if (!result) return undefined;
return result.payload;
}
async function findByUserCode(name, userCode) {
const result = await findOne(name, { 'payload.userCode': userCode }, { payload: 1 });
if (!result) return undefined;
return result.payload;
}
async function findByUid(name, uid) {
const result = await findOne(name, { 'payload.uid': uid }, { payload: 1 });
if (!result) return undefined;
return result.payload;
}
async function destroy(name, _id) {
await deleteOne(name, { _id });
}
async function revokeByGrantId(name, grantId) {
await deleteMany(name, { 'payload.grantId': grantId });
}
async function consume(name, _id) {
await findOneAndUpdate(name, { _id }, { $set: { 'payload.consumed': Math.floor(Date.now() / 1000) } });
}
function findOneAndUpdate(name, filter, update) {
return DB.collection(name).findOneAndUpdate(filter, update);
}
function findOne(name, filter, projection) {
return DB.collection(name).findOne(filter, projection);
}
function updateOne(name, filter, update, options) {
return DB.collection(name).updateOne(filter, update, options);
}
function deleteOne(name, filter) {
return DB.collection(name).deleteOne(filter);
}
function deleteMany(name, filter) {
return DB.collection(name).deleteMany(filter);
}
function connect() {
return MongoClient.connect(process.env.MONGODB_URI)
.then(connection => {
DB = connection.db(connection.s.options.dbName);
});
}
module.exports = {
addCollection,
upsert,
find,
findByUserCode,
findByUid,
destroy,
revokeByGrantId,
consume,
connect
};
Posted on March 1, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.