UNPKG

ltijs

Version:

Easily turn your web application into a LTI 1.3 Learning Tool.

176 lines • 8.16 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MongoDatabaseManager = void 0; const mongoose_1 = __importDefault(require("mongoose")); const validation_1 = require("#utils/validation/validation"); const mongo_database_manager_schemas_1 = require("#services/database-manager/mongo/mongo-database-manager.schemas"); const database_schemas_1 = require("#services/database-manager/mongo/database-schemas"); const errors_1 = require("#services/database-manager/mongo/errors"); class MongoDatabaseManager { LOG_COMPONENT = 'database'; CONNECTED_EVENT = 'connected'; OPEN_EVENT = 'open'; ERROR_EVENT = 'error'; RECONNECTED_EVENT = 'reconnected'; DISCONNECTED_EVENT = 'disconnected'; url; connectionOptions; logger; deployed = false; constructor(logger, config) { if (config === undefined || config.url === '') throw new errors_1.MissingDatabaseConfigError(); this.url = config.url; if (config.debug === true) mongoose_1.default.set('debug', true); this.connectionOptions = { connectTimeoutMS: 300000, ...config.connection }; this.logger = logger; } async listen() { const connection = mongoose_1.default.connection; connection.removeAllListeners(this.CONNECTED_EVENT); connection.removeAllListeners(this.ERROR_EVENT); connection.removeAllListeners(this.RECONNECTED_EVENT); connection.removeAllListeners(this.DISCONNECTED_EVENT); connection.on(this.CONNECTED_EVENT, () => { this.logger.debug(this.LOG_COMPONENT, 'Database connected'); }); connection.once(this.OPEN_EVENT, () => { this.logger.debug(this.LOG_COMPONENT, 'Database connection open'); }); connection.on(this.ERROR_EVENT, () => { mongoose_1.default.disconnect().catch(() => undefined); }); connection.on(this.RECONNECTED_EVENT, () => { this.logger.debug(this.LOG_COMPONENT, 'Database reconnected'); }); connection.on(this.DISCONNECTED_EVENT, () => { this.logger.debug(this.LOG_COMPONENT, 'Database disconnected'); this.logger.debug(this.LOG_COMPONENT, 'Attempting to reconnect'); setTimeout(() => { if (connection.readyState === mongoose_1.default.ConnectionStates.disconnected) { mongoose_1.default.connect(this.url, this.connectionOptions).catch((err) => { this.logger.error(this.LOG_COMPONENT, `Error in MongoDb connection: ${String(err)}`); }); } }, 1000); }); if (connection.readyState === mongoose_1.default.ConnectionStates.disconnected) { await mongoose_1.default.connect(this.url, this.connectionOptions); } // The `idTokens` collection has no Mongoose model/schema (see // `IdTokenDoc`'s comment in `database-schemas.ts`), so its TTL index is // created directly -- `createIndex()` is a no-op once it already exists // with the same spec. Lookups are by the document's own `_id`, so no // other index is needed. await mongoose_1.default.connection .collection(database_schemas_1.IDTOKEN_COLLECTION) .createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 * 24 }); this.deployed = true; } async close() { mongoose_1.default.connection.removeAllListeners(); await mongoose_1.default.connection.close(); this.deployed = false; } async getPlatformByUrlAndClientId(url, clientId) { this.ensureDeployed(); const doc = await database_schemas_1.PlatformModel.findOne({ url, clientId }).lean(); if (doc === null) return undefined; return this.toPlatformRecord(doc); } async getPlatforms(filter = {}) { this.ensureDeployed(); const docs = await database_schemas_1.PlatformModel.find(this.buildPlatformQuery(filter)).lean(); return docs.map(doc => this.toPlatformRecord(doc)); } async getPlatformById(id) { this.ensureDeployed(); if (!mongoose_1.default.isValidObjectId(id)) return undefined; const doc = await database_schemas_1.PlatformModel.findOne({ _id: new mongoose_1.default.Types.ObjectId(id) }).lean(); if (doc === null) return undefined; return this.toPlatformRecord(doc); } async savePlatform(platform) { this.ensureDeployed(); const doc = await database_schemas_1.PlatformModel.create(platform); return doc._id.toString(); } async updatePlatformById(id, fields) { this.ensureDeployed(); await database_schemas_1.PlatformModel.updateOne({ _id: new mongoose_1.default.Types.ObjectId(id) }, { $set: { ...fields } }); } async deletePlatformById(id) { this.ensureDeployed(); await database_schemas_1.PlatformModel.deleteOne({ _id: new mongoose_1.default.Types.ObjectId(id) }); } async getAccessToken(platformUrl, clientId, scopes) { this.ensureDeployed(); const doc = await database_schemas_1.AccessTokenModel.findOne({ platformUrl, clientId, scopes }).lean(); if (doc === null) return undefined; const merged = { ...doc.value, createdAt: doc.createdAt.getTime() }; return (0, validation_1.validate)(mongo_database_manager_schemas_1.AccessTokenRecordSchema, merged); } async saveAccessToken(platformUrl, clientId, scopes, token) { this.ensureDeployed(); const { createdAt: _createdAt, ...value } = token; const doc = await database_schemas_1.AccessTokenModel.findOneAndReplace({ platformUrl, clientId, scopes }, { platformUrl, clientId, scopes, value }, { upsert: true, returnDocument: 'after' }); return doc._id.toString(); } async getIdToken(id) { this.ensureDeployed(); if (!mongoose_1.default.isValidObjectId(id)) return undefined; const doc = await mongoose_1.default.connection .collection(database_schemas_1.IDTOKEN_COLLECTION) .findOne({ _id: new mongoose_1.default.Types.ObjectId(id) }); if (doc === null) return undefined; const { _id, createdAt: _createdAt, ...token } = doc; return (0, validation_1.validate)(mongo_database_manager_schemas_1.IdTokenRecordSchema, { ...token, id: _id.toString() }); } async saveIdToken(token) { this.ensureDeployed(); const doc = { ...token, createdAt: new Date() }; const result = await mongoose_1.default.connection.collection(database_schemas_1.IDTOKEN_COLLECTION).insertOne(doc); return result.insertedId.toString(); } async consumeNonce(nonce) { this.ensureDeployed(); const result = await database_schemas_1.NonceModel.deleteOne({ nonce }); return result.deletedCount > 0; } async saveNonce(nonce) { this.ensureDeployed(); const doc = await new database_schemas_1.NonceModel({ nonce }).save(); return doc._id.toString(); } ensureDeployed() { if (!this.deployed) throw new errors_1.ProviderNotDeployedError(); } buildPlatformQuery(filter) { const query = {}; if (filter.url !== undefined) query.url = filter.url; if (filter.name !== undefined) query.name = filter.name; if (filter.clientId !== undefined) { query.clientId = Array.isArray(filter.clientId) ? { $in: filter.clientId } : filter.clientId; } return query; } toPlatformRecord(doc) { return (0, validation_1.validate)(mongo_database_manager_schemas_1.PlatformRecordSchema, { ...doc, id: doc._id.toString() }); } } exports.MongoDatabaseManager = MongoDatabaseManager; exports.default = MongoDatabaseManager; //# sourceMappingURL=mongo-database-manager.service.js.map