diff --git a/README.md b/README.md index 0b88a2c..2a5b6a4 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ An item with no filter value is returned in all cases, and is thus also public. ## Local Development Environment In order to quickly setup a development environment, make use of the `setup_script.sh` script. This will setup the project, initialize and seed the database configurations, import routes and initialize environment config files and generate the keys required. -First clone the Caracal (backup-dev branch), caMicroscope and the Distro repositories and make sure that all of them are in the same parent directory. +First clone Caracal, caMicroscope and the Distro repositories and make sure that all of them are in the same parent directory. Run the script with `./setup_script` or `bash ./setup_script.sh` diff --git a/caracal.js b/caracal.js index 762283c..2e646c5 100644 --- a/caracal.js +++ b/caracal.js @@ -75,11 +75,13 @@ var HANDLERS = { }, "monitorCheck": monitor.check, "mongoFind": dataHandlers.General.find, + "mongoPaginatedFind": dataHandlers.General.paginatedFind, "mongoFindWithRegex": dataHandlers.General.findWithRegex, "mongoAdd": dataHandlers.General.add, "mongoUpdate": dataHandlers.General.update, "mongoDelete": dataHandlers.General.delete, "mongoDistinct": dataHandlers.General.distinct, + "mongoCount": dataHandlers.General.count, "filterHandler": auth.filterHandler, "permissionHandler": permissionHandler, "editHandler": auth.editHandler, diff --git a/handlers/dataHandlers.js b/handlers/dataHandlers.js index e0c585f..4e69192 100644 --- a/handlers/dataHandlers.js +++ b/handlers/dataHandlers.js @@ -13,6 +13,26 @@ General.find = function(db, collection) { }; }; +General.paginatedFind = function(db, collection) { + return function(req, res, next) { + var query = req.query; + mongoDB.paginatedFind(db, collection, query).then((x) => { + req.data = x; + next(); + }).catch((e) => next(e)); + }; +}; + +General.count = function(db, collection) { + return function(req, res, next) { + var query = req.query; + mongoDB.count(db, collection, query).then((x) => { + req.data = x; + next(); + }).catch((e) => next(e)); + }; +}; + General.findWithRegex = function(db, collection) { return function(req, res, next) { var query = req.query; diff --git a/handlers/pathdbIipHandler.js b/handlers/pathdbIipHandler.js index 78a7eec..ebc8de1 100644 --- a/handlers/pathdbIipHandler.js +++ b/handlers/pathdbIipHandler.js @@ -28,7 +28,10 @@ iipCheck = function(req, res, next) { console.log(x); // get path if (x && x['field_iip_path'] && x['field_iip_path'].length && x['field_iip_path'][0]['value']) { - req.newFilepath = x['field_iip_path'][0]['value']; + newFilepath = x['field_iip_path'][0]['value']; + newFilepath = encodeURIComponent(newFilepath); + newFilepath = newFilepath.replaceAll("%2F", "/"); + req.newFilepath = newFilepath; console.log(req.newFilepath); next(); } else { diff --git a/service/database/index.js b/service/database/index.js index 81e9a97..e4bdefd 100644 --- a/service/database/index.js +++ b/service/database/index.js @@ -42,6 +42,72 @@ class Mongo { } } + /** + * Runs the MongoDB find() method to fetch documents with pagination. + * + * @async + * @param {string} database Name of the database + * @param {string} collectionName Name of the collection to run operation on + * @param {document} query Specifies selection filter using query operators. + * To return all documents in a collection, omit this parameter or pass an empty document ({}). + * @param {boolean} [transform=false] check to transform the IDs to ObjectID in response + * + * {@link https://docs.mongodb.com/manual/reference/method/db.collection.find/ Read MongoDB Reference} + */ + static async paginatedFind(database, collectionName, query, transform = true) { + try { + query = transformIdToObjectId(query); + + const collection = getConnection(database).collection(collectionName); + let { _page = 0, _pageSize = 1000, ...filterQuery } = query; + const _skip = _page * _pageSize; + _pageSize = parseInt(_pageSize, 10); + const data = await collection.find(filterQuery).skip(_skip).limit(_pageSize).toArray(); + + /** allow caller method to toggle response transformation */ + if (transform) { + data.forEach((x) => { + x["_id"] = { + $oid: x["_id"], + }; + }); + } + + return data; + } catch (e) { + console.error(e); + throw e; + } + } + + /** + * Runs the MongoDB count() method to count documents. + * + * @async + * @param {string} database Name of the database + * @param {string} collectionName Name of the collection to run operation on + * @param {document} query Specifies selection filter using query operators. + * To return all documents in a collection, omit this parameter or pass an empty document ({}). + * @param {boolean} [transform=false] check to transform the IDs to ObjectID in response + * + * {@link https://docs.mongodb.com/manual/reference/method/db.collection.count/ Read MongoDB Reference} + */ + static async count(database, collectionName, query, transform = true) { + try { + query = transformIdToObjectId(query); + + const collection = getConnection(database).collection(collectionName); + const count = await collection.count(query); + + let data =[{"count": count}]; + + return data; + } catch (e) { + console.error(e); + throw e; + } + } + /** * Runs a distinct find operation based on given query * @@ -201,10 +267,12 @@ class Mongo { module.exports = { add: Mongo.add, find: Mongo.find, + paginatedFind: Mongo.paginatedFind, update: Mongo.update, delete: Mongo.delete, aggregate: Mongo.aggregate, distinct: Mongo.distinct, createIndex: Mongo.createIndex, - createCollection: Mongo.createCollection + createCollection: Mongo.createCollection, + count: Mongo.count, }; diff --git a/setup_script.sh b/setup_script.sh index c90afff..7b65f18 100755 --- a/setup_script.sh +++ b/setup_script.sh @@ -24,9 +24,12 @@ fi ### ## check if the system has required services installed ### -if ! command -v "mongo" &>/dev/null; then - echo "mongo could not be found on path. Please ensure that mongo is installed and is on PATH" - exit +if command -v "mongo" &>/dev/null; then + MONGO="mongo" +elif command -v "mongosh" &>/dev/null; then + MONGO="mongosh" +else + echo "mongo or mongo could not be found on path. Please ensure that mongo is installed and is on PATH" fi if ! command -v "node" &>/dev/null; then @@ -109,7 +112,7 @@ echo "Copying files complete!" ### ## try connecting to mongodb instance ### -until mongo --host "${HOST}" --eval "print(\"Connected!\")" >/dev/null; do +until $MONGO --host "${HOST}" --eval "print(\"Connected!\")" >/dev/null; do sleep 2 done echo "[ database ] : connection established" @@ -118,8 +121,8 @@ echo "[ database ] : connection established" ## check if database exists ### QUERY="db.getMongo().getDBNames().indexOf(\"${DB_NAME}\")" -COMMAND="mongo ${HOST} --eval '${QUERY}' --quiet" -if [ $(mongo ${HOST} --eval ${QUERY} --quiet) -lt 0 ]; then +COMMAND="${MONGO} ${HOST} --eval '${QUERY}' --quiet" +if [ $(${MONGO} ${HOST} --eval ${QUERY} --quiet) -lt 0 ]; then echo "[ database ] : does not exist" exit 1 else @@ -149,11 +152,11 @@ case $yn in echo "[ resource ] : clearing old configurations" echo "[ resource ] : seeding collections" - mongo --quiet --host $HOST $DB_NAME .seeder.collection.js + $MONGO --quiet --host $HOST $DB_NAME .seeder.collection.js echo "[ resource ] : seeding indexes" - mongo --quiet --host $HOST $DB_NAME .seeder.idx.js + $MONGO --quiet --host $HOST $DB_NAME .seeder.idx.js echo "[ resource ] : seeding configurations" - mongo --quiet --host $HOST $DB_NAME .seeder.default.js + $MONGO --quiet --host $HOST $DB_NAME .seeder.default.js ### ## ask the user if they want to remove the seeding files