UNPKG

oidc-lib

Version:

A library for creating OIDC Service Providers

349 lines (308 loc) 12.5 kB
module.exports = { initialize: initialize, createOrUpdateDocument: createOrUpdateDocument, getDocument: getDocument, deleteDocument: deleteDocument, queryCollection: queryCollection /* cleanup: cleanup, createDocument: createDocument, getDocument: getDocument, queryCollection: queryCollection, replaceDocument: replaceDocument, deleteDocument: deleteDocument, isDbDisabled: isDbDisabled */ }; var pk = null; const documentDbDocumentClient = require("documentdb").DocumentClient; const HttpStatusCodes = { NOTFOUND: 404 }; function initialize(pkInput, contentModuleName, provider){ return new Promise((resolve, reject) => { pk = pkInput; var dbInfo = { provider: provider, contentModuleName: contentModuleName }; validateModuleConfig(contentModuleName); pk.util.log_debug("Initializing DocumentDb in content module " + contentModuleName); dbInfo.contentModuleName = contentModuleName; dbInfo.databaseName = getDbModuleConfigProperty(contentModuleName, 'databaseName'); dbInfo.endpoint = getDbModuleConfigProperty(contentModuleName, 'endpoint'); dbInfo.primaryKey = getDbModuleConfigProperty(contentModuleName, 'primaryKey'); dbInfo.client = new documentDbDocumentClient(dbInfo.endpoint, { "masterKey": dbInfo.primaryKey }); dbInfo.databaseDefinition = { id: dbInfo.databaseName }; dbInfo.databaseUrl = `dbs/${dbInfo.databaseDefinition.id}`; dbInfo.collections = {}; var collectionNames = getDbModuleConfigProperty(contentModuleName, 'collectionNames'); for (var count=0; count < collectionNames.length; count++){ collectionName = collectionNames[count]; var collectionInfo = { definition: { "id": collectionName }, url: `${dbInfo.databaseUrl}/colls/${collectionName}` }; dbInfo.collections[collectionName] = collectionInfo; } pk.dbs[contentModuleName] = dbInfo; var promises = []; getDatabase(dbInfo) .then(function() { for (var key in dbInfo.collections){ promises.push(getCollection(dbInfo, key)); } Promise.all(promises).then(function(data){ resolve(dbInfo); }); }, function(err){ pk.util.log_error('Initialize', "Error getting database in content module " + contentModuleName); }) .then(function() {}, function(err){ if (err.code !== undefined){ switch (err.code){ case 'ENOENT': if (err.syscall === 'getaddrinfo'){ pk.util.log_debug('Unable to lookup database service in DNS in module ' + contentModuleName); pk.util.log_debug('Hostname: ' + err.hostname); return; } break; default: break; } } pk.util.log_debug('Database initialization failed for module ' + contentModuleName); reject(err); }); }); }; function getDatabase (dbInfo) { return new Promise((resolve, reject) => { dbInfo.client.readDatabase(dbInfo.databaseUrl, (err, result) => { if (err) { if (err.code == HttpStatusCodes.NOTFOUND) { dbInfo.client.createDatabase(dbInfo.databaseDefinition, (err, created) => { if (err){ reject(err) } else{ resolve(created); } }); } else { reject(err); } } else { resolve(result); } }); }); }; function getCollection(dbInfo, collectionName) { var collectionInfo = dbInfo.collections[collectionName]; return new Promise((resolve, reject) => { dbInfo.client.readCollection(collectionInfo.url, (err, result) => { if (err) { if (err.code == HttpStatusCodes.NOTFOUND) { dbInfo.client.createCollection(dbInfo.databaseUrl, collectionInfo.definition, { offerThroughput: 400 }, (err, created) => { if (err) reject(err) else resolve(created); }); } else { reject(err); } } else { resolve(result); } }); }); } function getDocument(dbInfo, collectionName, id) { var collectionInfo = dbInfo.collections[collectionName]; let documentUrl = `${collectionInfo.url}/docs/${id}`; return new Promise((resolve, reject) => { dbInfo.client.readDocument(documentUrl, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); }); }; function createDocument(dbInfo, collectionName, document){ var collectionInfo = dbInfo.collections[collectionName]; return new Promise((resolve, reject) => { dbInfo.client.createDocument(collectionInfo.url, document, (err, created) => { if (err){ pk.util.log_detail('Document creation error', err); reject(err); } else{ pk.util.log_debug('Document creation succeeded'); resolve(created); } }); }); }; function createOrUpdateDocument(dbInfo, collectionName, document, updateLogic){ pk.util.log_debug('Attempting to create or update document'); var collectionInfo = dbInfo.collections[collectionName]; let documentUrl = `${collectionInfo.url}/docs/${document.id}`; return new Promise((resolve, reject) => { dbInfo.client.readDocument(documentUrl, (err, result) => { if (err) { if (err.code === HttpStatusCodes.NOTFOUND){ pk.util.log_debug('Document does not exist so creating it'); dbInfo.client.createDocument(collectionInfo.url, document, (err, created) => { if (err){ pk.util.log_detail('Document creation error', err); reject(err); } else{ pk.util.log_debug('Document creation succeeded'); resolve(created); } }); } else { pk.util.log_detail('Unexpected error attempting to retrieve document', err); reject(err); } } else { if (updateLogic !== undefined){ pk.util.log_debug('Document existed - update logic being applied'); updateLogic(result, document); } dbInfo.client.upsertDocument(collectionInfo.url, document, (err, created) => { if (err){ pk.util.log_detail('Document upset error', err); reject(err); } else{ pk.util.log_debug('Document upsert succeeded'); resolve(created); } }); } }); }); }; // currently indexName is not used in azure module function queryCollection(dbInfo, collectionName, queryDictionaryOrString, indexName) { var collectionInfo = dbInfo.collections[collectionName]; var queryString = queryDictionaryOrString; if (typeof queryDictionaryOrString === 'object'){ queryString = 'SELECT * FROM ' + collectionName; if (isset(queryDictionaryOrString)){ queryString += ' c WHERE '; var starting = true; for (var qKey in queryDictionaryOrString){ if (starting){ starting = false; } else { queryString += " AND "; } queryString += 'c.' + qKey + ' = "' + queryDictionaryOrString[qKey] + '"'; } } } return new Promise((resolve, reject) => { dbInfo.client.queryDocuments( collectionInfo.url, queryString ).toArray((err, results) => { if (err){ reject(err); } else { resolve(results); } }); }); }; function replaceDocument(document) { var collectionInfo = dbInfo.collections[collectionName]; let documentUrl = `${collectionInfo.url}/docs/${document.id}`; pk.util.log_debug(`Replacing document:\n${document.id}\n`); document.children[0].grade = 6; return new Promise((resolve, reject) => { dbInfo.client.replaceDocument(documentUrl, document, (err, result) => { if (err) reject(err); else { resolve(result); } }); }); }; function deleteDocument(dbInfo, collectionName, id) { var collectionInfo = dbInfo.collections[collectionName]; let documentUrl = `${collectionInfo.url}/docs/${id}`; return new Promise((resolve, reject) => { dbInfo.client.deleteDocument(documentUrl, (err, result) => { if (err){ if (err.code === 404){ resolve(err); } else { reject(err); } } else { resolve(result); } }); }); }; function cleanup(pkInput, contentModuleName) { pk = pkInput; validateModuleConfig(contentModuleName); var endpoint = getDbModuleConfigProperty(contentModuleName, 'endpoint'); var primaryKey = getDbModuleConfigProperty(contentModuleName, 'primaryKey'); var client = new documentDbDocumentClient(endpoint, { "masterKey": primaryKey }); var databaseName = getDbModuleConfigProperty(contentModuleName, 'databaseName'); var databaseDefinition = { id: databaseName }; var databaseUrl = `dbs/${databaseDefinition.id}`; pk.util.log_debug(`Cleaning up by deleting database ${databaseDefinition.id}`); return new Promise((resolve, reject) => { client.deleteDatabase(databaseUrl, (err) => { if (err) reject(err) else resolve(null); }); }); } function validateModuleConfig(contentModuleName){ if (contentModuleName !== 'sts'){ if (pk.util.config.content_modules[contentModuleName].db === undefined){ throw "The " + contentModuleName + " content module does not define a db property in claimer_config"; } } } function getDbModuleConfigProperty(contentModuleName, propertyName, throwOnUndefined) { if (throwOnUndefined === undefined || throwOnUndefined === true){ var dbInstance = pk.util.config.sts.db; if (contentModuleName !== 'sts'){ dbInstance = pk.util.config.content_modules[contentModuleName].db; } if (dbInstance[propertyName] === undefined){ throw "Configuration property " + propertyName + " is not defined in content module " + contentModuleName; } } return dbInstance[propertyName]; } function isDbDisabled(pkInput, contentModuleName){ pk = pkInput; var isDisabled = getDbModuleConfigProperty('disabled', false, contentModuleName); if (isDisabled === undefined){ isDisabled = false; } return isDisabled; } function isset(param){ if (typeof param !== 'object'){ if (param === undefined || param === null || param.length === 0) return false; } return true; }