<commit_before>var Snoocore = window.Snoocore;
var hash = window.location.hash;

var reddit = new Snoocore({
	userAgent: 'HummHumm Web',
	oauth: {
		type: 'implicit',
		consumerKey: 'qVjwB7K3EUJBBg',
		redirectUri: "http://loki.cpfk.net:31415",
		scope: [ 'identity', 'vote', 'submit', 'read' ],
		expires_in: 7200,
		duration: 'permanent'
	}
});

$(function() {
	$('#captcha').hide();
	$('#download').addClass('disabled');

	var token = localStorage.getItem('accessToken');
	if (typeof token !== 'undefined') {
		accessToken = token;
	}

	if (accessToken) {
		localStorage.setItem('accessToken', accessToken);
		$("#login").hide();
	}

	reddit.auth(accessToken).then(function() {
		return reddit('/r/hummhumm/hot').get()
	}).then(function(data) {
		console.log(data)
		var posts = data.data.children

		// var html = 'View Post on /r/HummHumm';

		// $('#audio').html('<audio controls preload autoplay load><source src="' + post.url + '" type="audio/wav"></audio>')

		var html = ''

		for (var i = 0, l = posts.length; i < l; i++) {
			var p = posts[i].data;

			html +=
			'
' +
				'
' +
					'' +
						p.title +
					'' +
				'
' +
				'<audio controls preload><source src="' + p.url.replace("player", "sounds") + '" type="audio/wav"></audio>' +
				'
' +
					'' +
						'' +
							p.author +
						'' +
						' · ' +
						'' +
							moment(new Date(p.created_utc * 1000)).fromNow() +
						'' +
						' · ' +
						'' +
							p.num_comments + ' commentaire' + (p.num_comments > 1 ? 's' : '') +
						'' +
					'' +
				'
' +
			'
';
		}

		$('#posts').html(html)
	});
});

var globlob = "";
var globurl = "";
var startRecTime;
var interval;

// Audio capture button actions
$(document).on('click', '#record:not(.disabled)', function () {
	$.voice.record(false, function () {
		$('#record, #download').addClass('disabled');
		$('#stop').removeClass('disabled');

		var html = 'Recording...';
		startRecTime = new Date();

		interval = setInterval(function () {
		var html = 'Recording...
';
			html += Math.floor((new Date() - startRecTime) / 1000) + ' seconds';
			$('#humming-info').html(html);
		}, 200);

		$('#humming-info').html(html);
	});
});

$(document).on('click', '#stop:not(.disabled)', function () {
	$.voice.export(function (blob) {
		globlob = blob;
		globurl = URL.createObjectURL(blob)
		$.voice.stop();
		clearInterval(interval);

		$('#audio').attr('src', globurl);
		$('#download').removeClass('disabled');
		$('#record').removeClass('disabled');
		$('#stop').addClass('disabled');
		$('#humming-info').html(
			'
Clicking the button will create a post on /r/HummHumm with your recorded voice.
' +
			'<input maxlength="300" type="text" id="input-title" name="input-title" placeholder="Add tags like [Metal][Rock]"/>' +
			'<button id="upload">Create a post</button>' +
			'
'
		);
	}, 'blob');
});

$(document).on('click', '#download:not(.disabled)', function () {
	$('')[0].click();
});

$(document).on('click', '#upload', function () {
	//console.log(blob);
	var fd = new FormData();
	var title = $("#input-title").val();
	fd.append('fname', 'upload.wav');
	fd.append('data', globlob);

	$.ajax({
		type: 'POST',
		url: '/sounds',
		data: fd,
		processData: false,
		contentType: false
	}).done(function (data) {
		console.log(data);
		console.log(title);
		postLink("http://loki.cpfk.net:31415"+data, title);
	});

});

$(document).on('click', '#login-button:not(.disabled)', function() {
	login();
});

// Check if we have an access token in the hash, if so
// we can authenticate with reddit and make our call!
var match = ('' + window.location.hash).match(/access_token=(.*?)&/);
var accessToken = match ? match[1] : '';

function showCaptcha(link, titleText, iden) {
	$('#captcha').show();
	$('#captcha:not(:has(#captcha-img))').append(
		'
Please enter what you see :
' +
		'' +
		'
' +
			'<input type="text" id="captcha-input"></input>' +
			'<button type="submit" id="captcha-submit">Submit</button>' +
		'
'
	);

	$(document).off('click', '#captcha-submit');

	$(document).on('click', '#captcha-submit', function () {
		console.log('---------')
		var captchaCode = $("#captcha-input").val();
		$("#captcha").hide();
		console.log('postLink()', link, titleText, iden, captchaCode);
		postLink(link, titleText, iden, captchaCode);
	});
}

function addPost() {
	$('#reddit').append(
		'
marrant
'
	);
}
<commit_msg>Login fixed<commit_after>var Snoocore = window.Snoocore;
var hash = window.location.hash;

var reddit = new Snoocore({
	userAgent: 'HummHumm Web',
	oauth: {
		type: 'implicit',
		consumerKey: 'qVjwB7K3EUJBBg',
		redirectUri: "http://loki.cpfk.net:31415",
		scope: [ 'identity', 'vote', 'submit', 'read' ],
		expires_in: 7200,
		duration: 'permanent'
	}
});

// Check if we have an access token in the hash, if so
// we can authenticate with reddit and make our call!
var match = ('' + window.location.hash).match(/access_token=(.*?)&/);
var accessToken = match ? match[1] : '';

$(function() {
	$('#captcha').hide();
	$('#download').addClass('disabled');

	var token = localStorage.getItem('accessToken');
	if (typeof token !== 'undefined') {
		accessToken = token;
	}

	if (accessToken) {
		localStorage.setItem('accessToken', accessToken);
		$("#login").hide();
	}

	reddit.auth(accessToken).then(function() {
		return reddit('/r/hummhumm/hot').get()
	}).then(function(data) {
		console.log(data)
		var posts = data.data.children

		// var html = 'View Post on /r/HummHumm';

		// $('#audio').html('<audio controls preload autoplay load><source src="' + post.url + '" type="audio/wav"></audio>')

		var html = ''

		for (var i = 0, l = posts.length; i < l; i++) {
			var p = posts[i].data;

			html +=
			'
' +
				'
' +
					'' +
						p.title +
					'' +
				'
' +
				'<audio controls preload><source src="' + p.url.replace("player", "sounds") + '" type="audio/wav"></audio>' +
				'
' +
					'' +
						'' +
							p.author +
						'' +
						' · ' +
						'' +
							moment(new Date(p.created_utc * 1000)).fromNow() +
						'' +
						' · ' +
						'' +
							p.num_comments + ' commentaire' + (p.num_comments > 1 ? 's' : '') +
						'' +
					'' +
				'
' +
			'
';
		}

		$('#posts').html(html)
	});
});

var globlob = "";
var globurl = "";
var startRecTime;
var interval;

// Audio capture button actions
$(document).on('click', '#record:not(.disabled)', function () {
	$.voice.record(false, function () {
		$('#record, #download').addClass('disabled');
		$('#stop').removeClass('disabled');

		var html = 'Recording...';
		startRecTime = new Date();

		interval = setInterval(function () {
		var html = 'Recording...
';
			html += Math.floor((new Date() - startRecTime) / 1000) + ' seconds';
			$('#humming-info').html(html);
		}, 200);

		$('#humming-info').html(html);
	});
});

$(document).on('click', '#stop:not(.disabled)', function () {
	$.voice.export(function (blob) {
		globlob = blob;
		globurl = URL.createObjectURL(blob)
		$.voice.stop();
		clearInterval(interval);

		$('#audio').attr('src', globurl);
		$('#download').removeClass('disabled');
		$('#record').removeClass('disabled');
		$('#stop').addClass('disabled');
		$('#humming-info').html(
			'
Clicking the button will create a post on /r/HummHumm with your recorded voice.
' +
			'<input maxlength="300" type="text" id="input-title" name="input-title" placeholder="Add tags like [Metal][Rock]"/>' +
			'<button id="upload">Create a post</button>' +
			'
'
		);
	}, 'blob');
});

$(document).on('click', '#download:not(.disabled)', function () {
	$('')[0].click();
});

$(document).on('click', '#upload', function () {
	//console.log(blob);
	var fd = new FormData();
	var title = $("#input-title").val();
	fd.append('fname', 'upload.wav');
	fd.append('data', globlob);

	$.ajax({
		type: 'POST',
		url: '/sounds',
		data: fd,
		processData: false,
		contentType: false
	}).done(function (data) {
		console.log(data);
		console.log(title);
		postLink("http://loki.cpfk.net:31415"+data, title);
	});

});

$(document).on('click', '#login-button:not(.disabled)', function() {
	login();
});

function showCaptcha(link, titleText, iden) {
	$('#captcha').show();
	$('#captcha:not(:has(#captcha-img))').append(
		'
Please enter what you see :
' +
		'' +
		'
' +
			'<input type="text" id="captcha-input"></input>' +
			'<button type="submit" id="captcha-submit">Submit</button>' +
		'
'
	);

	$(document).off('click', '#captcha-submit');

	$(document).on('click', '#captcha-submit', function () {
		console.log('---------')
		var captchaCode = $("#captcha-input").val();
		$("#captcha").hide();
		console.log('postLink()', link, titleText, iden, captchaCode);
		postLink(link, titleText, iden, captchaCode);
	});
}

function addPost() {
	$('#reddit').append(
		'
marrant
'
	);
}
<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator",
	"Tone/signal/Signal", "Tone/signal/WaveShaper", "Tone/core/Gain"], function(Tone){

	"use strict";

	/**
	 *  @class Tone.PulseOscillator is a pulse oscillator with control over pulse width,
	 *         also known as the duty cycle. At 50% duty cycle (width = 0.5) the wave is
	 *         a square and only odd-numbered harmonics are present. At all other widths
	 *         even-numbered harmonics are present. Read more
	 *         [here](https://wigglewave.wordpress.com/2014/08/16/pulse-waveforms-and-harmonics/).
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {Frequency} [frequency] The frequency of the oscillator
	 *  @param {NormalRange} [width] The width of the pulse
	 *  @example
	 * var pulse = new Tone.PulseOscillator("E5", 0.4).toMaster().start();
	 */
	Tone.PulseOscillator = function(){

		var options = Tone.defaults(arguments, ["frequency", "width"], Tone.Oscillator);
		Tone.Source.call(this, options);

		/**
		 *  The width of the pulse.
		 *  @type {NormalRange}
		 *  @signal
		 */
		this.width = new Tone.Signal(options.width, Tone.Type.NormalRange);

		/**
		 *  gate the width amount
		 *  @type {Tone.Gain}
		 *  @private
		 */
		this._widthGate = new Tone.Gain();

		/**
		 *  the sawtooth oscillator
		 *  @type {Tone.Oscillator}
		 *  @private
		 */
		this._sawtooth = new Tone.Oscillator({
			frequency : options.frequency,
			detune : options.detune,
			type : "sawtooth",
			phase : options.phase
		});

		/**
		 *  The frequency control.
		 *  @type {Frequency}
		 *  @signal
		 */
		this.frequency = this._sawtooth.frequency;

		/**
		 *  The detune in cents.
		 *  @type {Cents}
		 *  @signal
		 */
		this.detune = this._sawtooth.detune;

		/**
		 *  Threshold the signal to turn it into a square
		 *  @type {Tone.WaveShaper}
		 *  @private
		 */
		this._thresh = new Tone.WaveShaper(function(val){
			if (val < 0){
				return -1;
			} else {
				return 1;
			}
		});

		//connections
		this._sawtooth.chain(this._thresh, this.output);
		this.width.chain(this._widthGate, this._thresh);
		this._readOnly(["width", "frequency", "detune"]);
	};

	Tone.extend(Tone.PulseOscillator, Tone.Source);

	/**
	 *  The default parameters.
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.PulseOscillator.defaults = {
		"frequency" : 440,
		"detune" : 0,
		"phase" : 0,
		"width" : 0.2,
	};

	/**
	 *  start the oscillator
	 *  @param  {Time} time
	 *  @private
	 */
	Tone.PulseOscillator.prototype._start = function(time){
		time = this.toSeconds(time);
		this._sawtooth.start(time);
		this._widthGate.gain.setValueAtTime(1, time);
	};

	/**
	 *  stop the oscillator
	 *  @param  {Time} time
	 *  @private
	 */
	Tone.PulseOscillator.prototype._stop = function(time){
		time = this.toSeconds(time);
		this._sawtooth.stop(time);
		//the width is still connected to the output.
		//that needs to be stopped also
		this._widthGate.gain.setValueAtTime(0, time);
	};

	/**
	 *  restart the oscillator
	 *  @param  {Time} time (optional) timing parameter
	 *  @private
	 */
	Tone.PulseOscillator.prototype.restart = function(time){
		this._sawtooth.restart(time);
	};

	/**
	 * The phase of the oscillator in degrees.
	 * @memberOf Tone.PulseOscillator#
	 * @type {Degrees}
	 * @name phase
	 */
	Object.defineProperty(Tone.PulseOscillator.prototype, "phase", {
		get : function(){
			return this._sawtooth.phase;
		},
		set : function(phase){
			this._sawtooth.phase = phase;
		}
	});

	/**
	 * The type of the oscillator. Always returns "pulse".
	 * @readOnly
	 * @memberOf Tone.PulseOscillator#
	 * @type {string}
	 * @name type
	 */
	Object.defineProperty(Tone.PulseOscillator.prototype, "type", {
		get : function(){
			return "pulse";
		}
	});

	/**
	 * The partials of the waveform. Cannot set partials for this waveform type
	 * @memberOf Tone.PulseOscillator#
	 * @type {Array}
	 * @name partials
	 * @private
	 */
	Object.defineProperty(Tone.PulseOscillator.prototype, "partials", {
		get : function(){
			return [];
		}
	});

	/**
	 *  Clean up method.
	 *  @return {Tone.PulseOscillator} this
	 */
	Tone.PulseOscillator.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		this._sawtooth.dispose();
		this._sawtooth = null;
		this._writable(["width", "frequency", "detune"]);
		this.width.dispose();
		this.width = null;
		this._widthGate.dispose();
		this._widthGate = null;
		this._thresh.dispose();
		this._thresh = null;
		this.frequency = null;
		this.detune = null;
		return this;
	};

	return Tone.PulseOscillator;
});
<commit_msg>correctly restarting PulseOscillator<commit_after>define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator",
	"Tone/signal/Signal", "Tone/signal/WaveShaper", "Tone/core/Gain"], function(Tone){

	"use strict";

	/**
	 *  @class Tone.PulseOscillator is a pulse oscillator with control over pulse width,
	 *         also known as the duty cycle. At 50% duty cycle (width = 0.5) the wave is
	 *         a square and only odd-numbered harmonics are present. At all other widths
	 *         even-numbered harmonics are present. Read more
	 *         [here](https://wigglewave.wordpress.com/2014/08/16/pulse-waveforms-and-harmonics/).
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {Frequency} [frequency] The frequency of the oscillator
	 *  @param {NormalRange} [width] The width of the pulse
	 *  @example
	 * var pulse = new Tone.PulseOscillator("E5", 0.4).toMaster().start();
	 */
	Tone.PulseOscillator = function(){

		var options = Tone.defaults(arguments, ["frequency", "width"], Tone.Oscillator);
		Tone.Source.call(this, options);

		/**
		 *  The width of the pulse.
		 *  @type {NormalRange}
		 *  @signal
		 */
		this.width = new Tone.Signal(options.width, Tone.Type.NormalRange);

		/**
		 *  gate the width amount
		 *  @type {Tone.Gain}
		 *  @private
		 */
		this._widthGate = new Tone.Gain();

		/**
		 *  the sawtooth oscillator
		 *  @type {Tone.Oscillator}
		 *  @private
		 */
		this._sawtooth = new Tone.Oscillator({
			frequency : options.frequency,
			detune : options.detune,
			type : "sawtooth",
			phase : options.phase
		});

		/**
		 *  The frequency control.
		 *  @type {Frequency}
		 *  @signal
		 */
		this.frequency = this._sawtooth.frequency;

		/**
		 *  The detune in cents.
		 *  @type {Cents}
		 *  @signal
		 */
		this.detune = this._sawtooth.detune;

		/**
		 *  Threshold the signal to turn it into a square
		 *  @type {Tone.WaveShaper}
		 *  @private
		 */
		this._thresh = new Tone.WaveShaper(function(val){
			if (val < 0){
				return -1;
			} else {
				return 1;
			}
		});

		//connections
		this._sawtooth.chain(this._thresh, this.output);
		this.width.chain(this._widthGate, this._thresh);
		this._readOnly(["width", "frequency", "detune"]);
	};

	Tone.extend(Tone.PulseOscillator, Tone.Source);

	/**
	 *  The default parameters.
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.PulseOscillator.defaults = {
		"frequency" : 440,
		"detune" : 0,
		"phase" : 0,
		"width" : 0.2,
	};

	/**
	 *  start the oscillator
	 *  @param  {Time} time
	 *  @private
	 */
	Tone.PulseOscillator.prototype._start = function(time){
		time = this.toSeconds(time);
		this._sawtooth.start(time);
		this._widthGate.gain.setValueAtTime(1, time);
	};

	/**
	 *  stop the oscillator
	 *  @param  {Time} time
	 *  @private
	 */
	Tone.PulseOscillator.prototype._stop = function(time){
		time = this.toSeconds(time);
		this._sawtooth.stop(time);
		//the width is still connected to the output.
		//that needs to be stopped also
		this._widthGate.gain.setValueAtTime(0, time);
	};

	/**
	 *  restart the oscillator
	 *  @param  {Time} time (optional) timing parameter
	 *  @private
	 */
	Tone.PulseOscillator.prototype.restart = function(time){
		this._sawtooth.restart(time);
		this._widthGate.gain.cancelScheduledValues(time);
		this._widthGate.gain.setValueAtTime(1, time);
	};

	/**
	 * The phase of the oscillator in degrees.
	 * @memberOf Tone.PulseOscillator#
	 * @type {Degrees}
	 * @name phase
	 */
	Object.defineProperty(Tone.PulseOscillator.prototype, "phase", {
		get : function(){
			return this._sawtooth.phase;
		},
		set : function(phase){
			this._sawtooth.phase = phase;
		}
	});

	/**
	 * The type of the oscillator. Always returns "pulse".
	 * @readOnly
	 * @memberOf Tone.PulseOscillator#
	 * @type {string}
	 * @name type
	 */
	Object.defineProperty(Tone.PulseOscillator.prototype, "type", {
		get : function(){
			return "pulse";
		}
	});

	/**
	 * The partials of the waveform. Cannot set partials for this waveform type
	 * @memberOf Tone.PulseOscillator#
	 * @type {Array}
	 * @name partials
	 * @private
	 */
	Object.defineProperty(Tone.PulseOscillator.prototype, "partials", {
		get : function(){
			return [];
		}
	});

	/**
	 *  Clean up method.
	 *  @return {Tone.PulseOscillator} this
	 */
	Tone.PulseOscillator.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		this._sawtooth.dispose();
		this._sawtooth = null;
		this._writable(["width", "frequency", "detune"]);
		this.width.dispose();
		this.width = null;
		this._widthGate.dispose();
		this._widthGate = null;
		this._thresh.dispose();
		this._thresh = null;
		this.frequency = null;
		this.detune = null;
		return this;
	};

	return Tone.PulseOscillator;
});
<|endoftext|>


<commit_before>describe('app.controllers.api.sequences.create', function () {

  var operationId;
  var structureId;

  beforeEach(function (done) {
    app.models.Operation
      .create({
        validation: { type: 'string' }
      }, function (err, op) {
        operationId = op._id;

        app.models.DataStructure
          .create({
            validation: { type: 'string' },
            operations: [ operationId ]
          }, function (err, struct) {
            structureId = struct._id;
            done();
          });
      });
  });

  it('fails if the user is not logged in', function (done) {
    session
      .post('/api/sequences')
      .send({
        name: 'fake',
        data: 'fake',
        operations: [
          { type: operationId, data: 'fake' }
        ],
        type: structureId
      })
      .end(function (err, res) {
        assert.equal(res.status, 400);
        done();
      });
  });

  it('fails if the appropriate params are not provided', function (done) {
    helpers.session.create(function () {
      session
        .post('/api/sequences')
        .end(function (err, res) {
          assert.equal(res.status, 400);
          done();
        });
    });
  });

  it('succeeds if the appropriate params are provided', function (done) {
    helpers.session.create(function () {
      session
        .post('/api/sequences')
        .send({
          name: 'fake',
          data: 'fake',
          operations: [
            { type: operationId, data: 'fake' }
          ],
          type: structureId
        })
        .end(function (err, res) {
          assert.equal(res.status, 201);
          app.models.Sequence
            .findOne({
              _id: res.body._id
            })
            .exec(function (err, seq) {
              assert.isNotNull(seq);
              done();
            });
        });
    });
  });
});<commit_msg>added test to sequence route<commit_after>describe('app.controllers.api.sequences.create', function () {

  var operationId;
  var structureId;

  beforeEach(function (done) {
    app.models.Operation
      .create({
        validation: { type: 'string' }
      }, function (err, op) {
        operationId = op._id;

        app.models.DataStructure
          .create({
            validation: { type: 'string' },
            operations: [ operationId ]
          }, function (err, struct) {
            structureId = struct._id;
            done();
          });
      });
  });

  it('fails if the user is not logged in', function (done) {
    session
      .post('/api/sequences')
      .send({
        name: 'fake',
        data: 'fake',
        operations: [
          { type: operationId, data: 'fake' }
        ],
        type: structureId
      })
      .end(function (err, res) {
        assert.equal(res.status, 400);
        done();
      });
  });

  it('fails if the operation type is not sent', function (done) {
    session
      .post('/api/sequences')
      .send({
        name: 'fake',
        data: 'fake',
        operations: [
          'fake'
        ],
        type: structureId
      })
      .end(function (err, res) {
        assert.equal(res.status, 400);
        done();
      })
  });

  it('fails if the appropriate params are not provided', function (done) {
    helpers.session.create(function () {
      session
        .post('/api/sequences')
        .end(function (err, res) {
          assert.equal(res.status, 400);
          done();
        });
    });
  });

  it('succeeds if the appropriate params are provided', function (done) {
    helpers.session.create(function () {
      session
        .post('/api/sequences')
        .send({
          name: 'fake',
          data: 'fake',
          operations: [
            { type: operationId, data: 'fake' }
          ],
          type: structureId
        })
        .end(function (err, res) {
          assert.equal(res.status, 201);
          app.models.Sequence
            .findOne({
              _id: res.body._id
            })
            .exec(function (err, seq) {
              assert.isNotNull(seq);
              done();
            });
        });
    });
  });
});<|endoftext|>


<commit_before>var throttle = require('lodash-node/modern/functions/throttle');
var data = require('./data');
var sound = require('../../sound');
var game = require('./game');
var ground = require('./ground');
var promotion = require('./promotion');
var replayCtrl = require('./replay/replayCtrl');
var chat = require('./chat');
var clockCtrl = require('./clock/clockCtrl');
var i18n = require('../../i18n');
var gameStatus = require('./status');
var correspondenceClockCtrl = require('./correspondenceClock/correspondenceCtrl');
var menu = require('../menu');
var session = require('../../session');
var socket = require('../../socket');
var socketHandler = require('./socketHandler');
var signals = require('../../signals');
var atomic = require('./atomic');
var backbutton = require('../../backbutton');
var helper = require('../helper')

module.exports = function(cfg) {

  this.data = data(cfg);

  helper.analyticsTrackView('Round');

  this.vm = {
    connectedWS: true,
    flip: false,
    showingActions: false
  };

  this.socket = socket.connectGame(
    this.data.url.socket,
    this.data.player.version,
    socketHandler(this),
    this.data.url.round
  );

  this.showActions = function() {
    menu.close();
    backbutton.stack.push(this.hideActions);
    this.vm.showingActions = true;
  }.bind(this);

  this.hideActions = function(fromBB) {
    if (fromBB !== 'backbutton' && this.vm.showingActions) backbutton.stack.pop();
    this.vm.showingActions = false;
  }.bind(this);

  this.flip = function() {
    this.vm.flip = !this.vm.flip;
    this.chessground.set({
      orientation: this.vm.flip ? this.data.opponent.color : this.data.player.color
    });
  }.bind(this);

  this.setTitle = function() {
    if (this.data.player.spectator)
      this.title = 'lichess.org';
    else if (gameStatus.finished(this.data))
      this.title = i18n('gameOver');
    else if (gameStatus.aborted(this.data))
      this.title = i18n('gameAborted');
    else if (game.isPlayerTurn(this.data))
      this.title = i18n('yourTurn');
    else
      this.title = i18n('waitingForOpponent');
  };
  this.setTitle();

  this.sendMove = function(orig, dest, prom) {
    var move = {
      from: orig,
      to: dest
    };
    if (prom) move.promotion = prom;
    this.socket.send('move', move, {
      ackable: true
    });
  }.bind(this);

  var userMove = function(orig, dest, meta) {
    if (!promotion.start(this, orig, dest, meta.premove)) this.sendMove(orig, dest);
    if (this.data.game.speed === 'correspondence' && session.isConnected())
      session.refresh();
  }.bind(this);

  var onMove = function(orig, dest, capturedPiece) {
    if (!capturedPiece)
      sound.move();
    else if (this.data.game.variant.key === 'atomic') atomic.capture(this, dest);
    else sound.capture();
  }.bind(this);

  this.apiMove = function(o) {
    m.startComputation();
    if (!this.replay.active) this.chessground.apiMove(o.from, o.to);
    if (this.data.game.threefold) this.data.game.threefold = false;
    this.data.game.moves.push(o.san);
    game.setOnGame(this.data, o.color, true);
    m.endComputation();
  }.bind(this);

  this.chessground = ground.make(this.data, cfg.game.fen, userMove, onMove);

  this.reload = function(cfg) {
    this.replay.onReload(cfg);
    if (this.chat) this.chat.onReload(cfg.chat);
    this.data = data(cfg);
    makeCorrespondenceClock();
    this.setTitle();
    if (!this.replay.active) ground.reload(this.chessground, this.data, cfg.game.fen, this.vm.flip);
  }.bind(this);

  this.clock = this.data.clock ? new clockCtrl(
    this.data.clock,
    this.data.player.spectator ? function() {} : throttle(function() {
      if (this.socket) this.socket.send('outoftime');
    }.bind(this), 500),
    this.data.player.spectator ? null : this.data.player.color
  ) : false;

  this.isClockRunning = function() {
    return this.data.clock && game.playable(this.data) &&
      ((this.data.game.turns - this.data.game.startedAtTurn) > 1 || this.data.clock.running);
  }.bind(this);

  this.clockTick = function() {
    if (this.isClockRunning()) this.clock.tick(this.data.game.player);
  }.bind(this);

  var makeCorrespondenceClock = function() {
    if (this.data.correspondence && !this.correspondenceClock)
      this.correspondenceClock = new correspondenceClockCtrl(
        this.data.correspondence,
        function() { if (this.socket) this.socket.send('outoftime'); }.bind(this)
      );
  }.bind(this);
  makeCorrespondenceClock();

  var correspondenceClockTick = function() {
    if (this.correspondenceClock && game.playable(this.data))
      this.correspondenceClock.tick(this.data.game.player);
  }.bind(this);

  var clockIntervId;
  if (this.clock) clockIntervId = setInterval(this.clockTick, 100);
  else clockIntervId = setInterval(correspondenceClockTick, 1000);

  this.replay = new replayCtrl(this);

  this.chat = !this.data.opponent.ai ? new chat.controller(this) : false;

  window.plugins.insomnia.keepAwake();

  var onConnected = function() {
    var wasOff = !this.vm.connectedWS;
    this.vm.connectedWS = true;
    if (wasOff) m.redraw();
  }.bind(this);

  var onDisconnected = function() {
    var wasOn = this.vm.connectedWS;
    this.vm.connectedWS = false;
    if (wasOn) setTimeout(function() {
      m.redraw();
    }, 2000);
  }.bind(this);

  signals.connected.add(onConnected);
  signals.disconnected.add(onDisconnected);

  this.onunload = function() {
    this.socket.destroy();
    this.socket = null;
    if (clockIntervId) clearInterval(clockIntervId);
    if (this.chat) this.chat.onunload();
    signals.connected.remove(onConnected);
    signals.disconnected.remove(onDisconnected);
    window.plugins.insomnia.allowSleepAgain();
  };
};
<commit_msg>Disable chat in spectator mode<commit_after>var throttle = require('lodash-node/modern/functions/throttle');
var data = require('./data');
var sound = require('../../sound');
var game = require('./game');
var ground = require('./ground');
var promotion = require('./promotion');
var replayCtrl = require('./replay/replayCtrl');
var chat = require('./chat');
var clockCtrl = require('./clock/clockCtrl');
var i18n = require('../../i18n');
var gameStatus = require('./status');
var correspondenceClockCtrl = require('./correspondenceClock/correspondenceCtrl');
var menu = require('../menu');
var session = require('../../session');
var socket = require('../../socket');
var socketHandler = require('./socketHandler');
var signals = require('../../signals');
var atomic = require('./atomic');
var backbutton = require('../../backbutton');
var helper = require('../helper')

module.exports = function(cfg) {

  this.data = data(cfg);

  helper.analyticsTrackView('Round');

  this.vm = {
    connectedWS: true,
    flip: false,
    showingActions: false
  };

  this.socket = socket.connectGame(
    this.data.url.socket,
    this.data.player.version,
    socketHandler(this),
    this.data.url.round
  );

  this.showActions = function() {
    menu.close();
    backbutton.stack.push(this.hideActions);
    this.vm.showingActions = true;
  }.bind(this);

  this.hideActions = function(fromBB) {
    if (fromBB !== 'backbutton' && this.vm.showingActions) backbutton.stack.pop();
    this.vm.showingActions = false;
  }.bind(this);

  this.flip = function() {
    this.vm.flip = !this.vm.flip;
    this.chessground.set({
      orientation: this.vm.flip ? this.data.opponent.color : this.data.player.color
    });
  }.bind(this);

  this.setTitle = function() {
    if (this.data.player.spectator)
      this.title = 'lichess.org';
    else if (gameStatus.finished(this.data))
      this.title = i18n('gameOver');
    else if (gameStatus.aborted(this.data))
      this.title = i18n('gameAborted');
    else if (game.isPlayerTurn(this.data))
      this.title = i18n('yourTurn');
    else
      this.title = i18n('waitingForOpponent');
  };
  this.setTitle();

  this.sendMove = function(orig, dest, prom) {
    var move = {
      from: orig,
      to: dest
    };
    if (prom) move.promotion = prom;
    this.socket.send('move', move, {
      ackable: true
    });
  }.bind(this);

  var userMove = function(orig, dest, meta) {
    if (!promotion.start(this, orig, dest, meta.premove)) this.sendMove(orig, dest);
    if (this.data.game.speed === 'correspondence' && session.isConnected())
      session.refresh();
  }.bind(this);

  var onMove = function(orig, dest, capturedPiece) {
    if (!capturedPiece)
      sound.move();
    else if (this.data.game.variant.key === 'atomic') atomic.capture(this, dest);
    else sound.capture();
  }.bind(this);

  this.apiMove = function(o) {
    m.startComputation();
    if (!this.replay.active) this.chessground.apiMove(o.from, o.to);
    if (this.data.game.threefold) this.data.game.threefold = false;
    this.data.game.moves.push(o.san);
    game.setOnGame(this.data, o.color, true);
    m.endComputation();
  }.bind(this);

  this.chessground = ground.make(this.data, cfg.game.fen, userMove, onMove);

  this.reload = function(cfg) {
    this.replay.onReload(cfg);
    if (this.chat) this.chat.onReload(cfg.chat);
    this.data = data(cfg);
    makeCorrespondenceClock();
    this.setTitle();
    if (!this.replay.active) ground.reload(this.chessground, this.data, cfg.game.fen, this.vm.flip);
  }.bind(this);

  this.clock = this.data.clock ? new clockCtrl(
    this.data.clock,
    this.data.player.spectator ? function() {} : throttle(function() {
      if (this.socket) this.socket.send('outoftime');
    }.bind(this), 500),
    this.data.player.spectator ? null : this.data.player.color
  ) : false;

  this.isClockRunning = function() {
    return this.data.clock && game.playable(this.data) &&
      ((this.data.game.turns - this.data.game.startedAtTurn) > 1 || this.data.clock.running);
  }.bind(this);

  this.clockTick = function() {
    if (this.isClockRunning()) this.clock.tick(this.data.game.player);
  }.bind(this);

  var makeCorrespondenceClock = function() {
    if (this.data.correspondence && !this.correspondenceClock)
      this.correspondenceClock = new correspondenceClockCtrl(
        this.data.correspondence,
        function() { if (this.socket) this.socket.send('outoftime'); }.bind(this)
      );
  }.bind(this);
  makeCorrespondenceClock();

  var correspondenceClockTick = function() {
    if (this.correspondenceClock && game.playable(this.data))
      this.correspondenceClock.tick(this.data.game.player);
  }.bind(this);

  var clockIntervId;
  if (this.clock) clockIntervId = setInterval(this.clockTick, 100);
  else clockIntervId = setInterval(correspondenceClockTick, 1000);

  this.replay = new replayCtrl(this);

  this.chat = (this.data.opponent.ai || this.data.player.spectator) ?
    null : new chat.controller(this);

  window.plugins.insomnia.keepAwake();

  var onConnected = function() {
    var wasOff = !this.vm.connectedWS;
    this.vm.connectedWS = true;
    if (wasOff) m.redraw();
  }.bind(this);

  var onDisconnected = function() {
    var wasOn = this.vm.connectedWS;
    this.vm.connectedWS = false;
    if (wasOn) setTimeout(function() {
      m.redraw();
    }, 2000);
  }.bind(this);

  signals.connected.add(onConnected);
  signals.disconnected.add(onDisconnected);

  this.onunload = function() {
    this.socket.destroy();
    this.socket = null;
    if (clockIntervId) clearInterval(clockIntervId);
    if (this.chat) this.chat.onunload();
    signals.connected.remove(onConnected);
    signals.disconnected.remove(onDisconnected);
    window.plugins.insomnia.allowSleepAgain();
  };
};
<|endoftext|>


<commit_before><commit_msg>Update ogario.v4.master.js<commit_after><|endoftext|>


<commit_before>/* global Dropzone*/
import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['dropzone'],

  myDropzone: document.body || undefined,

  dropzoneOptions: null,

  // Configuration Options

  url: '#',
  withCredentials: null,
  method: null,
  parallelUploads: null,
  maxFilesize: null,
  filesizeBase: null,
  paramName: null,
  uploadMultiple: null,
  headers: null,
  addRemoveLinks: null,
  previewsContainer: null,
  clickable: null,
  maxThumbnailFilesize: null,
  thumbnailWidth: null,
  thumbnailHeight: null,
  maxFiles: null,
  createImageThumbnails: null,

  //params hash
  params: null,

  // resize: not available
  acceptedFiles: null,
  autoProcessQueue: null,
  forceFallback: null,
  previewTemplate: null,

  // Dropzone translations
  dictDefaultMessage: null,
  dictFallbackMessage: null,
  dictFallbackText: null,
  dictInvalidFileType: null,
  dictFileTooBig: null,
  dictResponseError: null,
  dictCancelUpload: null,
  dictCancelUploadConfirmation: null,
  dictRemoveFile: null,
  dictMaxFilesExceeded: null,

  // Bonus for full screen zones
  maxDropRegion: null,

  // Events

  // All of these receive the event as first parameter:
  drop: null,
  dragstart: null,
  dragend: null,
  dragenter: null,
  dragover: null,
  dragleave: null,

  // All of these receive the file as first parameter:
  addedfile: null,
  removedfile: null,
  thumbnail: null,
  error: null,
  processing: null,
  uploadprogress: null,
  sending: null,
  success: null,
  complete: null,
  canceled: null,
  maxfilesreached: null,
  maxfilesexceeded: null,

  // All of these receive a list of files as first parameter and are only called if the uploadMultiple option is true:
  processingmultiple: null,
  sendingmultiple: null,
  successmultiple: null,
  completemultiple: null,
  canceledmultiple: null,

  // Special events:
  totaluploadprogress: null,
  reset: null,
  queuecomplete: null,
  files: null,

  // Callback functions
  accept: null,

  setEvents() {
    let myDropzone = this.get('myDropzone');
    let events = {
      drop: this.drop,
      dragstart: this.dragstart,
      dragend: this.dragend,
      dragenter: this.dragenter,
      dragover: this.dragover,
      dragleave: this.dragleave,
      addedfile: this.addedfile,
      removedfile: this.removedfile,
      thumbnail: this.thumbnail,
      error: this.error,
      processing: this.processing,
      uploadprogress: this.uploadprogress,
      sending: this.sending,
      success: this.success,
      complete: this.complete,
      canceled: this.canceled,
      maxfilesreached: this.maxfilesreached,
      maxfilesexceeded: this.maxfilesexceeded,
      processingmultiple: this.processingmultiple,
      sendingmultiple: this.sendingmultiple,
      successmultiple: this.successmultiple,
      completemultiple: this.completemultiple,
      canceledmultiple: this.canceledmultiple,
      totaluploadprogress: this.totaluploadprogress,
      reset: this.reset,
      queuecomplete: this.queuecomplete,
      files: this.files,
      accept: this.accept,
    };

    for (let e in events) {
      if (events[e] !== null) {
        myDropzone.on(e, events[e]);
      }
    }
  },

  getDropzoneOptions() {
    let dropzoneOptions = {};
    let dropzoneConfig = {
      url: this.url,
      withCredentials: this.withCredentials,
      method: this.method,
      parallelUploads: this.parallelUploads,
      maxFilesize: this.maxFilesize,
      filesizeBase: this.filesizeBase,
      paramName: this.paramName,
      uploadMultiple: this.uploadMultiple,
      headers: this.headers,
      addRemoveLinks: this.addRemoveLinks,
      previewsContainer: this.previewsContainer,
      clickable: this.clickable,
      maxThumbnailFilesize: this.maxThumbnailFilesize,
      thumbnailWidth: this.thumbnailWidth,
      thumbnailHeight: this.thumbnailHeight,
      maxFiles: this.maxFiles,
      createImageThumbnails: this.createImageThumbnails,
      params: this.params,

      // resize: not available
      acceptedFiles: this.acceptedFiles,
      autoProcessQueue: this.autoProcessQueue,
      forceFallback: this.forceFallback,
      previewTemplate: this.previewTemplate,

      // Dropzone translations
      dictDefaultMessage: this.dictDefaultMessage,
      dictFallbackMessage: this.dictFallbackMessage,
      dictFallbackText: this.dictFallbackText,
      dictInvalidFileType: this.dictInvalidFileType,
      dictFileTooBig: this.dictFileTooBig,
      dictResponseError: this.dictResponseError,
      dictCancelUpload: this.dictCancelUpload,
      dictCancelUploadConfirmation: this.dictCancelUploadConfirmation,
      dictRemoveFile: this.dictRemoveFile,
      dictMaxFilesExceeded: this.dictMaxFilesExceeded,

      // Fix flickering dragging over child elements: https://github.com/enyo/dropzone/issues/438
      init: function() {
        this.dragEnteredEls = new Array();
      },
      dragenter: function(e) {
        this.dragEnteredEls.push(e.target);
        Ember.$(this.element).addClass('dz-drag-hover');
      },
      dragleave: function(e) {
        this.dragEnteredEls = Ember.$(this.dragEnteredEls).not(e.target);
        if (this.dragEnteredEls.length === 0) {
          Ember.$(this.element).removeClass('dz-drag-hover');
        }
      },
    };

    for (let option in dropzoneConfig) {
      let data = dropzoneConfig[option];
      if (data !== null) {
        dropzoneOptions[option] = data;
      } else if (option === 'thumbnailHeight' || option === 'thumbnailWidth') {
        dropzoneOptions[option] = data;
      }
    }

    this.set('dropzoneOptions', dropzoneOptions);
  },

  createDropzone(element) {
    let region = this.get('maxDropRegion') ? document.body : element;
    this.set('myDropzone', new Dropzone(region, this.dropzoneOptions));
  },

  destroyDropzone: Ember.on('willDestroyElement', function() {
    this.get('myDropzone').destroy();
  }),

  insertDropzone: Ember.on('didInsertElement', function() {
    let _this = this;
    this.getDropzoneOptions();
    Dropzone.autoDiscover = false;
    this.createDropzone(this.element);
    //make sure events are set before any files are added
    this.setEvents();

    //this condition requires a fully resolved array to work
    //will not work with model.get('files') as it returns promise not array hence length condition is failed
    if (this.files && this.files.length > 0) {
      this.files.map(function(file) {
        let dropfile = {
          name: file.get('name'),
          type: file.get('type'),
          size: file.get('size'),
          status: Dropzone.ADDED,
          //add support for id  in files object so that it can be access in addedFile,removedFile callbacks for files identified by id
          id: file.get('id')
        };
        let thumbnail = file.get('thumbnail');

        if (typeof (thumbnail) === 'string') {
          dropfile.thumbnail = thumbnail;
        }

        _this.myDropzone.emit('addedfile', dropfile);

        if (typeof (thumbnail) === 'string') {

          _this.myDropzone.emit('thumbnail', dropfile, thumbnail);
        }

        _this.myDropzone.emit('complete', dropfile);
        _this.myDropzone.files.push(file);
      });
    }

    return this.myDropzone;
  }),
});
<commit_msg>Fix failing build due to jshint<commit_after>/* global Dropzone*/
import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['dropzone'],

  myDropzone: document.body || undefined,

  dropzoneOptions: null,

  // Configuration Options

  url: '#',
  withCredentials: null,
  method: null,
  parallelUploads: null,
  maxFilesize: null,
  filesizeBase: null,
  paramName: null,
  uploadMultiple: null,
  headers: null,
  addRemoveLinks: null,
  previewsContainer: null,
  clickable: null,
  maxThumbnailFilesize: null,
  thumbnailWidth: null,
  thumbnailHeight: null,
  maxFiles: null,
  createImageThumbnails: null,

  //params hash
  params: null,

  // resize: not available
  acceptedFiles: null,
  autoProcessQueue: null,
  forceFallback: null,
  previewTemplate: null,

  // Dropzone translations
  dictDefaultMessage: null,
  dictFallbackMessage: null,
  dictFallbackText: null,
  dictInvalidFileType: null,
  dictFileTooBig: null,
  dictResponseError: null,
  dictCancelUpload: null,
  dictCancelUploadConfirmation: null,
  dictRemoveFile: null,
  dictMaxFilesExceeded: null,

  // Bonus for full screen zones
  maxDropRegion: null,

  // Events

  // All of these receive the event as first parameter:
  drop: null,
  dragstart: null,
  dragend: null,
  dragenter: null,
  dragover: null,
  dragleave: null,

  // All of these receive the file as first parameter:
  addedfile: null,
  removedfile: null,
  thumbnail: null,
  error: null,
  processing: null,
  uploadprogress: null,
  sending: null,
  success: null,
  complete: null,
  canceled: null,
  maxfilesreached: null,
  maxfilesexceeded: null,

  // All of these receive a list of files as first parameter and are only called if the uploadMultiple option is true:
  processingmultiple: null,
  sendingmultiple: null,
  successmultiple: null,
  completemultiple: null,
  canceledmultiple: null,

  // Special events:
  totaluploadprogress: null,
  reset: null,
  queuecomplete: null,
  files: null,

  // Callback functions
  accept: null,

  setEvents() {
    let myDropzone = this.get('myDropzone');
    let events = {
      drop: this.drop,
      dragstart: this.dragstart,
      dragend: this.dragend,
      dragenter: this.dragenter,
      dragover: this.dragover,
      dragleave: this.dragleave,
      addedfile: this.addedfile,
      removedfile: this.removedfile,
      thumbnail: this.thumbnail,
      error: this.error,
      processing: this.processing,
      uploadprogress: this.uploadprogress,
      sending: this.sending,
      success: this.success,
      complete: this.complete,
      canceled: this.canceled,
      maxfilesreached: this.maxfilesreached,
      maxfilesexceeded: this.maxfilesexceeded,
      processingmultiple: this.processingmultiple,
      sendingmultiple: this.sendingmultiple,
      successmultiple: this.successmultiple,
      completemultiple: this.completemultiple,
      canceledmultiple: this.canceledmultiple,
      totaluploadprogress: this.totaluploadprogress,
      reset: this.reset,
      queuecomplete: this.queuecomplete,
      files: this.files,
      accept: this.accept,
    };

    for (let e in events) {
      if (events[e] !== null) {
        myDropzone.on(e, events[e]);
      }
    }
  },

  getDropzoneOptions() {
    let dropzoneOptions = {};
    let dropzoneConfig = {
      url: this.url,
      withCredentials: this.withCredentials,
      method: this.method,
      parallelUploads: this.parallelUploads,
      maxFilesize: this.maxFilesize,
      filesizeBase: this.filesizeBase,
      paramName: this.paramName,
      uploadMultiple: this.uploadMultiple,
      headers: this.headers,
      addRemoveLinks: this.addRemoveLinks,
      previewsContainer: this.previewsContainer,
      clickable: this.clickable,
      maxThumbnailFilesize: this.maxThumbnailFilesize,
      thumbnailWidth: this.thumbnailWidth,
      thumbnailHeight: this.thumbnailHeight,
      maxFiles: this.maxFiles,
      createImageThumbnails: this.createImageThumbnails,
      params: this.params,

      // resize: not available
      acceptedFiles: this.acceptedFiles,
      autoProcessQueue: this.autoProcessQueue,
      forceFallback: this.forceFallback,
      previewTemplate: this.previewTemplate,

      // Dropzone translations
      dictDefaultMessage: this.dictDefaultMessage,
      dictFallbackMessage: this.dictFallbackMessage,
      dictFallbackText: this.dictFallbackText,
      dictInvalidFileType: this.dictInvalidFileType,
      dictFileTooBig: this.dictFileTooBig,
      dictResponseError: this.dictResponseError,
      dictCancelUpload: this.dictCancelUpload,
      dictCancelUploadConfirmation: this.dictCancelUploadConfirmation,
      dictRemoveFile: this.dictRemoveFile,
      dictMaxFilesExceeded: this.dictMaxFilesExceeded,

      // Fix flickering dragging over child elements: https://github.com/enyo/dropzone/issues/438
      init: function() {
        this.dragEnteredEls = [];
      },
      dragenter: function(e) {
        this.dragEnteredEls.push(e.target);
        Ember.$(this.element).addClass('dz-drag-hover');
      },
      dragleave: function(e) {
        this.dragEnteredEls = Ember.$(this.dragEnteredEls).not(e.target);
        if (this.dragEnteredEls.length === 0) {
          Ember.$(this.element).removeClass('dz-drag-hover');
        }
      },
    };

    for (let option in dropzoneConfig) {
      let data = dropzoneConfig[option];
      if (data !== null) {
        dropzoneOptions[option] = data;
      } else if (option === 'thumbnailHeight' || option === 'thumbnailWidth') {
        dropzoneOptions[option] = data;
      }
    }

    this.set('dropzoneOptions', dropzoneOptions);
  },

  createDropzone(element) {
    let region = this.get('maxDropRegion') ? document.body : element;
    this.set('myDropzone', new Dropzone(region, this.dropzoneOptions));
  },

  destroyDropzone: Ember.on('willDestroyElement', function() {
    this.get('myDropzone').destroy();
  }),

  insertDropzone: Ember.on('didInsertElement', function() {
    let _this = this;
    this.getDropzoneOptions();
    Dropzone.autoDiscover = false;
    this.createDropzone(this.element);
    //make sure events are set before any files are added
    this.setEvents();

    //this condition requires a fully resolved array to work
    //will not work with model.get('files') as it returns promise not array hence length condition is failed
    if (this.files && this.files.length > 0) {
      this.files.map(function(file) {
        let dropfile = {
          name: file.get('name'),
          type: file.get('type'),
          size: file.get('size'),
          status: Dropzone.ADDED,
          //add support for id  in files object so that it can be access in addedFile,removedFile callbacks for files identified by id
          id: file.get('id')
        };
        let thumbnail = file.get('thumbnail');

        if (typeof (thumbnail) === 'string') {
          dropfile.thumbnail = thumbnail;
        }

        _this.myDropzone.emit('addedfile', dropfile);

        if (typeof (thumbnail) === 'string') {

          _this.myDropzone.emit('thumbnail', dropfile, thumbnail);
        }

        _this.myDropzone.emit('complete', dropfile);
        _this.myDropzone.files.push(file);
      });
    }

    return this.myDropzone;
  }),
});
<|endoftext|>


<commit_before>/*
 * CS3283/4 dataModifier.js
 * This acts as a facade class for modifying and update data for storage facade
 *
 */

import dataAdd from 'src/database/data-modifier/dataAdd';
import dataDelete from 'src/database/data-modifier/dataDelete';
import dataUpdate from 'src/database/data-modifier/dataUpdate';
import exceptions from 'src/database/exceptions';
import SqlCommands from 'src/database/sql-related/sqlCommands';
import StringManipulator from 'src/database/stringManipulation';

const stringManipulator = new StringManipulator();

const sqlCommands = new SqlCommands();

function resolveFileSaving(fileContent) {
  return stringManipulator.replaceAll(fileContent, '"', '\\"');
}

export default class dataModifier {
  static constructor() {}

  static deleteAllEntities(databaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataDelete.deleteAllEntities(databaseName)
        .then(data => resolve(data))
        .catch(sqlErr => reject(sqlErr))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createNewFile(organizationId, filePath, folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataAdd.createNewFile(organizationId, filePath, folderId)
        .then(fileObject => resolve(fileObject))
        .catch(sqlErr => reject(sqlErr))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createNewFolder(organizationId, folderPath, folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataAdd.createNewFolder(organizationId, folderPath, folderId)
        .then(folderObject => resolve(folderObject))
        .catch(sqlErr => reject(sqlErr))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static saveFile(fileId, file) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataUpdate.saveFile(fileId, file)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataDelete.deleteFile(fileId)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataDelete.deleteFolder(folderId)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }
}
<commit_msg>Add saveFile function implementation to dataModifier.js<commit_after>/*
 * CS3283/4 dataModifier.js
 * This acts as a facade class for modifying and update data for storage facade
 *
 */

import dataAdd from 'src/database/data-modifier/dataAdd';
import dataDelete from 'src/database/data-modifier/dataDelete';
import dataUpdate from 'src/database/data-modifier/dataUpdate';
import exceptions from 'src/database/exceptions';
import SqlCommands from 'src/database/sql-related/sqlCommands';
import StringManipulator from 'src/database/stringManipulation';

const stringManipulator = new StringManipulator();

const sqlCommands = new SqlCommands();

function resolveFileSaving(fileContent) {
  return stringManipulator.replaceAll(fileContent, '"', '\\"');
}

export default class dataModifier {
  static constructor() {}

  static deleteAllEntities(databaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataDelete.deleteAllEntities(databaseName)
        .then(data => resolve(data))
        .catch(sqlErr => reject(sqlErr))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createNewFile(organizationId, filePath, folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataAdd.createNewFile(organizationId, filePath, folderId)
        .then(fileObject => resolve(fileObject))
        .catch(sqlErr => reject(sqlErr))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createNewFolder(organizationId, folderPath, folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataAdd.createNewFolder(organizationId, folderPath, folderId)
        .then(folderObject => resolve(folderObject))
        .catch(sqlErr => reject(sqlErr))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static saveFile(fileId, file) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataUpdate.saveFile(fileId, file)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static saveFile(fileId, fileContent) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        fileContent = resolveFileSaving(fileContent);
        dataUpdate.saveFile(fileId, fileContent)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataDelete.deleteFile(fileId)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataDelete.deleteFolder(folderId)
        .then(() => resolve())
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }
}
<|endoftext|>


<commit_before>$(document).ready(function() {
    if($('#q')) {
        $('#categories label').click(function(e) {
            $('#categories input[type="checkbox"]').each(function(i, checkbox) {
                $(checkbox).prop('checked', false);
            });
            $('#categories label').removeClass('btn-primary').removeClass('active').addClass('btn-default');
            $(this).removeClass('btn-default').addClass('btn-primary').addClass('active');
            $($(this).children()[0]).prop('checked', 'checked');
            $('#search_form').submit();
            return false;
        });
    }
});
<commit_msg>[fix] do not use category select js if there is no search query field on the page<commit_after>$(document).ready(function() {
    if($('#q').length) {
        $('#categories label').click(function(e) {
            $('#categories input[type="checkbox"]').each(function(i, checkbox) {
                $(checkbox).prop('checked', false);
            });
            $('#categories label').removeClass('btn-primary').removeClass('active').addClass('btn-default');
            $(this).removeClass('btn-default').addClass('btn-primary').addClass('active');
            $($(this).children()[0]).prop('checked', 'checked');
            $('#search_form').submit();
            return false;
        });
    }
});
<|endoftext|>


<commit_before>define(
    [
        'service/serviceBase'
    ],
    function (ServiceBase) {
      'use strict';

        function OntologyService() {
            ServiceBase.call(this);
            return this;
        }

        OntologyService.prototype = Object.create(ServiceBase.prototype);

        OntologyService.prototype.clearCaches = function () {
            cachedConcepts = null;
            cachedRelationships = null;
            cachedProperties = null;
        };

        var cachedConcepts;
        OntologyService.prototype.concepts = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedConcepts) {
                cachedConcepts.done(function(v) {callback(null, v); });
                return cachedConcepts;
            }

            cachedConcepts = this._ajaxGet({
                url: 'ontology/concept'
            }).then(function(response) {
                var entityConcept = findConceptByTitle(response, 'entity');
                return {
                    tree: response,
                    entityConcept: entityConcept,
                    byId: buildConceptMapById(response, {}),
                    byTitle: flattenConcepts(entityConcept)
                };
            }).always(function(data) {callback(null, data); });

            return cachedConcepts;

            function findConceptByTitle(concept, title) {
                if (concept.title == title) {
                    return concept;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        var child = concept.children[i];
                        var c = findConceptByTitle(child, title);
                        if (c) {
                            return c;
                        }
                    }
                }
                return null;
            }

            function buildConceptMapById(concept, map, parentId) {
                map[concept.id] = concept;
                if (parentId) {
                    concept.parentId = parentId;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        buildConceptMapById(concept.children[i], map, concept.id);
                    }
                }
                return map;
            }

            function flattenConcepts(concept) {
                var childIdx, child, grandChildIdx;
                var flattenedConcepts = [];
                for (childIdx in concept.children) {
                    child = concept.children[childIdx];
                    if (concept.flattenedTitle) {
                        child.flattenedTitle = concept.flattenedTitle + "/" + child.title;
                        child.flattenedDisplayName = concept.flattenedDisplayName + "/" + child.displayName;
                    } else {
                        child.flattenedTitle = child.title;
                        child.flattenedDisplayName = child.displayName;
                    }
                    flattenedConcepts.push(child);
                    var grandChildren = flattenConcepts(child);
                    for (grandChildIdx in grandChildren) {
                        flattenedConcepts.push(grandChildren[grandChildIdx]);
                    }
                }
                return _.sortBy(flattenedConcepts, 'flattenedDisplayName');
            }
        };

        var cachedRelationships;
        OntologyService.prototype.relationships = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedRelationships) {
                cachedRelationships.done(function(v) {callback(null, v); });
                return cachedRelationships;
            }

            cachedRelationships = this._ajaxGet({
                url: 'ontology/relationship'
            }).then(function(response) {
                return {
                    list: response.relationships,
                    byTitle: buildRelationshipsByTitle(response.relationships),
                    byId: buildRelationshipsById(response.relationships)
                };
            }).always(function(data) {callback(null, data); });

            return cachedRelationships;

            function buildRelationshipsByTitle(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.title] = relationship;
                });
                return result;
            }

            function buildRelationshipsById(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.id] = relationship;
                });
                return result;
            }
        };

        OntologyService.prototype.conceptToConceptRelationships = function(sourceConceptTypeId, destConceptTypeId) {
            return this._ajaxGet({
                url: 'ontology/relationship',
                data: {
                    sourceConceptTypeId: sourceConceptTypeId,
                    destConceptTypeId: destConceptTypeId
                }
            });
        };

        var cachedProperties;
        OntologyService.prototype.properties = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedProperties) {
                cachedProperties.done(function(v) {callback(null, v); });
                return cachedProperties;
            }

            cachedProperties = this._ajaxGet({
                url: 'ontology/property'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            }).always(function(data) {callback(null, data); });

            return cachedProperties;
        };

        OntologyService.prototype.propertiesByConceptId = function (conceptId) {
            return this._ajaxGet({
                url: 'ontology/concept/' + conceptId + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        OntologyService.prototype.propertiesByRelationshipLabel = function (relationshipLabel) {
            return this._ajaxGet({
                url: 'ontology/' + relationshipLabel + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        function buildPropertiesByTitle(properties) {
            var result = {};
            properties.forEach(function (property) {
                result[property.title] = property;
            });
            return result;
        }

        return OntologyService;
    });

<commit_msg>Cache ontology requests in browser<commit_after>define(
    [
        'service/serviceBase'
    ],
    function (ServiceBase) {
      'use strict';

        function OntologyService() {
            ServiceBase.call(this);

            var toMemoize = [
                'propertiesByConceptId',
                'propertiesByRelationshipLabel',
                'conceptToConceptRelationships'
            ];

            var self = this;
            toMemoize.forEach(function(f) {
                self[f] = _.memoize(self[f].bind(self), self[f].memoizeHashFunction);
            });
            return this;
        }

        OntologyService.prototype = Object.create(ServiceBase.prototype);

        OntologyService.prototype.clearCaches = function () {
            cachedConcepts = null;
            cachedRelationships = null;
            cachedProperties = null;
        };

        var cachedConcepts;
        OntologyService.prototype.concepts = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedConcepts) {
                cachedConcepts.done(function(v) {callback(null, v); });
                return cachedConcepts;
            }

            cachedConcepts = this._ajaxGet({
                url: 'ontology/concept'
            }).then(function(response) {
                var entityConcept = findConceptByTitle(response, 'entity');
                return {
                    tree: response,
                    entityConcept: entityConcept,
                    byId: buildConceptMapById(response, {}),
                    byTitle: flattenConcepts(entityConcept)
                };
            }).always(function(data) {callback(null, data); });

            return cachedConcepts;

            function findConceptByTitle(concept, title) {
                if (concept.title == title) {
                    return concept;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        var child = concept.children[i];
                        var c = findConceptByTitle(child, title);
                        if (c) {
                            return c;
                        }
                    }
                }
                return null;
            }

            function buildConceptMapById(concept, map, parentId) {
                map[concept.id] = concept;
                if (parentId) {
                    concept.parentId = parentId;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        buildConceptMapById(concept.children[i], map, concept.id);
                    }
                }
                return map;
            }

            function flattenConcepts(concept) {
                var childIdx, child, grandChildIdx;
                var flattenedConcepts = [];
                for (childIdx in concept.children) {
                    child = concept.children[childIdx];
                    if (concept.flattenedTitle) {
                        child.flattenedTitle = concept.flattenedTitle + "/" + child.title;
                        child.flattenedDisplayName = concept.flattenedDisplayName + "/" + child.displayName;
                    } else {
                        child.flattenedTitle = child.title;
                        child.flattenedDisplayName = child.displayName;
                    }
                    flattenedConcepts.push(child);
                    var grandChildren = flattenConcepts(child);
                    for (grandChildIdx in grandChildren) {
                        flattenedConcepts.push(grandChildren[grandChildIdx]);
                    }
                }
                return _.sortBy(flattenedConcepts, 'flattenedDisplayName');
            }
        };

        var cachedRelationships;
        OntologyService.prototype.relationships = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedRelationships) {
                cachedRelationships.done(function(v) {callback(null, v); });
                return cachedRelationships;
            }

            cachedRelationships = this._ajaxGet({
                url: 'ontology/relationship'
            }).then(function(response) {
                return {
                    list: response.relationships,
                    byTitle: buildRelationshipsByTitle(response.relationships),
                    byId: buildRelationshipsById(response.relationships)
                };
            }).always(function(data) {callback(null, data); });

            return cachedRelationships;

            function buildRelationshipsByTitle(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.title] = relationship;
                });
                return result;
            }

            function buildRelationshipsById(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.id] = relationship;
                });
                return result;
            }
        };

        OntologyService.prototype.conceptToConceptRelationships = function(sourceConceptTypeId, destConceptTypeId) {
            return this._ajaxGet({
                url: 'ontology/relationship',
                data: {
                    sourceConceptTypeId: sourceConceptTypeId,
                    destConceptTypeId: destConceptTypeId
                }
            });
        };
        OntologyService.prototype.conceptToConceptRelationships.memoizeHashFunction = function(s,d) {
            return s+d;
        };

        var cachedProperties;
        OntologyService.prototype.properties = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedProperties) {
                cachedProperties.done(function(v) {callback(null, v); });
                return cachedProperties;
            }

            cachedProperties = this._ajaxGet({
                url: 'ontology/property'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            }).always(function(data) {callback(null, data); });

            return cachedProperties;
        };

        OntologyService.prototype.propertiesByConceptId = function (conceptId) {
            return this._ajaxGet({
                url: 'ontology/concept/' + conceptId + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        OntologyService.prototype.propertiesByRelationshipLabel = function (relationshipLabel) {
            return this._ajaxGet({
                url: 'ontology/' + relationshipLabel + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        function buildPropertiesByTitle(properties) {
            var result = {};
            properties.forEach(function (property) {
                result[property.title] = property;
            });
            return result;
        }

        return OntologyService;
    });

<|endoftext|>


<commit_before>var ProxyHandler = require('lib/proxy_handlers/proxy_handler');

module.exports = UserIdentityModelHandler.inherits( ProxyHandler );

function UserIdentityModelHandler( params ) {
  this._init( params );
}

UserIdentityModelHandler.prototype._init = function( params ) {
  this.super_._init( params );

  this.user_identity = params.user_identity;
  this.params        = params.params;

  this.methods = [
    'get_attribute',
    'set_attribute',
    'get_attributes',
    'set_attributes',
    'save',
    'remove',
    'release'
  ];
};

UserIdentityModelHandler.prototype.access_rights_methods = {
  'can_be_viewed'   : function() { return this.user_identity.can( 'view',   this.target, null, this.params ); },
  'can_be_edited'   : function() { return this.user_identity.can( 'edit',   this.target, null, this.params ); },
  'can_be_removed'  : function() { return this.user_identity.can( 'remove', this.target, null, this.params ); },
  'can_be_created'  : function() { return this.user_identity.can( 'create', this.target, null, this.params ); }
};

UserIdentityModelHandler.prototype.get = function ( receiver, name ) {
  var self = this;

  if ( ~this.methods.indexOf( name ) ) return function() {
    return self[ name ].apply( self, arguments );
  }

  if ( this._has_attribute( name ) )
    return this.get_attribute( name );

  if ( this.access_rights_methods[ name ] )
    return this.access_rights_methods[ name ].call( this );

  return this.super_.get( receiver, name );
};

UserIdentityModelHandler.prototype.set = function ( receiver, name, value ) {
  if ( this._has_attribute( name ) )
    return this.set_attribute( name, value );

  return this.super_.set( receiver, name, value );
};

UserIdentityModelHandler.prototype._has_attribute = function ( name ) {
  return this.target.get_attributes()[ name ];
};

UserIdentityModelHandler.prototype.get_attribute = function ( name ) {
  if ( this.user_identity.can( 'view', this.target, name, this.params ) )
    return this.target.get_attribute( name );

  this.user_identity.app.log(
    'Permission denied to view attribute `%s` in model `%s`'.format( name, this.target.class_name ), 'warning'
  );
  return null;
};

UserIdentityModelHandler.prototype.set_attribute = function ( name, value ) {
  if ( this.user_identity.can( 'edit', this.target, name, this.params ) )
    return this.target.set_attribute( name, value );

  this.target.validator.errors.push(
    'Permission denied to change `%s`'.format( name )
  );

  return null;
};

UserIdentityModelHandler.prototype.get_attributes = function ( names ) {
  var attributes = this.target.get_attributes( names );

  for ( var name in attributes )
    if ( !this.user_identity.can( 'view', this.target, name, this.params ) )
      attributes[ name ] = null;

  return attributes;
};

UserIdentityModelHandler.prototype.set_attributes = function ( attributes ) {
  var attrs = {};

  for ( var name in attributes )
    if ( this.user_identity.can( 'edit', this.target, name, this.params ) )
      attrs[ name ] = attributes[ name ];
    else this.target.validator.errors.push( 'Permission denied to change `%s`'.format( name ) );

  this.target.set_attributes( attrs );
};

UserIdentityModelHandler.prototype.save = function ( attributes, scenario ) {
  var action = this.target.is_new ? 'create' : 'edit';
  if ( !this.user_identity.can( action, this.model, null, this.params ) )
    this.target.validator.errors.push( 'Permission denied to %s model `%s`'.format( action, this.target.class_name ) );

  return this.target.save( attributes, scenario );
};

UserIdentityModelHandler.prototype.remove = function () {
  if ( this.user_identity.can( 'remove', this.target, null, this.params ) )
    return this.target.remove();

  return new Error( 'Permission denied to remove model `%s`'.format( this.target.class_name ) );
};

UserIdentityModelHandler.prototype.release = function () {
  return this.target;
};<commit_msg>universal actoin accessor for models_proxy_handler<commit_after>var ProxyHandler = require('lib/proxy_handlers/proxy_handler');

module.exports = UserIdentityModelHandler.inherits( ProxyHandler );

function UserIdentityModelHandler( params ) {
  this._init( params );
}

UserIdentityModelHandler.prototype._init = function( params ) {
  this.super_._init( params );

  this.user_identity = params.user_identity;
  this.params        = params.params;

  this.methods = [
    'get_attribute',
    'set_attribute',
    'get_attributes',
    'set_attributes',
    'save',
    'remove',
    'release'
  ];

  var self      = this;
  var accessor  = null;
  this.__defineGetter__( 'accessor', function(){
    if ( accessor ) return accessor;

    var handler = new ProxyHandler({
      target : {}
    });

    handler.get = function( reciever, name ){
      return self.user_identity.can( name, self.target, null, self.params );
    }

    accessor = handler.get_proxy();
    return accessor;
  } );
};

UserIdentityModelHandler.prototype.access_rights_methods = {
  'can_be_viewed'   : function() { return this.user_identity.can( 'view',   this.target, null, this.params ); },
  'can_be_edited'   : function() { return this.user_identity.can( 'edit',   this.target, null, this.params ); },
  'can_be_removed'  : function() { return this.user_identity.can( 'remove', this.target, null, this.params ); },
  'can_be_created'  : function() { return this.user_identity.can( 'create', this.target, null, this.params ); }
};

UserIdentityModelHandler.prototype.get = function ( receiver, name ) {
  var self = this;

  if ( ~this.methods.indexOf( name ) ) return function() {
    return self[ name ].apply( self, arguments );
  }

  if ( this._has_attribute( name ) )
    return this.get_attribute( name );

  if ( this.access_rights_methods[ name ] )
    return this.access_rights_methods[ name ].call( this );

  if ( name == 'is_permitted_for' ) return this.accessor;

  return this.super_.get( receiver, name );
};

UserIdentityModelHandler.prototype.set = function ( receiver, name, value ) {
  if ( this._has_attribute( name ) )
    return this.set_attribute( name, value );

  return this.super_.set( receiver, name, value );
};

UserIdentityModelHandler.prototype._has_attribute = function ( name ) {
  return this.target.get_attributes()[ name ];
};

UserIdentityModelHandler.prototype.get_attribute = function ( name ) {
  if ( this.user_identity.can( 'view', this.target, name, this.params ) )
    return this.target.get_attribute( name );

  this.user_identity.app.log(
    'Permission denied to view attribute `%s` in model `%s`'.format( name, this.target.class_name ), 'warning'
  );
  return null;
};

UserIdentityModelHandler.prototype.set_attribute = function ( name, value ) {
  if ( this.user_identity.can( 'edit', this.target, name, this.params ) )
    return this.target.set_attribute( name, value );

  this.target.validator.errors.push(
    'Permission denied to change `%s`'.format( name )
  );

  return null;
};

UserIdentityModelHandler.prototype.get_attributes = function ( names ) {
  var attributes = this.target.get_attributes( names );

  for ( var name in attributes )
    if ( !this.user_identity.can( 'view', this.target, name, this.params ) )
      attributes[ name ] = null;

  return attributes;
};

UserIdentityModelHandler.prototype.set_attributes = function ( attributes ) {
  var attrs = {};

  for ( var name in attributes )
    if ( this.user_identity.can( 'edit', this.target, name, this.params ) )
      attrs[ name ] = attributes[ name ];
    else this.target.validator.errors.push( 'Permission denied to change `%s`'.format( name ) );

  this.target.set_attributes( attrs );
};

UserIdentityModelHandler.prototype.save = function ( attributes, scenario ) {
  var action = this.target.is_new ? 'create' : 'edit';
  if ( !this.user_identity.can( action, this.model, null, this.params ) )
    this.target.validator.errors.push( 'Permission denied to %s model `%s`'.format( action, this.target.class_name ) );

  return this.target.save( attributes, scenario );
};

UserIdentityModelHandler.prototype.remove = function () {
  if ( this.user_identity.can( 'remove', this.target, null, this.params ) )
    return this.target.remove();

  return new Error( 'Permission denied to remove model `%s`'.format( this.target.class_name ) );
};

UserIdentityModelHandler.prototype.release = function () {
  return this.target;
};<|endoftext|>