routes/api/roomdata.js

/**
 * @module routes/api/roomdata
 * @author jesse reichler <mouser@donationcoder.com>
 * @copyright 4/16/20
 * @description
 * ##### Overview
 * This file handles all requests related to the programmatic API interface for accessing the system.
 * These routes are all intended to be called programmatically by other code, and so should all return json replies
*/

"use strict";


// modules
const express = require("express");


// requirement service locator
const jrequire = require("../../helpers/jrequire");

// controllers
const arserver = jrequire("arserver");
const aclAid = jrequire("aclaid");

// helpers
const JrContext = require("../../helpers/jrcontext");
const JrResult = require("../../helpers/jrresult");
const jrhExpress = require("../../helpers/jrh_express");
const jrhMisc = require("../../helpers/jrh_misc");
const jrdebug = require("../../helpers/jrdebug");
const jrhMongo = require("../../helpers/jrh_mongo");

// models
const RoomModel = jrequire("models/room");

// constants
const appdef = jrequire("appdef");







//---------------------------------------------------------------------------
/**
 * Add the API routes
 *
 * @param {string} urlPath - the base path of these relative paths
 * @returns router object
 */
function setupRouter(urlPath) {
	// create express router
	const router = express.Router();

	// setup routes
	router.all("/list", routerList);
	router.all("/get", routerGet);
	router.all("/add", routerAdd);

	// return router
	return router;
}
//---------------------------------------------------------------------------















//---------------------------------------------------------------------------
async function routerList(req, res, next) {
	// consume access token
	const jrContext = JrContext.makeNew(req, res, next);

	// new
	const user = await arserver.lookupLoggedInUser(jrContext);
	if (!user) {
		jrContext.pushError("Failed to authenticate user for request; missing access token?");
	}
	if (jrContext.isError()) {
		jrhExpress.sendJsonErrorAuthToken(jrContext);
		return;
	}

	// the api roomdata list function is for retrieving a list of (matching) roomdata items
	// for a specific appid, and roomid, with optional filters (on data)
	const query = jrhExpress.parseReqGetJsonField(jrContext, "query");
	if (jrContext.isError()) {
		jrhExpress.sendJsonResult(jrContext, 400);
		return;
	}

	// allow lookup by app shortcode instead of id
	if (!query.roomId && query.roomShortcode) {
		const queryRoom = await RoomModel.mFindOneByShortcode(query.roomShortcode);
		query.roomId = !queryRoom ? null : queryRoom.getIdAsString();
	}

	// get roomdata items for room
	const roomId = jrhMisc.getNonNullValueFromObject(jrContext, query, "roomId", "room id");
	if (roomId && !jrhMongo.isValidMongooseObjectId(roomId)) {
		jrContext.pushFieldError("roomId", "Bad syntax for rooomId: " + roomId);
	}
	if (jrContext.isError()) {
		jrhExpress.sendJsonResult(jrContext, 400);
		return;
	}

	// now let's ask if user is actually ALLOWED to look at the data in this room
	const permission = appdef.DefAclActionViewData;
	const permissionObjType = RoomModel.getAclName();
	const permissionObjId = roomId;
	const hasPermission = await user.aclHasPermission(jrContext, permission, permissionObjType, permissionObjId);
	if (!hasPermission) {
		jrhExpress.sendJsonErorrAcl(jrContext, permission, permissionObjType, permissionObjId);
		return;
	}

	// get all room data
	const RoomDataModel = jrequire("models/roomdata");
	const findArgs = {
		roomid: roomId,
	};
	const roomData = await RoomDataModel.mFindAll(findArgs);

	// success
	const returnData = {
		roomData,
		// oringinalQuery: query,
	};

	// provide it
	jrhExpress.sendJsonDataSuccess(jrContext, "roomdata", returnData);
}



async function routerGet(req, res, next) {
	const jrContext = JrContext.makeNew(req, res, next);
	jrhExpress.sendJsonError(jrContext, 400, "not implemented yet", "internal");
}


async function routerAdd(req, res, next) {
	const jrContext = JrContext.makeNew(req, res, next);

	// new
	const user = await arserver.lookupLoggedInUser(jrContext);
	if (!user) {
		jrContext.pushError("Failed to authenticate user for request; missing access token?");
	}
	if (jrContext.isError()) {
		jrhExpress.sendJsonErrorAuthToken(jrContext);
		return;
	}

	// get query
	const query = jrhExpress.parseReqGetJsonField(jrContext, "query");
	if (jrContext.isError()) {
		jrhExpress.sendJsonResult(jrContext, 400);
		return;
	}

	// allow lookup by app shortcode instead of id
	if (!query.roomId && query.roomShortcode) {
		const queryRoom = await RoomModel.mFindOneByShortcode(query.roomShortcode);
		query.roomId = !queryRoom ? null : queryRoom.getIdAsString();
	}

	// now let's ask if user is actually ALLOWED to look at the data in this room
	const roomId = query.roomId;
	const permission = appdef.DefAclActionAddData;
	const permissionObjType = RoomModel.getAclName();
	const permissionObjId = roomId;
	const hasPermission = await user.aclHasPermission(jrContext, permission, permissionObjType, permissionObjId);
	if (!hasPermission) {
		jrhExpress.sendJsonErorrAcl(jrContext, permission, permissionObjType, permissionObjId);
		return;
	}

	// create the item
	const RoomDataModel = jrequire("models/roomdata");
	const roomdata = RoomDataModel.createModel();
	// force some values
	roomdata.creator = user.getIdAsM();

	// validate and save the fields passed
	const saveFields = RoomDataModel.getSaveFields("add");
	const preValidatedFields = [];
	// form fields that we dont complain about finding even though they arent for the form object
	const ignoreFields = [];

	const roomdatadoc = await RoomDataModel.validateSave(jrContext, {}, true, user, query, saveFields, preValidatedFields, ignoreFields, roomdata, RoomModel.getShouldBeOwned());
	if (jrContext.isError()) {
		jrhExpress.sendJsonResult(jrContext, 400);
		return;
	}

	// success
	const returnData = {
		roomData: roomdatadoc,
	};

	// provide it
	jrhExpress.sendJsonDataSuccess(jrContext, "roomdata", returnData);
}
//---------------------------------------------------------------------------









module.exports = {
	setupRouter,
};