<commit_before>/*******************************************************************************
 * @license
 * Copyright (c) 2012 VMware, Inc. All Rights Reserved.
 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
 * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
 * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
 * You can obtain a current copy of the Eclipse Public License from
 * http://www.opensource.org/licenses/eclipse-1.0.php
 *
 * Contributors:
 *     Kris De Volder - initial API and implementation
 ******************************************************************************/

/*global resolve require define:true esprima console module*/
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
define(function(require, exports, module) {

////////////////////////////////////////
// amd-support
//
//   Support for resolving amd references.
/////////////////////////////////////////

/**
 * Currently we provide support for any plugin names listed below.
 * References with these plugins are handled by adding an extension to
 * the resource path and resolving that using the same logic as
 * other references.
 *
 * Plugins not listed in here are not currently supported and references
 * containing them will be marked as 'ignored' which suppresses any
 * errors indicating resolution problems.
 */
var PLUGIN_EXTENSIONS = {
	'text' : '',
	'i18n' : '.js'
};

var mPathMapper = require('./amd-path-mapper');
var startsWith = require('./utils').startsWith;
var endsWith = require('./utils').endsWith;
var pathResolve = require('./utils').pathResolve;
var getDirectory = require('./utils').getDirectory;
var when = require('when');

function configure(conf) {

	var getAmdConfig = require('./amd-config-finder').configure(conf).getAmdConfig;

	/**
	 * @param {string}
	 * @return {Promise}
	 */
	function getPathMapper(context) {
		var deferred = when.defer();
		getAmdConfig(context, function (resolverConf) {
			deferred.resolve(mPathMapper.configure(resolverConf));
		});
		return deferred;
	}

	function isRelative(path) {
		return startsWith(path, './') || startsWith(path, '../');
	}

	function parseName(dep) {
		//in requirejs the way plugins work is that there's a split at the first !
		//the piece before the ! determines the plugin and the rest is passed to
		//that plugin for loading, optimizing, resolving etc.
		var name = dep.name;
		var pos = name.indexOf('!');
		if (pos>=0) {
			var pieces = name.split('!');
			dep.resource = pieces[1];
			dep.plugin = pieces[0];
		}
		//We could put dep.resource = dep.name in the else case to make
		//code simpler / more uniform, but can save some space if we don't.
	}

	function getPluginName(dep) {
		if (dep.plugin) {
			var pieces = dep.plugin.split('/');
			return pieces[pieces.length-1];
		}
	}

	//dep must be parsed before calling this!
	function getResource(dep) {
		return dep.hasOwnProperty('plugin') ? dep.resource : dep.name;
	}

	/**
	 * Get the file extension to be added after resolving a reference to a path.
	 * If the reference is based on an unsupported plugin this will return 'null'.
	 *
	 * Note that the extension may be the empty string so be careul when testing the
	 * result since empty strings are 'falsy' in javascript.
	 */
	function getExtension(dep) {
		var pluginName = getPluginName(dep);
		if (pluginName) {
			if (PLUGIN_EXTENSIONS.hasOwnProperty(pluginName)) {
				return PLUGIN_EXTENSIONS[pluginName];
			} else {
				return null; //Makes the reference be ignored (rather reported as 'missing').
			}
		}
		return '.js'; //Default extension added by typical amd loader.
	}

	function logBack(msg, callback) {
		return function (result) {
			console.log(msg);
			return callback(result);
		};
	}

	function amdResolver(context, dep, callback) {
//		console.log('>>> amdResolver: '+JSON.stringify(dep));
//		callback = logBack("<<< amdResolver "+JSON.stringify(dep), callback);
		parseName(dep);
		//TODO: special case where resource already has a .js extension. This is
		// treated specially in requirejs.
		var resource = getResource(dep);
		var ext = getExtension(dep);
		if (!resource || ext===null) {
			//This is a case like 'domReady!' or an unsupported plugin
			//There's nothing to resolve. Let client know not to report this as an error.
			dep.ignore = true;
			return callback(dep);
		} else if ('require'===resource) {
			dep.ignore = true;
			return callback(dep); //TODO: add a regression test!
		} else if (isRelative(resource)) {
			//Relative resolution doesn't require the resolverConf so avoid fetching it
			var baseDir = getDirectory(context); //relative to context file, not amd config
			dep.path = pathResolve(baseDir, resource) + ext;
			return callback(dep);
		} else {
			when(getPathMapper(context), function (mapper) {
				//console.log(resolverConf);
				dep.path = mapper(resource) + ext;
				callback(dep);
			});
		}
	}

	//A 'resolver support' module provides a resolver for a particular kind of dependency.
	return {
		kind: 'AMD',
		resolver: amdResolver
	};

} //end: function configure

exports.configure = configure;

/////////////////////////////////////////////////////////////////////////
}); //end amd define
<commit_msg>Fix another case of returning a deferred where it should be a promise.<commit_after>/*******************************************************************************
 * @license
 * Copyright (c) 2012 VMware, Inc. All Rights Reserved.
 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
 * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
 * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
 * You can obtain a current copy of the Eclipse Public License from
 * http://www.opensource.org/licenses/eclipse-1.0.php
 *
 * Contributors:
 *     Kris De Volder - initial API and implementation
 ******************************************************************************/

/*global resolve require define:true esprima console module*/
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
define(function(require, exports, module) {

////////////////////////////////////////
// amd-support
//
//   Support for resolving amd references.
/////////////////////////////////////////

/**
 * Currently we provide support for any plugin names listed below.
 * References with these plugins are handled by adding an extension to
 * the resource path and resolving that using the same logic as
 * other references.
 *
 * Plugins not listed in here are not currently supported and references
 * containing them will be marked as 'ignored' which suppresses any
 * errors indicating resolution problems.
 */
var PLUGIN_EXTENSIONS = {
	'text' : '',
	'i18n' : '.js'
};

var mPathMapper = require('./amd-path-mapper');
var startsWith = require('./utils').startsWith;
var endsWith = require('./utils').endsWith;
var pathResolve = require('./utils').pathResolve;
var getDirectory = require('./utils').getDirectory;
var when = require('when');

function configure(conf) {

	var getAmdConfig = require('./amd-config-finder').configure(conf).getAmdConfig;

	/**
	 * @param {string}
	 * @return {Promise}
	 */
	function getPathMapper(context) {
		var deferred = when.defer();
		getAmdConfig(context, function (resolverConf) {
			deferred.resolve(mPathMapper.configure(resolverConf));
		});
		return deferred.promise;
	}

	function isRelative(path) {
		return startsWith(path, './') || startsWith(path, '../');
	}

	function parseName(dep) {
		//in requirejs the way plugins work is that there's a split at the first !
		//the piece before the ! determines the plugin and the rest is passed to
		//that plugin for loading, optimizing, resolving etc.
		var name = dep.name;
		var pos = name.indexOf('!');
		if (pos>=0) {
			var pieces = name.split('!');
			dep.resource = pieces[1];
			dep.plugin = pieces[0];
		}
		//We could put dep.resource = dep.name in the else case to make
		//code simpler / more uniform, but can save some space if we don't.
	}

	function getPluginName(dep) {
		if (dep.plugin) {
			var pieces = dep.plugin.split('/');
			return pieces[pieces.length-1];
		}
	}

	//dep must be parsed before calling this!
	function getResource(dep) {
		return dep.hasOwnProperty('plugin') ? dep.resource : dep.name;
	}

	/**
	 * Get the file extension to be added after resolving a reference to a path.
	 * If the reference is based on an unsupported plugin this will return 'null'.
	 *
	 * Note that the extension may be the empty string so be careul when testing the
	 * result since empty strings are 'falsy' in javascript.
	 */
	function getExtension(dep) {
		var pluginName = getPluginName(dep);
		if (pluginName) {
			if (PLUGIN_EXTENSIONS.hasOwnProperty(pluginName)) {
				return PLUGIN_EXTENSIONS[pluginName];
			} else {
				return null; //Makes the reference be ignored (rather reported as 'missing').
			}
		}
		return '.js'; //Default extension added by typical amd loader.
	}

	function logBack(msg, callback) {
		return function (result) {
			console.log(msg);
			return callback(result);
		};
	}

	function amdResolver(context, dep, callback) {
//		console.log('>>> amdResolver: '+JSON.stringify(dep));
//		callback = logBack("<<< amdResolver "+JSON.stringify(dep), callback);
		parseName(dep);
		//TODO: special case where resource already has a .js extension. This is
		// treated specially in requirejs.
		var resource = getResource(dep);
		var ext = getExtension(dep);
		if (!resource || ext===null) {
			//This is a case like 'domReady!' or an unsupported plugin
			//There's nothing to resolve. Let client know not to report this as an error.
			dep.ignore = true;
			return callback(dep);
		} else if ('require'===resource) {
			dep.ignore = true;
			return callback(dep); //TODO: add a regression test!
		} else if (isRelative(resource)) {
			//Relative resolution doesn't require the resolverConf so avoid fetching it
			var baseDir = getDirectory(context); //relative to context file, not amd config
			dep.path = pathResolve(baseDir, resource) + ext;
			return callback(dep);
		} else {
			when(getPathMapper(context), function (mapper) {
				//console.log(resolverConf);
				dep.path = mapper(resource) + ext;
				callback(dep);
			}).otherwise(function (err) {
				console.error(err);
				if (err.stack) {
					console.log(err.stack);
				}
				callback(err);
			});
		}
	}

	//A 'resolver support' module provides a resolver for a particular kind of dependency.
	return {
		kind: 'AMD',
		resolver: amdResolver
	};

} //end: function configure

exports.configure = configure;

/////////////////////////////////////////////////////////////////////////
}); //end amd define
<|endoftext|>


<commit_before>Meteor.methods({
	messageSearch: function(text, rid, limit) {
		var from, mention, options, query, r, result, currentUserName, currentUserId, currentUserTimezoneOffset;
		check(text, String);
		check(rid, String);
		check(limit, Match.Optional(Number));
		currentUserId = Meteor.userId();
		if (!currentUserId) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'messageSearch'
			});
		}
		currentUserName = Meteor.user().username;
		currentUserTimezoneOffset = Meteor.user().utcOffset;

		// I would place these methods at the bottom of the file for clarity but travis doesn't appreciate that.
		// (no-use-before-define)

		function filterStarred() {
			query['starred._id'] = currentUserId;
			return '';
		}

		function filterUrl() {
			query['urls.0'] = {
				$exists: true
			};
			return '';
		}

		function filterPinned() {
			query.pinned = true;
			return '';
		}

		function filterLocation() {
			query.location = {
				$exist: true
			};
			return '';
		}

		function filterBeforeDate(_, day, month, year) {
			month--;
			var beforeDate = new Date(year, month, day);
			beforeDate.setHours(beforeDate.getUTCHours() + beforeDate.getTimezoneOffset()/60 + currentUserTimezoneOffset);
			query.ts = {
				$lte: beforeDate
			};
			return '';
		}

		function filterAfterDate(_, day, month, year) {
			month--;
			day++;
			var afterDate = new Date(year, month, day);
			afterDate.setUTCHours(afterDate.getUTCHours() + afterDate.getTimezoneOffset()/60 + currentUserTimezoneOffset);
			if (query.ts) {
				query.ts.$gte = afterDate;
			} else {
				query.ts = {
					$gte: afterDate
				};
			}
			return '';
		}

		function filterOnDate(_, day, month, year) {
			month--;
			var date, dayAfter;
			date = new Date(year, month, day);
			date.setUTCHours(date.getUTCHours() + date.getTimezoneOffset()/60 + currentUserTimezoneOffset);
			dayAfter = new Date(date);
			dayAfter.setDate(dayAfter.getDate() + 1);
			delete query.ts;
			query.ts = {
				$gte: date,
				$lt: dayAfter
			};
			return '';
		}

		function sortByTimestamp(_, direction) {
			if (direction.startsWith('asc')) {
				options.sort.ts = 1;
			} else if (direction.startsWith('desc')) {
				options.sort.ts = -1;
			}
			return '';
		}

		/*
		 text = 'from:rodrigo mention:gabriel chat'
		 */
		result = {
			messages: [],
			users: [],
			channels: []
		};
		query = {};
		options = {
			sort: {
				ts: -1
			},
			limit: limit || 20
		};

		// Query for senders
		from = [];
		text = text.replace(/from:([a-z0-9.-_]+)/ig, function(match, username) {
			if (username === 'me' && !from.includes(currentUserName)) {
				username = currentUserName;
			}
			from.push(username);
			return '';
		});
		if (from.length > 0) {
			query['u.username'] = {
				$regex: from.join('|'),
				$options: 'i'
			};
		}
		// Query for senders
		mention = [];
		text = text.replace(/mention:([a-z0-9.-_]+)/ig, function(match, username) {
			mention.push(username);
			return '';
		});
		if (mention.length > 0) {
			query['mentions.username'] = {
				$regex: mention.join('|'),
				$options: 'i'
			};
		}
		// Filter on messages that are starred by the current user.
		text = text.replace(/has:star/g, filterStarred);
		// Filter on messages that have an url.
		text = text.replace(/has:url|has:link/g, filterUrl);
		// Filter on pinned messages.
		text = text.replace(/is:pinned|has:pin/g, filterPinned);
		// Filter on messages which have a location attached.
		text = text.replace(/has:location|has:map/g, filterLocation);
		// Filtering before/after/on a date
		// matches dd-MM-yyyy, dd/MM/yyyy, dd-MM-yyyy, prefixed by before:, after: and on: respectively.
		// Example: before:15/09/2016 after: 10-08-2016
		// if "on:" is set, "before:" and "after:" are ignored.
		text = text.replace(/before:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterBeforeDate);
		text = text.replace(/after:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterAfterDate);
		text = text.replace(/on:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterOnDate);
		// Sort order
		text = text.replace(/(?:order|sort):(asc|ascend|ascending|desc|descend|descening)/g, sortByTimestamp);

		// Query in message text
		text = text.trim().replace(/\s\s/g, ' ');
		if (text !== '') {
			if (/^\/.+\/[imxs]*$/.test(text)) {
				r = text.split('/');
				query.msg = {
					$regex: r[1],
					$options: r[2]
				};
			} else if (RocketChat.settings.get('Message_AlwaysSearchRegExp')) {
				query.msg = {
					$regex: text,
					$options: 'i'
				};
			} else {
				query.$text = {
					$search: text
				};
				options.fields = {
					score: {
						$meta: 'textScore'
					}
				};
			}
		}
		if (Object.keys(query).length > 0) {
			query.t = {
				$ne: 'rm'  //hide removed messages (useful when searching for user messages)
			};
			query._hidden = {
				$ne: true  // don't return _hidden messages
			};
			if (rid != null) {
				query.rid = rid;
				if (Meteor.call('canAccessRoom', rid, currentUserId) !== false) {
					if (!RocketChat.settings.get('Message_ShowEditedStatus')) {
						options.fields = {
							'editedAt': 0
						};
					}
					result.messages = RocketChat.models.Messages.find(query, options).fetch();
				}
			}
		}

		return result;
	}
});
<commit_msg>Fix typo in result ordering regex.<commit_after>Meteor.methods({
	messageSearch: function(text, rid, limit) {
		var from, mention, options, query, r, result, currentUserName, currentUserId, currentUserTimezoneOffset;
		check(text, String);
		check(rid, String);
		check(limit, Match.Optional(Number));
		currentUserId = Meteor.userId();
		if (!currentUserId) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'messageSearch'
			});
		}
		currentUserName = Meteor.user().username;
		currentUserTimezoneOffset = Meteor.user().utcOffset;

		// I would place these methods at the bottom of the file for clarity but travis doesn't appreciate that.
		// (no-use-before-define)

		function filterStarred() {
			query['starred._id'] = currentUserId;
			return '';
		}

		function filterUrl() {
			query['urls.0'] = {
				$exists: true
			};
			return '';
		}

		function filterPinned() {
			query.pinned = true;
			return '';
		}

		function filterLocation() {
			query.location = {
				$exist: true
			};
			return '';
		}

		function filterBeforeDate(_, day, month, year) {
			month--;
			var beforeDate = new Date(year, month, day);
			beforeDate.setHours(beforeDate.getUTCHours() + beforeDate.getTimezoneOffset()/60 + currentUserTimezoneOffset);
			query.ts = {
				$lte: beforeDate
			};
			return '';
		}

		function filterAfterDate(_, day, month, year) {
			month--;
			day++;
			var afterDate = new Date(year, month, day);
			afterDate.setUTCHours(afterDate.getUTCHours() + afterDate.getTimezoneOffset()/60 + currentUserTimezoneOffset);
			if (query.ts) {
				query.ts.$gte = afterDate;
			} else {
				query.ts = {
					$gte: afterDate
				};
			}
			return '';
		}

		function filterOnDate(_, day, month, year) {
			month--;
			var date, dayAfter;
			date = new Date(year, month, day);
			date.setUTCHours(date.getUTCHours() + date.getTimezoneOffset()/60 + currentUserTimezoneOffset);
			dayAfter = new Date(date);
			dayAfter.setDate(dayAfter.getDate() + 1);
			delete query.ts;
			query.ts = {
				$gte: date,
				$lt: dayAfter
			};
			return '';
		}

		function sortByTimestamp(_, direction) {
			if (direction.startsWith('asc')) {
				options.sort.ts = 1;
			} else if (direction.startsWith('desc')) {
				options.sort.ts = -1;
			}
			return '';
		}

		/*
		 text = 'from:rodrigo mention:gabriel chat'
		 */
		result = {
			messages: [],
			users: [],
			channels: []
		};
		query = {};
		options = {
			sort: {
				ts: -1
			},
			limit: limit || 20
		};

		// Query for senders
		from = [];
		text = text.replace(/from:([a-z0-9.-_]+)/ig, function(match, username) {
			if (username === 'me' && !from.includes(currentUserName)) {
				username = currentUserName;
			}
			from.push(username);
			return '';
		});
		if (from.length > 0) {
			query['u.username'] = {
				$regex: from.join('|'),
				$options: 'i'
			};
		}
		// Query for senders
		mention = [];
		text = text.replace(/mention:([a-z0-9.-_]+)/ig, function(match, username) {
			mention.push(username);
			return '';
		});
		if (mention.length > 0) {
			query['mentions.username'] = {
				$regex: mention.join('|'),
				$options: 'i'
			};
		}
		// Filter on messages that are starred by the current user.
		text = text.replace(/has:star/g, filterStarred);
		// Filter on messages that have an url.
		text = text.replace(/has:url|has:link/g, filterUrl);
		// Filter on pinned messages.
		text = text.replace(/is:pinned|has:pin/g, filterPinned);
		// Filter on messages which have a location attached.
		text = text.replace(/has:location|has:map/g, filterLocation);
		// Filtering before/after/on a date
		// matches dd-MM-yyyy, dd/MM/yyyy, dd-MM-yyyy, prefixed by before:, after: and on: respectively.
		// Example: before:15/09/2016 after: 10-08-2016
		// if "on:" is set, "before:" and "after:" are ignored.
		text = text.replace(/before:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterBeforeDate);
		text = text.replace(/after:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterAfterDate);
		text = text.replace(/on:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterOnDate);
		// Sort order
		text = text.replace(/(?:order|sort):(asc|ascend|ascending|desc|descend|descending)/g, sortByTimestamp);

		// Query in message text
		text = text.trim().replace(/\s\s/g, ' ');
		if (text !== '') {
			if (/^\/.+\/[imxs]*$/.test(text)) {
				r = text.split('/');
				query.msg = {
					$regex: r[1],
					$options: r[2]
				};
			} else if (RocketChat.settings.get('Message_AlwaysSearchRegExp')) {
				query.msg = {
					$regex: text,
					$options: 'i'
				};
			} else {
				query.$text = {
					$search: text
				};
				options.fields = {
					score: {
						$meta: 'textScore'
					}
				};
			}
		}
		if (Object.keys(query).length > 0) {
			query.t = {
				$ne: 'rm'  //hide removed messages (useful when searching for user messages)
			};
			query._hidden = {
				$ne: true  // don't return _hidden messages
			};
			if (rid != null) {
				query.rid = rid;
				if (Meteor.call('canAccessRoom', rid, currentUserId) !== false) {
					if (!RocketChat.settings.get('Message_ShowEditedStatus')) {
						options.fields = {
							'editedAt': 0
						};
					}
					result.messages = RocketChat.models.Messages.find(query, options).fetch();
				}
			}
		}

		return result;
	}
});
<|endoftext|>


<commit_before>module.exports = bundleClient

var fs = require('fs')
var path = require('path')
var parallel = require('async').parallel
var requireResolve = require('../resolver')

function checkModule (module) {
  try {
    requireResolve(module)
    return true
  } catch (err) {
    if (err.code !== 'MODULE_NOT_FOUND') {
      throw err
    }
    return false
  }
}

/**
 * we compare the mtime (modified time) for the last modified dependency of the
 * Hoodie client and the target bundle file. If the latter does not exist or
 * any dependency was modified more recently, we read out the client and add
 * the `new Hoodie()` init code, otherwise we simply read out the bundle file.
 *
 * This optimisation is in preparation for plugins. Plugins can extend the
 * client, so we need to browserify on-the-fly to avoid dependency duplication,
 * and avoiding unneeded bundling with browserify saves a significant time.
 */
function bundleClient (hoodieClientPath, bundleTargetPath, options, callback) {
  var pluginPaths = options.plugins.map(function (pluginName) {
    return pluginName + '/hoodie/client'
  })

  var plugins = [path.resolve('hoodie/client')]
    .concat(pluginPaths)
    .filter(checkModule)

  var getPluginsModifiedTimes = plugins.map(function (pluginPath) {
    return getModifiedTime.bind(null, requireResolve(pluginPath))
  })

  parallel(getPluginsModifiedTimes.concat([
    getModifiedTime.bind(null, hoodieClientPath),
    getModifiedTime.bind(null, bundleTargetPath)
  ]), function (error, results) {
    /* istanbul ignore if */
    if (error) {
      return callback(error)
    }

    var targetTime = results.pop()
    var sourceTime = Math.max.apply(null, results)
    var hasUpdate = sourceTime > targetTime

    var get = hasUpdate ? buildBundle.bind(null, options, plugins) : fs.readFile.bind(null, bundleTargetPath)

    get(function (error, buffer) {
      if (error) {
        return callback(error)
      }

      callback(null, buffer, hasUpdate)
    })
  })
}

function getModifiedTime (path, callback) {
  fs.stat(path, function (error, stats) {
    // we can ignore error, it means the file does not exist which is fine
    if (error) {
      return callback(null, -1)
    }

    callback(null, +stats.mtime)
  })
}

function buildBundle (options, plugins, callback) {
  var ReadableStream = require('stream').Readable
  var browserify = require('browserify')
  var stream = new ReadableStream()

  var b = browserify(stream, {
    standalone: 'hoodie'
  })
  var hoodieBundleSource = ''

  hoodieBundleSource += 'var Hoodie = require("@hoodie/client")\n'
  hoodieBundleSource += 'var options = {\n'

  if (options.client) {
    Object.keys(options.client).forEach(function (key) {
      hoodieBundleSource += '  "' + key + '": ' + JSON.stringify(options.client[key]) + ',\n'
    })
  }

  if (options.url) {
    hoodieBundleSource += '  url: "' + options.url + '",\n'
  } else {
    hoodieBundleSource += '  url: location.origin,\n'
  }

  hoodieBundleSource += '  PouchDB: require("pouchdb-browser")\n'

  hoodieBundleSource += '}\n'
  hoodieBundleSource += 'module.exports = new Hoodie(options)\n'
  plugins.forEach(function (pluginPath) {
    hoodieBundleSource += '  .plugin(require("' + pluginPath + '"))\n'
  })

  stream.push(hoodieBundleSource)
  stream.push(null)

  b.bundle(callback)
}
<commit_msg>Fix: client plugins crashing hoodie server in Windows (#867)<commit_after>module.exports = bundleClient

var fs = require('fs')
var path = require('path')
var parallel = require('async').parallel
var requireResolve = require('../resolver')

function checkModule (module) {
  try {
    requireResolve(module)
    return true
  } catch (err) {
    if (err.code !== 'MODULE_NOT_FOUND') {
      throw err
    }
    return false
  }
}

/**
 * we compare the mtime (modified time) for the last modified dependency of the
 * Hoodie client and the target bundle file. If the latter does not exist or
 * any dependency was modified more recently, we read out the client and add
 * the `new Hoodie()` init code, otherwise we simply read out the bundle file.
 *
 * This optimisation is in preparation for plugins. Plugins can extend the
 * client, so we need to browserify on-the-fly to avoid dependency duplication,
 * and avoiding unneeded bundling with browserify saves a significant time.
 */
function bundleClient (hoodieClientPath, bundleTargetPath, options, callback) {
  var pluginPaths = options.plugins.map(function (pluginName) {
    return pluginName + '/hoodie/client'
  })

  var plugins = [path.resolve('hoodie/client')]
    .concat(pluginPaths)
    .map(p => p.replace(/\\/g,"/") )  // fix backslashes in Windows paths
    .filter(checkModule)

  var getPluginsModifiedTimes = plugins.map(function (pluginPath) {
    return getModifiedTime.bind(null, requireResolve(pluginPath))
  })

  parallel(getPluginsModifiedTimes.concat([
    getModifiedTime.bind(null, hoodieClientPath),
    getModifiedTime.bind(null, bundleTargetPath)
  ]), function (error, results) {
    /* istanbul ignore if */
    if (error) {
      return callback(error)
    }

    var targetTime = results.pop()
    var sourceTime = Math.max.apply(null, results)
    var hasUpdate = sourceTime > targetTime

    var get = hasUpdate ? buildBundle.bind(null, options, plugins) : fs.readFile.bind(null, bundleTargetPath)

    get(function (error, buffer) {
      if (error) {
        return callback(error)
      }

      callback(null, buffer, hasUpdate)
    })
  })
}

function getModifiedTime (path, callback) {
  fs.stat(path, function (error, stats) {
    // we can ignore error, it means the file does not exist which is fine
    if (error) {
      return callback(null, -1)
    }

    callback(null, +stats.mtime)
  })
}

function buildBundle (options, plugins, callback) {
  var ReadableStream = require('stream').Readable
  var browserify = require('browserify')
  var stream = new ReadableStream()

  var b = browserify(stream, {
    standalone: 'hoodie'
  })
  var hoodieBundleSource = ''

  hoodieBundleSource += 'var Hoodie = require("@hoodie/client")\n'
  hoodieBundleSource += 'var options = {\n'

  if (options.client) {
    Object.keys(options.client).forEach(function (key) {
      hoodieBundleSource += '  "' + key + '": ' + JSON.stringify(options.client[key]) + ',\n'
    })
  }

  if (options.url) {
    hoodieBundleSource += '  url: "' + options.url + '",\n'
  } else {
    hoodieBundleSource += '  url: location.origin,\n'
  }

  hoodieBundleSource += '  PouchDB: require("pouchdb-browser")\n'

  hoodieBundleSource += '}\n'
  hoodieBundleSource += 'module.exports = new Hoodie(options)\n'
  plugins.forEach(function (pluginPath) {
    hoodieBundleSource += '  .plugin(require("' + pluginPath + '"))\n'
  })

  stream.push(hoodieBundleSource)
  stream.push(null)

  b.bundle(callback)
}
<|endoftext|>


<commit_before><commit_msg>Add preferences controller<commit_after>var Prefs = require( './prefs' );

module.exports = {

  /*insert methods here*/

};
<|endoftext|>


<commit_before>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function (uid_day, uid_offering, callback) {
 	var numStud = 0;
 	con.query('SELECT COUNT(*) AS count FROM choices WHERE uid_offering = ? AND uid_day = ?', [uid_offering, uid_day], function(err, students) {
 		if(!err) {
	 		callback(students[0].count);
 		} else {
 			console.error("Cannot count students in offering.");
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, max_size, callback) {
    //	Gets the number of students in an offering
    module.exports.numStudents(uid_day, uid_offering, function(numStud) {
        //	Compares that number to the offering's maximum size
        //	CHANGE
        console.log((numStud >= max_size));
        if(numStud >= max_size) {
          callback(true);
        } else {
          callback(false);
        }
    });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list of Offering objects including a property for avalialability ('.disbaled')
 getOfferings: function (uid_day, callback) {
 	//	Join query to find a list of offerings on a certain day with the name of their teacher
 	con.query('SELECT * from offerings JOIN calendar on offerings.uid_offering = calendar.uid_offering JOIN teachers on teachers.uid_teacher = offerings.uid_teacher WHERE calendar.uid_day = ?', [uid_day], function(err, result) {
		//	Makes sure the join query didn't error or produce an empty set
		if (!err && result != undefined) {

			//	Loops through every offering to find whether or not it is full
			var j = 0;
		    for(var i = 0; i < result.length; i++) {
		      //	Checks if every offering is full or not
		      module.exports.isOfferingFull(uid_day, result[i].uid_offering, result[i].max_size, function(truth) {
				  //	Adds the availability of the offering as a property
				  if(truth) {
				  	truth = "disabled";
				  } else {
				  	truth = "able";
				  }
				  result[j].disabled = truth;
				  j+=1;

				  //	Calls back the list once all the queries have run
				  if (j==result.length) {
					callback(result);
				  }
		      });
		    }
		} else {
			console.log("We're sorry. A join query produced an error and or an empty set.");
		}
	});
 },

 //	A middleware to get the uid and date of the next OppBlock for future use
 nextOppblockDay: function(req, res, next) {
 	// Gets all Oppblock days
	con.query('SELECT * FROM opp_block_day ORDER BY day DESC', function(err, results){
		if(!err){
			var closest;
			var uid_day;
			//	Loops to find soonest Oppblock
			for (var i=0; i<results.length; i++) {
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and replaces it as the closest if so
				if (curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			//	Leaves the uid_day and moment date object in req.student for use by future middlewares
			req.student.uid_day = uid_day;
			req.student.day = closest;

			return next();
		} else {
			//	Renders an error page if one occured
			res.render('error.html', {err:err});
		}
	});
 },

 //	A middleware checking if the student exists in the choices table; saves his/her choice for future use if so; otherwise renders the excluded student page
 isStudentExcluded: function(req, res, next) {
 	//	Gets student/day from req object
	var uid_student = req.user.local[0].uid_student;
 	var uid_day = req.student.uid_day;

 	con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, choice) { // only gets the uid not the name
 		if(!err) {
 			if (choice.length != 0) {
 				//	Leaves the choice in req.student for use by future middlewares
 				req.student.choice = choice[0].uid_offering;

 				return next();
 			} else {
 				// Renders the page without any choices, since the student is excluded
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
 			}
 		} else {
 			//	Renders an error page if one occured
			res.render('error.html', {err:err});
 		}
 	});
 },

 //	A middleware
 isStudentTime: function(req, res, next) {
 	// Gets Student's id from the req object
	var student = req.user.local[0];
	var uid_student = student.uid_student;

 	//	Creates Cutoff time variables relative to closest oppblock, based on admin settings
	var oppBlockDay = req.student.day;
	var studentCutoff = moment(oppBlockDay.add({hours:settings["hours_close_student"].value_int}));
	var teacherCutoff = moment(oppBlockDay.add({hours:settings["hours_close_teacher"].value_int}));

	//	Checks if after the teacher cutoff
	if (moment().isSameOrAfter(teacherCutoff)) {
		//	Checks if after the student cutoff
		if (moment().isSameOrAfter(studentCutoff)) {
			//	Checks whether the student has chosen yet
			if (req.student.choice == null) {
				// Renders the page with an admin's message for the student, as they have neglected to sign up.
				res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
			} else {
				// Renders the page only with the user's current choice
				res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
			}
		} else {
			return next();
		}
	} else {
		//	Renders the page to show that the choices aren't ready yet, since the teachers haven't yet been cutoff
		res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
	}
 },

 //	A middleware to determine whether a choice is valid (a real offering, existing on the current day, that's not yet full)
 isValidChoice: function(req, res, next) {
 	var uid_offering = req.body.choice;
	var uid_day = req.student.uid_day;

 	// Makes sure the student has actually made a choice
	if(uid_offering != undefined) {
		//	Join query checks if the offering has a valid uid and is offered on the current day
		con.query('SELECT offerings.name, offerings.max_size calendar.uid_offering FROM calendar JOIN offerings ON calendar.uid_offering = offerings.uid_offering WHERE calendar.uid_offering = ? AND calendar.uid_day = ?', [uid_offering, uid_day], function(err, resultsOffering) {
			if(!err && resultsOffering != undefined && resultsOffering.length != 0 && ) {
				//	Checks if the offering is full
				isOfferingFull(uid_day, uid_offering, resultsOffering[0].max_size, function(full) {
					if(!full) {
						return next();
					} else {
						res.render('error.html', {err:"You tried to sign up for a full offering! Go back."});
					}
				});
	 		} else {
	 			//	Renders an error page if one occured OR if the user sent a malformed post request
				res.render('error.html', {err:err});
	 		}
		});
	} else {
		res.redirect('/student');
	}
 	return next();
 },

 init: function(app) {
	app.get('/student', middleware.isStudent, module.exports.nextOppblockDay, module.exports.isStudentExcluded, module.exports.isStudentTime, function(req, res){
		// Gets Student's id from the req object
		var student = req.user.local[0];
		var uid_student = student.uid_student;

		// Gets all offerings for the user
		module.exports.getOfferings(uid_day, function(offerings) {
			//	Checks whether the student has chosen yet
			if (req.student.choice == null) {
				// At last, renders the page with the lack of choice, and the choices table
				res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
			} else {
				// At last, renders the page with the current choice, and the choices table
				res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
			}
		});
	});

	//	The student post request serves to insert/update a student's choice in the database
	app.post('/student', middleware.isStudent, module.exports.nextOppblockDay, module.exports.isStudentExcluded, module.exports.isStudentTime, module.exports.isValidChoice, function(req, res) {
		// Gets the student's uid, the uid of their offering of choice, and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_offering = req.body.choice;
		var uid_day = req.student.uid_day;

		// Updates the student's choice in the database
		con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [uid_offering, uid_student, uid_day], function(err, results) {
			if(!err) {
				//	Redirects back once the update has been carried out
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});

	//	This post request is for when students are excluded wrongfully from an OppBlock Day
	app.post('/studentOverride', middleware.isStudent, module.exports.nextOppblockDay, function(req, res) {
		// Gets the student's uid and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_day = req.student.uid_day;

		// Overrides an excluded group by adding the student into the choice table
		con.query('INSERT INTO choices (uid_student, uid_day) values (?, ?)', [uid_student, uid_day], function(err) {
			if(!err) {
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});
	return this;
 }
}
<commit_msg>Bug Fixes to Student; Massive Overhaul Completed & Issue Resolved<commit_after>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function (uid_day, uid_offering, callback) {
 	var numStud = 0;
 	con.query('SELECT COUNT(*) AS count FROM choices WHERE uid_offering = ? AND uid_day = ?', [uid_offering, uid_day], function(err, students) {
 		if(!err) {
	 		callback(students[0].count);
 		} else {
 			console.error("Cannot count students in offering.");
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, max_size, callback) {
    //	Gets the number of students in an offering
    module.exports.numStudents(uid_day, uid_offering, function(numStud) {
        //	Calls back that number compared to the offering's maximum size
        callback((numStud >= max_size));
    });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list of Offering objects including a property for avalialability ('.disbaled')
 getOfferings: function (uid_day, callback) {
 	//	Join query to find a list of offerings on a certain day with the name of their teacher
 	con.query('SELECT * from offerings JOIN calendar on offerings.uid_offering = calendar.uid_offering JOIN teachers on teachers.uid_teacher = offerings.uid_teacher WHERE calendar.uid_day = ?', [uid_day], function(err, result) {
		//	Makes sure the join query didn't error or produce an empty set
		if (!err && result != undefined) {

			//	Loops through every offering to find whether or not it is full
			var j = 0;
		    for(var i = 0; i < result.length; i++) {
		      //	Checks if every offering is full or not
		      module.exports.isOfferingFull(uid_day, result[i].uid_offering, result[i].max_size, function(truth) {
				  //	Adds the availability of the offering as a property
				  if(truth) {
				  	truth = "disabled";
				  } else {
				  	truth = "able";
				  }
				  result[j].disabled = truth;
				  j+=1;

				  //	Calls back the list once all the queries have run
				  if (j==result.length) {
					callback(result);
				  }
		      });
		    }
		} else {
			console.log("We're sorry. A join query produced an error and or an empty set.");
		}
	});
 },

 //	A middleware to get the uid and date of the next OppBlock for future use
 nextOppblockDay: function(req, res, next) {
 	// Gets all Oppblock days
	con.query('SELECT * FROM opp_block_day ORDER BY day DESC', function(err, results){
		if(!err){
			var closest;
			var uid_day;
			//	Loops to find soonest Oppblock
			for (var i=0; i<results.length; i++) {
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and replaces it as the closest if so
				if (curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}

			//	Leaves the uid_day and moment date object in req.student for use by future middlewares
			req.student = {uid_day: uid_day, day: closest};

			return next();
		} else {
			//	Renders an error page if one occured
			res.render('error.html', {err:err});
		}
	});
 },

 //	A middleware checking if the student exists in the choices table; saves his/her choice for future use if so; otherwise renders the excluded student page
 isStudentExcluded: function(req, res, next) {
 	//	Gets student/day from req object
	var student = req.user.local[0];
	var uid_student = student.uid_student;
 	var uid_day = req.student.uid_day;

 	//	Gets a student's choice or lack thereof
 	con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, choiceUid) { // only gets the uid not the name
 		if(!err) {
 			if (choiceUid.length != 0) {
 				//	Gets specific information about the student's choice
 				con.query('SELECT uid_offering, name, location FROM offerings WHERE uid_offering = ?', [choiceUid[0].uid_offering], function(err, choice) {
					if(!err) {
						if (choice.length == 0) {
							choice = [choiceUid[0].uid_offering];
						}
		 				//	Leaves the choice in req.student for use by future middlewares
		 				req.student.choice = choice[0];

		 				return next();
					} else {
						//	Renders an error page if one occured
						res.render('error.html', {err:err});
					}
				});
 			} else {
 				// Renders the page without any choices, since the student is excluded
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
 			}
 		} else {
 			//	Renders an error page if one occured
			res.render('error.html', {err:err});
 		}
 	});
 },

 //	A middleware checking whether the students should be waiting to choose, choosing, or attending their choices, only moving on if it is choice time
 isStudentTime: function(req, res, next) {
 	// Gets Student's id from the req object
	var student = req.user.local[0];
	var uid_student = student.uid_student;
	var choice = req.student.choice;

 	//	Creates Cutoff time variables relative to closest oppblock, based on admin settings
	var oppBlockDay = req.student.day;
	var studentCutoff = moment(oppBlockDay.add({hours:settings["hours_close_student"].value_int}));
	var teacherCutoff = moment(oppBlockDay.add({hours:settings["hours_close_teacher"].value_int}));

	//	Checks if after the teacher cutoff
	if (moment().isSameOrAfter(teacherCutoff)) {
		//	Checks if after the student cutoff
		if (moment().isSameOrAfter(studentCutoff)) {
			//	Checks whether the student has chosen yet
			if (req.student.choice == null) {
				// Renders the page with an admin's message for the student, as they have neglected to sign up.
				res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
			} else {
				// Renders the page only with the user's current choice
				res.render('student.html', {Student:student.firstname, Choice:choice.name, Description:"The time for selection has passed. At 2:45, head to " + choice.location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
			}
		} else {
			return next();
		}
	} else {
		//	Renders the page to show that the choices aren't ready yet, since the teachers haven't yet been cutoff
		res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
	}
 },

 //	A middleware to determine whether a choice is valid (a real offering, existing on the current day, that's not yet full)
 isValidChoice: function(req, res, next) {
 	var uid_offering = req.body.choice;
	var uid_day = req.student.uid_day;

 	// Makes sure the student has actually made a choice
	if(uid_offering != undefined) {
		//	Join query checks if the offering has a valid uid and is offered on the current day
		con.query('SELECT offerings.name, offerings.max_size, calendar.uid_offering FROM offerings JOIN calendar ON offerings.uid_offering = calendar.uid_offering WHERE calendar.uid_offering = ? AND calendar.uid_day = ?', [uid_offering, uid_day], function(err, resultsOffering) {
			if(!err && resultsOffering != undefined && resultsOffering.length != 0) {
				//	Checks if the offering is full
				module.exports.isOfferingFull(uid_day, uid_offering, resultsOffering[0].max_size, function(full) {
					if (!full) {
						return next();
					} else {
						res.render('error.html', {err:"You tried to sign up for a full offering! Go back."});
					}
				});
	 		} else {
	 			//	Renders an error page if one occured OR if the user sent a malformed post request
				res.render('error.html', {err:err});
	 		}
		});
	} else {
		res.redirect('/student');
	}
 },

 init: function(app) {
	//	General Student Endpoint
	app.get('/student', middleware.isStudent, module.exports.nextOppblockDay, module.exports.isStudentExcluded, module.exports.isStudentTime, function(req, res){
		// Gets Student's id and the day from the req object
		var student = req.user.local[0];
		var uid_student = student.uid_student;
		var uid_day = req.student.uid_day;
		var choice = req.student.choice;

		// Gets all offerings for the user
		module.exports.getOfferings(uid_day, function(offerings) {
			//	Checks whether the student has chosen yet
			if (req.student.choice == null) {
				// At last, renders the page with the lack of choice, and the choices table
				res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
			} else {
				// At last, renders the page with the current choice, and the choices table
				res.render('student.html', {Student:student.firstname, Choice:choice.name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
			}
		});
	});

	//	The student post request serves to insert/update a student's choice in the database
	app.post('/student', middleware.isStudent, module.exports.nextOppblockDay, module.exports.isStudentExcluded, module.exports.isStudentTime, module.exports.isValidChoice, function(req, res) {
		// Gets the student's uid, the uid of their offering of choice, and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_offering = req.body.choice;
		var uid_day = req.student.uid_day;

		// Updates the student's choice in the database
		con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [uid_offering, uid_student, uid_day], function(err, results) {
			if(!err) {
				//	Redirects back after update
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});

	//	This post request is for when students are excluded wrongfully from an OppBlock Day
	app.post('/studentOverride', middleware.isStudent, module.exports.nextOppblockDay, function(req, res) {
		// Gets the student's uid and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_day = req.student.uid_day;

		// Overrides an excluded group by adding the student into the choice table // Deletes first for security
		con.query('DELETE FROM choices WHERE uid_student = ? AND uid_day = ? AND uid_offering IS NULL', [uid_student, uid_day], function(err) {
			if(!err) {
				con.query('INSERT INTO choices (uid_student, uid_day) values (?, ?)', [uid_student, uid_day], function(err) {
					if(!err) {
						res.redirect('/student');
					} else {
						//	Renders an error page if one occured
						res.render('error.html', {err:err});
					}
				});
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});
	return this;
 }
}
<|endoftext|>


<commit_before>/**
 * @module server/lib/routes/post/sequences
 */
'use strict';

var hasKeypaths = require('101/has-keypaths');
var last = require('101/last');
var pick = require('101/pick');

var alerts = require('models/alerts');
var app = require('app');
var errors = require('lib/errors');
var log = require('lib/logger')(__filename);
var sequences = require('models/sequences');

var exports = module.exports;

/**
 * Validate POST request body.
 * 1. Assert body contains keypaths:
 *  - name
 *  - uuid
 * 2. Assert `name` is a registered sequence
 */
exports._postSequencesInitialValidation = (req, res, next) => {
  if(!hasKeypaths(req.body, ['name', 'uuid'])) {
    return next(errors.handleRequestError('invalid request'));
  }
  var s = sequences.getSequenceSpecification(req.body.name);
  if (!s) {
    return next(errors.handleRequestError('unknown sequence'));
  }
  next();
};

/**
 * Persist sequence document to database collection
 */
exports._createNewSequence = (req, res, next) => {
  var opts = pick(req.body, ['name', 'uuid', 'meta']);
  sequences.createSequence(opts, function (err, sequence) {
    if (err) {
      return next(err);
    }
    req.runnableData.sequence = sequence;
    next();
  });
};

/**
 *
 */
exports._initializeCheckpointAlert = (req, res, next) => {
  var s = req.runnableData.sequence;
  alerts.createAlert(s.name, s.uuid, last(s.checkpoints).name);
  next();
};

/**
 * POST /sequences
 */
exports._postSequences = [
    /**
     * 1. Is valid sequence?
     * 2. Persist sequence (w/ automatically created first checkpoint)
     * 3. Initialize alert countdown
     */
  exports._postSequencesInitialValidation,
  exports._createNewSequence,
  exports._initializeAlertCountdown,
  (req, res) => {
    res.send(201);
  },
  (err, req, res, next) => {
    if (err.code === 11000) {
      res.status(409).send();
      return next();
    }
    res.status(500).send();
    next();
  }
];

/**
 * POST /sequences/checkpoint
 */
exports._postSequencesCheckpoint = [
];

var _routes = exports._routes = [
  //['post', '/sequences', exports._postSequences],
  //['post', '/sequences/checkpoint', exports._postSequencesCheckpoint]
];

/**
 * Bind route middlewares to request paths
 * @param {Object} app instance of express
 */
exports.initialize = () => {
  _routes.forEach((route) => {
    log.trace([
      'Route loaded:',
    ].concat(route).join(' '));
    app[route[0]](route[1], route[2]);
  });
};
<commit_msg>Fix typo in post/sequences route module<commit_after>/**
 * @module server/lib/routes/post/sequences
 */
'use strict';

var hasKeypaths = require('101/has-keypaths');
var last = require('101/last');
var pick = require('101/pick');

var alerts = require('models/alerts');
var app = require('app');
var errors = require('lib/errors');
var log = require('lib/logger')(__filename);
var messenger = require('lib/messenger');
var sequences = require('models/sequences');

var exports = module.exports;

/**
 * Validate POST request body.
 * 1. Assert body contains keypaths:
 *  - name
 *  - uuid
 * 2. Assert `name` is a registered sequence
 */
exports._postSequencesInitialValidation = (req, res, next) => {
  if(!hasKeypaths(req.body, ['name', 'uuid'])) {
    return next(errors.handleRequestError('invalid request'));
  }
  var s = sequences.getSequenceSpecification(req.body.name);
  if (!s) {
    return next(errors.handleRequestError('unknown sequence'));
  }
  next();
};

/**
 * Persist sequence document to database collection
 */
exports._createNewSequence = (req, res, next) => {
  var opts = pick(req.body, ['name', 'uuid', 'meta']);
  sequences.createSequence(opts, function (err, sequence) {
    if (err) {
      return next(err);
    }
    req.runnableData.sequence = sequence;
    next();
  });
};

/**
 *
 */
exports._initializeCheckpointAlert = (req, res, next) => {
  var s = req.runnableData.sequence;
  alerts.createAlert(s.name, s.uuid, last(s.checkpoints).name);
  next();
};

/**
 *
 */
exports._emitPostSequences = (req, res, next) => {
  var s = req.runnableData.sequence;
  messenger.emitPostSequences(s.name, s.uuid);
  next();
};

/**
 * POST /sequences
 */
exports._postSequences = [
    /**
     * 1. Is valid sequence?
     * 2. Persist sequence (w/ automatically created first checkpoint)
     * 3. Initialize alert countdown
     */
  exports._postSequencesInitialValidation,
  exports._createNewSequence,
  exports._initializeCheckpointAlert,
  exports._emitPostSequences,
  (req, res) => {
    res.send(201);
  },
  (err, req, res, next) => {
    if (err.code === 11000) {
      res.status(409).send();
      return next();
    }
    res.status(500).send();
    next();
  }
];

/**
 * POST /sequences/checkpoint
 */
exports._postSequencesCheckpoint = [
];

var _routes = exports._routes = [
  ['post', '/sequences', exports._postSequences],
  //['post', '/sequences/checkpoint', exports._postSequencesCheckpoint]
];

/**
 * Bind route middlewares to request paths
 * @param {Object} app instance of express
 */
exports.initialize = () => {
  _routes.forEach((route) => {
    log.trace([
      'Route loaded:',
    ].concat(route).join(' '));
    app[route[0]](route[1], route[2]);
  });
};
<|endoftext|>


<commit_before>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function (uid_day, uid_offering, callback) {
 	var numStud = 0;
 	con.query('SELECT students.uid_student FROM choices JOIN students ON choices.uid_student = students.uid_student WHERE uid_offering = ? AND uid_day = ?', [uid_offering, uid_day], function(err, students) {
 		if(!err) {
	 		for (var i = 0; i < students.length; i++) {
	 			numStud += 1;
	 		}
	 		callback(numStud);
 		} else {
 			console.log("Join Query Produced an Error.");
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, max_size, callback) {
    //	Gets the number of students in an offering
    module.exports.numStudents(uid_day, uid_offering, function(numStud) {
        //	Compares that number to the offering's maximum size
        if(numStud >= max_size) {
          callback("disabled");
        } else {
          callback("able");
        }
    });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list of Offering objects including a property for avalialability ('.disbaled')
 getOfferings: function (uid_day, callback) {
 	//	Join query to find a list of offerings on a certain day with the name of their teacher
 	con.query('SELECT * from offerings JOIN calendar on offerings.uid_offering = calendar.uid_offering JOIN teachers on teachers.uid_teacher = offerings.uid_teacher WHERE calendar.uid_day = ?', [uid_day], function(err, result) {
		//	Makes sure the join query didn't error or produce an empty set
		if (!err && result != undefined) {

			//	Loops through every offering to find whether or not it is full
			var j = 0;
		    for(var i = 0; i < result.length; i++) {
		      //	Uses isOfferingFull for every one, which will return either 'disabled' or 'able'
		      module.exports.isOfferingFull(uid_day, result[i].uid_offering, result[i].max_size, function(truth) {
				  //	Adds the availability of the offering as a property
				  result[j].disabled = truth;
				  j+=1;
				  //	Calls back the list once all the queries have run
				  if (j==result.length) {
					callback(result);
				  }
		      });
		    }
		} else {
			console.log("We're sorry. A join query produced an error and or an empty set.");
		}
	});
 },

// Takes in nothing
// Returns two values:
// A uid_day of the coming oppblock (null if the students can't yet choose) AND
// A boolean cutOff, signifying whether the user is now past the cutoff time for students' choices
 getSoonestOppblockDay: function(callback) {
	// Gets all Oppblock days
	con.query('SELECT * FROM opp_block_day', function(err, results){
		if(!err){
			var uid_day = null;
			var closest = moment().add(1, 'y');
			for (var i=0; i<results.length; i++) {
				//	Loops to find soonest Oppblock
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				//	TO DO: SIMPLY THIS CODE
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and before the closest
				//	If so, replaces closest with the current
				if (curr.isBefore(closest) && curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			// 	Creates Cutoff time variables relative to closest oppblock, based on admin settings
			var studentCutoff = moment(closest.add({hours:settings["hours_close_student"].value_int}));
			var teacherCutoff = moment(closest.add({hours:settings["hours_close_teacher"].value_int}));

			//	Checks to see whether the date is before or after the student and teacher cutoff times
			if (moment().isSameOrAfter(teacherCutoff)) {
				if (moment().isSameOrAfter(studentCutoff)) {
					callback(uid_day, true);
				} else {
					callback(uid_day, false);
				}
			} else {
				callback(null, null);
			}
		} else {
			console.log("Error in finding the upcoming oppblock");
		}
	});
 },

 //	A middleware to determine whether an offering is full or not
 //	Used in the post request to make sure students don't sign up for closed offerings
 isOpenOffering:function(req,res,next){
 	con.query('SELECT max_size FROM offerings WHERE uid_offering', [req.body.choice], function(err, result) {
 		if(!err) {
 			//	Checks if the offering is full
		 	module.exports.isOfferingFull(req.body.uid_day, req.body.choice, result[0].max_size, function(truth) {
		 		if(truth == "able") {
		 			//	Keeps going if the offering is open
			 		return next();
			    } else {
			    	//	Redirects to student if the offering is full, thereby cancelling the student's form submission
			    	res.redirect('/student');
			 	}
		 	});
 		} else {
 			//	Renders an error page if one occured
			res.render('error.html', {err:err});
 		}
 	});
 },

 init: function(app) {
	app.get('/student', middleware.isStudent, function(req, res){
		// Gets Student's id from middleware
		var student = req.user.local[0];
		var uid_student = student.uid_student;

		// This query gets the student's first name for the display page, thereby checking whether the url contained a valid uid
		// This function finds the upcoming oppblock, whether it is time for students to choose, and whether it is past the cutoff time
		module.exports.getSoonestOppblockDay(function(uid_day, cutOff) {
		// Checks whether it is time for students to choose yet
			if (uid_day == null) {
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
			} else {
				// Knowing there is an upcoming oppblock day with choices, the system queries to find the student's current choice
				con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, currentChoice) { // only gets the uid not the name
					if(!err) {
						// Checks if the student is in the choice table at all, thereby seeing if he/she is excluded from the oppblock day
						if(currentChoice.length != 0) {
							//	Checks to see if the student hasn't chosen yet
							if (currentChoice[0].uid_offering == null) {
								// Checks to see if it is past the cutoff time for the students to choose
								if (cutOff) {
									// Renders the page with an admin's message for the student, as they have neglected to sign up.
									res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
								} else {
									// Gets all offerings for the user to choose from
									module.exports.getOfferings(uid_day, function(offerings) {
										// At last, renders the page with the lack of choice, and the choices table
										res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
									});
								}
							} else {
								//	Knowing the student has chosen, it gets the name of their choice
								con.query('SELECT * FROM offerings WHERE uid_offering = ?', [currentChoice[0].uid_offering], function(err, choice) {
									if(!err) {
										// Checks to see if it is past the cutoff time for the students to choose
										if (cutOff) {
											// Renders the page only with the user's current choice
											res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
										} else {
											// Gets all offerings for the user to choose from
											module.exports.getOfferings(uid_day, function(offerings) {
												// At last, renders the page with the current choice, and the choices table
												res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
											});
										}
									} else {
										res.render('error.html', {err:err});
									}
								});
							}
						} else {
							// Renders the page without any choices, since the student is excluded
							res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
						}
					} else {
						console.log("An error done occured.");
						res.render('error.html', {err:err});
					}
				});
			}
		});
	});

	//	The student post request serves to insert/update a student's choice in the database
	app.post('/student', middleware.isStudent, module.exports.isOpenOffering, function(req, res) {
		// Gets the student's uid, the uid of their offering of choice, and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_offering = req.body.choice;
		var uid_day = req.body.uid_day;

		// Makes sure the student has chosen something
		if(uid_offering != undefined) {
			// Updates their choice in the database
			con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [uid_offering, uid_student, uid_day], function(err, results) {
				if(!err) {
					//	Redirects back once the update has been carried out
					res.redirect('/student');
				} else {
					//	Renders an error page if one occured
					res.render('error.html', {err:err});
				}
			});
		} else {
			//	Redirects back if the student hasn't chosen anything
			res.redirect('/student');
		}

	});

	//	This post request is for when students are excluded wrongfully from an OppBlock Day
	app.post('/studentOverride', middleware.isStudent, function(req, res) {
		// Gets the student's uid and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_day = req.body.uid_day;

		// Overrides an excluded group by adding the student into the choice table
		con.query('INSERT INTO choices (uid_student, uid_day) values (?, ?)', [uid_student, uid_day], function(err) {
			if(!err) {
				//	Redirects back since the request has been carried out
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});
	return this;
 }
}
<commit_msg>issue-108 resolved<commit_after>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function (uid_day, uid_offering, callback) {
 	var numStud = 0;
 	con.query('SELECT students.uid_student FROM choices JOIN students ON choices.uid_student = students.uid_student WHERE uid_offering = ? AND uid_day = ?', [uid_offering, uid_day], function(err, students) {
 		if(!err) {
	 		for (var i = 0; i < students.length; i++) {
	 			numStud += 1;
	 		}
	 		callback(numStud);
 		} else {
 			console.log("Join Query Produced an Error.");
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, max_size, callback) {
    //	Gets the number of students in an offering
    module.exports.numStudents(uid_day, uid_offering, function(numStud) {
        //	Compares that number to the offering's maximum size
        if(numStud >= max_size) {
          callback("disabled");
        } else {
          callback("able");
        }
    });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list of Offering objects including a property for avalialability ('.disbaled')
 getOfferings: function (uid_day, callback) {
 	//	Join query to find a list of offerings on a certain day with the name of their teacher
 	con.query('SELECT * from offerings JOIN calendar on offerings.uid_offering = calendar.uid_offering JOIN teachers on teachers.uid_teacher = offerings.uid_teacher WHERE calendar.uid_day = ?', [uid_day], function(err, result) {
		//	Makes sure the join query didn't error or produce an empty set
		if (!err && result != undefined) {

			//	Loops through every offering to find whether or not it is full
			var j = 0;
		    for(var i = 0; i < result.length; i++) {
		      //	Uses isOfferingFull for every one, which will return either 'disabled' or 'able'
		      module.exports.isOfferingFull(uid_day, result[i].uid_offering, result[i].max_size, function(truth) {
				  //	Adds the availability of the offering as a property
				  result[j].disabled = truth;
				  j+=1;
				  //	Calls back the list once all the queries have run
				  if (j==result.length) {
					callback(result);
				  }
		      });
		    }
		} else {
			console.log("We're sorry. A join query produced an error and or an empty set.");
		}
	});
 },

// Takes in nothing
// Returns two values:
// A uid_day of the coming oppblock (null if the students can't yet choose) AND
// A boolean cutOff, signifying whether the user is now past the cutoff time for students' choices
 getSoonestOppblockDay: function(callback) {
	// Gets all Oppblock days
	con.query('SELECT * FROM opp_block_day', function(err, results){
		if(!err){
			var uid_day = null;
			var closest = moment().add(1, 'y');
			for (var i=0; i<results.length; i++) {
				//	Loops to find soonest Oppblock
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				//	TO DO: SIMPLY THIS CODE
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and before the closest
				//	If so, replaces closest with the current
				if (curr.isBefore(closest) && curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			// 	Creates Cutoff time variables relative to closest oppblock, based on admin settings
			var studentCutoff = moment(closest.add({hours:settings["hours_close_student"].value_int}));
			var teacherCutoff = moment(closest.add({hours:settings["hours_close_teacher"].value_int}));

			//	Checks to see whether the date is before or after the student and teacher cutoff times
			if (moment().isSameOrAfter(teacherCutoff)) {
				if (moment().isSameOrAfter(studentCutoff)) {
					callback(uid_day, true);
				} else {
					callback(uid_day, false);
				}
			} else {
				callback(null, null);
			}
		} else {
			console.log("Error in finding the upcoming oppblock");
		}
	});
 },

 //	A middleware to determine whether an offering is full or not
 //	Used in the post request to make sure students don't sign up for closed offerings
 isOpenOffering:function(req,res,next){
 	con.query('SELECT max_size FROM offerings WHERE uid_offering', [req.body.choice], function(err, result) {
 		if(!err && result != undefined && result.length != 0) {
 			//	Checks if the offering is full
		 	module.exports.isOfferingFull(req.body.uid_day, req.body.choice, result[0].max_size, function(truth) {
		 		if(truth == "able") {
		 			//	Keeps going if the offering is open
			 		return next();
			    } else {
			    	//	Redirects to student if the offering is full, thereby cancelling the student's form submission
			    	res.redirect('/student');
			 	}
		 	});
 		} else {
 			//	Renders an error page if one occured
			res.render('error.html', {err:err});
 		}
 	});
 },

 init: function(app) {
	app.get('/student', middleware.isStudent, function(req, res){
		// Gets Student's id from middleware
		var student = req.user.local[0];
		var uid_student = student.uid_student;

		// This query gets the student's first name for the display page, thereby checking whether the url contained a valid uid
		// This function finds the upcoming oppblock, whether it is time for students to choose, and whether it is past the cutoff time
		module.exports.getSoonestOppblockDay(function(uid_day, cutOff) {
		// Checks whether it is time for students to choose yet
			if (uid_day == null) {
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
			} else {
				// Knowing there is an upcoming oppblock day with choices, the system queries to find the student's current choice
				con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, currentChoice) { // only gets the uid not the name
					if(!err) {
						// Checks if the student is in the choice table at all, thereby seeing if he/she is excluded from the oppblock day
						if(currentChoice.length != 0) {
							//	Checks to see if the student hasn't chosen yet
							if (currentChoice[0].uid_offering == null) {
								// Checks to see if it is past the cutoff time for the students to choose
								if (cutOff) {
									// Renders the page with an admin's message for the student, as they have neglected to sign up.
									res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
								} else {
									// Gets all offerings for the user to choose from
									module.exports.getOfferings(uid_day, function(offerings) {
										// At last, renders the page with the lack of choice, and the choices table
										res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
									});
								}
							} else {
								//	Knowing the student has chosen, it gets the name of their choice
								con.query('SELECT * FROM offerings WHERE uid_offering = ?', [currentChoice[0].uid_offering], function(err, choice) {
									if(!err) {
										// Checks to see if it is past the cutoff time for the students to choose
										if (cutOff) {
											// Renders the page only with the user's current choice
											res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
										} else {
											// Gets all offerings for the user to choose from
											module.exports.getOfferings(uid_day, function(offerings) {
												// At last, renders the page with the current choice, and the choices table
												res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
											});
										}
									} else {
										res.render('error.html', {err:err});
									}
								});
							}
						} else {
							// Renders the page without any choices, since the student is excluded
							res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
						}
					} else {
						console.log("An error done occured.");
						res.render('error.html', {err:err});
					}
				});
			}
		});
	});

	//	The student post request serves to insert/update a student's choice in the database
	app.post('/student', middleware.isStudent, module.exports.isOpenOffering, function(req, res) {
		// Gets the student's uid, the uid of their offering of choice, and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_offering = req.body.choice;
		var uid_day = req.body.uid_day;

		// Makes sure the student has chosen something
		if(uid_offering != undefined) {
			// Updates their choice in the database
			con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [uid_offering, uid_student, uid_day], function(err, results) {
				if(!err) {
					//	Redirects back once the update has been carried out
					res.redirect('/student');
				} else {
					//	Renders an error page if one occured
					res.render('error.html', {err:err});
				}
			});
		} else {
			//	Redirects back if the student hasn't chosen anything
			res.redirect('/student');
		}

	});

	//	This post request is for when students are excluded wrongfully from an OppBlock Day
	app.post('/studentOverride', middleware.isStudent, function(req, res) {
		// Gets the student's uid and the current day uid
		var uid_student = req.user.local[0].uid_student;
		var uid_day = req.body.uid_day;

		// Overrides an excluded group by adding the student into the choice table
		con.query('INSERT INTO choices (uid_student, uid_day) values (?, ?)', [uid_student, uid_day], function(err) {
			if(!err) {
				//	Redirects back since the request has been carried out
				res.redirect('/student');
			} else {
				//	Renders an error page if one occured
				res.render('error.html', {err:err});
			}
		});
	});
	return this;
 }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node -r babel/register

import fs from 'fs'
import path from 'path'
import { graphql } from 'graphql'
import loadModels from '../models'
import * as config from '../config'
import loadSchema from '../db/schema'
import { introspectionQuery, printSchema } from 'graphql/utilities'

export async function updateSchema () {
  const models = loadModels(config.database)
  const Schema = loadSchema(models)

  const result = await graphql(Schema, introspectionQuery)
  if (result.errors) {
    console.error(
      'ERROR introspecting schema: ',
      JSON.stringify(result.errors, null, 2)
    )
  } else {
    fs.writeFileSync(
      path.join(__dirname, '../db/schema.json'),
      JSON.stringify(result, null, 2)
    )
  }

  fs.writeFileSync(
    path.join(__dirname, '../db/schema.graphql'),
    printSchema(Schema)
  )
}

if (require.main === module) {
  updateSchema().then(
    () => console.log('finished'),
    (err) => console.error('error', err)
  )
}
<commit_msg>Clean up update-schema script<commit_after>#!/usr/bin/env node -r babel/register

import fs from 'fs'
import path from 'path'
import { graphql } from 'graphql'
import loadModels from '../models'
import * as config from '../config'
import loadSchema from '../db/schema'
import { introspectionQuery, printSchema } from 'graphql/utilities'

export async function updateSchema () {
  const models = loadModels(config.database)
  const Schema = loadSchema(models)

  const result = await graphql(Schema, introspectionQuery)
  if (result.errors) {
    console.error(
      'ERROR introspecting schema:',
      JSON.stringify(result.errors, null, 2)
    )
    throw result.errors
  }

  await Promise.all([
    writeFilePromise(
      path.join(__dirname, '../db/schema.json'),
      JSON.stringify(result, null, 2)
    ),
    writeFilePromise(
      path.join(__dirname, '../db/schema.graphql'),
      printSchema(Schema)
    )
  ])
}

if (require.main === module) {
  updateSchema().then(
    () => console.log('finished'),
    (err) => console.error('error', err)
  )
}

function writeFilePromise (filePath, file) {
  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, file, err => {
      err ? reject(err) : resolve()
    })
  })
}
<|endoftext|>


<commit_before>/**
 * @license
 * Code City: Interpreter JS Tests
 *
 * Copyright 2017 Google Inc.
 * https://github.com/NeilFraser/CodeCity
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Benchmarks for JavaScript interpreter.
 * @author cpcallen@google.com (Christopher Allen)
 */
'use strict';

const fs = require('fs');
const path = require('path');
const util = require('util');

const Interpreter = require('../interpreter');
const {getInterpreter, startupFiles} = require('./interpreter_common');
const Serializer = require('../serialize');

/**
 * Run a benchmark of the interpreter being serialized/deserialized.
 * @param {!B} b The benchmark runner object.
 * @param {string} name The name of the test.
 * @param {string} src The code to be evaled before roundtripping.
 * @param {function(!Interpreter)=} initFunc Optional function to be
 *     called after creating new interpreter instance but before
 *     running src.  Can be used to insert extra native functions into
 *     the interpreter.  initFunc is called with the interpreter
 *     instance to be configured as its parameter.
 */
function runSerializationBench(b, name, src, initFunc) {
  for (let i = 0; i < 4; i++) {
    const intrp1 = new Interpreter();
    const intrp2 = new Interpreter();
    if (initFunc) {
      initFunc(intrp1);
      initFunc(intrp2);
    }
    const err = undefined;
    try {
      intrp1.createThreadForSrc(src);
      intrp1.run();
      intrp1.stop();
      b.start(name, i);
      const json = Serializer.serialize(intrp1);
      Serializer.deserialize(json, intrp2);
      b.end(name, i);
    } catch (err) {
      b.crash(name, util.format('%s\n%s', src, err.stack));
    }
  }
};

/**
 * Run a benchmark of the interpreter after being
 * serialized/deserialized.
 * @param {!B} b The benchmark runner object.
 * @param {string} name The name of the test.
 * @param {string} src The code to be evaled.
 */
function runInterpreterBench(b, name, src) {
  for (let i = 0; i < 4; i++) {
    const intrp1 = getInterpreter();
    const intrp2 = new Interpreter();
    try {
      intrp1.createThreadForSrc(src);
      intrp1.stop();
      const json = Serializer.serialize(intrp1);
      Serializer.deserialize(json, intrp2);
      // Deserialized interpreter was stopped, but we want to be able to
      // step/run it, so wake it up to PAUSED.
      intrp2.pause();
      b.start(name, i);
      intrp2.run();
      b.end(name, i);
    } catch (err) {
      b.crash(name, util.format('%s\n%s', src, err.stack));
    } finally {
      intrp2.stop();
    }
  }
};

/**
 * Run benchmarks roundtripping the interpreter.
 * @param {!B} b The test runner object.
 */
exports.benchRoundtrip = function(b) {
  let name = 'Roundtrip empty';
  let src = '';
  runSerializationBench(b, name, src);

  name = 'Roundtrip builtins';
  src =  Object.values(startupFiles).reduce((acc, cur) => acc += cur);
  runSerializationBench(b, name, src);

  name = 'Roundtrip demo';
  const demoDir = path.join(__dirname, '../../demo');
  const filenames = fs.readdirSync(demoDir);
  filenames.sort();
  src = '';
  for (const filename of filenames) {
    if (!(filename.match(/.js$/))) continue;
    src += fs.readFileSync(String(path.join(demoDir, filename)));
  }
  const fakeBuiltins = function(intrp) {
    // Hack to install stubs for builtins found in codecity.js.
    for (const bi of ['CC.log', 'CC.checkpoint', 'CC.shutdown']) {
      new intrp.NativeFunction({id: bi, length: 0,});
    }
  };
  runSerializationBench(b, name, src, fakeBuiltins);
};

/**
 * Run the fibbonacci10k benchmark.
 * @param {!B} b The test runner object.
 */
exports.benchResurrectedFibbonacci10k = function(b) {
  let name = 'ressurrectedFibonacci10k';
  let src = `
    var fibonacci = function(n, output) {
      var a = 1, b = 1, sum;
      for (var i = 0; i < n; i++) {
        output.push(a);
        sum = a + b;
        a = b;
        b = sum;
      }
    }
    for(var i = 0; i < 10000; i++) {
      var result = [];
      fibonacci(78, result);
    }
    result;
  `;
  runInterpreterBench(b, name, src);
};
<commit_msg>Show serialised JSON size in benchmarks<commit_after>/**
 * @license
 * Code City: Interpreter JS Tests
 *
 * Copyright 2017 Google Inc.
 * https://github.com/NeilFraser/CodeCity
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Benchmarks for JavaScript interpreter.
 * @author cpcallen@google.com (Christopher Allen)
 */
'use strict';

const fs = require('fs');
const path = require('path');
const util = require('util');

const Interpreter = require('../interpreter');
const {getInterpreter, startupFiles} = require('./interpreter_common');
const Serializer = require('../serialize');

/**
 * Run a benchmark of the interpreter being serialized/deserialized.
 * @param {!B} b The benchmark runner object.
 * @param {string} name The name of the test.
 * @param {string} src The code to be evaled before roundtripping.
 * @param {function(!Interpreter)=} initFunc Optional function to be
 *     called after creating new interpreter instance but before
 *     running src.  Can be used to insert extra native functions into
 *     the interpreter.  initFunc is called with the interpreter
 *     instance to be configured as its parameter.
 */
function runSerializationBench(b, name, src, initFunc) {
  for (let i = 0; i < 4; i++) {
    const intrp1 = new Interpreter();
    const intrp2 = new Interpreter();
    if (initFunc) {
      initFunc(intrp1);
      initFunc(intrp2);
    }
    const err = undefined;
    try {
      intrp1.createThreadForSrc(src);
      intrp1.run();
      intrp1.stop();
      b.start(name, i);
      const json = Serializer.serialize(intrp1);
      var len = JSON.stringify(json).length;
      Serializer.deserialize(json, intrp2);
      b.end(name + ' (' + Math.ceil(len / 1024) + 'kiB)', i);
    } catch (err) {
      b.crash(name, util.format('%s\n%s', src, err.stack));
    }
  }
};

/**
 * Run a benchmark of the interpreter after being
 * serialized/deserialized.
 * @param {!B} b The benchmark runner object.
 * @param {string} name The name of the test.
 * @param {string} src The code to be evaled.
 */
function runInterpreterBench(b, name, src) {
  for (let i = 0; i < 4; i++) {
    const intrp1 = getInterpreter();
    const intrp2 = new Interpreter();
    try {
      intrp1.createThreadForSrc(src);
      intrp1.stop();
      const json = Serializer.serialize(intrp1);
      Serializer.deserialize(json, intrp2);
      // Deserialized interpreter was stopped, but we want to be able to
      // step/run it, so wake it up to PAUSED.
      intrp2.pause();
      b.start(name, i);
      intrp2.run();
      b.end(name, i);
    } catch (err) {
      b.crash(name, util.format('%s\n%s', src, err.stack));
    } finally {
      intrp2.stop();
    }
  }
};

/**
 * Run benchmarks roundtripping the interpreter.
 * @param {!B} b The test runner object.
 */
exports.benchRoundtrip = function(b) {
  let name = 'Roundtrip empty';
  let src = '';
  runSerializationBench(b, name, src);

  name = 'Roundtrip builtins';
  src =  Object.values(startupFiles).reduce((acc, cur) => acc += cur);
  runSerializationBench(b, name, src);

  name = 'Roundtrip demo';
  const demoDir = path.join(__dirname, '../../demo');
  const filenames = fs.readdirSync(demoDir);
  filenames.sort();
  src = '';
  for (const filename of filenames) {
    if (!(filename.match(/.js$/))) continue;
    src += fs.readFileSync(String(path.join(demoDir, filename)));
  }
  const fakeBuiltins = function(intrp) {
    // Hack to install stubs for builtins found in codecity.js.
    for (const bi of ['CC.log', 'CC.checkpoint', 'CC.shutdown']) {
      new intrp.NativeFunction({id: bi, length: 0,});
    }
  };
  runSerializationBench(b, name, src, fakeBuiltins);
};

/**
 * Run the fibbonacci10k benchmark.
 * @param {!B} b The test runner object.
 */
exports.benchResurrectedFibbonacci10k = function(b) {
  let name = 'ressurrectedFibonacci10k';
  let src = `
    var fibonacci = function(n, output) {
      var a = 1, b = 1, sum;
      for (var i = 0; i < n; i++) {
        output.push(a);
        sum = a + b;
        a = b;
        b = sum;
      }
    }
    for(var i = 0; i < 10000; i++) {
      var result = [];
      fibonacci(78, result);
    }
    result;
  `;
  runInterpreterBench(b, name, src);
};
<|endoftext|>