ltijs
Version:
Easily turn your web application into a LTI 1.3 Learning Tool.
176 lines • 8.16 kB
JavaScript
"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