<commit_before>var path = require('path');
var fs = require('fs');
var Page = require('./page');
var Component = require('./component');
var utils = require('./utils');
var $ = require('cheerio');
var async = require('async');

var basePaths = [path.resolve(path.dirname(require.main.filename))];
var allPaths = basePaths;

exports.controller = function (name) {
	var controllerPath = this.resolve('controllers/'+name+'.js');

	if(controllerPath){
		return require(controllerPath);
	}else{
		return false;
	}
}

exports.page = function(name,methodName,args,req,cb){
	var that = this;

		args = args || {};
		args.moduleName = name;
		methodName = methodName || 'get';

	var pagePath = (name.search('/') != -1) ? name : this.resolve('pages/'+name);

	if(pagePath){
		var page = new Page();
		this.moduleResourcesAndRender(page,pagePath,methodName,args,req,function(err){
			if(!err){
				that.renderComponentTags(page,function(err,newPage){
					cb.call(newPage,null,newPage);
				})
			}else{
				cb(err);
			}
		})
	}else{
		cb({error:'page ' + name + ' path not found'});
	}
}

exports.component = function(name,methodName,args,req,cb){
	var that = this;

		args = args || {};
		args.moduleName = name;

		methodName = methodName || 'init';

	var componentPath = (name.search('/') != -1) ? name : this.resolve('components/'+name);

	if(componentPath){
		var component = new Component();

		this.moduleResourcesAndRender(component,componentPath,methodName,args,req,function(err){
			if(!err){
				that.renderComponentTags(component,function(err,newComponent){
					cb.call(newComponent,null,newComponent);
				})
			}else{
				cb(err);
			}
		})

	}else{
		cb({error:'component ' + name + ' path not found'});
	}
}

exports.moduleResourcesAndRender = function(module,modulePath,methodName,args,req,cb){
	var that = this;

	module.config = utils.cloneObject(args);
	module.req = req;
	module.controller = this.moduleController(modulePath);

	module.setModelAndConfigFromMethod(methodName,function(err){
		if(!err){
			module.i18n = that.moduleI18n(modulePath,module.req.config.locale);
			module.template = module.config['data-template-string'] || that.moduleTemplate(modulePath,module.config['data-template']);
			module.render(function(){
				cb.call(module,null,module);
			});
		}else{
			cb(err);
		}
	});
}

exports.moduleController = function(modulePath){
	var controllerPath = path.resolve(modulePath,'controller');

	if(fs.existsSync(controllerPath+'.js')){
		return require(controllerPath);
	}else{
		return null;
	}
}
exports.moduleI18n = function(modulePath,locale){
	var i18nPath = path.resolve(modulePath,'i18n.json');

	if(fs.existsSync(i18nPath)){
		var i18n = require(i18nPath);
		return utils.mergei18n(i18n, locale || 'ar');
	}else{
		return null;
	}
}

exports.moduleTemplate = function(modulePath, templateName){
	templateName = templateName || 'template';

	var templatePath = path.resolve(modulePath,templateName + '.html');
	if(fs.existsSync(templatePath)){
		return fs.readFileSync(templatePath).toString();
	}else{
		return null;
	}
}

exports.resolve = function(item){
	var paths = this.paths();

	for (var i = 0; i < paths.length; i++) {
		var currentPath = paths[i]+ '/' +item;
		if(fs.existsSync(currentPath)){
			return currentPath;
		}
	};

	return false;
}

exports.renderComponentTags = function(module,cb){
	var that = this;

	var pageDom = $.load(module.html);
    var componentTags = pageDom("[data-component]");

    async.forEach(componentTags, function(elem, callback) {
        var componentElement = $(elem);
	    var componentName = componentElement.data('component');

		var componentArgs = utils.cloneObject(componentElement.attr());

	    that.component(componentName,'init',componentArgs,module.req,function(err,component){
	    	if(!err){
	    		componentElement.html(component.html);
	    	}
	    	callback();
	    })
    }, function(err) {
    	module.html = pageDom.html();
        cb(null,module);
    });
}

exports.paths = function(newPaths){
	if(newPaths){
		allPaths = basePaths.concat(newPaths);
	}
	return allPaths;
}<commit_msg>Commit message<commit_after>var path = require('path');
var fs = require('fs');
var Page = require('./page');
var Component = require('./component');
var utils = require('./utils');
var $ = require('cheerio');
var async = require('async');

var templateCacheEnable = false;
var templatesCache = {}

var basePaths = [path.resolve(path.dirname(require.main.filename))];
var allPaths = basePaths;
var objectSize = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

exports.controller = function (name) {
	var controllerPath = this.resolve('controllers/'+name+'.js');

	if(controllerPath){
		return require(controllerPath);
	}else{
		return false;
	}
}

exports.page = function(name,methodName,args,req,cb){
	var that = this;

		args = args || {};
		args.moduleName = name;
		methodName = methodName || 'get';

	var pagePath = (name.search('/') != -1) ? name : this.resolve('pages/'+name);

	if(pagePath){
		var page = new Page();
		this.moduleResourcesAndRender(page,pagePath,methodName,args,req,function(err){
			if(!err){
				that.renderComponentTags(page,function(err,newPage){
					cb.call(newPage,null,newPage);
				})
			}else{
				cb(err);
			}
		})
	}else{
		cb({error:'page ' + name + ' path not found'});
	}
}

exports.component = function(name,methodName,args,req,cb){
	var that = this;

		args = args || {};
		args.moduleName = name;

		methodName = methodName || 'init';

	var componentPath = (name.search('/') != -1) ? name : this.resolve('components/'+name);

	if(componentPath){
		var component = new Component();

		this.moduleResourcesAndRender(component,componentPath,methodName,args,req,function(err){
			if(!err){
				that.renderComponentTags(component,function(err,newComponent){
					cb.call(newComponent,null,newComponent);
				})
			}else{
				cb(err);
			}
		})

	}else{
		cb({error:'component ' + name + ' path not found'});
	}
}

exports.moduleResourcesAndRender = function(module,modulePath,methodName,args,req,cb){
	var that = this;

	module.config = utils.cloneObject(args);
	module.req = req;
	module.controller = this.moduleController(modulePath);

	module.setModelAndConfigFromMethod(methodName,function(err){
		if(!err){
			module.i18n = that.moduleI18n(modulePath,module.req.config.locale);
			module.template = module.config['data-template-string'] || that.moduleTemplate(modulePath,module.config['data-template']);
			module.render(function(){
				cb.call(module,null,module);
			});
		}else{
			cb(err);
		}
	});
}

exports.moduleController = function(modulePath){
	var controllerPath = path.resolve(modulePath,'controller');

	if(fs.existsSync(controllerPath+'.js')){
		return require(controllerPath);
	}else{
		return null;
	}
}
exports.moduleI18n = function(modulePath,locale){
	var i18nPath = path.resolve(modulePath,'i18n.json');

	if(fs.existsSync(i18nPath)){
		var i18n = require(i18nPath);
		return utils.mergei18n(i18n, locale || 'ar');
	}else{
		return null;
	}
}

exports.moduleTemplate = function(modulePath, templateName){
	templateName = templateName || 'template';
	var templateCode;
	var templatePath = path.resolve(modulePath,templateName + '.html');

	if(templateCacheEnable && templatesCache[templatePath]){
		return templatesCache[templatePath];
	}

	if(fs.existsSync(templatePath)){
		templateCode = fs.readFileSync(templatePath).toString();
		templatesCache[templatePath] = templateCode;
		return templateCode;
	}else{
		return null;
	}
}

exports.resolve = function(item){
	var paths = this.paths();

	for (var i = 0; i < paths.length; i++) {
		var currentPath = paths[i]+ '/' +item;
		if(fs.existsSync(currentPath)){
			return currentPath;
		}
	};

	return false;
}

exports.renderComponentTags = function(module,cb){
	var that = this;

	var pageDom = $.load(module.html);
    var componentTags = pageDom("[data-component]");

    async.forEach(componentTags, function(elem, callback) {
        var componentElement = $(elem);
	    var componentName = componentElement.data('component');

		var componentArgs = utils.cloneObject(componentElement.attr());

	    that.component(componentName,'init',componentArgs,module.req,function(err,component){
	    	if(!err){
	    		componentElement.html(component.html);
	    	}
	    	callback();
	    })
    }, function(err) {
    	module.html = pageDom.html();
        cb(null,module);
    });
}

exports.enableTemplateCache = function(){
	templateCacheEnable = true;
}

exports.paths = function(newPaths){
	if(newPaths){
		allPaths = basePaths.concat(newPaths);
	}
	return allPaths;
}<|endoftext|>


<commit_before>'use strict';

var net = require('net');
var dns = require('dns');
var IOServer = require('socket.io');
var util = require('../lib/utils/util');
var IP = require('../lib/utils/ip');
var BufferWriter = require('../lib/utils/writer');
var EventEmitter = require('events').EventEmitter;

var NAME_REGEX = /^[a-z0-9\-\.]+?\.(?:be|me|org|com|net|ch|de)$/i;

var TARGET = new Buffer(
  '0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
  'hex');

function WSProxy(options) {
  if (!(this instanceof WSProxy))
    return new WSProxy(options);

  EventEmitter.call(this);

  if (!options)
    options = {};

  this.options = options;
  this.target = options.target || TARGET;
  this.pow = options.pow === true;
  this.ports = options.ports || [];
  this.io = new IOServer();
  this.sockets = new WeakMap();

  this._init();
}

util.inherits(WSProxy, EventEmitter);

WSProxy.prototype._init = function _init() {
  var self = this;

  this.io.on('error', function(err) {
    self.emit('error', err);
  });

  this.io.on('connection', function(ws) {
    self._handleSocket(ws);
  });
};

WSProxy.prototype._handleSocket = function _handleSocket(ws) {
  var self = this;
  var state = new SocketState(this, ws);

  // Use a weak map to avoid
  // mutating the websocket object.
  this.sockets.set(ws, state);

  ws.emit('info', state.toInfo());

  ws.on('error', function(err) {
    self.emit('error', err);
  });

  ws.on('tcp connect', function(port, host, nonce) {
    self._handleConnect(ws, port, host, nonce);
  });

  ws.on('dns resolve', function(name, record, callback) {
    self._handleResolve(ws, name, record, callback);
  });
};

WSProxy.prototype._handleResolve = function _handleResolve(ws, name, record, callback) {
  if (typeof name !== 'string') {
    ws.disconnect();
    return;
  }

  if (typeof record !== 'string') {
    ws.disconnect();
    return;
  }

  if (typeof callback !== 'function') {
    ws.disconnect();
    return;
  }

  if (!NAME_REGEX.test(name) || name.length > 200) {
    this.log('Client sent a bad domain: %s.', name);
    ws.disconnect();
    return;
  }

  dns.resolve(name, record, function(err, result) {
    if (err) {
      callback({ message: err.message, code: err.code });
      return;
    }
    callback(null, result);
  });
};

WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce) {
  var self = this;
  var state = this.sockets.get(ws);
  var socket, pow;

  if (state.socket) {
    this.log('Client is trying to reconnect (%s).', state.host);
    return;
  }

  if (!util.isNumber(port)
      || typeof host !== 'string'
      || host.length === 0) {
    this.log('Client gave bad arguments (%s).', state.host);
    ws.emit('tcp close');
    ws.disconnect();
    return;
  }

  if (this.pow) {
    if (!util.isNumber(nonce)) {
      this.log('Client did not solve proof of work (%s).', state.host);
      ws.emit('tcp close');
      ws.disconnect();
      return;
    }

    pow = new BufferWriter();
    pow.writeU32(nonce);
    pow.writeBytes(state.snonce);
    pow.writeU32(port);
    pow.writeString(host, 'ascii');
    pow = pow.render();

    if (util.cmp(util.hash256(pow), this.target) > 0) {
      this.log('Client did not solve proof of work (%s).', state.host);
      ws.emit('tcp close');
      ws.disconnect();
      return;
    }
  }

  if (!/^[a-zA-Z0-9\.:\-]+$/.test(host)) {
    this.log('Client gave a bad host (%s).', state.host);
    ws.emit('tcp error', {
      message: 'EHOSTUNREACH',
      code: 'EHOSTUNREACH'
    });
    ws.disconnect();
    return;
  }

  if (IP.isPrivate(host)) {
    this.log('Client is trying to connect to a private ip (%s).', state.host);
    ws.emit('tcp error', {
      message: 'ENETUNREACH',
      code: 'ENETUNREACH'
    });
    ws.disconnect();
    return;
  }

  if (this.ports.indexOf(port) === -1) {
    this.log('Client is connecting to non-whitelist port (%s).', state.host);
    ws.emit('tcp error', {
      message: 'ENETUNREACH',
      code: 'ENETUNREACH'
    });
    ws.disconnect();
    return;
  }

  try {
    socket = state.connect(port, host);
    this.log('Connecting to %s (%s).', state.remoteHost, state.host);
  } catch (e) {
    this.log(e.message);
    this.log('Closing %s (%s).', state.remoteHost, state.host);
    ws.emit('tcp error', {
      message: 'ENETUNREACH',
      code: 'ENETUNREACH'
    });
    ws.disconnect();
    return;
  }

  socket.on('connect', function() {
    ws.emit('tcp connect', socket.remoteAddress, socket.remotePort);
  });

  socket.on('data', function(data) {
    ws.emit('tcp data', data.toString('hex'));
  });

  socket.on('error', function(err) {
    ws.emit('tcp error', {
      message: err.message,
      code: err.code || null
    });
  });

  socket.on('close', function() {
    self.log('Closing %s (%s).', state.remoteHost, state.host);
    ws.emit('tcp close');
    ws.disconnect();
  });

  ws.on('tcp data', function(data) {
    if (typeof data !== 'string')
      return;
    socket.write(new Buffer(data, 'hex'));
  });

  ws.on('disconnect', function() {
    socket.destroy();
  });
};

WSProxy.prototype.log = function log() {
  process.stdout.write('wsproxy: ');
  console.log.apply(console, arguments);
};

WSProxy.prototype.attach = function attach(server) {
  this.io.attach(server);
};

function SocketState(server, socket) {
  this.pow = server.pow;
  this.target = server.target;
  this.snonce = util.nonce(true);
  this.socket = null;
  this.host = IP.normalize(socket.conn.remoteAddress);
  this.remoteHost = null;
}

SocketState.prototype.toInfo = function toInfo() {
  return {
    pow: this.pow,
    target: this.target.toString('hex'),
    snonce: this.snonce.toString('hex')
  };
};

SocketState.prototype.connect = function connect(port, host) {
  this.socket = net.connect(port, host);
  this.remoteHost = IP.hostname(host, port);
  return this.socket;
};

module.exports = WSProxy;
<commit_msg>wsproxy: stricter validation.<commit_after>'use strict';

var net = require('net');
var dns = require('dns');
var IOServer = require('socket.io');
var util = require('../lib/utils/util');
var IP = require('../lib/utils/ip');
var BufferWriter = require('../lib/utils/writer');
var EventEmitter = require('events').EventEmitter;

var NAME_REGEX = /^[a-z0-9\-\.]+?\.(?:be|me|org|com|net|ch|de)$/i;

var TARGET = new Buffer(
  '0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
  'hex');

function WSProxy(options) {
  if (!(this instanceof WSProxy))
    return new WSProxy(options);

  EventEmitter.call(this);

  if (!options)
    options = {};

  this.options = options;
  this.target = options.target || TARGET;
  this.pow = options.pow === true;
  this.ports = options.ports || [];
  this.io = new IOServer();
  this.sockets = new WeakMap();

  this._init();
}

util.inherits(WSProxy, EventEmitter);

WSProxy.prototype._init = function _init() {
  var self = this;

  this.io.on('error', function(err) {
    self.emit('error', err);
  });

  this.io.on('connection', function(ws) {
    self._handleSocket(ws);
  });
};

WSProxy.prototype._handleSocket = function _handleSocket(ws) {
  var self = this;
  var state = new SocketState(this, ws);

  // Use a weak map to avoid
  // mutating the websocket object.
  this.sockets.set(ws, state);

  ws.emit('info', state.toInfo());

  ws.on('error', function(err) {
    self.emit('error', err);
  });

  ws.on('tcp connect', function(port, host, nonce) {
    self._handleConnect(ws, port, host, nonce);
  });

  ws.on('dns resolve', function(name, record, callback) {
    self._handleResolve(ws, name, record, callback);
  });
};

WSProxy.prototype._handleResolve = function _handleResolve(ws, name, record, callback) {
  if (typeof name !== 'string') {
    ws.disconnect();
    return;
  }

  if (typeof record !== 'string') {
    ws.disconnect();
    return;
  }

  if (typeof callback !== 'function') {
    ws.disconnect();
    return;
  }

  if (record !== 'A' && record !== 'AAAA') {
    this.log('Client sent a bad record type: %s.', record);
    ws.disconnect();
    return;
  }

  if (!NAME_REGEX.test(name) || name.length > 200) {
    this.log('Client sent a bad domain: %s.', name);
    ws.disconnect();
    return;
  }

  dns.resolve(name, record, function(err, result) {
    if (err) {
      callback({ message: err.message, code: err.code });
      return;
    }
    callback(null, result);
  });
};

WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce) {
  var self = this;
  var state = this.sockets.get(ws);
  var socket, pow;

  if (state.socket) {
    this.log('Client is trying to reconnect (%s).', state.host);
    return;
  }

  if (!util.isNumber(port)
      || typeof host !== 'string'
      || host.length === 0) {
    this.log('Client gave bad arguments (%s).', state.host);
    ws.emit('tcp close');
    ws.disconnect();
    return;
  }

  if (this.pow) {
    if (!util.isNumber(nonce)) {
      this.log('Client did not solve proof of work (%s).', state.host);
      ws.emit('tcp close');
      ws.disconnect();
      return;
    }

    pow = new BufferWriter();
    pow.writeU32(nonce);
    pow.writeBytes(state.snonce);
    pow.writeU32(port);
    pow.writeString(host, 'ascii');
    pow = pow.render();

    if (util.cmp(util.hash256(pow), this.target) > 0) {
      this.log('Client did not solve proof of work (%s).', state.host);
      ws.emit('tcp close');
      ws.disconnect();
      return;
    }
  }

  if (IP.version(host) === -1) {
    this.log('Client gave a bad host: %s (%s).', host, state.host);
    ws.emit('tcp error', {
      message: 'EHOSTUNREACH',
      code: 'EHOSTUNREACH'
    });
    ws.disconnect();
    return;
  }

  if (IP.isPrivate(host)) {
    this.log('Client is trying to connect to a private ip (%s).', state.host);
    ws.emit('tcp error', {
      message: 'ENETUNREACH',
      code: 'ENETUNREACH'
    });
    ws.disconnect();
    return;
  }

  if (this.ports.indexOf(port) === -1) {
    this.log('Client is connecting to non-whitelist port (%s).', state.host);
    ws.emit('tcp error', {
      message: 'ENETUNREACH',
      code: 'ENETUNREACH'
    });
    ws.disconnect();
    return;
  }

  try {
    socket = state.connect(port, host);
    this.log('Connecting to %s (%s).', state.remoteHost, state.host);
  } catch (e) {
    this.log(e.message);
    this.log('Closing %s (%s).', state.remoteHost, state.host);
    ws.emit('tcp error', {
      message: 'ENETUNREACH',
      code: 'ENETUNREACH'
    });
    ws.disconnect();
    return;
  }

  socket.on('connect', function() {
    ws.emit('tcp connect', socket.remoteAddress, socket.remotePort);
  });

  socket.on('data', function(data) {
    ws.emit('tcp data', data.toString('hex'));
  });

  socket.on('error', function(err) {
    ws.emit('tcp error', {
      message: err.message,
      code: err.code || null
    });
  });

  socket.on('close', function() {
    self.log('Closing %s (%s).', state.remoteHost, state.host);
    ws.emit('tcp close');
    ws.disconnect();
  });

  ws.on('tcp data', function(data) {
    if (typeof data !== 'string')
      return;
    socket.write(new Buffer(data, 'hex'));
  });

  ws.on('disconnect', function() {
    socket.destroy();
  });
};

WSProxy.prototype.log = function log() {
  process.stdout.write('wsproxy: ');
  console.log.apply(console, arguments);
};

WSProxy.prototype.attach = function attach(server) {
  this.io.attach(server);
};

function SocketState(server, socket) {
  this.pow = server.pow;
  this.target = server.target;
  this.snonce = util.nonce(true);
  this.socket = null;
  this.host = IP.normalize(socket.conn.remoteAddress);
  this.remoteHost = null;
}

SocketState.prototype.toInfo = function toInfo() {
  return {
    pow: this.pow,
    target: this.target.toString('hex'),
    snonce: this.snonce.toString('hex')
  };
};

SocketState.prototype.connect = function connect(port, host) {
  this.socket = net.connect(port, host);
  this.remoteHost = IP.hostname(host, port);
  return this.socket;
};

module.exports = WSProxy;
<|endoftext|>


<commit_before>/*
  Created by Sharynne Azhar - 9/9/2016
  Handles calendar methods
*/

var displayedMonth = 0;
var displayedWeek= {};

const months = [
  { 'month': 'August', 'numeric': 8, 'days': 31, 'firstDay': 1 },
  { 'month': 'September', 'numeric': 9, 'days': 30, 'firstDay': 4 },
  { 'month': 'October', 'numeric': 10, 'days': 31, 'firstDay': 6 },
  { 'month': 'November', 'numeric': 11, 'days': 30, 'firstDay': 2 },
  { 'month': 'December', 'numeric': 12, 'days': 31, 'firstDay': 4 },
  { 'month': 'January', 'numeric': 1, 'days': 31, 'firstDay': 0 },
  { 'month': 'February', 'numeric': 2, 'days': 28, 'firstDay': 3 },
  { 'month': 'March', 'numeric': 3, 'days': 31, 'firstDay': 3 },
  { 'month': 'April', 'numeric': 4, 'days': 30, 'firstDay': 6 },
  { 'month': 'May', 'numeric': 5, 'days': 30, 'firstDay': 1 }
];

let currentDate = new Date();
let selectedDate = currentDate;

/** Class representing a calendar. */
class Calendar {
  /**
  * Initializes the calendar views. Default view - Yearly
  */
  init() {
  	//this.globalSetup();

  	// The "current_month" value is to be used for both the month
  	// and the week view. Hence this bit was pulled out of both the
  	// methods to avoid repetition.
  	let current_month = months.filter(function(m) {
      return m.numeric === currentDate.getMonth() + 1;
    })[0];

    let current_date = currentDate.getDate();
    let current_dayOfWeek = currentDate.getDay();

    displayedMonth = function(current_month) {
    	for (var i = 0; i < 10; i++) {
    		if (current_month.numeric == months[i].numeric) {
    			return i;
    		}
    	}
    	return -1;
    }(current_month);

    displayedWeek= {mnth: current_month, dt: current_date, dy: current_dayOfWeek};

    this.createCalendar('year');
    this.populateYearCalendar();

    this.createCalendar('week');
    this.populateWeekCalendar(current_month, current_date, current_dayOfWeek);
    $('#week').hide();

    this.createCalendar('month');
    this.populateMonthCalendar(current_month);
    $('#month').hide();

    this.createCalendar('agenda');
    this.showAgenda();
    $('#agenda').hide();

    // Set default date in create event form
    $('input[type="date"]').val(moment().format('YYYY-MM-DD'));
  }

  /**
  * Creates a calendar element
  * @param {String} view - The calendar view type.
  */
  createCalendar(view) {
    $('.calendar').append('

');
  }

  /**
  * Populates the yearly calendar view with months and dates
  */
  populateYearCalendar() {
    $.each(months, function(index, month) {
      let calendar = '

' +
                     'Su	' + 'M	' +
                     'Tu	' + 'W	' +
                     'Th	' + 'F	' +
                     'Sa	' + '
';

      let cellCount = 1;
      for (let j = 0; j < month.firstDay; j++) {
          calendar += '	';
          cellCount++;
      }

      for (let i = 1; i <= month.days; i++) {
        let highlight = '';
        if (currentDate.getMonth() + 1 === month.numeric && currentDate.getDate() === i) {
          highlight = 'currentDate';
        }

        if (cellCount === 1) {
          calendar += '
';
        }

        calendar += '' + i + '	';
        cellCount++;

        if (cellCount === 8) {
          calendar += '
';
          cellCount = 1;
        }
      }

      calendar += '
';
      $('#year').append('

' + month.month + '
' + calendar + '
');
    });
  }

  /**
  * Populates the monthly calendar view with dates
  */
  populateMonthCalendar(month) {
    let calendar = '

' +
                   'Su	' + 'M	' +
                   'Tu	' + 'W	' +
                   'Th	' + 'F	' +
                   'Sa	' + '
';

    let cellCount = 1;
    for (let j = 0; j < month.firstDay; j++) {
        calendar += '	';
        cellCount++;
    }

    for (let i = 1; i <= month.days; i++) {
      let highlight = '';
      if (currentDate.getMonth() + 1 === month.numeric && currentDate.getDate() === i) {
        highlight = 'currentDate';
      }

      if (cellCount === 1) {
        calendar += '
';
      }

      calendar += '' + i + '	';
      cellCount++;

      if (cellCount === 8) {
        calendar += '
';
        cellCount = 1;
      }
    }

    calendar += '
';
    $('#month').html('

' + month.month + '
' + calendar + '
');
    $('#month .month').prepend('<button id= "nxt_btn" class="btn btn-danger" style="float:right;" onclick="calendar.nextMonth()">NEXT</button>');
    $('#month .month').prepend('<button id= "prv_btn" class="btn btn-danger" style="float:left;" onclick="calendar.prevMonth()">PREV</button>');
  }

  /**
  * Displays the next month in monthly calendar view
  */
  nextMonth() {
    if (displayedMonth != 9) {
      calendar.populateMonthCalendar(months[displayedMonth + 1]);
      displayedMonth += 1;
      if (displayedMonth == 9) {
        document.getElementById("prv_btn").className = "btn btn-danger disabled";
      }
    }
  }

  /**
  * Displays the previous month in monthly calendar view
  */
  prevMonth(){
    if (displayedMonth != 0) {
      calendar.populateMonthCalendar(months[displayedMonth - 1]);
      displayedMonth -= 1;
      if (displayedMonth == 0) {
        document.getElementById("prv_btn").className = "btn btn-danger disabled";
      }
    }
  }

  /**
  * Populates the weekly calendar view with dates
  */
  populateWeekCalendar(month, date, dayOfWeek) {
    let calendar = '

' +
                   'Su	' + 'M	' +
                   'Tu	' + 'W	' +
                   'Th	' + 'F	' +
                   'Sa	' + '

';

    let startOfWeek = date - dayOfWeek;
    let endOfWeek = date + (7 - dayOfWeek);

    for (let i = startOfWeek; i < endOfWeek; i++) {
    	if (i < 1 || i > month.days) {
    		calendar += "	";
    	} else {
    		let highlight = '';
    		if (currentDate.getMonth() + 1 === month.numeric && currentDate.getDate() === i) highlight = 'currentDate';
    		calendar += '' + i + '	';
    	}
    }

    calendar += '

';
    $('#week').html('

' + month.month + '
' + calendar + '
');
    $('#week .week').prepend('<button id="nxt_btn_week" class="btn btn-danger" style="float:right;" onclick="calendar.nextWeek()">NEXT</button>');
    $('#week .week').prepend('<button id="prv_btn_week" class="btn btn-danger" style="float:left;" onclick="calendar.prevWeek()">PREV</button>');
  }

  /**
  * Displays the next week in weekly calendar view
  */
  nextWeek() {
    let month = displayedWeek.mnth;
    let date = displayedWeek.dt- displayedWeek.dy;
    let dayOfWeek = 0;
    calendar.populateWeekCalendar(month, date + 7, dayOfWeek);
    displayedWeek= {mnth: month, dt: date+7, dy: dayOfWeek};
  }

  /**
  * Displays the previous week in weekly calendar view
  */
  prevWeek() {
    let month = displayedWeek.mnth;
    let date = displayedWeek.dt- displayedWeek.dy;
    let dayOfWeek = 0;
    calendar.populateWeekCalendar(month, date - 7, dayOfWeek);
    displayedWeek= {mnth: month, dt: date-7, dy: dayOfWeek};
  }

  /**
  * Shows the Agenda view with a list of events
  */
  showAgenda() {
    let agenda = '
' +
                 '
' +
                 '
Agenda

' +
                 '
';
    $.ajax({
      url: 'api/dbSetup.php',
      data: '',
      dataType: 'json',
      success: function(data) {
        $.each(data, function(index, event) {
          if (event.start_date > currentDate.toISOString().slice(0,10)) {
            $('#agenda .list-group').append(
              '
' +
              '
' + event.event_name + '
' +
              '
' + event.event_desc + '
' +
              '
'
            );
            if (event.start_date != '0000-00-00') {
              $('.' + event.event_id).append(
                '
' +
                moment(event.start_date, "YYYY-MM-DD").format("ddd, MMM D YYYY") +
                '
'
              );
            }
            if (event.end_date != '0000-00-00') {
              $('.' + event.event_id).append(
                '
' +
                moment(event.end_date, "YYYY-MM-DD").format("ddd, MMM D YYYY") +
                '
');
            }
            $('.' + event.event_id).append(
              '
' +
              moment(event.start_time, "HH-mm-ss").format("h:mm A") +
              '
');
            if (event.start_time != event.end_time) {
              $('.' + event.event_id).append(
                '
' +
                moment(event.end_time, "HH-mm-ss").format("h:mm A") +
                '
');
            }
          }
        });
      }
    });
    agenda += '

';
    $('#agenda').html(agenda);
  }
}
<commit_msg>show events on current date on the agenda too<commit_after>/*
  Created by Sharynne Azhar - 9/9/2016
  Handles calendar methods
*/

var displayedMonth = 0;
var displayedWeek= {};

const months = [
  { 'month': 'August', 'numeric': 8, 'days': 31, 'firstDay': 1 },
  { 'month': 'September', 'numeric': 9, 'days': 30, 'firstDay': 4 },
  { 'month': 'October', 'numeric': 10, 'days': 31, 'firstDay': 6 },
  { 'month': 'November', 'numeric': 11, 'days': 30, 'firstDay': 2 },
  { 'month': 'December', 'numeric': 12, 'days': 31, 'firstDay': 4 },
  { 'month': 'January', 'numeric': 1, 'days': 31, 'firstDay': 0 },
  { 'month': 'February', 'numeric': 2, 'days': 28, 'firstDay': 3 },
  { 'month': 'March', 'numeric': 3, 'days': 31, 'firstDay': 3 },
  { 'month': 'April', 'numeric': 4, 'days': 30, 'firstDay': 6 },
  { 'month': 'May', 'numeric': 5, 'days': 30, 'firstDay': 1 }
];

let currentDate = new Date();
let selectedDate = currentDate;

/** Class representing a calendar. */
class Calendar {
  /**
  * Initializes the calendar views. Default view - Yearly
  */
  init() {
  	//this.globalSetup();

  	// The "current_month" value is to be used for both the month
  	// and the week view. Hence this bit was pulled out of both the
  	// methods to avoid repetition.
  	let current_month = months.filter(function(m) {
      return m.numeric === currentDate.getMonth() + 1;
    })[0];

    let current_date = currentDate.getDate();
    let current_dayOfWeek = currentDate.getDay();

    displayedMonth = function(current_month) {
    	for (var i = 0; i < 10; i++) {
    		if (current_month.numeric == months[i].numeric) {
    			return i;
    		}
    	}
    	return -1;
    }(current_month);

    displayedWeek= {mnth: current_month, dt: current_date, dy: current_dayOfWeek};

    this.createCalendar('year');
    this.populateYearCalendar();

    this.createCalendar('week');
    this.populateWeekCalendar(current_month, current_date, current_dayOfWeek);
    $('#week').hide();

    this.createCalendar('month');
    this.populateMonthCalendar(current_month);
    $('#month').hide();

    this.createCalendar('agenda');
    this.showAgenda();
    $('#agenda').hide();

    // Set default date in create event form
    $('input[type="date"]').val(moment().format('YYYY-MM-DD'));
  }

  /**
  * Creates a calendar element
  * @param {String} view - The calendar view type.
  */
  createCalendar(view) {
    $('.calendar').append('

');
  }

  /**
  * Populates the yearly calendar view with months and dates
  */
  populateYearCalendar() {
    $.each(months, function(index, month) {
      let calendar = '

' +
                     'Su	' + 'M	' +
                     'Tu	' + 'W	' +
                     'Th	' + 'F	' +
                     'Sa	' + '
';

      let cellCount = 1;
      for (let j = 0; j < month.firstDay; j++) {
          calendar += '	';
          cellCount++;
      }

      for (let i = 1; i <= month.days; i++) {
        let highlight = '';
        if (currentDate.getMonth() + 1 === month.numeric && currentDate.getDate() === i) {
          highlight = 'currentDate';
        }

        if (cellCount === 1) {
          calendar += '
';
        }

        calendar += '' + i + '	';
        cellCount++;

        if (cellCount === 8) {
          calendar += '
';
          cellCount = 1;
        }
      }

      calendar += '
';
      $('#year').append('

' + month.month + '
' + calendar + '
');
    });
  }

  /**
  * Populates the monthly calendar view with dates
  */
  populateMonthCalendar(month) {
    let calendar = '

' +
                   'Su	' + 'M	' +
                   'Tu	' + 'W	' +
                   'Th	' + 'F	' +
                   'Sa	' + '
';

    let cellCount = 1;
    for (let j = 0; j < month.firstDay; j++) {
        calendar += '	';
        cellCount++;
    }

    for (let i = 1; i <= month.days; i++) {
      let highlight = '';
      if (currentDate.getMonth() + 1 === month.numeric && currentDate.getDate() === i) {
        highlight = 'currentDate';
      }

      if (cellCount === 1) {
        calendar += '
';
      }

      calendar += '' + i + '	';
      cellCount++;

      if (cellCount === 8) {
        calendar += '
';
        cellCount = 1;
      }
    }

    calendar += '
';
    $('#month').html('

' + month.month + '
' + calendar + '
');
    $('#month .month').prepend('<button id= "nxt_btn" class="btn btn-danger" style="float:right;" onclick="calendar.nextMonth()">NEXT</button>');
    $('#month .month').prepend('<button id= "prv_btn" class="btn btn-danger" style="float:left;" onclick="calendar.prevMonth()">PREV</button>');
  }

  /**
  * Displays the next month in monthly calendar view
  */
  nextMonth() {
    if (displayedMonth != 9) {
      calendar.populateMonthCalendar(months[displayedMonth + 1]);
      displayedMonth += 1;
      if (displayedMonth == 9) {
        document.getElementById("prv_btn").className = "btn btn-danger disabled";
      }
    }
  }

  /**
  * Displays the previous month in monthly calendar view
  */
  prevMonth(){
    if (displayedMonth != 0) {
      calendar.populateMonthCalendar(months[displayedMonth - 1]);
      displayedMonth -= 1;
      if (displayedMonth == 0) {
        document.getElementById("prv_btn").className = "btn btn-danger disabled";
      }
    }
  }

  /**
  * Populates the weekly calendar view with dates
  */
  populateWeekCalendar(month, date, dayOfWeek) {
    let calendar = '

' +
                   'Su	' + 'M	' +
                   'Tu	' + 'W	' +
                   'Th	' + 'F	' +
                   'Sa	' + '

';

    let startOfWeek = date - dayOfWeek;
    let endOfWeek = date + (7 - dayOfWeek);

    for (let i = startOfWeek; i < endOfWeek; i++) {
    	if (i < 1 || i > month.days) {
    		calendar += "	";
    	} else {
    		let highlight = '';
    		if (currentDate.getMonth() + 1 === month.numeric && currentDate.getDate() === i) highlight = 'currentDate';
    		calendar += '' + i + '	';
    	}
    }

    calendar += '

';
    $('#week').html('

' + month.month + '
' + calendar + '
');
    $('#week .week').prepend('<button id="nxt_btn_week" class="btn btn-danger" style="float:right;" onclick="calendar.nextWeek()">NEXT</button>');
    $('#week .week').prepend('<button id="prv_btn_week" class="btn btn-danger" style="float:left;" onclick="calendar.prevWeek()">PREV</button>');
  }

  /**
  * Displays the next week in weekly calendar view
  */
  nextWeek() {
    let month = displayedWeek.mnth;
    let date = displayedWeek.dt- displayedWeek.dy;
    let dayOfWeek = 0;
    calendar.populateWeekCalendar(month, date + 7, dayOfWeek);
    displayedWeek= {mnth: month, dt: date+7, dy: dayOfWeek};
  }

  /**
  * Displays the previous week in weekly calendar view
  */
  prevWeek() {
    let month = displayedWeek.mnth;
    let date = displayedWeek.dt- displayedWeek.dy;
    let dayOfWeek = 0;
    calendar.populateWeekCalendar(month, date - 7, dayOfWeek);
    displayedWeek= {mnth: month, dt: date-7, dy: dayOfWeek};
  }

  /**
  * Shows the Agenda view with a list of events
  */
  showAgenda() {
    let agenda = '
' +
                 '
' +
                 '
Agenda

' +
                 '
';
    $.ajax({
      url: 'api/dbSetup.php',
      data: '',
      dataType: 'json',
      success: function(data) {
        $.each(data, function(index, event) {
          if (event.start_date >= currentDate.toISOString().slice(0,10)) {
            $('#agenda .list-group').append(
              '
' +
              '
' + event.event_name + '
' +
              '
' + event.event_desc + '
' +
              '
'
            );
            if (event.start_date != '0000-00-00') {
              $('.' + event.event_id).append(
                '
' +
                moment(event.start_date, "YYYY-MM-DD").format("ddd, MMM D YYYY") +
                '
'
              );
            }
            if (event.end_date != '0000-00-00') {
              $('.' + event.event_id).append(
                '
' +
                moment(event.end_date, "YYYY-MM-DD").format("ddd, MMM D YYYY") +
                '
');
            }
            $('.' + event.event_id).append(
              '
' +
              moment(event.start_time, "HH-mm-ss").format("h:mm A") +
              '
');
            if (event.start_time != event.end_time) {
              $('.' + event.event_id).append(
                '
' +
                moment(event.end_time, "HH-mm-ss").format("h:mm A") +
                '
');
            }
          }
        });
      }
    });
    agenda += '

';
    $('#agenda').html(agenda);
  }
}
<|endoftext|>


<commit_before>'use strict';

var forEach = require('lodash/collection/forEach');

/**
 * A handler that implements reversible replacing of shapes.
 * Internally the old shape will be removed and the new shape will be added.
 *
 *
 * @class
 * @constructor
 *
 * @param {canvas} Canvas
 */
function ReplaceShapeHandler(modeling, rules) {
  this._modeling = modeling;
  this._rules = rules;
}

ReplaceShapeHandler.$inject = [ 'modeling', 'rules' ];

module.exports = ReplaceShapeHandler;

////// api /////////////////////////////////////////

/**
 * Replaces a shape with an replacement Element.
 *
 * The newData object should contain type, x, y.
 *
 * If possible also the incoming/outgoing connection
 * will be restored.
 *
 * @param {Object} context
 */
 ReplaceShapeHandler.prototype.preExecute = function(context) {

  var modeling = this._modeling,
      rules = this._rules;

  var oldShape = context.oldShape,
      newData = context.newData,
      newShape;

  var pos = {
    x: newData.x,
    y: newData.y
  };

  newShape = context.newShape = modeling.createShape(newData, pos, oldShape.parent);

  var incoming = oldShape.incoming,
      outgoing = oldShape.outgoing;

  forEach(incoming, function(connection) {
    var lastIndex = connection.waypoints.length - 1;
    if (canConnect(connection.source, newShape)) {
      modeling.reconnectEnd(connection, newShape, connection.waypoints[lastIndex]);
    }
  });

  forEach(outgoing, function(connection) {
    if (canConnect(newShape, connection.target)) {
      modeling.reconnectStart(connection, newShape, connection.waypoints[0]);
    }
  });

  return context.newShape;

  function canConnect(source, target) {

    return rules.allowed('connection.create', {
      source: source,
      target: target
    });
  }
};

ReplaceShapeHandler.prototype.execute = function(context) {
};

ReplaceShapeHandler.prototype.postExecute = function(context) {

  var modeling = this._modeling;

  var oldShape = context.oldShape;

  modeling.removeShape(oldShape);
};

ReplaceShapeHandler.prototype.revert = function(context) {
};
<commit_msg>fix(modeling): reconnect was moved to execute phase<commit_after>'use strict';

var forEach = require('lodash/collection/forEach');

/**
 * A handler that implements reversible replacing of shapes.
 * Internally the old shape will be removed and the new shape will be added.
 *
 *
 * @class
 * @constructor
 *
 * @param {canvas} Canvas
 */
function ReplaceShapeHandler(modeling, rules) {
  this._modeling = modeling;
  this._rules = rules;
}

ReplaceShapeHandler.$inject = [ 'modeling', 'rules' ];

module.exports = ReplaceShapeHandler;

////// api /////////////////////////////////////////

/**
 * Replaces a shape with an replacement Element.
 *
 * The newData object should contain type, x, y.
 *
 * If possible also the incoming/outgoing connection
 * will be restored.
 *
 * @param {Object} context
 */
 ReplaceShapeHandler.prototype.preExecute = function(context) {

  var modeling = this._modeling;

  var oldShape = context.oldShape,
      newData = context.newData,
      newShape;

  var pos = {
    x: newData.x,
    y: newData.y
  };

  newShape = context.newShape = modeling.createShape(newData, pos, oldShape.parent);

  return context.newShape;
};

ReplaceShapeHandler.prototype.execute = function(context) {

  var modeling = this._modeling,
         rules = this._rules;

  var oldShape = context.oldShape,
      newShape = context.newShape,
      incoming = oldShape.incoming,
      outgoing = oldShape.outgoing;

  forEach(incoming, function(connection) {
    var lastIndex = connection.waypoints.length - 1;
    if (canConnect(connection.source, newShape)) {
      modeling.reconnectEnd(connection, newShape, connection.waypoints[lastIndex]);
    }
  });

  forEach(outgoing, function(connection) {
    if (canConnect(newShape, connection.target)) {
      modeling.reconnectStart(connection, newShape, connection.waypoints[0]);
    }
  });

  function canConnect(source, target) {

    return rules.allowed('connection.create', {
      source: source,
      target: target
    });
  }
};

ReplaceShapeHandler.prototype.postExecute = function(context) {

  var modeling = this._modeling;

  var oldShape = context.oldShape;

  modeling.removeShape(oldShape);
};

ReplaceShapeHandler.prototype.revert = function(context) {
};
<|endoftext|>


<commit_before>// Command regexp
const reCMD = /^\/([0-9а-я\w\d\_\-]+)/;

// Message types
const MESSAGE_TYPES = [
    'edit_date',  'forward_date',
    'text', 'audio', 'voice', 'document', 'photo',
    'sticker', 'video', 'contact', 'location', 'venue',
    'new_chat_member', 'left_chat_member', 'new_chat_title',
    'new_chat_photo', 'delete_chat_photo', 'group_chat_created',
    'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id',
    'migrate_from_chat_id', 'pinned_message'
];

const SHORTCUTS = {
    edit_date: 'edit',
    forward_date: 'forward',
    new_chat_member: 'userJoined',
    left_chat_member: 'userLeft',
    new_chat_title: 'newTitle',
    new_chat_photo: 'newPhoto',
    delete_chat_photo: 'deletePhoto',
    pinned_message: 'pinnedMessage',
    group_chat_created: 'groupCreated',
    channel_chat_created: 'channelCreated',
    supergroup_chat_created: 'supergroupCreated',
    migrate_to_chat_id: 'migrateTo',
    migrate_from_chat_id: 'migrateFrom'
};

// Update type functions
const updateFunctions = {

    // Message
    message(update, props) {

        // Set promise
        var promise = Promise.resolve();

        // Run global message mod
        let mod = this.modRun('message', {message: update, props});

        update = mod.message;
        props = mod.props;
        promise = promise.then(() => mod.promise);

        for (let type of MESSAGE_TYPES) {

            // Check for Telegram API documented types
            if (!(type in update)) continue;

            // Shortcut
            if (SHORTCUTS[type]) type = SHORTCUTS[type];

            // Set message type
            props.type = type;

            // Run message type mod
            mod = this.modRun(type, {message: update, props});

            update = mod.message;
            props = mod.props;
            promise = promise.then(() => mod.promise);

            // Send type event
            promise = promise.then(() => this.event(['*', type], update, props));

            // Check for command
            if (type == 'text') {

                const match = reCMD.exec(update.text);
                if (!match) continue;

                // Command found
                props.type = 'command';
                props.match = update.text.split(' ');
                promise = promise.then(() => {
                    return this.event(['/*', '/' + match[1]], update, props);
                });

            }

        }

        return promise;
    },

    // Edited message
    edited_message(update, props) {
        return updateFunctions.message.call(this, update, props);
    },

    // Inline query
    inline_query(update, props) {
        props.type = 'inlineQuery';
        return this.event('inlineQuery', update, props);
    },

    // Inline choice
    chosen_inline_result(update, props) {
        props.type = 'inlineChoice';
        return this.event('inlineChoice', update, props);
    },

    // Callback query
    callback_query(update, props) {
        props.type = 'callbackQuery';
        return this.event('callbackQuery', update, props);
    }

};

module.exports = updateFunctions;
<commit_msg>Fix duplicate "any" events<commit_after>// Command regexp
const reCMD = /^\/([0-9а-я\w\d\_\-]+)/;

// Message types
const MESSAGE_TYPES = [
    'edit_date',  'forward_date',
    'text', 'audio', 'voice', 'document', 'photo',
    'sticker', 'video', 'contact', 'location', 'venue',
    'new_chat_member', 'left_chat_member', 'new_chat_title',
    'new_chat_photo', 'delete_chat_photo', 'group_chat_created',
    'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id',
    'migrate_from_chat_id', 'pinned_message'
];

const SHORTCUTS = {
    edit_date: 'edit',
    forward_date: 'forward',
    new_chat_member: 'userJoined',
    left_chat_member: 'userLeft',
    new_chat_title: 'newTitle',
    new_chat_photo: 'newPhoto',
    delete_chat_photo: 'deletePhoto',
    pinned_message: 'pinnedMessage',
    group_chat_created: 'groupCreated',
    channel_chat_created: 'channelCreated',
    supergroup_chat_created: 'supergroupCreated',
    migrate_to_chat_id: 'migrateTo',
    migrate_from_chat_id: 'migrateFrom'
};

// Update type functions
const updateFunctions = {

    // Message
    message(update, props) {

        // Any event status: ['*', '/*']
        let anyEventFlags = [false, false];

        let promise = Promise.resolve();
        let mod = this.modRun('message', {message: update, props});

        update = mod.message;
        props = mod.props;
        promise = promise.then(() => mod.promise);

        for (let type of MESSAGE_TYPES) {

            // Check for Telegram API documented types
            if (!(type in update)) continue;

            // Shortcut
            if (SHORTCUTS[type]) type = SHORTCUTS[type];

            // Set message type
            props.type = type;

            // Run message type mod
            mod = this.modRun(type, {message: update, props});

            update = mod.message;
            props = mod.props;
            promise = promise.then(() => mod.promise);

            const eventList = [type];
            if (!anyEventFlags[0]) {
                eventList.push('*');
                anyEventFlags[0] = true;
            }

            promise = promise.then(() => {
                return this.event(eventList, update, props);
            });

            // Check for command
            if (type == 'text') {

                const match = reCMD.exec(update.text);
                if (!match) continue;

                // Command found
                props.type = 'command';

                const eventList = ['/' + match[1]];
                if (!anyEventFlags[1]) {
                    eventList.push(['/*']);
                    anyEventFlags[1] = true;
                }

                promise = promise.then(() => {
                    return this.event(eventList, update, props);
                });

            }

        }

        return promise;
    },

    // Edited message
    edited_message(update, props) {
        return updateFunctions.message.call(this, update, props);
    },

    // Inline query
    inline_query(update, props) {
        props.type = 'inlineQuery';
        return this.event('inlineQuery', update, props);
    },

    // Inline choice
    chosen_inline_result(update, props) {
        props.type = 'inlineChoice';
        return this.event('inlineChoice', update, props);
    },

    // Callback query
    callback_query(update, props) {
        props.type = 'callbackQuery';
        return this.event('callbackQuery', update, props);
    }

};

module.exports = updateFunctions;
<|endoftext|>


<commit_before>var setup = require('./test_setup');
var should = require('chai').should();
var serverbone = require('..');
var ACL = serverbone.acl.ACL;
var ACLModel = setup.ACLModel;
var ACLCollection = setup.ACLCollection;
var ACLUserCollection = setup.ACLUserCollection;
var SystemUser = setup.SystemUser;
var when = require('when');
var sequence = require('when/sequence');

describe('Test ACL', function () {
  describe('Access Roles', function () {
    var acl;

    before(function () {
      acl = new ACL({
        'owner': ['write', 'read', 'update'],
        '*': ['read']
      });
    });

    after(function (next) {
      setTimeout(next, 50);
    });

    it('should be possible to make ACL assertions agains roles and actions', function () {
      acl.assert('owner', 'write').should.equal(true);
      acl.assert('public', 'write').should.equal(false);
      acl.assert('owner', 'delete').should.equal(false);
      acl.assert('read').should.equal(true);
      acl.assert('write').should.equal(false);
    });

    it('should be possible to add more rules with .allow', function () {
      acl.grant({
        'owner': ['delete'],
        'admin': ['*']
      });
      acl.assert('admin', 'write').should.equal(true);
      acl.assert('admin', 'read').should.equal(true);
      acl.assert('admin', 'nonexisting').should.equal(true);
      acl.assert('owner', 'delete').should.equal(true);
    });

    it('should be possible to grant and revoke access', function () {
      acl.grant({
        'tester': ['read', 'write'],
        'owner': ['read', 'write', 'delete']
      });
      acl.assert('owner', 'delete').should.equal(true);
      acl.revoke('owner');
      acl.assert('owner', 'delete').should.equal(false);
      acl.grant({
        'owner': ['delete']
      });
      acl.assert('owner', 'delete').should.equal(true);
      acl.revoke(['owner', 'user', 'tester']);
      acl.assert('owner', 'delete').should.equal(false);
    });

    it('should recognice the "*" selector in roles and permissions', function () {
      acl.grant({
        'test': '*'
      });
      acl.assert('test', 'anything').should.equal(true);
      acl.assert('test2', 'anything').should.equal(false);
      acl.grant({
        '*': 'abolish'
      });
      acl.assert('anyone', 'abolish').should.equal(true);
      acl.assert('anyone', 'destroye').should.equal(false);
    });

    describe('ACLModel', function () {
      var user, admin, model, users, actor, aclmodel;

      before(function(next) {
        setup.setupDbs(function() {
          users = new ACLUserCollection(null, {actor: SystemUser});
          users.create().done(function(model) {
            user = model;
            users.create(null).done(function(adm) {
              admin = adm;
              next();
            }, next);
          }, next);
        });
      });

      after(function(next) {
        setup.clearDb();
        setTimeout(next, 50);
      });

      beforeEach(function() {
        actor = new ACLModel({id: 1234});
        aclmodel = new ACLModel({user_id: 1234}, {actor: SystemUser});
        return actor.save();
      });

      it('should set actor and action on fetch', function(next) {
        var options = {};
        aclmodel.save().done(function() {
          aclmodel.fetch(options).done(function() {
            options.action.should.equal('read');
            options.should.have.property('actor');
            aclmodel = new ACLModel({id: aclmodel.id}, options);
              aclmodel.fetch(options).done(function() {
              options.action.should.equal('read');
              options.should.have.property('actor');
              next();
            });
          });
        });
      });

      it('should set actor and action on save', function() {
        var opt = {};
        function destroy() {
          return aclmodel
            .destroy(opt)
            .then(function() {
            });
        }
        function testOpts() {
          return aclmodel
            .save(null, opt)
            .then(function() {
              opt.action.should.equal('create');
              opt.should.have.property('actor');
            });
        }
        function saveAsSystem() {
          aclmodel = new ACLModel();
          opt = {actor: SystemUser};
          return aclmodel
            .save(null, opt)
            .then(function() {
              opt.action.should.equal('create');
              opt.should.have.property('actor');
            });
        }
        function updateAsSystem() {
          opt = {actor: SystemUser};
          aclmodel = new ACLModel({id: 123123}, {actor: SystemUser});
          return aclmodel
            .save(null, opt)
            .then(function() {
              opt.action.should.equal('update');
              opt.should.have.property('actor');
            });
        }

        return sequence([
          testOpts,
          destroy,
          saveAsSystem,
          destroy,
          updateAsSystem,
          destroy
        ]);
      });

      it('should set actor and action on destroy', function() {
        var options = {actor: SystemUser};
        return aclmodel.destroy(options).then(function() {
          options.action.should.equal('destroy');
          options.should.have.property('actor');
          options = {actor: SystemUser};
          aclmodel = new ACLModel(null, {actor: SystemUser});

          return aclmodel.save(null, options).then(function() {
            options = {actor: SystemUser};
            return aclmodel.destroy(options).then(function() {
              options.action.should.equal('destroy');
              options.should.have.property('actor');
              aclmodel = new ACLModel({id: 123123}, {actor: SystemUser});
              return aclmodel.save(null, options).then(function() {
                options = {actor: SystemUser};
                return aclmodel.destroy(options).then(function() {
                  options.action.should.equal('destroy');
                  options.should.have.property('actor');
                });
              });
            });
          });
        });
      });

      it('should save with an actor that has access', function() {
        model = new ACLModel({
          user_id: user.get(user.idAttribute),
          description: 'foo'
        });
        var acl = model.acl;
        return model
          .save(null, {actor: user})
          .then(function() {
            model.acl.permissions['*'].should.equal(acl.permissions['*']);
          });
      });

      it('should update with an actor that has access', function() {
        var options = {actor: user};
        return model.save({description: 'test desription'}, options).then(function() {
          var m = new ACLModel({id: model.get(model.idAttribute)});
          return m.fetch({actor: user}).then(function() {
            m.get('description').should.equal('test desription');
          });
        });
      });

      it('should have given read access to everyone', function() {
        var anon = new ACLModel({id: 666});
        return model
          .fetch({actor: anon})
          .then(function() {
            should.exist(model.get('description'));
            var json = model.toJSON({actor: anon});
            should.exist(json.description);
          });
      });

      it('should have not given delete access to everyone', function() {
        var anon = new ACLModel({id: 666});
        return model
          .destroy({actor: anon})
          .then(function() {
            return when.reject(new Error('should not have access to destroy'));
          }, function(err) {
            err.statusCode.should.equal(403);
            should.exist(err);
          });
      });

      it('should destroy with an actor that has access', function() {
        return model.destroy({actor: user});
      });

      it('should verify that the resource was deleted', function() {
        var m = new ACLModel({id: model.get(model.idAttribute)});
        return m.fetch({actor: user}).then(function() {
          return when.reject(new Error('should not fetch a deleted model'));
        }, function() {
          return when.resolve();
        });
      });
    });
  });

  describe('ACLCollection tests', function() {
    var model, collection, actor;

    after(function(next) {
      collection.length.should.equal(0);
      setTimeout(next, 50);
    });

    beforeEach(function() {
      model = new ACLCollection.prototype.model({id: 12345});
      actor = new ACLCollection.prototype.model({id: 12346});
      actor.addRoles('owner'); // TODO: fix roles
      collection = new ACLCollection(null, {actor: actor});
    });

    it('should set correct action and actor for fetch', function() {
      var options = {};
      collection.fetch(options);
      options.action.should.equal('fetch');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
      options = {actor: actor};
      collection = new ACLCollection(null);
      collection.fetch(options);
      options.action.should.equal('fetch');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
    });

    it('should set correct action and actor for create', function() {
      var options = {};
      collection.create(null, options);
      options.action.should.equal('create');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
      options = {actor: actor};
      collection = new ACLCollection(null);
      collection.create(null, options);
      options.action.should.equal('create');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
    });

    it('should set correct action and actor for destroyAll', function() {
      var options = {};
      var promise = collection.destroyAll(options);
      options.action.should.equal('destroy');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
      options = {actor: actor};
      return promise;
    });
  });

  describe('ACLModel Roles', function() {
    var TestUser = ACLModel.extend({
      type: 'acl-test-user'
    });

    var schema = {
      properties: {
        id: {
          type: 'integer'
        },
        user_id: {
          type: 'integer'
        },
        user: {
          type: 'relation',
          model: TestUser,
          roles: ['owner'],
          references: {
            id: 'user_id'
          }
        }
      }
    };

    var TestModel = ACLModel.extend({
      type: 'acl-test-model',
      schema: schema
    });

    var actor;

    before(function() {
      actor = new TestUser({id: 1234});
    });

    it('should generate owner role based on relations', function() {
      var aclmodel = new TestModel({id: 1, user_id: actor.id});
      var roles = aclmodel.getRoles(actor);
      roles.indexOf('owner').should.be.above( -1 );
      aclmodel = new TestModel({id: 1, user_id: 22});
      roles = aclmodel.getRoles(actor);
      roles.indexOf('owner').should.equal( -1 );
    });
  });

});

<commit_msg>More ACL CRUD tests<commit_after>var setup = require('./test_setup');
var should = require('chai').should();
var serverbone = require('..');
var ACL = serverbone.acl.ACL;
var ACLModel = setup.ACLModel;
var ACLCollection = setup.ACLCollection;
var ACLUser = setup.ACLUser;
var ACLUserCollection = setup.ACLUserCollection;
var SystemUser = setup.SystemUser;
var when = require('when');
var sequence = require('when/sequence');

describe('Test ACL', function () {
  describe('Access Roles', function () {
    var acl;

    before(function () {
      acl = new ACL({
        'owner': ['write', 'read', 'update'],
        '*': ['read']
      });
    });

    after(function (next) {
      setTimeout(next, 50);
    });

    it('should be possible to make ACL assertions agains roles and actions', function () {
      acl.assert('owner', 'write').should.equal(true);
      acl.assert('public', 'write').should.equal(false);
      acl.assert('owner', 'delete').should.equal(false);
      acl.assert('read').should.equal(true);
      acl.assert('write').should.equal(false);
    });

    it('should be possible to add more rules with .allow', function () {
      acl.grant({
        'owner': ['delete'],
        'admin': ['*']
      });
      acl.assert('admin', 'write').should.equal(true);
      acl.assert('admin', 'read').should.equal(true);
      acl.assert('admin', 'nonexisting').should.equal(true);
      acl.assert('owner', 'delete').should.equal(true);
    });

    it('should be possible to grant and revoke access', function () {
      acl.grant({
        'tester': ['read', 'write'],
        'owner': ['read', 'write', 'delete']
      });
      acl.assert('owner', 'delete').should.equal(true);
      acl.revoke('owner');
      acl.assert('owner', 'delete').should.equal(false);
      acl.grant({
        'owner': ['delete']
      });
      acl.assert('owner', 'delete').should.equal(true);
      acl.revoke(['owner', 'user', 'tester']);
      acl.assert('owner', 'delete').should.equal(false);
    });

    it('should recognice the "*" selector in roles and permissions', function () {
      acl.grant({
        'test': '*'
      });
      acl.assert('test', 'anything').should.equal(true);
      acl.assert('test2', 'anything').should.equal(false);
      acl.grant({
        '*': 'abolish'
      });
      acl.assert('anyone', 'abolish').should.equal(true);
      acl.assert('anyone', 'destroye').should.equal(false);
    });

    describe('ACLModel', function () {
      var user, admin, model, users, actor, aclmodel;

      before(function(next) {
        setup.setupDbs(function() {
          users = new ACLUserCollection(null, {actor: SystemUser});
          users.create().done(function(model) {
            user = model;
            users.create(null).done(function(adm) {
              admin = adm;
              next();
            }, next);
          }, next);
        });
      });

      after(function(next) {
        setup.clearDb();
        setTimeout(next, 50);
      });

      beforeEach(function() {
        actor = new ACLModel({id: 1234});
        aclmodel = new ACLModel({user_id: 1234}, {actor: SystemUser});
        return actor.save();
      });

      it('should set actor and action on fetch', function(next) {
        var options = {};
        aclmodel.save().done(function() {
          aclmodel.fetch(options).done(function() {
            options.action.should.equal('read');
            options.should.have.property('actor');
            aclmodel = new ACLModel({id: aclmodel.id}, options);
              aclmodel.fetch(options).done(function() {
              options.action.should.equal('read');
              options.should.have.property('actor');
              next();
            });
          });
        });
      });

      it('should set actor and action on save', function() {
        var opt = {};
        function destroy() {
          return aclmodel
            .destroy(opt)
            .then(function() {
            });
        }
        function testOpts() {
          return aclmodel
            .save(null, opt)
            .then(function() {
              opt.action.should.equal('create');
              opt.should.have.property('actor');
            });
        }
        function saveAsSystem() {
          aclmodel = new ACLModel();
          opt = {actor: SystemUser};
          return aclmodel
            .save(null, opt)
            .then(function() {
              opt.action.should.equal('create');
              opt.should.have.property('actor');
            });
        }
        function updateAsSystem() {
          opt = {actor: SystemUser};
          aclmodel = new ACLModel({id: 123123}, {actor: SystemUser});
          return aclmodel
            .save(null, opt)
            .then(function() {
              opt.action.should.equal('update');
              opt.should.have.property('actor');
            });
        }

        return sequence([
          testOpts,
          destroy,
          saveAsSystem,
          destroy,
          updateAsSystem,
          destroy
        ]);
      });

      it('should set actor and action on destroy', function() {
        var options = {actor: SystemUser};
        return aclmodel.destroy(options).then(function() {
          options.action.should.equal('destroy');
          options.should.have.property('actor');
          options = {actor: SystemUser};
          aclmodel = new ACLModel(null, {actor: SystemUser});

          return aclmodel.save(null, options).then(function() {
            options = {actor: SystemUser};
            return aclmodel.destroy(options).then(function() {
              options.action.should.equal('destroy');
              options.should.have.property('actor');
              aclmodel = new ACLModel({id: 123123}, {actor: SystemUser});
              return aclmodel.save(null, options).then(function() {
                options = {actor: SystemUser};
                return aclmodel.destroy(options).then(function() {
                  options.action.should.equal('destroy');
                  options.should.have.property('actor');
                });
              });
            });
          });
        });
      });

      it('should save with an actor that has access', function() {
        model = new ACLModel({
          user_id: user.get(user.idAttribute),
          description: 'foo'
        });
        var acl = model.acl;
        return model
          .save(null, {actor: user})
          .then(function() {
            model.acl.permissions['*'].should.equal(acl.permissions['*']);
          });
      });

      it('should update with an actor that has access', function() {
        var options = {actor: user};
        return model.save({description: 'test desription'}, options).then(function() {
          var m = new ACLModel({id: model.get(model.idAttribute)});
          return m.fetch({actor: user}).then(function() {
            m.get('description').should.equal('test desription');
          });
        });
      });

      it('should have given read access to everyone', function() {
        var anon = new ACLModel({id: 666});
        return model
          .fetch({actor: anon})
          .then(function() {
            should.exist(model.get('description'));
            var json = model.toJSON({actor: anon});
            should.exist(json.description);
          });
      });

      it('should have not given delete access to everyone', function() {
        var anon = new ACLModel({id: 666});
        return model
          .destroy({actor: anon})
          .then(function() {
            return when.reject(new Error('should not have access to destroy'));
          }, function(err) {
            err.statusCode.should.equal(403);
            should.exist(err);
          });
      });

      it('should destroy with an actor that has access', function() {
        return model.destroy({actor: user});
      });

      it('should verify that the resource was deleted', function() {
        var m = new ACLModel({id: model.get(model.idAttribute)});
        return m.fetch({actor: user}).then(function() {
          return when.reject(new Error('should not fetch a deleted model'));
        }, function() {
          return when.resolve();
        });
      });
    });
  });

  describe('ACLCollection tests', function() {
    var model, collection, actor;

    after(function(next) {
      collection.length.should.equal(0);
      setTimeout(next, 50);
    });

    beforeEach(function() {
      model = new ACLCollection.prototype.model({id: 12345});
      actor = new ACLCollection.prototype.model({id: 12346});
      actor.addRoles('owner'); // TODO: fix roles
      collection = new ACLCollection(null, {actor: actor});
    });

    it('should set correct action and actor for fetch', function() {
      var options = {};
      collection.fetch(options);
      options.action.should.equal('fetch');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
      options = {actor: actor};
      collection = new ACLCollection(null);
      collection.fetch(options);
      options.action.should.equal('fetch');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
    });

    it('should set correct action and actor for create', function() {
      var options = {};
      collection.create(null, options);
      options.action.should.equal('create');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
      options = {actor: actor};
      collection = new ACLCollection(null);
      collection.create(null, options);
      options.action.should.equal('create');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
    });

    it('should set correct action and actor for destroyAll', function() {
      var options = {};
      var promise = collection.destroyAll(options);
      options.action.should.equal('destroy');
      options.should.have.property('actor');
      options.actor.get('id').should.equal(actor.id);
      options = {actor: actor};
      return promise;
    });
  });

  describe.only('ACLModel Roles', function() {
    var TestUser = ACLUser.extend({
    });

    var schema = {
      properties: {
        id: {
          type: 'integer'
        },
        user_id: {
          type: 'integer'
        },
        user: {
          type: 'relation',
          model: TestUser,
          roles: ['owner'],
          references: {
            id: 'user_id'
          }
        }
      }
    };

    var TestModel = ACLModel.extend({
      type: 'acl-test-model',
      schema: schema
    });

    var actor;
    var model;

    before(function() {
      actor = new TestUser({id: 1234});
      model = new ACLModel({user_id: actor.id}, {actor: actor});
      return when.all([actor.save(), model.save()]);
    });

    after(function() {
      var fns = [
        actor.destroy({actor: SystemUser}),
      ];
      return when.all(fns);
    });

    it('should generate owner role based on relations', function() {
      var aclmodel = new TestModel({id: 1, user_id: actor.id});
      var roles = aclmodel.getRoles(actor);
      roles.indexOf('owner').should.be.above( -1 );
      aclmodel = new TestModel({id: 1, user_id: 22});
      roles = aclmodel.getRoles(actor);
      roles.indexOf('owner').should.equal( -1 );
    });

    it('should not be able to update description if not owner', function() {
      model.set('description', 'foo');
      return model
        .save(null, {actor: new TestUser({id: 222})})
        .then(function() {
          return new Error('should not be able to save');
        }, function(err) {
          err.statusCode.should.equal(403);
        });
    });

    it('should be able to update description if owner', function() {
      model.set('description', 'allowed desc');
      return model.save({actor: actor});
    });

    it('should not be able to delete if not owner', function() {
      return model
        .destroy({actor: new TestUser({id: 33})})
        .then(function() {
          return new Error('should not be able to destroy');
        }, function(err) {
          err.statusCode.should.equal(403);
        });
    });

    it('should be able to delete if owner', function() {
      return model.destroy();
    });
  });

});

<|endoftext|>


<commit_before>/*jshint globalstrict: true*/
"use strict";

var TYPE_A_VERBS = [
    ["verb-expand", "verb-type-a", "future-tense", "first-person", "singular"],
    ["I will turn", "θα γυρίσω"],
    ["I will close", "θα κλείσω"],
    ["I will arrive", "θα φτάνω"],
    ["I will look", "θα κοιτάξω"],
];

var FUTURE_VERBS = [
    ["verb", "future-tense", "first-person", "singular"],
    ["I will bring", "θα φέρω"],
    ["I will leave", "θα φύγω"],
    ["I will send", "θα στείλω"],
    ["I will wash", "θα πλύνω"],
    ["I will fall", "θα πέσω"],
    ["I will die", "θα πεθάνω"],
    ["I will take", "θα πάρνω"],
    ["I will give", "θα δώσω"],
    ["I will live", "θα ζήσω"],
    ["I will live/stay", "θα μείνω"],
    ["I will put", "θα βάλω"],
    ["I will remove", "θα βγάλω"],
    ["I will learn", "θα μάθω"],
    ["I will suffer", "θα πάθω"],
    ["I will enter", "θα μπω"],
    ["I will burn", "θα κάψω"],
    ["I will cry", "θα κλάψω"],
    ["I will rise", "θα ανεβώ"],
    ["I will descend", "θα κατεβώ"],
    ["I will understand", "θα καταλαβώ"],
    ["I will see", "θα δω"],
    ["I will say", "θα πω"],
    ["I will eat", "θα φάω"],
    ["I will drink", "θα πίω"],
    ["I will find", "θα βρω"],
    ["I will go out", "θα βγω"],
];

var PRESENT_VERBS = [
    ["verb", "present-tense", "first-person", "singular"],
    ["I bring", "φέρνω"],
    ["I leave", "φεύγω"],
    ["I send", "στέλνω"],
    ["I wash", "πλένω"],
    ["I fall", "πέφτω"],
    ["I die", "πεθαίνω"],
    ["I take", "παίρνω"],
    ["I give", "δίνω"],
    ["I live", "ζω"],
    ["I live/stay", "μένω"],
    ["I put", "βάζω"],
    ["I remove", "βγάζω"],
    ["I learn", "μαθαίνω"],
    ["I suffer", "παθαίνω"],
    ["I enter", "μπαίνω"],
    ["I burn", "καίω"],
    ["I cry", "κλαίω"],
    ["I rise", "ανεβαίνω"],
    ["I descend", "κατεβαίνω"],
    ["I understand", "καταλαβαίνω"],
    ["I see", "βλέπω"],
    ["I say", "λέω"],
    ["I eat", "τρώω"],
    ["I drink", "πίνω"],
    ["I find", "βρίσκω"],
    ["I go out", "βγαίνω"],
    ["I look", "κοιτάζω"],
    ["I know", "ξέρω"],
    ["I close", "κλείνω"],
    ["I have", "έχω"],
];

var NUMBERS = [
    ["number"],
    ["zero", "μηδέν"],
    ["one", "ένα"],
    ["two", "δύο"],
    ["three", "τρία"],
    ["four", "τέσσαρα"],
    ["five", "πέντε"],
    ["six", "έξι"],
    ["seven", "εφτά"],
    ["eight", "οχτώ"],
    ["nine", "εννιά"],
    ["ten", "δέκα"]
];

var ORDINALS = [
    ["gender-expand", "masculine", "ordinal"],
    ["first", "πρώτος"],
    ["second", "δεύτερος"],
    ["third", "τρίτος"],
    ["fourth", "τέταρτος"],
    ["fifth", "πέμπτος"],
    ["sixth", "έκτος"],
    ["seventh", "έβδομος"],
    ["eighth", "όγδοος"],
    ["ninth", "ένατος"],
    ["tenth", "δέκατος"],
    ["eleventh", "εντέκατος"],
    ["twelfth", "δωδέκατος"],
    ["twentieth", "εικοστός"],
];

var MASCULINE_SINGULAR_NOUNS = [
    ["noun-expand", "noun", "masculine", "singular"],
    ["The lighter", "ο αναπτήρας"],
    ["The computer", "ο υπολογιστής"],
    ["The envelope", "ο φάκελος"],
    ["The garden", "ο κήπος"],
    ["The air / wind", "ο αέρας"],
    ["The man / husband", "ο άντρας"],
    ["The rock", "ο βράχος"],
    ["The bakery", "ο φούρνος"],
];

var FEMININE_SINGULAR_NOUNS = [
    ["noun-expand", "noun", "feminine", "singular"],
    ["The chair", "η καρέκλα"],
    ["The motorbike", "η μηχανή"],
    ["The television", "η τηλεόραση"],
    ["The newspaper", "η εφημερίδα"],
    ["The market", "η αγορά"],
    ["The receipt", "η απόδειξη"],
    ["The diary / agenda", "η ατζέντα"],
    ["The courtyard", "η αυλή"],
    ["The vanilla", "η βανίλια"],
    ["The gasoline", "η βενζίνη"],
    ["The balcony / porch", "η βεράντα"],
    ["The night / evening", "η βραδιά"],
    ["The apple", "η μήλα"],
    ["The strawberry", "η φράουλα"],
    ["The tomato", "η ντομάτα"],
    ["The potato", "η πατάτα"],
    ["The tavern", "η ταβέρνα"],
    ["The bank", "η τράπεζα"],
];

var FEMININE_SINGULAR_UNEXPANDED_NOUNS = [
    ["noun", "feminine", "singular"],
    ["England", "η Αγγλία"],
    ["Athens", "η Αθήνα"],
    ["America", "η Αμερική"],
    ["Britain", "η Βριτανία"],
];

var NEUTER_SINGULAR_NOUNS = [
    ["noun-expand", "noun", "neuter", "singular", "nominative"],
    ["The statue", "το άγαλμα"],
    ["The wallet", "το πορτοφόλι"],
    ["The car", "το αυτοκίνητο"],
    ["The souvlaki", "το σουβλάκι"],
    ["The coin", "το κέρμα"],
    ["The house", "το σπίτι"],
    ["The book", "το βιβλίο"],
    ["The clock", "το ρολόι"],
    ["The egg", "το αβγό"],
    ["The cucumber", "το αγγούρι"],
    ["The airport", "το αεροδρόμιο"],
    ["The airplane", "το αεροπλάνο"],
    ["The salt", "το αλάτι"],
    ["The alphabet", "το αλφάβητο"],
    ["The refreshment", "το αναψυκτικό"],
    ["The pear", "το αχλάδι"],
    ["The vase", "το βάζο"],
    ["The apricot", "το βερίκοκο"],
    ["The video", "το βίντεο"],
    ["The mountain", "το βουνό"],
    ["The butter", "το βούτυρο"],
    ["The orange", "το πορτοκάλι"],
    ["The lemon", "το λεμόνι"],
    ["The cherry", "το κεράσι"],
    ["The grape", "το σταφύλι"],
    ["The melon", "το καρπούζι"],
    ["The carrot", "το καρότο"],
    ["The pharmacy", "το φαρμακείο"],
    ["The sweet shop", "το ζαχαροπλαστείο"],
    ["The laundromat", "το καθαραριστήριο"],
];

var NEUTER_SINGULAR_UNEXPANDED_NOUNS = [
    ["noun", "neuter", "singular", "nominative"],
    ["The milk", "το γάλα"],
];

var QUESTIONS = [
    ["question"],
    ["how many? (m, nom)", "πόσοι;"],
    ["how many? (m, acc)", "πόσους;"],
    ["how many? (f)", "πόσες;"],
    ["how many? (n)", "πόσα;"],
]

var LISTS_TO_EXPAND = [
    TYPE_A_VERBS, FUTURE_VERBS, PRESENT_VERBS, ORDINALS,
    MASCULINE_SINGULAR_NOUNS, FEMININE_SINGULAR_NOUNS, NEUTER_SINGULAR_NOUNS,
    FEMININE_SINGULAR_UNEXPANDED_NOUNS, NEUTER_SINGULAR_UNEXPANDED_NOUNS,
    NUMBERS, QUESTIONS
];

var TRANSLATIONS = [
];
<commit_msg>Don't expand "The video"<commit_after>/*jshint globalstrict: true*/
"use strict";

var TYPE_A_VERBS = [
    ["verb-expand", "verb-type-a", "future-tense", "first-person", "singular"],
    ["I will turn", "θα γυρίσω"],
    ["I will close", "θα κλείσω"],
    ["I will arrive", "θα φτάνω"],
    ["I will look", "θα κοιτάξω"],
];

var FUTURE_VERBS = [
    ["verb", "future-tense", "first-person", "singular"],
    ["I will bring", "θα φέρω"],
    ["I will leave", "θα φύγω"],
    ["I will send", "θα στείλω"],
    ["I will wash", "θα πλύνω"],
    ["I will fall", "θα πέσω"],
    ["I will die", "θα πεθάνω"],
    ["I will take", "θα πάρνω"],
    ["I will give", "θα δώσω"],
    ["I will live", "θα ζήσω"],
    ["I will live/stay", "θα μείνω"],
    ["I will put", "θα βάλω"],
    ["I will remove", "θα βγάλω"],
    ["I will learn", "θα μάθω"],
    ["I will suffer", "θα πάθω"],
    ["I will enter", "θα μπω"],
    ["I will burn", "θα κάψω"],
    ["I will cry", "θα κλάψω"],
    ["I will rise", "θα ανεβώ"],
    ["I will descend", "θα κατεβώ"],
    ["I will understand", "θα καταλαβώ"],
    ["I will see", "θα δω"],
    ["I will say", "θα πω"],
    ["I will eat", "θα φάω"],
    ["I will drink", "θα πίω"],
    ["I will find", "θα βρω"],
    ["I will go out", "θα βγω"],
];

var PRESENT_VERBS = [
    ["verb", "present-tense", "first-person", "singular"],
    ["I bring", "φέρνω"],
    ["I leave", "φεύγω"],
    ["I send", "στέλνω"],
    ["I wash", "πλένω"],
    ["I fall", "πέφτω"],
    ["I die", "πεθαίνω"],
    ["I take", "παίρνω"],
    ["I give", "δίνω"],
    ["I live", "ζω"],
    ["I live/stay", "μένω"],
    ["I put", "βάζω"],
    ["I remove", "βγάζω"],
    ["I learn", "μαθαίνω"],
    ["I suffer", "παθαίνω"],
    ["I enter", "μπαίνω"],
    ["I burn", "καίω"],
    ["I cry", "κλαίω"],
    ["I rise", "ανεβαίνω"],
    ["I descend", "κατεβαίνω"],
    ["I understand", "καταλαβαίνω"],
    ["I see", "βλέπω"],
    ["I say", "λέω"],
    ["I eat", "τρώω"],
    ["I drink", "πίνω"],
    ["I find", "βρίσκω"],
    ["I go out", "βγαίνω"],
    ["I look", "κοιτάζω"],
    ["I know", "ξέρω"],
    ["I close", "κλείνω"],
    ["I have", "έχω"],
];

var NUMBERS = [
    ["number"],
    ["zero", "μηδέν"],
    ["one", "ένα"],
    ["two", "δύο"],
    ["three", "τρία"],
    ["four", "τέσσαρα"],
    ["five", "πέντε"],
    ["six", "έξι"],
    ["seven", "εφτά"],
    ["eight", "οχτώ"],
    ["nine", "εννιά"],
    ["ten", "δέκα"]
];

var ORDINALS = [
    ["gender-expand", "masculine", "ordinal"],
    ["first", "πρώτος"],
    ["second", "δεύτερος"],
    ["third", "τρίτος"],
    ["fourth", "τέταρτος"],
    ["fifth", "πέμπτος"],
    ["sixth", "έκτος"],
    ["seventh", "έβδομος"],
    ["eighth", "όγδοος"],
    ["ninth", "ένατος"],
    ["tenth", "δέκατος"],
    ["eleventh", "εντέκατος"],
    ["twelfth", "δωδέκατος"],
    ["twentieth", "εικοστός"],
];

var MASCULINE_SINGULAR_NOUNS = [
    ["noun-expand", "noun", "masculine", "singular"],
    ["The lighter", "ο αναπτήρας"],
    ["The computer", "ο υπολογιστής"],
    ["The envelope", "ο φάκελος"],
    ["The garden", "ο κήπος"],
    ["The air / wind", "ο αέρας"],
    ["The man / husband", "ο άντρας"],
    ["The rock", "ο βράχος"],
    ["The bakery", "ο φούρνος"],
];

var FEMININE_SINGULAR_NOUNS = [
    ["noun-expand", "noun", "feminine", "singular"],
    ["The chair", "η καρέκλα"],
    ["The motorbike", "η μηχανή"],
    ["The television", "η τηλεόραση"],
    ["The newspaper", "η εφημερίδα"],
    ["The market", "η αγορά"],
    ["The receipt", "η απόδειξη"],
    ["The diary / agenda", "η ατζέντα"],
    ["The courtyard", "η αυλή"],
    ["The vanilla", "η βανίλια"],
    ["The gasoline", "η βενζίνη"],
    ["The balcony / porch", "η βεράντα"],
    ["The night / evening", "η βραδιά"],
    ["The apple", "η μήλα"],
    ["The strawberry", "η φράουλα"],
    ["The tomato", "η ντομάτα"],
    ["The potato", "η πατάτα"],
    ["The tavern", "η ταβέρνα"],
    ["The bank", "η τράπεζα"],
];

var FEMININE_SINGULAR_UNEXPANDED_NOUNS = [
    ["noun", "feminine", "singular"],
    ["England", "η Αγγλία"],
    ["Athens", "η Αθήνα"],
    ["America", "η Αμερική"],
    ["Britain", "η Βριτανία"],
];

var NEUTER_SINGULAR_NOUNS = [
    ["noun-expand", "noun", "neuter", "singular", "nominative"],
    ["The statue", "το άγαλμα"],
    ["The wallet", "το πορτοφόλι"],
    ["The car", "το αυτοκίνητο"],
    ["The souvlaki", "το σουβλάκι"],
    ["The coin", "το κέρμα"],
    ["The house", "το σπίτι"],
    ["The book", "το βιβλίο"],
    ["The clock", "το ρολόι"],
    ["The egg", "το αβγό"],
    ["The cucumber", "το αγγούρι"],
    ["The airport", "το αεροδρόμιο"],
    ["The airplane", "το αεροπλάνο"],
    ["The salt", "το αλάτι"],
    ["The alphabet", "το αλφάβητο"],
    ["The refreshment", "το αναψυκτικό"],
    ["The pear", "το αχλάδι"],
    ["The vase", "το βάζο"],
    ["The apricot", "το βερίκοκο"],
    ["The mountain", "το βουνό"],
    ["The butter", "το βούτυρο"],
    ["The orange", "το πορτοκάλι"],
    ["The lemon", "το λεμόνι"],
    ["The cherry", "το κεράσι"],
    ["The grape", "το σταφύλι"],
    ["The melon", "το καρπούζι"],
    ["The carrot", "το καρότο"],
    ["The pharmacy", "το φαρμακείο"],
    ["The sweet shop", "το ζαχαροπλαστείο"],
    ["The laundromat", "το καθαραριστήριο"],
];

var NEUTER_SINGULAR_UNEXPANDED_NOUNS = [
    ["noun", "neuter", "singular", "nominative"],
    ["The milk", "το γάλα"],
    ["The video", "το βίντεο"],
];

var QUESTIONS = [
    ["question"],
    ["how many? (m, nom)", "πόσοι;"],
    ["how many? (m, acc)", "πόσους;"],
    ["how many? (f)", "πόσες;"],
    ["how many? (n)", "πόσα;"],
]

var LISTS_TO_EXPAND = [
    TYPE_A_VERBS, FUTURE_VERBS, PRESENT_VERBS, ORDINALS,
    MASCULINE_SINGULAR_NOUNS, FEMININE_SINGULAR_NOUNS, NEUTER_SINGULAR_NOUNS,
    FEMININE_SINGULAR_UNEXPANDED_NOUNS, NEUTER_SINGULAR_UNEXPANDED_NOUNS,
    NUMBERS, QUESTIONS
];

var TRANSLATIONS = [
];
<|endoftext|>