<commit_before>/* globals describe, it, expect, expectObservable, expectSubscriptions, hot, cold */
var Rx = require('../../dist/cjs/Rx');

describe('Observable.prototype.first()', function () {
  it('should take the first value of an observable with one value', function () {
    var e1 =   hot('---(a|)');
    var expected = '---(a|)';
    var sub =      '^  !';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should take the first value of an observable with many values', function () {
    var e1 = hot('--a--^--b----c---d--|');
    var expected =    '---(b|)';
    var sub =         '^  !';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should error on empty', function () {
    var e1 = hot('--a--^----|');
    var expected =    '-----#';
    var sub =         '^    !';

    expectObservable(e1.first()).toBe(expected, null, new Rx.EmptyError());
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return the default value if source observable was empty', function () {
    var e1 = hot('-----^----|');
    var expected =    '-----(a|)';
    var sub =         '^    !';

    expectObservable(e1.first(null, null, 'a')).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should propagate error from the source observable', function () {
    var e1 = hot('---^---#');
    var expected =  '----#';
    var sub =       '^   !';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should go on forever on never', function () {
    var e1 = hot('--^-------');
    var expected = '--------';
    var sub =      '^       ';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return first value that matches a predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '------(c|)';
    var sub =        '^     !';
    var predicate = function (value) {
      return value === 'c';
    };

    expectObservable(e1.first(predicate)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return first value that matches a predicate for odd numbers', function () {
    var e1 = hot('--a-^--b--c--d--e--|', {a: 1, b: 2, c: 3, d: 4, e: 5});
    var expected =   '------(c|)';
    var sub =        '^     !';
    var predicate = function (value) {
      return value % 2 === 1;
    };

    expectObservable(e1.first(predicate)).toBe(expected, {c: 3});
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should error when no value matches the predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '---------------#';
    var sub =        '^              !';
    var predicate = function (value) {
      return value === 's';
    };

    expectObservable(e1.first(predicate)).toBe(expected, null, new Rx.EmptyError());
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return the default value when no value matches the predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '---------------(d|)';
    var sub =        '^              !';
    var predicate = function (value) {
      return value === 's';
    };

    expectObservable(e1.first(predicate, null, 'd')).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should propagate error when no value matches the predicate', function () {
    var e1 = hot('--a-^--b--c--a--#');
    var expected =   '------------#';
    var sub =        '^           !';
    var predicate = function (value) {
      return value === 's';
    };

    expectObservable(e1.first(predicate)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return first value that matches the index in the predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '---------(a|)';
    var sub =        '^        !';
    var predicate = function (value, index) {
      return index === 2;
    };

    expectObservable(e1.first(predicate)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should propagate error from predicate', function () {
    var e1 = hot('--a-^--b--c--d--e--|', {a: 1, b: 2, c: 3, d: 4, e: 5});
    var expected =   '---------#';
    var sub =        '^        !';
    var predicate = function (value) {
      if (value < 4) {
        return false;
      } else {
        throw 'error';
      }
    };

    expectObservable(e1.first(predicate)).toBe(expected, null, 'error');
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should support a result selector argument', function () {
    var e1 = hot('--a--^---b---c---d---e--|');
    var expected =    '--------(x|)';
    var sub =         '^       !';
    var predicate = function (x) { return x === 'c'; };
    var resultSelector = function (x, i) {
      expect(i).toBe(1);
      expect(x).toBe('c');
      return 'x';
    };

    expectObservable(e1.first(predicate, resultSelector)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should raise error when result selector throws', function () {
    var e1 = hot('--a--^---b---c---d---e--|');
    var expected =    '--------#';
    var sub =         '^       !';
    var predicate = function (x) { return x === 'c'; };
    var resultSelector = function (x, i) {
      throw 'error';
    };

    expectObservable(e1.first(predicate, resultSelector)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });
});
<commit_msg>test(first): fix error in resultSelector test<commit_after>/* globals describe, it, expect, expectObservable, expectSubscriptions, hot, cold */
var Rx = require('../../dist/cjs/Rx');

describe('Observable.prototype.first()', function () {
  it('should take the first value of an observable with one value', function () {
    var e1 =   hot('---(a|)');
    var expected = '---(a|)';
    var sub =      '^  !';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should take the first value of an observable with many values', function () {
    var e1 = hot('--a--^--b----c---d--|');
    var expected =    '---(b|)';
    var sub =         '^  !';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should error on empty', function () {
    var e1 = hot('--a--^----|');
    var expected =    '-----#';
    var sub =         '^    !';

    expectObservable(e1.first()).toBe(expected, null, new Rx.EmptyError());
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return the default value if source observable was empty', function () {
    var e1 = hot('-----^----|');
    var expected =    '-----(a|)';
    var sub =         '^    !';

    expectObservable(e1.first(null, null, 'a')).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should propagate error from the source observable', function () {
    var e1 = hot('---^---#');
    var expected =  '----#';
    var sub =       '^   !';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should go on forever on never', function () {
    var e1 = hot('--^-------');
    var expected = '--------';
    var sub =      '^       ';

    expectObservable(e1.first()).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return first value that matches a predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '------(c|)';
    var sub =        '^     !';
    var predicate = function (value) {
      return value === 'c';
    };

    expectObservable(e1.first(predicate)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return first value that matches a predicate for odd numbers', function () {
    var e1 = hot('--a-^--b--c--d--e--|', {a: 1, b: 2, c: 3, d: 4, e: 5});
    var expected =   '------(c|)';
    var sub =        '^     !';
    var predicate = function (value) {
      return value % 2 === 1;
    };

    expectObservable(e1.first(predicate)).toBe(expected, {c: 3});
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should error when no value matches the predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '---------------#';
    var sub =        '^              !';
    var predicate = function (value) {
      return value === 's';
    };

    expectObservable(e1.first(predicate)).toBe(expected, null, new Rx.EmptyError());
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return the default value when no value matches the predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '---------------(d|)';
    var sub =        '^              !';
    var predicate = function (value) {
      return value === 's';
    };

    expectObservable(e1.first(predicate, null, 'd')).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should propagate error when no value matches the predicate', function () {
    var e1 = hot('--a-^--b--c--a--#');
    var expected =   '------------#';
    var sub =        '^           !';
    var predicate = function (value) {
      return value === 's';
    };

    expectObservable(e1.first(predicate)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should return first value that matches the index in the predicate', function () {
    var e1 = hot('--a-^--b--c--a--c--|');
    var expected =   '---------(a|)';
    var sub =        '^        !';
    var predicate = function (value, index) {
      return index === 2;
    };

    expectObservable(e1.first(predicate)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should propagate error from predicate', function () {
    var e1 = hot('--a-^--b--c--d--e--|', {a: 1, b: 2, c: 3, d: 4, e: 5});
    var expected =   '---------#';
    var sub =        '^        !';
    var predicate = function (value) {
      if (value < 4) {
        return false;
      } else {
        throw 'error';
      }
    };

    expectObservable(e1.first(predicate)).toBe(expected, null, 'error');
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should support a result selector argument', function () {
    var e1 = hot('--a--^---b---c---d---e--|');
    var expected =    '--------(x|)';
    var sub =         '^       !';
    var predicate = function (x) { return x === 'c'; };
    var resultSelector = function (x, i) {
      expect(i).toBe(1);
      expect(x).toBe('c');
      return 'x';
    };

    expectObservable(e1.first(predicate, resultSelector)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });

  it('should raise error when result selector throws', function () {
    var e1 = hot('--a--^---b---c---d---e--|');
    var expected =    '--------#';
    var sub =         '^       !';
    var predicate = function (x) { return x === 'c'; };
    var resultSelector = function (x, i) {
      throw 'error';
    };

    expectObservable(e1.first(predicate, resultSelector)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(sub);
  });
});
<|endoftext|>


<commit_before>var Storage = function () {

	var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

	var name = 'threejs-editor';
	var version = 1;

	var database;

	return {

		init: function ( callback ) {

			var request = indexedDB.open( name, version );
			request.onupgradeneeded = function ( event ) {

				var db = event.target.result;

				if ( db.objectStoreNames.contains( 'states' ) === false ) {

					db.createObjectStore( 'states' );

				}

			};
			request.onsuccess = function ( event ) {

				database = event.target.result;
				database.onabort = function ( event ) {

					database.close();
					database = null;

				};

				callback();

			};
			request.onerror = function ( event ) {

				console.error( 'IndexedDB', event );

			};

		},

		get: function ( callback ) {

			var transaction = database.transaction( [ 'states' ], 'readwrite' );
			var objectStore = transaction.objectStore( 'states' );
			var request = objectStore.get( 0 );
			request.onsuccess = function ( event ) {

				callback( event.target.result );

			};

		},

		set: function ( data, callback ) {

			var transaction = database.transaction( [ 'states' ], 'readwrite' );
			var objectStore = transaction.objectStore( 'states' );
			var request = objectStore.put( data, 0 );
			request.onsuccess = function ( event ) {

				console.log( '[' + /\d\d\:\d\d\:\d\d/.exec( new Date() )[ 0 ] + ']', 'Saved state to IndexedDB.' );

			};

		},

		clear: function ( callback ) {

			var transaction = database.transaction( [ 'states' ], 'readwrite' );
			var objectStore = transaction.objectStore( 'states' );
			var request = objectStore.clear();
			request.onsuccess = function ( event ) {
				callback();
			};

		}

	}

};<commit_msg>Minor clean up.<commit_after>var Storage = function () {

	var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

	var name = 'threejs-editor';
	var version = 1;

	var database;

	return {

		init: function ( callback ) {

			var request = indexedDB.open( name, version );
			request.onupgradeneeded = function ( event ) {

				var db = event.target.result;

				if ( db.objectStoreNames.contains( 'states' ) === false ) {

					db.createObjectStore( 'states' );

				}

			};
			request.onsuccess = function ( event ) {

				database = event.target.result;

				callback();

			};
			request.onerror = function ( event ) {

				console.error( 'IndexedDB', event );

			};

		},

		get: function ( callback ) {

			var transaction = database.transaction( [ 'states' ], 'readwrite' );
			var objectStore = transaction.objectStore( 'states' );
			var request = objectStore.get( 0 );
			request.onsuccess = function ( event ) {

				callback( event.target.result );

			};

		},

		set: function ( data, callback ) {

			var transaction = database.transaction( [ 'states' ], 'readwrite' );
			var objectStore = transaction.objectStore( 'states' );
			var request = objectStore.put( data, 0 );
			request.onsuccess = function ( event ) {

				console.log( '[' + /\d\d\:\d\d\:\d\d/.exec( new Date() )[ 0 ] + ']', 'Saved state to IndexedDB.' );

			};

		},

		clear: function ( callback ) {

			var transaction = database.transaction( [ 'states' ], 'readwrite' );
			var objectStore = transaction.objectStore( 'states' );
			var request = objectStore.clear();
			request.onsuccess = function ( event ) {

				callback();

			};

		}

	}

};<|endoftext|>


<commit_before>var Model = function(params){
  if(typeof params === 'string'){
    this.IATA      = params;
    this.id        = null;
    this.Name      = ko.observable(null);
    this.Latitude  = ko.observable(null);
    this.Longitude = ko.observable(null);
    this.TimeZone  = ko.observable(null);
  }else{
    this.IATA      = params.IATA;
    this.id        = params.id;
    this.Name      = ko.observable(params.Name);
    this.Latitude  = ko.observable(params.Latitude);
    this.Longitude = ko.observable(params.Longitude);
    this.TimeZone  = ko.observable(params.TimeZone);
  }
}
Model.prototype.validate = function(){
  var errors = [];
  if(!this.IATA.match(/^[A-Z]{1,4}$/)
  ){
    errors.push('IATA must be 1, 2, 3, or 4 character combinations');
  }
  if(!(~this.TimeZone().indexOf('UTC'))){
    errors.push('TimeZone must contain "UTC"');
  }
  return errors;
}
Model.prototype.set = function(data){
  this.Name(data.Name);
  this.Latitude(data.Latitude);
  this.Longitude(data.Longitude);
  this.TimeZone(data.TimeZone);
}<commit_msg>Version 0.0.1<commit_after>var Model = function(params){
  if(typeof params === 'string'){
    this.IATA      = params;
    this.id        = null;
    this.Name      = ko.observable(null);
    this.Latitude  = ko.observable(null);
    this.Longitude = ko.observable(null);
    this.TimeZone  = ko.observable(null);
  }else{
    this.IATA      = params.IATA;
    this.id        = params.id;
    this.Name      = ko.observable(params.Name);
    this.Latitude  = ko.observable(params.Latitude);
    this.Longitude = ko.observable(params.Longitude);
    this.TimeZone  = ko.observable(params.TimeZone);
  }
}
Model.prototype.validate = function(){
  var errors = [];
  if(!this.IATA.match(/^[A-Z]{1,4}$/)
  ){
    errors.push('IATA must be 1, 2, 3, or 4 character combinations');
  }
  if(
    this.TimeZone() && !== null &&
    !(~this.TimeZone().indexOf('UTC'))
  ){
    errors.push('TimeZone must contain "UTC"');
  }
  return errors;
}
Model.prototype.set = function(data){
  this.Name(data.Name);
  this.Latitude(data.Latitude);
  this.Longitude(data.Longitude);
  this.TimeZone(data.TimeZone);
}<|endoftext|>


<commit_before>var child_process = require('child_process');
var path = require('path');

module.exports = function(grunt) {
  grunt.registerTask('dmncompile', function() {
    var done = this.async();
    var dmnPath = path.join(__dirname, '../../dmn-js/');
    child_process.exec('npm i --silent && node_modules/.bin/rollup -c --silent', { maxBuffer: 1024 * 500, cwd: dmnPath }, function(err) {
      if(err) {
        console.log(err);
      }
      done();
    });
  });
};
<commit_msg>chore(dmn): make cmd to transpile dmn windows compatible<commit_after>var child_process = require('child_process');
var path = require('path');

module.exports = function(grunt) {
  grunt.registerTask('dmncompile', function() {
    var done = this.async();
    var dmnPath = path.join(__dirname, '../../dmn-js/');

    var cmd = 'npm i --silent && node_modules/.bin/rollup -c --silent';
    if (process.platform === 'win32') {
      cmd = cmd.replace(/\//g, '\\');
    }

    child_process.exec(cmd, { maxBuffer: 1024 * 500, cwd: dmnPath }, function(err) {
      if(err) {
        console.log(err);
      }
      done();
    });
  });
};
<|endoftext|>


<commit_before>describe('Mutiny.toggler', function() {
  beforeEach(function(){
    loadFixtures('toggler.html');
    Mutiny.init();
  });

  it('triggers Bare Bones toggler', function() {
    console.log(jasmine.getFixtures().fixturesPath);
    expect($('#bare-bones .toggled')).toBeVisible();
    $('#bare-bones [data-mutiny]').click();
    expect($('#bare-bones .toggled')).toBeHidden();
  });

  it('triggers Class Name toggler', function() {
    expect($('#class-name .toggled')).not.toHaveClass('active');
    $('#class-name [data-mutiny]').click();
    expect($('#class-name .toggled')).toHaveClass('active');
  });

  it('triggers Style Changes toggler', function() {
    expect($('#style-changes .toggled')).not.toHaveCss({'font-style':'italic'});
    $('#style-changes [data-mutiny]').click();
    expect($('#style-changes .toggled')).toHaveCss({'font-style':'italic'});
  });

  it('triggers Radio Button toggler', function() {
    expect($('#radio-buttons .toggled')).toBeHidden();
    $('#radio-buttons [data-mutiny]').click();
    expect($('#radio-buttons .toggled')).toBeVisible();
  });
});
<commit_msg>Removed console logging<commit_after>describe('Mutiny.toggler', function() {
  beforeEach(function(){
    loadFixtures('toggler.html');
    Mutiny.init();
  });

  it('triggers Bare Bones toggler', function() {
    expect($('#bare-bones .toggled')).toBeVisible();
    $('#bare-bones [data-mutiny]').click();
    expect($('#bare-bones .toggled')).toBeHidden();
  });

  it('triggers Class Name toggler', function() {
    expect($('#class-name .toggled')).not.toHaveClass('active');
    $('#class-name [data-mutiny]').click();
    expect($('#class-name .toggled')).toHaveClass('active');
  });

  it('triggers Style Changes toggler', function() {
    expect($('#style-changes .toggled')).not.toHaveCss({'font-style':'italic'});
    $('#style-changes [data-mutiny]').click();
    expect($('#style-changes .toggled')).toHaveCss({'font-style':'italic'});
  });

  it('triggers Radio Button toggler', function() {
    expect($('#radio-buttons .toggled')).toBeHidden();
    $('#radio-buttons [data-mutiny]').click();
    expect($('#radio-buttons .toggled')).toBeVisible();
  });
});
<|endoftext|>


<commit_before>(function() {
    'use strict';

    var express = require('express'),
        app = module.exports = express(),
        passport = require('passport');

    // User
    /**
     * @api {post} /users Create User
     *
     * @apiName CreateUser
     * @apiGroup User
     *
     * @apiSuccess (200) {String} success contains the success description
     *
     * @apiError (400) {String} message contains the error description
     *
     * @apiParam {String} email unique email address
     * @apiParam {String} password the users password
     */
    app.post('/api/v1/users/', function(req, res) {
        User.register(new User({
            email: req.body.email
        }), req.body.password, function(err, doc) {
            if (err) {
                res.status = 400;
                res.json({
                    message: err
                });
            } else {
                res.status = 200;
                res.json({
                    message: "registered user",
                    _id: doc._id
                });
            }
        });
    });

    /**
     * Update User
     */
    app.put('/api/v1/users/:userId', function(req, res) {
        // TODO
    });

    /**
     * @api {get} /users/:id Lookup User
     *
     * @apiName GetUser
     * @apiGroup User
     *
     * @apiSuccess (200) {String} _id id of the user
     * @apiSuccess (200) {String} email of the user
     * @apiSuccess (200) {String} creation_date when the user was created
     *
     * @apiError (500) {String} message something went wrong
     * @apiError (404) {String} message no such user
     * @apiError (401) {String} message unauthorized
     */
    app.get('/api/v1/users/:userId', function(req, res) {
        // validate token
        var incomingToken = User.decodeJwt(req.headers.token);

        if (incomingToken && incomingToken.email) {
            User.findOne({
                _id: req.params.userId
            }, function(err, doc) {
                if (err) {
                    res.status = 500;
                    res.json({
                        message: err
                    });
                }

                if (!doc) {
                    res.status = 404;
                    res.json({
                        message: "no such user"
                    });
                }

                res.status = 200;
                res.json({
                    _id: doc._id,
                    email: doc.email,
                    creation_date: doc.creation_date
                });
            });
        } else {
            res.status = 401;
            res.json({
                message: 'unauthorized'
            });
        }
    });

    /**
     * Delete User
     */
    app.delete('/api/v1/users/:userId', function(req, res) {
        // TODO
    });

    // Tokens
    /**
     * @api {post} /users/:id/authenticate Create Token for a User
     *
     * @apiName CreateUserToken
     * @apiGroup User
     *
     * @apiError (500) error error while generating token
     * @apiError (401) error unauthorized
     *
     * @apiSuccess (200) token the requested token
     *
     * @apiParam {String} email for the user
     */
    app.post('/api/v1/users/:userId/authenticate', passport.authenticate('local', {
        session: false
    }), function(req, res) {
        if (req.user) {
            User.createToken(req.user.email, function(err, token) {
                if (err) {
                    res.status = 500;
                    res.json({
                        error: err
                    });
                } else {
                    res.status = 200;
                    res.json({
                        token: token
                    });
                }
            });
        } else {
            res.status = 401;
            res.json({
                error: "unauthorized"
            });
        }
    });

    // Drops
    /**
     * List drops of a User
     */
    app.get('/api/v1/users/:userId/drops', function(req, res) {
        // TODO
    });

    /**
     * Get details for a drop of a User
     */
    app.get('/api/v1/users/:userId/drops/:dropId', function(req, res) {
        // TODO
    });

    /**
     * Create new drop of a User
     */
    app.post('/api/v1/users/:userId/drops/:dropId', function(req, res) {
        // TODO
    });

    /**
     * Delete drop of a User
     */
    app.delete('/api/v1/users/:userId/drops/:dropId', function(req, res) {
        // TODO
    });
})();
<commit_msg>improved docket, added token invalidation to adhere to #1; fixed #5<commit_after>(function() {
    'use strict';

    var express = require('express'),
        app = module.exports = express(),
        passport = require('passport');

    // User
    /**
     * @api {post} /users Create User
     *
     * @apiName CreateUser
     * @apiGroup User
     *
     * @apiSuccess (200) {String} success contains the success description
     *
     * @apiError (400) {String} message contains the error description
     *
     * @apiParam {String} email unique email address
     * @apiParam {String} password the users password
     */
    app.post('/api/v1/users/', function(req, res) {
        User.register(new User({
            email: req.body.email
        }), req.body.password, function(err, doc) {
            if (err) {
                res.status = 400;
                res.json({
                    message: err
                });
            } else {
                res.status = 200;
                res.json({
                    message: "registered user",
                    _id: doc._id
                });
            }
        });
    });

    /**
     * Update User
     */
    app.put('/api/v1/users/:userId', function(req, res) {
        // TODO
    });

    /**
     * @api {get} /users/:id Lookup User
     *
     * @apiName GetUser
     * @apiGroup User
     *
     * @apiSuccess (200) {String} _id id of the user
     * @apiSuccess (200) {String} email of the user
     * @apiSuccess (200) {String} creation_date when the user was created
     *
     * @apiError (500) {String} message something went wrong
     * @apiError (404) {String} message no such user
     * @apiError (401) {String} message unauthorized
     */
    app.get('/api/v1/users/:userId', function(req, res) {
        // validate token
        var incomingToken = User.decodeJwt(req.headers.token);

        if (incomingToken && incomingToken.email) {
            User.findOne({
                _id: req.params.userId
            }, function(err, doc) {
                if (err) {
                    res.status = 500;
                    res.json({
                        message: err
                    });
                }

                if (!doc) {
                    res.status = 404;
                    res.json({
                        message: "no such user"
                    });
                }

                res.status = 200;
                res.json({
                    _id: doc._id,
                    email: doc.email,
                    creation_date: doc.creation_date
                });
            });
        } else {
            res.status = 401;
            res.json({
                message: 'unauthorized'
            });
        }
    });

    /**
     * Delete User
     */
    app.delete('/api/v1/users/:userId', function(req, res) {
        // TODO
    });

    // Tokens
    /**
     * @api {post} /users/:id/authenticate Create Token for a User
     *
     * @apiName CreateUserToken
     * @apiGroup User
     *
     * @apiError (500) message error while generating token
     * @apiErorr (404) message no such user
     * @apiError (401) message unauthorized
     *
     * @apiSuccess (200) token the requested token
     *
     * @apiParam {String} email for the user
     */
    app.post('/api/v1/users/:userId/authenticate', passport.authenticate('local', {
        session: false
    }), function(req, res) {
        if (req.user) {
            User.findOne(req.user.email, function(err, doc) {
                if (err) {
                    res.status = 500;
                    res.json({
                        message: err
                    });
                }

                if (!doc) {
                    res.status = 404;
                    res.json({
                        message: "no such user"
                    });
                }

                doc.invalidateTokens();
                var token = doc.createToken();

                doc.save(function(err, doc) {
                    if (err) {
                        res.status = 500;
                        res.json({
                            message: err
                        });
                    }

                    res.status = 200;
                    res.json({
                        token: token
                    });
                });
            });
        } else {
            res.status = 401;
            res.json({
                message: "unauthorized"
            });
        }
    });

    // Drops
    /**
     * List drops of a User
     */
    app.get('/api/v1/users/:userId/drops', function(req, res) {
        // TODO
    });

    /**
     * Get details for a drop of a User
     */
    app.get('/api/v1/users/:userId/drops/:dropId', function(req, res) {
        // TODO
    });

    /**
     * Create new drop of a User
     */
    app.post('/api/v1/users/:userId/drops/:dropId', function(req, res) {
        // TODO
    });

    /**
     * Delete drop of a User
     */
    app.delete('/api/v1/users/:userId/drops/:dropId', function(req, res) {
        // TODO
    });
})();
<|endoftext|>


<commit_before>const BinaryPjax          = require('./binary_pjax');
const Client              = require('./client');
const GTM                 = require('./gtm');
const localize            = require('./localize').localize;
const Login               = require('./login');
const State               = require('./storage').State;
const Url                 = require('./url');
const createElement       = require('./utility').createElement;
const applyToAllElements  = require('./utility').applyToAllElements;
const elementInnerHtml    = require('../common_functions/common_functions').elementInnerHtml;
const elementTextContent  = require('../common_functions/common_functions').elementTextContent;
const checkClientsCountry = require('../common_functions/country_base').checkClientsCountry;
const jpClient            = require('../common_functions/country_base').jpClient;
const toTitleCase         = require('../common_functions/string_util').toTitleCase;
const BinarySocket        = require('../websocket_pages/socket');
const MetaTrader          = require('../websocket_pages/user/metatrader/metatrader');
const getCurrencies       = require('../websocket_pages/user/get_currency').getCurrencies;

const Header = (() => {
    const onLoad = () => {
        showOrHideLoginForm();
        bindClick();
        if (!Login.isLoginPages()) {
            checkClientsCountry();
        }
        const menu = document.getElementById('menu-top');
        if (menu && Client.isLoggedIn()) {
            menu.classList.add('smaller-font');
            displayAccountStatus();
            if (!Client.get('is_virtual')) {
                BinarySocket.wait('website_status', 'authorize', 'balance').then(() => {
                    if (Client.canTransferFunds()) {
                        const transfer = document.getElementById('user_menu_account_transfer');
                        if (transfer) transfer.setVisibility(1);
                    }
                });
            }
        }
    };

    const bindClick = () => {
        const logo = document.getElementById('logo');
        if (logo) {
            logo.removeEventListener('click', logoOnClick);
            logo.addEventListener('click', logoOnClick);
        }

        const btn_login = document.getElementById('btn_login');
        if (btn_login) {
            btn_login.removeEventListener('click', loginOnClick);
            btn_login.addEventListener('click', loginOnClick);
        }

        applyToAllElements('a.logout', (el) => {
            el.removeEventListener('click', () => { Client.sendLogoutRequest(); });
            el.addEventListener('click', () => { Client.sendLogoutRequest(); });
        });
    };

    const logoOnClick = () => {
        const url = Client.isLoggedIn() ? Client.defaultRedirectUrl() : Url.urlFor('');
        BinaryPjax.load(url);
    };

    const loginOnClick = (e) => {
        e.preventDefault();
        Login.redirectToLogin();
    };

    const showOrHideLoginForm = () => {
        if (!Client.isLoggedIn()) return;
        BinarySocket.wait('authorize').then(() => {
            const loginid_select = document.createElement('div');
            Client.getAllLoginids().forEach((loginid) => {
                if (!Client.get('is_disabled', loginid)) {
                    const account_title  = Client.getAccountTitle(loginid);
                    const is_real        = /real/i.test(account_title);
                    const currency       = Client.get('currency', loginid);
                    let localized_type = localize('[_1] Account', [is_real && currency ? currency : account_title]);
                    if (Client.get('is_ico_only', loginid)) {
                        localized_type += ' (ICO)';
                    }
                    if (loginid === Client.get('loginid')) { // default account
                        applyToAllElements('.account-type', (el) => { elementInnerHtml(el, localized_type); });
                        applyToAllElements('.account-id', (el) => { elementInnerHtml(el, loginid); });
                    } else {
                        const link    = createElement('a', { href: `${'java'}${'script:;'}`, 'data-value': loginid });
                        const li_type = createElement('li', { text: localized_type });

                        li_type.appendChild(createElement('div', { text: loginid }));
                        link.appendChild(li_type);
                        loginid_select.appendChild(link).appendChild(createElement('div', { class: 'separator-line-thin-gray' }));
                    }
                }
                applyToAllElements('.login-id-list', (el) => {
                    el.html(loginid_select.innerHTML);
                    applyToAllElements('a', (ele) => {
                        ele.removeEventListener('click', loginIDOnClick);
                        ele.addEventListener('click', loginIDOnClick);
                    }, '', el);
                });
            });
        });
    };

    const loginIDOnClick =  (e) => {
        e.preventDefault();
        const el_loginid = e.target.closest('A');
        if (el_loginid) {
            el_loginid.setAttribute('disabled', 'disabled');
            switchLoginid(el_loginid.getAttribute('data-value'));
        }
    };

    const metatraderMenuItemVisibility = (landing_company_response) => {
        BinarySocket.wait('get_account_status').then(() => {
            if (MetaTrader.isEligible(landing_company_response)) {
                const metatrader = document.getElementById('user_menu_metatrader');
                if (metatrader) metatrader.setVisibility(1);
            }
        });
    };

    const switchLoginid = (loginid) => {
        if (!loginid || loginid.length === 0) return;
        const token = Client.get('token', loginid);
        if (!token || token.length === 0) {
            Client.sendLogoutRequest(true);
            return;
        }

        sessionStorage.setItem('active_tab', '1');
        // set local storage
        GTM.setLoginFlag();
        Client.set('cashier_confirmed', 0);
        Client.set('loginid', loginid);
        window.location.reload();
    };

    const upgradeMessageVisibility = () => {
        BinarySocket.wait('authorize', 'landing_company', 'get_settings', 'get_account_status').then(() => {
            const landing_company = State.getResponse('landing_company');
            const upgrade_msg     = document.getElementsByClassName('upgrademessage');

            if (!upgrade_msg) {
                return;
            }

            const showUpgrade = (url, msg) => {
                applyToAllElements(upgrade_msg, (el) => {
                    el.setVisibility(1);
                    applyToAllElements('a', (ele) => {
                        ele.html(createElement('span', { text: localize(msg) })).setVisibility(1).setAttribute('href', Url.urlFor(url));
                    }, '', el);
                });
            };

            const jp_account_status = State.getResponse('get_settings.jp_account_status.status');
            const status            = State.getResponse('get_account_status.status');
            const is_ico_account    = /ico_only/.test(status);
            const upgrade_info      = Client.getUpgradeInfo(landing_company, jp_account_status, is_ico_account);
            const show_upgrade_msg  = upgrade_info.can_upgrade;
            const virtual_text      = document.getElementById('virtual-text');

            if (Client.get('is_virtual')) {
                applyToAllElements(upgrade_msg, (el) => {
                    el.setVisibility(1);
                    const span = el.getElementsByTagName('span')[0];
                    if (span) {
                        span.setVisibility(1);
                    }
                    applyToAllElements('a', (ele) => { ele.setVisibility(0); }, '', el);
                });

                if (jp_account_status) {
                    const has_disabled_jp = jpClient() && Client.getAccountOfType('real').is_disabled;
                    if (/jp_knowledge_test_(pending|fail)/.test(jp_account_status)) { // do not show upgrade for user that filled up form
                        showUpgrade('/new_account/knowledge_testws', '{JAPAN ONLY}Take knowledge test');
                    } else if (show_upgrade_msg || (has_disabled_jp && jp_account_status !== 'disabled')) {
                        applyToAllElements(upgrade_msg, (el) => { el.setVisibility(1); });
                        if (!virtual_text) {
                            return;
                        }
                        if (jp_account_status === 'jp_activation_pending' && !document.getElementsByClassName('activation-message')) {
                            virtual_text.appendChild(createElement('div', { class: 'activation-message', text: ` ${localize('Your Application is Being Processed.')}` }));
                        } else if (jp_account_status === 'activated' && !document.getElementsByClassName('activated-message')) {
                            virtual_text.appendChild(createElement('div', { class: 'activated-message', text: ` ${localize('{JAPAN ONLY}Your Application has Been Processed. Please Re-Login to Access Your Real-Money Account.')}` }));
                        }
                    }
                } else if (show_upgrade_msg) {
                    showUpgrade(upgrade_info.upgrade_link, `Open a ${toTitleCase(upgrade_info.type)} Account`);
                } else {
                    applyToAllElements(upgrade_msg, (el) => {
                        applyToAllElements('a', (ele) => {
                            ele.setVisibility(0).innerHTML = '';
                        }, '', el);
                    });
                }
            } else if (show_upgrade_msg) {
                if (virtual_text.parentNode) {
                    virtual_text.parentNode.setVisibility(0);
                }
                showUpgrade(upgrade_info.upgrade_link, 'Open a Financial Account');
            } else {
                applyToAllElements(upgrade_msg, (el) => { el.setVisibility(0); });
            }
            showHideNewAccount(show_upgrade_msg);
        });
    };

    const showHideNewAccount = (can_upgrade) => {
        const landing_company = State.getResponse('landing_company');
        const status          = State.getResponse('get_account_status.status');
        // only allow opening of multi account to costarica clients with remaining currency
        if (!/ico_only/.test(status) && (can_upgrade || (Client.get('landing_company_shortcode') === 'costarica' && getCurrencies(landing_company).length))) {
            changeAccountsText(1, 'Create Account');
        } else {
            changeAccountsText(0, 'Accounts List');
        }
    };

    const changeAccountsText = (add_new_style, text) => {
        const user_accounts = document.getElementById('user_accounts');
        if (user_accounts) {
            user_accounts.classList[add_new_style ? 'add' : 'remove']('create_new_account');
            const localized_text = localize(text);
            applyToAllElements('li', (el) => { elementTextContent(el, localized_text); }, '', user_accounts);
        }
    };

    const displayNotification = (message, is_error = false, msg_code = '') => {
        const msg_notification = document.getElementById('msg_notification');
        if (!msg_notification) return;
        if (msg_notification.getAttribute('data-code') === 'STORAGE_NOT_SUPPORTED') return;

        msg_notification.html(message);
        msg_notification.setAttribute('data-message', message);
        msg_notification.setAttribute('data-code', msg_code);

        if (!msg_notification.offsetParent) {
            $(msg_notification).slideDown(500, () => { if (is_error) msg_notification.classList.add('error'); });
        } else {
            msg_notification.toggleClass('error', is_error);
        }
    };

    const hideNotification = (msg_code) => {
        const msg_notification = document.getElementById('msg_notification');
        if (!msg_notification) return;
        if (msg_notification.getAttribute('data-code') === 'STORAGE_NOT_SUPPORTED' ||
            msg_code && msg_notification.getAttribute('data-code') !== msg_code) {
            return;
        }

        if (msg_notification.offsetParent) {
            msg_notification.classList.remove('error');
            $(msg_notification).slideUp(500, () => {
                elementInnerHtml(msg_notification, '');
                msg_notification.removeAttribute('data-message data-code');
            });
        }
    };

    const displayAccountStatus = () => {
        BinarySocket.wait('authorize').then(() => {
            let get_account_status,
                status;

            const riskAssessment = () => (
                (get_account_status.risk_classification === 'high' || Client.isAccountOfType('financial')) &&
                /financial_assessment_not_complete/.test(status) && !jpClient()
            );

            const buildMessage = (string, path, hash = '') => localize(string, [`<a href="${Url.urlFor(path)}${hash}">`, '</a>']);

            const messages = {
                authenticate         : () => buildMessage('[_1]Authenticate your account[_2] now to take full advantage of all payment methods available.',                                      'user/authenticate'),
                currency             : () => buildMessage('Please set the [_1]currency[_2] of your account.',                                                                                'user/set-currency'),
                document_needs_action: () => buildMessage('[_1]Your Proof of Identity or Proof of Address[_2] did not meet our requirements. Please check your email for further instructions.', 'user/authenticate'),
                document_review      : () => buildMessage('We are reviewing your documents. For more details [_1]contact us[_2].',                                                               'contact'),
                financial_limit      : () => buildMessage('Please set your [_1]30-day turnover limit[_2] to remove deposit limits.',                                                             'user/security/self_exclusionws'),
                residence            : () => buildMessage('Please set [_1]country of residence[_2] before upgrading to a real-money account.',                                                   'user/settings/detailsws'),
                risk                 : () => buildMessage('Please complete the [_1]financial assessment form[_2] to lift your withdrawal and trading limits.',                                   'user/settings/assessmentws'),
                tax                  : () => buildMessage('Please [_1]complete your account profile[_2] to lift your withdrawal and trading limits.',                                            'user/settings/detailsws'),
                tnc                  : () => buildMessage('Please [_1]accept the updated Terms and Conditions[_2] to lift your withdrawal and trading limits.',                                  'user/tnc_approvalws'),
                unwelcome            : () => buildMessage('Your account is restricted. Kindly [_1]contact customer support[_2] for assistance.',                                                 'contact'),
            };

            const validations = {
                authenticate         : () => +get_account_status.prompt_client_to_authenticate,
                currency             : () => !Client.get('currency'),
                document_needs_action: () => /document_needs_action/.test(status),
                document_review      : () => /document_under_review/.test(status),
                financial_limit      : () => /ukrts_max_turnover_limit_not_set/.test(status),
                residence            : () => !Client.get('residence'),
                risk                 : () => riskAssessment(),
                tax                  : () => Client.shouldCompleteTax(),
                tnc                  : () => Client.shouldAcceptTnc(),
                unwelcome            : () => /unwelcome|(cashier|withdrawal)_locked/.test(status),
            };

            // real account checks in order
            const check_statuses_real = [
                'tnc',
                'financial_limit',
                'risk',
                'tax',
                'currency',
                'document_review',
                'document_needs_action',
                'authenticate',
                'unwelcome',
            ];

            // virtual checks
            const check_statuses_virtual = [
                'residence',
            ];

            const checkStatus = (check_statuses) => {
                const notified = check_statuses.some((check_type) => {
                    if (validations[check_type]()) {
                        displayNotification(messages[check_type]());
                        return true;
                    }
                    return false;
                });
                if (!notified) hideNotification();
            };

            if (Client.get('is_virtual')) {
                checkStatus(check_statuses_virtual);
            } else {
                BinarySocket.wait('website_status', 'get_account_status', 'get_settings', 'balance').then(() => {
                    get_account_status = State.getResponse('get_account_status') || {};
                    status             = get_account_status.status;
                    checkStatus(check_statuses_real);
                });
            }
        });
    };

    return {
        onLoad,

        showOrHideLoginForm,
        upgradeMessageVisibility,
        metatraderMenuItemVisibility,
        displayNotification,
        hideNotification,
        displayAccountStatus,
    };
})();

module.exports = Header;
<commit_msg>ICO accounts redirect to ico subscribe page<commit_after>const BinaryPjax          = require('./binary_pjax');
const Client              = require('./client');
const GTM                 = require('./gtm');
const localize            = require('./localize').localize;
const Login               = require('./login');
const State               = require('./storage').State;
const Url                 = require('./url');
const createElement       = require('./utility').createElement;
const applyToAllElements  = require('./utility').applyToAllElements;
const elementInnerHtml    = require('../common_functions/common_functions').elementInnerHtml;
const elementTextContent  = require('../common_functions/common_functions').elementTextContent;
const checkClientsCountry = require('../common_functions/country_base').checkClientsCountry;
const jpClient            = require('../common_functions/country_base').jpClient;
const toTitleCase         = require('../common_functions/string_util').toTitleCase;
const BinarySocket        = require('../websocket_pages/socket');
const MetaTrader          = require('../websocket_pages/user/metatrader/metatrader');
const getCurrencies       = require('../websocket_pages/user/get_currency').getCurrencies;

const Header = (() => {
    const onLoad = () => {
        showOrHideLoginForm();
        bindClick();
        if (!Login.isLoginPages()) {
            checkClientsCountry();
        }
        const menu = document.getElementById('menu-top');
        if (menu && Client.isLoggedIn()) {
            menu.classList.add('smaller-font');
            displayAccountStatus();
            if (!Client.get('is_virtual')) {
                BinarySocket.wait('website_status', 'authorize', 'balance').then(() => {
                    if (Client.canTransferFunds()) {
                        const transfer = document.getElementById('user_menu_account_transfer');
                        if (transfer) transfer.setVisibility(1);
                    }
                });
            }
        }
    };

    const bindClick = () => {
        const logo = document.getElementById('logo');
        if (logo) {
            logo.removeEventListener('click', logoOnClick);
            logo.addEventListener('click', logoOnClick);
        }

        const btn_login = document.getElementById('btn_login');
        if (btn_login) {
            btn_login.removeEventListener('click', loginOnClick);
            btn_login.addEventListener('click', loginOnClick);
        }

        applyToAllElements('a.logout', (el) => {
            el.removeEventListener('click', () => { Client.sendLogoutRequest(); });
            el.addEventListener('click', () => { Client.sendLogoutRequest(); });
        });
    };

    const logoOnClick = () => {
        const url = Client.isLoggedIn() ? Client.defaultRedirectUrl() : Url.urlFor('');
        BinaryPjax.load(url);
    };

    const loginOnClick = (e) => {
        e.preventDefault();
        Login.redirectToLogin();
    };

    const showOrHideLoginForm = () => {
        if (!Client.isLoggedIn()) return;
        BinarySocket.wait('authorize').then(() => {
            const loginid_select = document.createElement('div');
            Client.getAllLoginids().forEach((loginid) => {
                if (!Client.get('is_disabled', loginid)) {
                    const account_title  = Client.getAccountTitle(loginid);
                    const is_real        = /real/i.test(account_title);
                    const currency       = Client.get('currency', loginid);
                    let localized_type = localize('[_1] Account', [is_real && currency ? currency : account_title]);
                    if (Client.get('is_ico_only', loginid)) {
                        localized_type += ' (ICO)';
                    }
                    if (loginid === Client.get('loginid')) { // default account
                        applyToAllElements('.account-type', (el) => { elementInnerHtml(el, localized_type); });
                        applyToAllElements('.account-id', (el) => { elementInnerHtml(el, loginid); });
                    } else {
                        const link    = createElement('a', { href: `${'java'}${'script:;'}`, 'data-value': loginid });
                        const li_type = createElement('li', { text: localized_type });

                        li_type.appendChild(createElement('div', { text: loginid }));
                        link.appendChild(li_type);
                        loginid_select.appendChild(link).appendChild(createElement('div', { class: 'separator-line-thin-gray' }));
                    }
                }
                applyToAllElements('.login-id-list', (el) => {
                    el.html(loginid_select.innerHTML);
                    applyToAllElements('a', (ele) => {
                        ele.removeEventListener('click', loginIDOnClick);
                        ele.addEventListener('click', loginIDOnClick);
                    }, '', el);
                });
            });
        });
    };

    const loginIDOnClick =  (e) => {
        e.preventDefault();
        const el_loginid = e.target.closest('A');
        if (el_loginid) {
            el_loginid.setAttribute('disabled', 'disabled');
            switchLoginid(el_loginid.getAttribute('data-value'));
        }
    };

    const metatraderMenuItemVisibility = (landing_company_response) => {
        BinarySocket.wait('get_account_status').then(() => {
            if (MetaTrader.isEligible(landing_company_response)) {
                const metatrader = document.getElementById('user_menu_metatrader');
                if (metatrader) metatrader.setVisibility(1);
            }
        });
    };

    const switchLoginid = (loginid) => {
        if (!loginid || loginid.length === 0) return;
        const token = Client.get('token', loginid);
        if (!token || token.length === 0) {
            Client.sendLogoutRequest(true);
            return;
        }

        sessionStorage.setItem('active_tab', '1');
        // set local storage
        GTM.setLoginFlag();
        Client.set('cashier_confirmed', 0);
        Client.set('loginid', loginid);
        Client.get('is_ico_only', loginid) ? window.location.assign(Client.defaultRedirectUrl()) : window.location.reload();

    };

    const upgradeMessageVisibility = () => {
        BinarySocket.wait('authorize', 'landing_company', 'get_settings', 'get_account_status').then(() => {
            const landing_company = State.getResponse('landing_company');
            const upgrade_msg     = document.getElementsByClassName('upgrademessage');

            if (!upgrade_msg) {
                return;
            }

            const showUpgrade = (url, msg) => {
                applyToAllElements(upgrade_msg, (el) => {
                    el.setVisibility(1);
                    applyToAllElements('a', (ele) => {
                        ele.html(createElement('span', { text: localize(msg) })).setVisibility(1).setAttribute('href', Url.urlFor(url));
                    }, '', el);
                });
            };

            const jp_account_status = State.getResponse('get_settings.jp_account_status.status');
            const status            = State.getResponse('get_account_status.status');
            const is_ico_account    = /ico_only/.test(status);
            const upgrade_info      = Client.getUpgradeInfo(landing_company, jp_account_status, is_ico_account);
            const show_upgrade_msg  = upgrade_info.can_upgrade;
            const virtual_text      = document.getElementById('virtual-text');

            if (Client.get('is_virtual')) {
                applyToAllElements(upgrade_msg, (el) => {
                    el.setVisibility(1);
                    const span = el.getElementsByTagName('span')[0];
                    if (span) {
                        span.setVisibility(1);
                    }
                    applyToAllElements('a', (ele) => { ele.setVisibility(0); }, '', el);
                });

                if (jp_account_status) {
                    const has_disabled_jp = jpClient() && Client.getAccountOfType('real').is_disabled;
                    if (/jp_knowledge_test_(pending|fail)/.test(jp_account_status)) { // do not show upgrade for user that filled up form
                        showUpgrade('/new_account/knowledge_testws', '{JAPAN ONLY}Take knowledge test');
                    } else if (show_upgrade_msg || (has_disabled_jp && jp_account_status !== 'disabled')) {
                        applyToAllElements(upgrade_msg, (el) => { el.setVisibility(1); });
                        if (!virtual_text) {
                            return;
                        }
                        if (jp_account_status === 'jp_activation_pending' && !document.getElementsByClassName('activation-message')) {
                            virtual_text.appendChild(createElement('div', { class: 'activation-message', text: ` ${localize('Your Application is Being Processed.')}` }));
                        } else if (jp_account_status === 'activated' && !document.getElementsByClassName('activated-message')) {
                            virtual_text.appendChild(createElement('div', { class: 'activated-message', text: ` ${localize('{JAPAN ONLY}Your Application has Been Processed. Please Re-Login to Access Your Real-Money Account.')}` }));
                        }
                    }
                } else if (show_upgrade_msg) {
                    showUpgrade(upgrade_info.upgrade_link, `Open a ${toTitleCase(upgrade_info.type)} Account`);
                } else {
                    applyToAllElements(upgrade_msg, (el) => {
                        applyToAllElements('a', (ele) => {
                            ele.setVisibility(0).innerHTML = '';
                        }, '', el);
                    });
                }
            } else if (show_upgrade_msg) {
                if (virtual_text.parentNode) {
                    virtual_text.parentNode.setVisibility(0);
                }
                showUpgrade(upgrade_info.upgrade_link, 'Open a Financial Account');
            } else {
                applyToAllElements(upgrade_msg, (el) => { el.setVisibility(0); });
            }
            showHideNewAccount(show_upgrade_msg);
        });
    };

    const showHideNewAccount = (can_upgrade) => {
        const landing_company = State.getResponse('landing_company');
        const status          = State.getResponse('get_account_status.status');
        // only allow opening of multi account to costarica clients with remaining currency
        if (!/ico_only/.test(status) && (can_upgrade || (Client.get('landing_company_shortcode') === 'costarica' && getCurrencies(landing_company).length))) {
            changeAccountsText(1, 'Create Account');
        } else {
            changeAccountsText(0, 'Accounts List');
        }
    };

    const changeAccountsText = (add_new_style, text) => {
        const user_accounts = document.getElementById('user_accounts');
        if (user_accounts) {
            user_accounts.classList[add_new_style ? 'add' : 'remove']('create_new_account');
            const localized_text = localize(text);
            applyToAllElements('li', (el) => { elementTextContent(el, localized_text); }, '', user_accounts);
        }
    };

    const displayNotification = (message, is_error = false, msg_code = '') => {
        const msg_notification = document.getElementById('msg_notification');
        if (!msg_notification) return;
        if (msg_notification.getAttribute('data-code') === 'STORAGE_NOT_SUPPORTED') return;

        msg_notification.html(message);
        msg_notification.setAttribute('data-message', message);
        msg_notification.setAttribute('data-code', msg_code);

        if (!msg_notification.offsetParent) {
            $(msg_notification).slideDown(500, () => { if (is_error) msg_notification.classList.add('error'); });
        } else {
            msg_notification.toggleClass('error', is_error);
        }
    };

    const hideNotification = (msg_code) => {
        const msg_notification = document.getElementById('msg_notification');
        if (!msg_notification) return;
        if (msg_notification.getAttribute('data-code') === 'STORAGE_NOT_SUPPORTED' ||
            msg_code && msg_notification.getAttribute('data-code') !== msg_code) {
            return;
        }

        if (msg_notification.offsetParent) {
            msg_notification.classList.remove('error');
            $(msg_notification).slideUp(500, () => {
                elementInnerHtml(msg_notification, '');
                msg_notification.removeAttribute('data-message data-code');
            });
        }
    };

    const displayAccountStatus = () => {
        BinarySocket.wait('authorize').then(() => {
            let get_account_status,
                status;

            const riskAssessment = () => (
                (get_account_status.risk_classification === 'high' || Client.isAccountOfType('financial')) &&
                /financial_assessment_not_complete/.test(status) && !jpClient()
            );

            const buildMessage = (string, path, hash = '') => localize(string, [`<a href="${Url.urlFor(path)}${hash}">`, '</a>']);

            const messages = {
                authenticate         : () => buildMessage('[_1]Authenticate your account[_2] now to take full advantage of all payment methods available.',                                      'user/authenticate'),
                currency             : () => buildMessage('Please set the [_1]currency[_2] of your account.',                                                                                'user/set-currency'),
                document_needs_action: () => buildMessage('[_1]Your Proof of Identity or Proof of Address[_2] did not meet our requirements. Please check your email for further instructions.', 'user/authenticate'),
                document_review      : () => buildMessage('We are reviewing your documents. For more details [_1]contact us[_2].',                                                               'contact'),
                financial_limit      : () => buildMessage('Please set your [_1]30-day turnover limit[_2] to remove deposit limits.',                                                             'user/security/self_exclusionws'),
                residence            : () => buildMessage('Please set [_1]country of residence[_2] before upgrading to a real-money account.',                                                   'user/settings/detailsws'),
                risk                 : () => buildMessage('Please complete the [_1]financial assessment form[_2] to lift your withdrawal and trading limits.',                                   'user/settings/assessmentws'),
                tax                  : () => buildMessage('Please [_1]complete your account profile[_2] to lift your withdrawal and trading limits.',                                            'user/settings/detailsws'),
                tnc                  : () => buildMessage('Please [_1]accept the updated Terms and Conditions[_2] to lift your withdrawal and trading limits.',                                  'user/tnc_approvalws'),
                unwelcome            : () => buildMessage('Your account is restricted. Kindly [_1]contact customer support[_2] for assistance.',                                                 'contact'),
            };

            const validations = {
                authenticate         : () => +get_account_status.prompt_client_to_authenticate,
                currency             : () => !Client.get('currency'),
                document_needs_action: () => /document_needs_action/.test(status),
                document_review      : () => /document_under_review/.test(status),
                financial_limit      : () => /ukrts_max_turnover_limit_not_set/.test(status),
                residence            : () => !Client.get('residence'),
                risk                 : () => riskAssessment(),
                tax                  : () => Client.shouldCompleteTax(),
                tnc                  : () => Client.shouldAcceptTnc(),
                unwelcome            : () => /unwelcome|(cashier|withdrawal)_locked/.test(status),
            };

            // real account checks in order
            const check_statuses_real = [
                'tnc',
                'financial_limit',
                'risk',
                'tax',
                'currency',
                'document_review',
                'document_needs_action',
                'authenticate',
                'unwelcome',
            ];

            // virtual checks
            const check_statuses_virtual = [
                'residence',
            ];

            const checkStatus = (check_statuses) => {
                const notified = check_statuses.some((check_type) => {
                    if (validations[check_type]()) {
                        displayNotification(messages[check_type]());
                        return true;
                    }
                    return false;
                });
                if (!notified) hideNotification();
            };

            if (Client.get('is_virtual')) {
                checkStatus(check_statuses_virtual);
            } else {
                BinarySocket.wait('website_status', 'get_account_status', 'get_settings', 'balance').then(() => {
                    get_account_status = State.getResponse('get_account_status') || {};
                    status             = get_account_status.status;
                    checkStatus(check_statuses_real);
                });
            }
        });
    };

    return {
        onLoad,

        showOrHideLoginForm,
        upgradeMessageVisibility,
        metatraderMenuItemVisibility,
        displayNotification,
        hideNotification,
        displayAccountStatus,
    };
})();

module.exports = Header;
<|endoftext|>


<commit_before>(function(){

	const $ = (_q) => document.querySelectorAll(_q);
	const $v = (_q) => {
		const _$ = $(_q);
		const len = _$.length;
		console.log(len);
		if(!len)
		{
			return null;
		}
		const i = len - 1;
		return _$[i].text || _$[i].src || _$[i].href || _$[i].content
	};

	const DEBUG = window.markdownWebNoteDebug;

	const LINK = "//erikccoder.github.io/markdown-web-note/index.html"
	const selection = window.getSelection().toString();
	const author = $v('meta[name="author"], meta[name="twitter:creator"], meta[property="article:author"]');
	const description = selection
						? selection
						: $v('meta[name="description"], meta[name="twitter:description"], meta[property="og:description"]');
	const image0 = $v('meta[name="twitter:image"], meta[property="og:image"]');
	const image = image0 ? image0 : $v('img');
	const keywords = $v('meta[name="keywords"]');
	const link = $v('link[rel="canonical"], meta[property="og:url"]') || window.location.href;
	const time = $v('meta[property="article:published_time"]');
	const title0 = $v('title, meta[name="twitter:title"], meta[property="og:title"]');
	const title = title0 ? title0.trim() : title0;
	const video = $v('meta[property="og:video"], meta[property="og:video:url"]');
	const tags = keywords
				 ?  '\n -' + keywords.replace(/,\ /g, ',').split(',').join('\n- ')
				 : null;

	const data = {
		link,
		author,
		image,
		time,
		title,
		video,
		tags
	};
	let str = `------\n`;
	Object.keys(data).forEach( k =>
	{
		if(data[k]) str += `${k}: ${data[k]}\n`
	});
	str += `------\n\n`;

	if(title){
		str += `# ${title}\n`;
	}
	if(description){
		str += `${description}\n\n`;
	}
	if(image){
		str += `![image](${image})\n\n`;
	}

	str += `${link}\n`;

	const markdown = encodeURIComponent(btoa(unescape(encodeURIComponent(str))));
	const fileName = location.pathname.replace(/\/$/g, '').split('/').pop();

	// return;
	setTimeout(()=>{
		location = DEBUG
					? `${LINK}?file=${fileName}&content=${markdown}`
					: `${LINK}?file=DEBUG&content=${markdown}`
	},0)

})()
<commit_msg>Update bookmarklet.js<commit_after>(function(){

	const $ = (_q) => document.querySelectorAll(_q);
	const $v = (_q) => {
		const _$ = $(_q);
		const len = _$.length;
		if(!len)
		{
			return null;
		}
		const i = len - 1;
		return _$[i].text || _$[i].src || _$[i].href || _$[i].content
	};

	const DEBUG = window.markdownWebNoteDebug;

	const LINK = "//erikccoder.github.io/markdown-web-note/index.html"
	const selection = window.getSelection().toString();
	const author = $v('meta[name="author"], meta[name="twitter:creator"], meta[property="article:author"]');
	const description = selection
						? selection
						: $v('meta[name="description"], meta[name="twitter:description"], meta[property="og:description"]');
	const image0 = $v('meta[name="twitter:image"], meta[property="og:image"]');
	const image = image0 ? image0 : $v('img');
	const keywords = $v('meta[name="keywords"]');
	const link = $v('link[rel="canonical"], meta[property="og:url"]') || window.location.href;
	const time = $v('meta[property="article:published_time"]');
	const title0 = $v('title, meta[name="twitter:title"], meta[property="og:title"]');
	const title = title0 ? title0.trim() : title0;
	const video = $v('meta[property="og:video"], meta[property="og:video:url"]');
	const tags = keywords
				 ?  '\n -' + keywords.replace(/,\ /g, ',').split(',').join('\n- ')
				 : null;

	const data = {
		link,
		author,
		image,
		time,
		title,
		video,
		tags
	};
	let str = `------\n`;
	Object.keys(data).forEach( k =>
	{
		if(data[k]) str += `${k}: ${data[k]}\n`
	});
	str += `------\n\n`;

	if(title){
		str += `# ${title}\n`;
	}
	if(description){
		str += `${description}\n\n`;
	}
	if(image){
		str += `![image](${image})\n\n`;
	}

	str += `${link}\n`;

	const markdown = encodeURIComponent(btoa(unescape(encodeURIComponent(str))));
	const fileName = location.pathname.replace(/\/$/g, '').split('/').pop();

	// return;
	setTimeout(()=>{
		location = DEBUG
					? `${LINK}?file=${fileName}&content=${markdown}`
					: `${LINK}?file=DEBUG&content=${markdown}`
	},0)

})()
<|endoftext|>


<commit_before>var relevantKeys = ['name', 'subject', 'body', 'author', 'subreddit', 'first_message_name', 'created_utc', 'parent_id', 'distinguished'];
var makeModmailObjects = function (modmails) {
  var all_modmails = [];
  for (let i = 0; i < modmails.length; i++) {
    let compressed = {};
    for (let j = 0; j < relevantKeys.length; j++) {
      compressed[relevantKeys[j]] = modmails[i].data[relevantKeys[j]];
    }
    all_modmails.push(compressed);
    if (modmails[i].data.replies) {
      all_modmails = all_modmails.concat(makeModmailObjects(modmails[i].data.replies.data.children));
    }
  }
  return all_modmails;
};
exports.updateArchive = async function (subreddit) {
  let most_recent = await Modmail.find({subreddit: subreddit, limit: 1, sort: 'created_utc DESC'});
  if (!most_recent.length) {
    console.log('Modmail archives for /r/' + subreddit + ' could not be found for some reason. Recreating from scratch...');
    return Modmail.findOrCreate(makeModmailObjects(await Reddit.getModmail(sails.config.reddit.adminRefreshToken, subreddit)));
  }
  let before = most_recent[0].first_message_name || most_recent[0].name;
  return Modmail.findOrCreate(makeModmailObjects(await Reddit.getModmail(sails.config.reddit.adminRefreshToken, subreddit, undefined, before)));
};
<commit_msg>Fixed modmail archiving<commit_after>var relevantKeys = ['name', 'subject', 'body', 'author', 'subreddit', 'first_message_name', 'created_utc', 'parent_id', 'distinguished'];
var makeModmailObjects = function (modmails) {
  var all_modmails = [];
  for (let i = 0; i < modmails.length; i++) {
    let compressed = {};
    for (let j = 0; j < relevantKeys.length; j++) {
      compressed[relevantKeys[j]] = modmails[i].data[relevantKeys[j]];
    }
    all_modmails.push(compressed);
    if (modmails[i].data.replies) {
      all_modmails = all_modmails.concat(makeModmailObjects(modmails[i].data.replies.data.children));
    }
  }
  return all_modmails;
};
exports.updateArchive = async function (subreddit) {
  let most_recent = await Modmail.find({subreddit: subreddit, limit: 1, sort: 'created_utc DESC'});
  if (!most_recent.length) {
    console.log('Modmail archives for /r/' + subreddit + ' could not be found for some reason. Recreating from scratch...');
    return Modmail.findOrCreate(makeModmailObjects(await Reddit.getModmail(sails.config.reddit.adminRefreshToken, subreddit)));
  }
  return Modmail.findOrCreate(makeModmailObjects(await Reddit.getModmail(sails.config.reddit.adminRefreshToken, subreddit, undefined, most_recent[0].name)));
};
<|endoftext|>


<commit_before>/**
 * Created by JetBrains WebStorm.
 * User: saar
 * Date: 13/05/12
 * Time: 13:19
 * To change this template use File | Settings | File Templates.
 */
var SEND_MAIL_NOTIFICATION = true;

var models = require('../models'),
    async = require('async'),
    notificationResource = require('./NotificationResource'),
    templates = require('../lib/templates'),
    mail = require('../lib/mail'),
    config = require('../config'),
    _ = require('underscore');

exports.create_user_notification = create_user_notification = function (notification_type, entity_id, user_id, notificatior_id, sub_entity, url, no_mail, callback) {

    if(typeof no_mail === 'function' && typeof callback !== 'function'){
        callback = no_mail;
        no_mail = null;
    }

    var single_notification_arr = [
        "new_discussion",
        "approved_change_suggestion_you_created",
        "approved_change_suggestion_on_discussion_you_are_part_of",
        "new_information_item_on_subject_you_are_part_of",
        "new_discussion_in_subject_you_are_part_of",
        "new_question_in_subject_you_are_part_of"
    ];

    var multi_notification_arr = [
        'comment_on_discussion_you_are_part_of',
        "comment_on_discussion_you_created",
        "comment_on_subject_you_are_part_of",
        "comment_on_your_forum_post",
        "comment_on_your_discussion_post",
        "comment_on_change_suggestion_i_created",
        "change_suggestion_on_discussion_you_created",
        "change_suggestion_on_discussion_you_are_part_of",
        "comment_on_question_in_subject_you_are_part_of"
    ];

    if (notificatior_id && _.indexOf(single_notification_arr, notification_type) == -1) {

        async.waterfall([
            //find existing notification
            function (cbk) {
                notification_type = notification_type + "";
                if (_.contains(multi_notification_arr, notification_type) && sub_entity) {
                    models.Notification.findOne({type:notification_type, 'notificators.sub_entity_id':sub_entity, user_id:user_id, visited: false}, function (err, obj) {
                        cbk(err, obj);
                    });
                }
                else if (entity_id)
                    models.Notification.findOne({type:notification_type, entity_id:entity_id, user_id:user_id}, function (err, obj) {
                        cbk(err, obj);
                    });
                else
                    models.Notification.findOne({type:notification_type, user_id:user_id}, function (err, obj) {
                        cbk(err, obj);
                    });
            },
            function(noti, cbk){
                //check if mail needs to be sent
                if(noti){
                    if(noti.visited)
                        cbk(null, noti, true);
                    else
                        cbk(null, noti, false);
                } else {
                    cbk(null, noti, true);
                }
            },
            function (noti, send_mail, cbk) {
                if (noti) {
                    noti.seen = false;
                    noti.visited = false;
                    noti.update_date = Date.now();

                    var new_notificator = {
                            notificator_id:notificatior_id,
                            sub_entity_id:sub_entity
                        },
                        notificator_exists = _.any(noti.notificators, function (notificator) {
                            return notificator.notificator_id + "" == notificatior_id + ""
                        });

                    if(notificator_exists) {
                        if(_.contains(multi_notification_arr, notification_type)) {
                            noti.notificators.push(new_notificator);
                        }
                    } else {
                        noti.notificators.push(new_notificator);
                    }

                    noti.save(function(err, obj){
                        if(!err && send_mail) {
                            sendNotificationToUser(obj);
                        }
                        cbk(err, obj);
                    });

                } else {
                    create_new_notification(notification_type, entity_id, user_id, notificatior_id, sub_entity, url, !send_mail, function (err, obj) {
                        cbk(err, obj);
                    });
                }
            }
        ],
        function (err, obj) {
            callback(err, obj);
        });
    } else {
        create_new_notification(notification_type, entity_id, user_id, notificatior_id, sub_entity, url, no_mail,function (err, obj) {
            callback(err, obj);
        });
    }
};

var create_new_notification = function (notification_type, entity_id, user_id, notificatior_id, sub_entity_id, url, no_mail, callback) {

    if(typeof no_mail === 'function' && typeof callback !== 'function'){
        callback = no_mail;
        no_mail = null;
    }

    var notification = new models.Notification();
    var notificator = {
        notificator_id:notificatior_id ? notificatior_id : null,
        sub_entity_id:sub_entity_id
    };

    notification.user_id = user_id;
    notification.notificators = notificator;
    notification.type = notification_type;
    notification.entity_id = entity_id;
    notification.url = url;
    notification.seen = false;
    notification.update_date = new Date();
    notification.visited = false;

    notification.save(function (err, obj) {
        if (err)
            console.error(err);
        callback(null, obj || notification);
        if (!err && obj && !no_mail)
            sendNotificationToUser(obj);
    });
};

/***
 * Send notification to user through mail or other external API
 * Checks if user should receive notification according to settings
 * @param notification
 * Notification object
 * @param last_update_date
 * notification last update date, or null if the notification is new
 * @param callback
 * function(err)
 */
var sendNotificationToUser = function (notification) {
    /**
     * Waterfall:
     * 1) Get user email
     * 2) Check user mail configuration
     * 3) create text message
     * 4) send message
     */

    var email;
    var  uru_group = [
        'saarsta@gmail.com',
        'themarianne@gmail.com',
        'maria@empeeric.com',
        'aharon.porath@gmail.com',
        'aharon@uru.org.il',
        'miriyaacobi@gmail.com',
        'miri@sheatufim.org.il',
        'ziv@sheatufim.co.il',
        'zivm21@gmail.com',
        'ziv@sheatufim.org.il'
    ];

    if (SEND_MAIL_NOTIFICATION)
        async.waterfall([
            // 1) Get user email
            function (cbk) {
                models.User.findById(notification.user_id, cbk);
            },

            // 2) Check user mail configuration
            function(user, cbk){
                if(user.mail_notification_configuration['get_alert_of_' + notification.type] && user.mail_notification_configuration.get_mails){
                    cbk(null, user);
                } else {
                    console.log('User should not receive mail because of his mail configuration');
                    cbk('break');
                }
            },

            // 3.1) create text message
            function(user, cbk){
                // notification populate references by notification type
                email = user.email;
                if (!_.find(uru_group, function(_mail){return _mail == email})){
                    console.error('not in uru group');
                    return cbk('not in uru group')
                }
                notificationResource.populateNotifications({objects:[notification]}, user.id, function(err, result){
                    cbk(err, result);
                });
            },

            // 3.2) create text message
            function (results, cbk) {
                var notification = results.objects[0];

                notification.entity_name = notification.name || '';
                notification.description_of_notificators = notification.description_of_notificators || '';
                notification.message_of_notificators = notification.message_of_notificators || '';
                templates.renderTemplate('notifications/' + notification.type, notification, function(err, result){
                    cbk(err, result);
                });
            },
            // 4) send message
            function (message, cbk) {
                mail.sendMailFromTemplate(email, message, cbk);
            }
        ],
            // Final
            function (err) {
                if (err) {
                    if (err != 'break') {
                        /*console.error('failed sending notification to user');
                        console.error(err);
                        console.trace();*/
                    }
                }
                else {
                    console.log('email ' + notification.type + ' sent to ' + email);
                    notification.visited = false;
                    notification.mail_was_sent = true;

                    notification.save(function (err) {
                        if (err) {
                            console.error('saving notification flag failed');
                        }
                    });
                }
            });
};

exports.update_user_notification = function (notification_type, obj_id, user, callback) {

};

exports.updateVisited = function (user, url) {
    models.Notification.update({user_id:user._id, url:url}, {$set:{visited:true}}, {multi:true}, function (err, count) {
        if (err) {
            console.error('failed setting notification visited to true', err);
        }
    })
};

function updateNotificationToSendMail(noti){
    models.Notification.update({_id: noti._id}, {$set: {mail_was_sent: false}}, function(err, num){
        if(err){
            console.error("could not set notification mail_was_sent flag to false");
            console.error(err);
        }
    })
}

models.InformationItem.onPreSave(function(next){
    var self = this;

    if(self.isNew) {
        async.each(self.subjects, function(subject_id, callback){
            models.User.find().where('subjects', subject_id).exec(function(err, users){
                if(err) next();
                async.each(users, function(user, cbk){
                    create_user_notification("new_information_item_on_subject_you_are_part_of", self._id, user._id, user._id, subject_id, "/discussions/subject/" + subject_id, function (err, results) {
                        cbk(err, results);
                    });
                }, function(err){
                    callback(err);
                });
            });
        } ,function(err){
            next();
        });
    } else {
        next();
    }
});

models.Discussion.onPreSave(function(next){
    var self = this;

    if(self.isNew) {
        models.User.find().where('subjects', self.subject_id).exec(function(err, users){
            if(err) next();
            async.each(users, function(user, cbk){
                create_user_notification("new_discussion_in_subject_you_are_part_of", self._id, user._id, self.creator_id, self.subject_id, "/discussions/" + self._id.toString(), function (err, results) {
                    cbk(err, results);
                });
            }, function(err){
                next();
            });
        });
    } else {
        next();
    }
});

models.Question.onPreSave(function(next){
    var self = this;

    if(self.isNew) {
        models.User.find().where('subjects', self.subject_id).exec(function(err, users){
            if(err) next();
            async.each(users, function(user, cbk){
                create_user_notification("new_question_in_subject_you_are_part_of", self._id, user._id, user._id, self.subject_id, "/discussions/subject/" + self.subject_id, function (err, results) {
                    cbk(err, results);
                });
            }, function(err){
                next();
            });
        });
    } else {
        next();
    }
});

//approved_info_item_i_created
if (/notifications\.js/.test(process.argv[1])) {
    var app = require('../app');

    console.log('testing');
    //function(notification_type, entity_id, user_id, notificatior_id, sub_entity_id, callback){
    //4f90064e360b9b01000000ac --info item
    //4fcdf7180a381201000005b3 --disc

    //a_dicussion_created_with_info_item_that_you_created
    //  sub //4fce400ccdd0570100000216

    //501fcef1e6ae520017000662 --הצעה לשינוי שהתקבלה
    setTimeout(function () {
        create_new_notification('comment_on_discussion_you_created',
            '4fcdf7180a381201000005b3', '4ff1b29aabf64e440f00013a', '4f45145968766b0100000002', '501fcef1e6ae520017000662', function (err) {
                console.log(err);
            });

    }, 1000);
}<commit_msg>remove uru_group condition<commit_after>/**
 * Created by JetBrains WebStorm.
 * User: saar
 * Date: 13/05/12
 * Time: 13:19
 * To change this template use File | Settings | File Templates.
 */
var SEND_MAIL_NOTIFICATION = true;

var models = require('../models'),
    async = require('async'),
    notificationResource = require('./NotificationResource'),
    templates = require('../lib/templates'),
    mail = require('../lib/mail'),
    config = require('../config'),
    _ = require('underscore');

exports.create_user_notification = create_user_notification = function (notification_type, entity_id, user_id, notificatior_id, sub_entity, url, no_mail, callback) {

    if(typeof no_mail === 'function' && typeof callback !== 'function'){
        callback = no_mail;
        no_mail = null;
    }

    var single_notification_arr = [
        "new_discussion",
        "approved_change_suggestion_you_created",
        "approved_change_suggestion_on_discussion_you_are_part_of",
        "new_information_item_on_subject_you_are_part_of",
        "new_discussion_in_subject_you_are_part_of",
        "new_question_in_subject_you_are_part_of"
    ];

    var multi_notification_arr = [
        'comment_on_discussion_you_are_part_of',
        "comment_on_discussion_you_created",
        "comment_on_subject_you_are_part_of",
        "comment_on_your_forum_post",
        "comment_on_your_discussion_post",
        "comment_on_change_suggestion_i_created",
        "change_suggestion_on_discussion_you_created",
        "change_suggestion_on_discussion_you_are_part_of",
        "comment_on_question_in_subject_you_are_part_of"
    ];

    if (notificatior_id && _.indexOf(single_notification_arr, notification_type) == -1) {

        async.waterfall([
            //find existing notification
            function (cbk) {
                notification_type = notification_type + "";
                if (_.contains(multi_notification_arr, notification_type) && sub_entity) {
                    models.Notification.findOne({type:notification_type, 'notificators.sub_entity_id':sub_entity, user_id:user_id, visited: false}, function (err, obj) {
                        cbk(err, obj);
                    });
                }
                else if (entity_id)
                    models.Notification.findOne({type:notification_type, entity_id:entity_id, user_id:user_id}, function (err, obj) {
                        cbk(err, obj);
                    });
                else
                    models.Notification.findOne({type:notification_type, user_id:user_id}, function (err, obj) {
                        cbk(err, obj);
                    });
            },
            function(noti, cbk){
                //check if mail needs to be sent
                if(noti){
                    if(noti.visited)
                        cbk(null, noti, true);
                    else
                        cbk(null, noti, false);
                } else {
                    cbk(null, noti, true);
                }
            },
            function (noti, send_mail, cbk) {
                if (noti) {
                    noti.seen = false;
                    noti.visited = false;
                    noti.update_date = Date.now();

                    var new_notificator = {
                            notificator_id:notificatior_id,
                            sub_entity_id:sub_entity
                        },
                        notificator_exists = _.any(noti.notificators, function (notificator) {
                            return notificator.notificator_id + "" == notificatior_id + ""
                        });

                    if(notificator_exists) {
                        if(_.contains(multi_notification_arr, notification_type)) {
                            noti.notificators.push(new_notificator);
                        }
                    } else {
                        noti.notificators.push(new_notificator);
                    }

                    noti.save(function(err, obj){
                        if(!err && send_mail) {
                            sendNotificationToUser(obj);
                        }
                        cbk(err, obj);
                    });

                } else {
                    create_new_notification(notification_type, entity_id, user_id, notificatior_id, sub_entity, url, !send_mail, function (err, obj) {
                        cbk(err, obj);
                    });
                }
            }
        ],
        function (err, obj) {
            callback(err, obj);
        });
    } else {
        create_new_notification(notification_type, entity_id, user_id, notificatior_id, sub_entity, url, no_mail,function (err, obj) {
            callback(err, obj);
        });
    }
};

var create_new_notification = function (notification_type, entity_id, user_id, notificatior_id, sub_entity_id, url, no_mail, callback) {

    if(typeof no_mail === 'function' && typeof callback !== 'function'){
        callback = no_mail;
        no_mail = null;
    }

    var notification = new models.Notification();
    var notificator = {
        notificator_id:notificatior_id ? notificatior_id : null,
        sub_entity_id:sub_entity_id
    };

    notification.user_id = user_id;
    notification.notificators = notificator;
    notification.type = notification_type;
    notification.entity_id = entity_id;
    notification.url = url;
    notification.seen = false;
    notification.update_date = new Date();
    notification.visited = false;

    notification.save(function (err, obj) {
        if (err)
            console.error(err);
        callback(null, obj || notification);
        if (!err && obj && !no_mail)
            sendNotificationToUser(obj);
    });
};

/***
 * Send notification to user through mail or other external API
 * Checks if user should receive notification according to settings
 * @param notification
 * Notification object
 * @param last_update_date
 * notification last update date, or null if the notification is new
 * @param callback
 * function(err)
 */
var sendNotificationToUser = function (notification) {
    /**
     * Waterfall:
     * 1) Get user email
     * 2) Check user mail configuration
     * 3) create text message
     * 4) send message
     */

    var email;
    var  uru_group = [
        'saarsta@gmail.com',
        'themarianne@gmail.com',
        'maria@empeeric.com',
        'aharon.porath@gmail.com',
        'aharon@uru.org.il',
        'miriyaacobi@gmail.com',
        'miri@sheatufim.org.il',
        'ziv@sheatufim.co.il',
        'zivm21@gmail.com',
        'ziv@sheatufim.org.il'
    ];

    if (SEND_MAIL_NOTIFICATION)
        async.waterfall([
            // 1) Get user email
            function (cbk) {
                models.User.findById(notification.user_id, cbk);
            },

            // 2) Check user mail configuration
            function(user, cbk){
                if(user.mail_notification_configuration['get_alert_of_' + notification.type] && user.mail_notification_configuration.get_mails){
                    cbk(null, user);
                } else {
                    console.log('User should not receive mail because of his mail configuration');
                    cbk('break');
                }
            },

            // 3.1) create text message
            function(user, cbk){
                // notification populate references by notification type
                email = user.email;
                /*if (!_.find(uru_group, function(_mail){return _mail == email})){
                    console.error('not in uru group');
                    return cbk('not in uru group')
                }*/
                notificationResource.populateNotifications({objects:[notification]}, user.id, function(err, result){
                    cbk(err, result);
                });
            },

            // 3.2) create text message
            function (results, cbk) {
                var notification = results.objects[0];

                notification.entity_name = notification.name || '';
                notification.description_of_notificators = notification.description_of_notificators || '';
                notification.message_of_notificators = notification.message_of_notificators || '';
                templates.renderTemplate('notifications/' + notification.type, notification, function(err, result){
                    cbk(err, result);
                });
            },
            // 4) send message
            function (message, cbk) {
                mail.sendMailFromTemplate(email, message, cbk);
            }
        ],
            // Final
            function (err) {
                if (err) {
                    if (err != 'break') {
                        /*console.error('failed sending notification to user');
                        console.error(err);
                        console.trace();*/
                    }
                }
                else {
                    console.log('email ' + notification.type + ' sent to ' + email);
                    notification.visited = false;
                    notification.mail_was_sent = true;

                    notification.save(function (err) {
                        if (err) {
                            console.error('saving notification flag failed');
                        }
                    });
                }
            });
};

exports.update_user_notification = function (notification_type, obj_id, user, callback) {

};

exports.updateVisited = function (user, url) {
    models.Notification.update({user_id:user._id, url:url}, {$set:{visited:true}}, {multi:true}, function (err, count) {
        if (err) {
            console.error('failed setting notification visited to true', err);
        }
    })
};

function updateNotificationToSendMail(noti){
    models.Notification.update({_id: noti._id}, {$set: {mail_was_sent: false}}, function(err, num){
        if(err){
            console.error("could not set notification mail_was_sent flag to false");
            console.error(err);
        }
    })
}

models.InformationItem.onPreSave(function(next){
    var self = this;

    if(self.isNew) {
        async.each(self.subjects, function(subject_id, callback){
            models.User.find().where('subjects', subject_id).exec(function(err, users){
                if(err) next();
                async.each(users, function(user, cbk){
                    create_user_notification("new_information_item_on_subject_you_are_part_of", self._id, user._id, user._id, subject_id, "/discussions/subject/" + subject_id, function (err, results) {
                        cbk(err, results);
                    });
                }, function(err){
                    callback(err);
                });
            });
        } ,function(err){
            next();
        });
    } else {
        next();
    }
});

models.Discussion.onPreSave(function(next){
    var self = this;

    if(self.isNew) {
        models.User.find().where('subjects', self.subject_id).exec(function(err, users){
            if(err) next();
            async.each(users, function(user, cbk){
                create_user_notification("new_discussion_in_subject_you_are_part_of", self._id, user._id, self.creator_id, self.subject_id, "/discussions/" + self._id.toString(), function (err, results) {
                    cbk(err, results);
                });
            }, function(err){
                next();
            });
        });
    } else {
        next();
    }
});

models.Question.onPreSave(function(next){
    var self = this;

    if(self.isNew) {
        models.User.find().where('subjects', self.subject_id).exec(function(err, users){
            if(err) next();
            async.each(users, function(user, cbk){
                create_user_notification("new_question_in_subject_you_are_part_of", self._id, user._id, user._id, self.subject_id, "/discussions/subject/" + self.subject_id, function (err, results) {
                    cbk(err, results);
                });
            }, function(err){
                next();
            });
        });
    } else {
        next();
    }
});

//approved_info_item_i_created
if (/notifications\.js/.test(process.argv[1])) {
    var app = require('../app');

    console.log('testing');
    //function(notification_type, entity_id, user_id, notificatior_id, sub_entity_id, callback){
    //4f90064e360b9b01000000ac --info item
    //4fcdf7180a381201000005b3 --disc

    //a_dicussion_created_with_info_item_that_you_created
    //  sub //4fce400ccdd0570100000216

    //501fcef1e6ae520017000662 --הצעה לשינוי שהתקבלה
    setTimeout(function () {
        create_new_notification('comment_on_discussion_you_created',
            '4fcdf7180a381201000005b3', '4ff1b29aabf64e440f00013a', '4f45145968766b0100000002', '501fcef1e6ae520017000662', function (err) {
                console.log(err);
            });

    }, 1000);
}<|endoftext|>