<commit_before>/**
 * Created by m-oez on 02.12.2015.
 */

define(['scripts/feierabend/player.js',
    'scripts/feierabend/collectable.js',
    'scripts/feierabend/workmate.js',
    'scripts/feierabend/viewable.js',
    'scripts/feierabend/music.js',
    'scripts/feierabend/audio.js',
], function (createPlayer, createCollectable, createWorkmate, createViewable, playMusic, playAudio) {

    var levels = [
        [
            {type: 'background', img: '././img/ground.jpg'},
            {type: 'player', id: 'player', x: 0, y: 0},
            {type: 'coffee', id: 'coffee1', x: 3, y: 3},
            {type: 'coffee', id: 'coffee2', x: 3, y: 8},
            {type: 'coffee', id: 'coffee3', x: 3, y: 9},
            {type: 'workmate', id: '1', x: 5, y: 8},
            {type: 'workmate', id: '2', x: 8, y: 8},
			{type: 'door', id: 'door', x: 15, y: 11},
            {type: 'paperjam', id: 'paper1', x: 4, y: 4},
            {type: 'notebook', id: 'notebook1', x: 7, y: 7},
        ]
    ];
	var player;
	var workmates = [];

    return function createLevel(currentLevel, loader, game, gameScene, renderer)  {

        levels[currentLevel].map(
            function (object) {

                switch (object.type) {
                    case 'background':
                        var background = PIXI.Sprite.fromImage(object.img);
                        background.width = renderer.width;
                        background.height = renderer.height;
                        gameScene.container.addChild(background);
                        break;
                    case 'player':
                        player = createPlayer(loader.resources.player.texture, game);
                        gameScene.container.addChild(player.getSprite());
                        break;
                    case 'coffee':
                        var newObject = createCollectable(object.id, loader.resources.coffee.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {
                                    collideObj.speed = 200;
                                    playAudio("drinkCoffee");
                                    playMusic('backgroundMusicFast');
                                    setTimeout(function () {
                                        collideObj.speed = 500;
                                        playMusic('backgroundMusic');
                                    }, 2000);
                                    eventObj.getSprite().visible = false;
                                }
                            }, {x: object.x, y: object.y});
                        gameScene.container.addChild(newObject.getSprite());
                        break;

                         case 'paperjam':
                        var newObject = createCollectable(object.id, loader.resources.paperjam.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {
                                    collideObj.speed = 200;
                                    playAudio("workOnPaper");
                                    setTimeout(function () {
                                        collideObj.speed = 100;
                                        playMusic('backgroundMusic');
                                    }, 2000);
                                    eventObj.getSprite().visible = false;
                                }
                            }, {x: object.x, y: object.y});
                        gameScene.container.addChild(newObject.getSprite());
                        break;

                        case 'notebook':
                        var newObject = createCollectable(object.id, loader.resources.notebook.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {
                                    collideObj.speed = 200;
                                    playAudio("workOnNotebook");
                                    setTimeout(function () {
                                        collideObj.speed = 100;
                                        playMusic('backgroundMusic');
                                    }, 2000);
                                    eventObj.getSprite().visible = false;
                                }
                            }, {x: object.x, y: object.y});
                        gameScene.container.addChild(newObject.getSprite());
                        break;

					case 'door':
                        var newObject = createCollectable(object.id, loader.resources.door.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {
									// play here a win audio
									game.changeGameState("FINISH");
                                }
                            }, {x: object.x, y: object.y});

                        gameScene.container.addChild(newObject.getSprite());
                        break;
                    case 'workmate':
                        var newWorkmate = createWorkmate(1, loader.resources.workmate.texture, game, {
                            x: object.x,
                            y: object.y
                        });
                        workmates.push(newWorkmate);
                        gameScene.container.addChild(newWorkmate.getSprite());
                }

            }
        );

        return [player, workmates];

    }

});
<commit_msg>fixed run bug by collecting paperjam or notebook<commit_after>/**
 * Created by m-oez on 02.12.2015.
 */

define(['scripts/feierabend/player.js',
    'scripts/feierabend/collectable.js',
    'scripts/feierabend/workmate.js',
    'scripts/feierabend/viewable.js',
    'scripts/feierabend/music.js',
    'scripts/feierabend/audio.js',
], function (createPlayer, createCollectable, createWorkmate, createViewable, playMusic, playAudio) {

    var levels = [
        [
            {type: 'background', img: '././img/ground.jpg'},
            {type: 'player', id: 'player', x: 0, y: 0},
            {type: 'coffee', id: 'coffee1', x: 3, y: 3},
            {type: 'coffee', id: 'coffee2', x: 3, y: 8},
            {type: 'coffee', id: 'coffee3', x: 3, y: 9},
            {type: 'workmate', id: '1', x: 5, y: 8},
            {type: 'workmate', id: '2', x: 8, y: 8},
			{type: 'door', id: 'door', x: 15, y: 11},
            {type: 'paperjam', id: 'paper1', x: 4, y: 4},
            {type: 'notebook', id: 'notebook1', x: 7, y: 7},
        ]
    ];
	var player;
	var workmates = [];

    return function createLevel(currentLevel, loader, game, gameScene, renderer)  {

        levels[currentLevel].map(
            function (object) {

                switch (object.type) {
                    case 'background':
                        var background = PIXI.Sprite.fromImage(object.img);
                        background.width = renderer.width;
                        background.height = renderer.height;
                        gameScene.container.addChild(background);
                        break;
                    case 'player':
                        player = createPlayer(loader.resources.player.texture, game);
                        gameScene.container.addChild(player.getSprite());
                        break;
                    case 'coffee':
                        var newObject = createCollectable(object.id, loader.resources.coffee.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {
                                    collideObj.speed = 200;
                                    playAudio("drinkCoffee");
                                    playMusic('backgroundMusicFast');
                                    setTimeout(function () {
                                        collideObj.speed = 500;
                                        playMusic('backgroundMusic');
                                    }, 2000);
                                    eventObj.getSprite().visible = false;
                                }
                            }, {x: object.x, y: object.y});
                        gameScene.container.addChild(newObject.getSprite());
                        break;

                         case 'paperjam':
                        var newObject = createCollectable(object.id, loader.resources.paperjam.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {

                                    playAudio("workOnPaper");
                                    setTimeout(function () {

                                        playMusic('backgroundMusic');
                                    }, 2000);
                                    eventObj.getSprite().visible = false;
                                }
                            }, {x: object.x, y: object.y});
                        gameScene.container.addChild(newObject.getSprite());
                        break;

                        case 'notebook':
                        var newObject = createCollectable(object.id, loader.resources.notebook.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {

                                    playAudio("workOnNotebook");
                                    setTimeout(function () {

                                        playMusic('backgroundMusic');
                                    }, 2000);
                                    eventObj.getSprite().visible = false;
                                }
                            }, {x: object.x, y: object.y});
                        gameScene.container.addChild(newObject.getSprite());
                        break;

					case 'door':
                        var newObject = createCollectable(object.id, loader.resources.door.texture, game,
                            function collideFn(collideObj, eventObj) {
                                if (collideObj.id === 'player') {
									// play here a win audio
									game.changeGameState("FINISH");
                                }
                            }, {x: object.x, y: object.y});

                        gameScene.container.addChild(newObject.getSprite());
                        break;
                    case 'workmate':
                        var newWorkmate = createWorkmate(1, loader.resources.workmate.texture, game, {
                            x: object.x,
                            y: object.y
                        });
                        workmates.push(newWorkmate);
                        gameScene.container.addChild(newWorkmate.getSprite());
                }

            }
        );

        return [player, workmates];

    }

});
<|endoftext|>


<commit_before>'use strict';

angular.module('qldarchApp').config(function($stateProvider) {
  $stateProvider.state('firm', {
    abstract : true,
    url : '/firm?firmId',
    templateUrl : 'views/firm/layout.html',
    resolve : {
      firm : [ '$stateParams', 'ArchObj', '$filter', function($stateParams, ArchObj, $filter) {
        if (!$stateParams.firmId) {
          return {};
        } else {
          return ArchObj.loadWithRelationshipLabels($stateParams.firmId).then(function(data) {
            data.media = $filter('orderBy')(data.media, function(media) {
              return (media.preferred || '');
            }, true);
            return data;
          }).catch(function() {
            console.log('unable to load firm ArchObj with relationship labels');
            return {};
          });
        }
      } ],
      architects : [ 'AggArchObjs', 'GraphHelper', '$filter', function(AggArchObjs, GraphHelper, $filter) {
        return AggArchObjs.loadArchitects().then(function(data) {
          var architects = GraphHelper.graphValues(data);
          return $filter('filter')(architects, function(architect) {
            return architect.label && !(/\s/.test(architect.label.substring(0, 1)));
          });
        }).catch(function() {
          console.log('unable to load all architects');
          return {};
        });
      } ],
      firms : [ 'AggArchObjs', '$filter', function(AggArchObjs, $filter) {
        return AggArchObjs.loadFirms().then(function(data) {
          return $filter('filter')(data, function(firm) {
            return firm.label && !(/\s/.test(firm.label.substring(0, 1)));
          });
        }).catch(function() {
          console.log('unable to load all firms');
          return {};
        });
      } ],
      allstructures : [ 'AggArchObjs', function(AggArchObjs) {
        return AggArchObjs.loadProjects().then(function(data) {
          return data;
        }).catch(function() {
          console.log('unable to load all projects');
          return {};
        });
      } ]
    },
    controller : [ '$scope', 'firm', 'ArchObj', '$state', function($scope, firm, ArchObj, $state) {
      $scope.firm = firm;
      $scope.delete = function(firm) {
        var r = window.confirm('Delete firm ' + firm.label + '?');
        if (r === true) {
          ArchObj.delete(firm.id).then(function() {
            $state.go('firm.australian');
          });
        }
      };
    } ]
  });
});<commit_msg>fixed a typo<commit_after>'use strict';

angular.module('qldarchApp').config(function($stateProvider) {
  $stateProvider.state('firm', {
    abstract : true,
    url : '/firm?firmId',
    templateUrl : 'views/firm/layout.html',
    resolve : {
      firm : [ '$stateParams', 'ArchObj', '$filter', function($stateParams, ArchObj, $filter) {
        if (!$stateParams.firmId) {
          return {};
        } else {
          return ArchObj.loadWithRelationshipLabels($stateParams.firmId).then(function(data) {
            data.media = $filter('orderBy')(data.media, function(media) {
              return (media.preferred || '');
            }, true);
            return data;
          }).catch(function() {
            console.log('unable to load firm ArchObj with relationship labels');
            return {};
          });
        }
      } ],
      architects : [ 'AggArchObjs', 'GraphHelper', '$filter', function(AggArchObjs, GraphHelper, $filter) {
        return AggArchObjs.loadArchitects().then(function(data) {
          var architects = GraphHelper.graphValues(data);
          return $filter('filter')(architects, function(architect) {
            return architect.label && !(/\s/.test(architect.label.substring(0, 1)));
          });
        }).catch(function() {
          console.log('unable to load all architects');
          return {};
        });
      } ],
      firms : [ 'AggArchObjs', '$filter', function(AggArchObjs, $filter) {
        return AggArchObjs.loadFirms().then(function(data) {
          return $filter('filter')(data, function(firm) {
            return firm.label && !(/\s/.test(firm.label.substring(0, 1)));
          });
        }).catch(function() {
          console.log('unable to load all firms');
          return {};
        });
      } ],
      allstructures : [ 'AggArchObjs', function(AggArchObjs) {
        return AggArchObjs.loadProjects().then(function(data) {
          return data;
        }).catch(function() {
          console.log('unable to load all projects');
          return {};
        });
      } ]
    },
    controller : [ '$scope', 'firm', 'ArchObj', '$state', function($scope, firm, ArchObj, $state) {
      $scope.firm = firm;
      $scope.delete = function(firm) {
        var r = window.confirm('Delete firm ' + firm.label + '?');
        if (r === true) {
          ArchObj.delete(firm.id).then(function() {
            $state.go('firms.australian');
          });
        }
      };
    } ]
  });
});<|endoftext|>


<commit_before>/*
 * grunt-flex-yui-group
 * http://gruntjs.com/
 *
 * Copyright (c) 2014 Bret K. Ikehara
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
    "use strict";

    var liboptions = require(__dirname + '/options.js'),
        libprecompile = require(__dirname + '/precompile.js'),
        libfilter = require(__dirname + '/filter.js'),
        libpath = require('path'),
        libutil = require('util'),
        metaConfig = {
            metaConfig: {},
            read: function(cwd, files) {
                files.map(function(filepath) {
                    var filecontent = grunt.file.read(cwd + '/' + filepath),
                        meta = JSON.parse(filecontent);

                    Object.keys(meta).forEach(function(key) {
                        this.set(key, meta[key]);
                    }, this);
                }, this);
                return this.get();
            },
            get: function() {
                return this.metaConfig;
            },
            set: function(key, value) {
                this.metaConfig[key] = value;
            },
            toString: function(spaces) {
                return JSON.stringify(this.metaConfig, null, spaces);
            }
        };

    grunt.registerMultiTask(
        'yui-meta',
        'Generates a meta file for a custom YUI group.',
        function() {
            var options = liboptions.get(this.options()),
                filter = libfilter.get(grunt, options);

            grunt.verbose.writeflags(options, 'Options');

            grunt.verbose.writeln('Reading configs from %s files', this.files.length);

            /**
            * Run the program.
            */
            if (this.files && this.files.length > 0) {
                this.files.forEach(function(file) {
                    // store the meta data in the modules object.
                    var metaConfig = getMetaConfig.call(this, file.src);

                    // Write joined contents to destination filepath.
                    grunt.file.write(file.dest, JSON.stringify(metaConfig, null, options.space));
                }, this);
            }
            else {
                grunt.verbose.writeln('Failed to find files');
            }
        }
    );

    grunt.registerMultiTask(
        'yui-config',
        'Generates a custom YUI group config.',
        function() {
            var options = liboptions.get(this.options()),
                precompiler = libprecompile.get(grunt, options),
                filter = libfilter.get(grunt, options);

            grunt.verbose.writeflags(options, 'Options');

            grunt.verbose.writeln('Reading configs from %s files', this.files.length);

            /**
            * Run the program.
            */
            if (this.files && this.files.length > 0) {
                this.files.forEach(function(file) {
                    var meta,
                        configContent;

                    // store the meta data in the modules object.
                    meta = file.src.map(function(filepath) {
                        return grunt.file.read(filepath);
                    }, this).join('');

                    // wrap meta in the config.
                    configContent = precompiler.wrap({
                        meta: meta
                    });

                    // Write joined contents to destination filepath.
                    grunt.file.write(file.dest, configContent);
                }, this);
            }
            else {
                grunt.verbose.writeln('Failed to find files');
            }
        }
    );

    grunt.registerMultiTask(
        'yui-build',
        'Builds each module',
        function() {
            var options = liboptions.get(this.options()),
                precompiler = libprecompile.get(grunt, options),
                filter = libfilter.get(grunt, options),
                modules = {};

            grunt.verbose.writeflags(options, 'Options');

            grunt.verbose.writeln('Reading configs from %s files', this.files.length);

            /**
            * Run the program.
            */
            if (this.files && this.files.length > 0) {
                this.files.forEach(function(file) {

                    file.src.forEach(function(buildFile) {
                        var build;

                        buildFile = libpath.join(file.cwd, buildFile);

                        grunt.log.writeln('Reading build: %s', buildFile);
                        build = JSON.parse(grunt.file.read(buildFile));

                        // loop through modules to build
                        Object.keys(build.builds).forEach(function(moduleName) {
                            var content = [],
                                destPath;

                            // join the js files.
                            build.builds[moduleName].jsfiles.forEach(function(jsfile) {
                                var data = grunt.file.read(libpath.join(libpath.dirname(buildFile), 'js', jsfile));
                                grunt.log.writeln('Reading module: %s', jsfile);
                                content.push(data);
                            });

                            destPath = libpath.join(file.dest, moduleName, moduleName + '.js');

                            // Write joined contents to destination filepath.
                            grunt.log.writeln('Writing file: %s', destPath);
                            grunt.file.write(destPath, content.join('\n'));
                        });
                    }, this);
                }, this);
            }
            else {
                grunt.verbose.writeln('Failed to find files');
            }
        }
    );
};<commit_msg>Refactored the template Handlebar handler.<commit_after>/*
 * grunt-flex-yui-group
 * http://gruntjs.com/
 *
 * Copyright (c) 2014 Bret K. Ikehara
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
    "use strict";

    var liboptions = require(__dirname + '/options.js'),
        libprecompile = require(__dirname + '/precompile.js'),
        libfilter = require(__dirname + '/filter.js'),
        libpath = require('path'),
        libutil = require('util'),
        Handlebars = require('handlebars'),
        metaConfig = {
            metaConfig: {},
            read: function(cwd, files) {
                files.map(function(filepath) {
                    var filecontent = grunt.file.read(cwd + '/' + filepath),
                        meta = JSON.parse(filecontent);

                    Object.keys(meta).forEach(function(key) {
                        this.set(key, meta[key]);
                    }, this);
                }, this);
                return this.get();
            },
            get: function() {
                return this.metaConfig;
            },
            set: function(key, value) {
                this.metaConfig[key] = value;
            },
            toString: function(spaces) {
                return JSON.stringify(this.metaConfig, null, spaces);
            }
        },
        template = {
            init: function(name, filepath) {
                var content = grunt.file.read(filepath);

                // create template handler.
                if (!content) {
                    return null;
                }

                this[name] = Handlebars.compile(Handlebars.parse(content));

                return this[name];
            }
        },
        options = {
            buildDir: 'build',
            srcDir: 'src',
            spaces: 2,
            configWrapper: __dirname + '/template/config-wrapper.hbs',
            moduleWrapper: __dirname + '/template/module-wrapper.hbs'
        };

    grunt.registerMultiTask(
        'yui-meta',
        'Generates a meta file for a custom YUI group.',
        function() {
            var options = liboptions.get(this.options()),
                filter = libfilter.get(grunt, options);

            grunt.verbose.writeflags(options, 'Options');

            grunt.verbose.writeln('Reading configs from %s files', this.files.length);

            /**
            * Run the program.
            */
            if (this.files && this.files.length > 0) {
                this.files.forEach(function(file) {
                    // store the meta data in the modules object.
                    var metaConfig = getMetaConfig.call(this, file.src);

                    // Write joined contents to destination filepath.
                    grunt.file.write(file.dest, JSON.stringify(metaConfig, null, options.space));
                }, this);
            }
            else {
                grunt.verbose.writeln('Failed to find files');
            }
        }
    );

    grunt.registerMultiTask(
        'yui-config',
        'Generates a custom YUI group config.',
        function() {
            var options = liboptions.get(this.options()),
                precompiler = libprecompile.get(grunt, options),
                filter = libfilter.get(grunt, options);

            grunt.verbose.writeflags(options, 'Options');

            grunt.verbose.writeln('Reading configs from %s files', this.files.length);

            /**
            * Run the program.
            */
            if (this.files && this.files.length > 0) {
                this.files.forEach(function(file) {
                    var meta,
                        configContent;

                    // store the meta data in the modules object.
                    meta = file.src.map(function(filepath) {
                        return grunt.file.read(filepath);
                    }, this).join('');

                    // wrap meta in the config.
                    configContent = precompiler.wrap({
                        meta: meta
                    });

                    // Write joined contents to destination filepath.
                    grunt.file.write(file.dest, configContent);
                }, this);
            }
            else {
                grunt.verbose.writeln('Failed to find files');
            }
        }
    );

    grunt.registerMultiTask(
        'yui-build',
        'Builds each module',
        function() {
            var options = liboptions.get(this.options()),
                precompiler = libprecompile.get(grunt, options),
                filter = libfilter.get(grunt, options),
                modules = {};

            grunt.verbose.writeflags(options, 'Options');

            grunt.verbose.writeln('Reading configs from %s files', this.files.length);

            /**
            * Run the program.
            */
            if (this.files && this.files.length > 0) {
                this.files.forEach(function(file) {

                    file.src.forEach(function(buildFile) {
                        var build;

                        buildFile = libpath.join(file.cwd, buildFile);

                        grunt.log.writeln('Reading build: %s', buildFile);
                        build = JSON.parse(grunt.file.read(buildFile));

                        // loop through modules to build
                        Object.keys(build.builds).forEach(function(moduleName) {
                            var content = [],
                                destPath;

                            // join the js files.
                            build.builds[moduleName].jsfiles.forEach(function(jsfile) {
                                var data = grunt.file.read(libpath.join(libpath.dirname(buildFile), 'js', jsfile));
                                grunt.log.writeln('Reading module: %s', jsfile);
                                content.push(data);
                            });

                            destPath = libpath.join(file.dest, moduleName, moduleName + '.js');

                            // Write joined contents to destination filepath.
                            grunt.log.writeln('Writing file: %s', destPath);
                            grunt.file.write(destPath, content.join('\n'));
                        });
                    }, this);
                }, this);
            }
            else {
                grunt.verbose.writeln('Failed to find files');
            }
        }
    );
};<|endoftext|>


<commit_before>Meteor.methods({
  'getAllResidentIds': function () {
    // TODO: determine how to secure this method to prevent client abuse

    // Get all residents
    var residents = Residents.find().fetch();

    // Create an array of resident IDs
    var residentIds = _.map(residents, function (resident) {
      return resident._id;
    });

    return residentIds;
  },
  'getCurrentResidentIds': function () {
    // TODO: determine how to secure this method to prevent client abuse

    // Get all residents
    var residents = Residents.find({departed: false}).fetch();

    // Create an array of resident IDs
    var residentIds = _.map(residents, function (resident) {
      return resident._id;
    });

    return residentIds;
  },
  'getResidentsNameHomeAndLatestActivityByType': function (activityTypeId) {
    // Get all resident IDs
    var residentIds = Meteor.call('getCurrentAllResidentIds');

    // Placeholder for residents latest activity
    var residentsLatestActivityByType = [];

    // Loop through all resident IDs
    residentIds.forEach(function (residentId) {
      // Return resident latest activity
      var residentLatestActivity = Meteor.call('getResidentLatestActivityByType', residentId, activityTypeId);

      // If resident activity exists
      if (residentLatestActivity !== undefined) {
        // Get resident from collection
        var resident = Residents.findOne(residentId);

        // Construct an object with resident name and last activity date
        var residentActivityObject = {
          residentName: resident.fullName(),
          homeName: resident.homeName(),
          activityDate: residentLatestActivity.activityDate
        };

        // Add resident latest activity to residents latest activity array
        residentsLatestActivityByType.push(residentActivityObject);
      }
    });

    return residentsLatestActivityByType;
  },
  'getResidentsWithoutActivityByType': function (activityTypeId) {
    // // Get resident latest activity by type
    // var residentLastActivityByType = Meteor.call('getResidentsLatestActivityByType', activityTypeId);
    //
    // // Get all resident IDs
    // var residentIds = Residents.find({}, {fields: {_id: 1}}).fetch();
    //
    // // Get residents who have participated in the activity type
    // var residentsWithPreviousActivity = _.map(residentLastActivityByType, function (resident) {
    //   return resident._id;
    // });
    //
    // // Get residents who have not participated in activity type
    // var residentsWithoutPreviousActivity = _.difference(residentIds, residentsWithPreviousActivity);
    //
    // return residentsWithoutPreviousActivity;
  },
  'getResidentRecentActivities': function (residentId) {
    // Date two weeks ago
    var twoWeeksAgo = moment().subtract(2, "weeks").toDate();

    // Date today
    var now = new Date();

    // Get all activities involving resident
    // make sure activities are in the past (i.e. not planned)
    //  sort in reverse order by activity date
    return Activities.find({'residentIds': residentId, activityDate: {$gte: twoWeeksAgo, $lte: now}}, {sort : {activityDate:  -1} });
  },
  'getResidentRecentActivitiesByType': function (residentId, activityTypeId) {
    // Date two weeks ago
    var twoWeeksAgo = moment().subtract(4, "weeks").toDate();

    // Date today
    var now = new Date();

    // Get all activities of a specific type involving resident
    // make sure activities are in the past (i.e. not planned)
    //  sort in reverse order by activity date
    var activities = Activities.find({
      'residentIds': residentId,
      'activityTypeId': activityTypeId,
      activityDate: {$gte: twoWeeksAgo, $lte: now}},
      {sort : {activityDate:  -1}
    }).fetch();

    if (activities) {
      return activities;
    };
  },
  'getSumOfResidentRecentActivitiesByType': function (residentId, activityTypeId) {
    var activities = Meteor.call('getResidentRecentActivitiesByType', residentId, activityTypeId);

    // Placeholder for sum of activities
    var sumOfActivities = 0;

    if (activities) {
      // Count each activity
      activities.forEach(function (activity) {
        // Count the resident activity
        sumOfActivities += 1;
      });
    };

    return sumOfActivities;
  },
  'getSumOfAllResidentRecentActivitiesByType': function (residentId) {
    // Get all activity type IDs
    var activityTypeIds = Meteor.call('getAllActivityTypeIds');

    // Placeholder for resident activity sums
    var residentActivitySumsByType = [];

    activityTypeIds.forEach(function (activityTypeId) {
      // Get the activity type
      var activityType = ActivityTypes.findOne(activityTypeId);

      // Get the resident
      var resident = Residents.findOne(residentId);

      // Get sum of activity type for the current resident
      var activitySum = Meteor.call('getSumOfResidentRecentActivitiesByType', residentId, activityTypeId);

      // Create an object with the activity type name and sum
      var activityTypeSum = {
        residentName: resident.fullName(),
        activityTypeName: activityType.name,
        sum: activitySum
      }

      // Add the resident activity type sum to the resident activity sums array
      residentActivitySumsByType.push(activityTypeSum);
    });

    return residentActivitySumsByType;
  },
  'getAllResidentsActivitySumsByType': function () {
    // Get all resident IDs
    var residentIds = Meteor.call('getCurrentResidentIds');

    // Placeholder for all resident activity sums by type
    var allResidentActivitySumsByType = [];

    // Iterate through all residents and get sum of resident recent activities by type
    residentIds.forEach(function (residentId) {
      // Get the sum of all activities by type for a given resident
       var residentActivitiesSumByType = Meteor.call('getSumOfAllResidentRecentActivitiesByType', residentId);

      // Add the resident activity sums to all resident activity sums array
      allResidentActivitySumsByType.push(residentActivitiesSumByType);
    });

    allResidentActivitySumsByTypeFlattened = _.flatten(allResidentActivitySumsByType)

    return allResidentActivitySumsByTypeFlattened;
  }
});
<commit_msg>Fix ambiguity in date query (30 days)<commit_after>Meteor.methods({
  'getAllResidentIds': function () {
    // TODO: determine how to secure this method to prevent client abuse

    // Get all residents
    var residents = Residents.find().fetch();

    // Create an array of resident IDs
    var residentIds = _.map(residents, function (resident) {
      return resident._id;
    });

    return residentIds;
  },
  'getCurrentResidentIds': function () {
    // TODO: determine how to secure this method to prevent client abuse

    // Get all residents
    var residents = Residents.find({departed: false}).fetch();

    // Create an array of resident IDs
    var residentIds = _.map(residents, function (resident) {
      return resident._id;
    });

    return residentIds;
  },
  'getResidentsNameHomeAndLatestActivityByType': function (activityTypeId) {
    // Get all resident IDs
    var residentIds = Meteor.call('getCurrentAllResidentIds');

    // Placeholder for residents latest activity
    var residentsLatestActivityByType = [];

    // Loop through all resident IDs
    residentIds.forEach(function (residentId) {
      // Return resident latest activity
      var residentLatestActivity = Meteor.call('getResidentLatestActivityByType', residentId, activityTypeId);

      // If resident activity exists
      if (residentLatestActivity !== undefined) {
        // Get resident from collection
        var resident = Residents.findOne(residentId);

        // Construct an object with resident name and last activity date
        var residentActivityObject = {
          residentName: resident.fullName(),
          homeName: resident.homeName(),
          activityDate: residentLatestActivity.activityDate
        };

        // Add resident latest activity to residents latest activity array
        residentsLatestActivityByType.push(residentActivityObject);
      }
    });

    return residentsLatestActivityByType;
  },
  'getResidentsWithoutActivityByType': function (activityTypeId) {
    // // Get resident latest activity by type
    // var residentLastActivityByType = Meteor.call('getResidentsLatestActivityByType', activityTypeId);
    //
    // // Get all resident IDs
    // var residentIds = Residents.find({}, {fields: {_id: 1}}).fetch();
    //
    // // Get residents who have participated in the activity type
    // var residentsWithPreviousActivity = _.map(residentLastActivityByType, function (resident) {
    //   return resident._id;
    // });
    //
    // // Get residents who have not participated in activity type
    // var residentsWithoutPreviousActivity = _.difference(residentIds, residentsWithPreviousActivity);
    //
    // return residentsWithoutPreviousActivity;
  },
  'getResidentRecentActivities': function (residentId) {
    // Date two weeks ago
    var twoWeeksAgo = moment().subtract(2, "weeks").toDate();

    // Date today
    var now = new Date();

    // Get all activities involving resident
    // make sure activities are in the past (i.e. not planned)
    //  sort in reverse order by activity date
    return Activities.find({'residentIds': residentId, activityDate: {$gte: twoWeeksAgo, $lte: now}}, {sort : {activityDate:  -1} });
  },
  'getResidentActivitiesByTypeLast30Days': function (residentId, activityTypeId) {
    // Date thirty days ago
    var thirtyDaysAgo = moment().subtract(30, "days").toDate();

    // Date today
    var now = new Date();

    // Get all activities of a specific type involving resident
    // make sure activities are in the past (i.e. not planned)
    //  sort in reverse order by activity date
    var activities = Activities.find({
      'residentIds': residentId,
      'activityTypeId': activityTypeId,
      activityDate: {$gte: thirtyDaysAgo, $lte: now}},
      {sort : {activityDate:  -1}
    }).fetch();

    if (activities) {
      return activities;
    };
  },
  'getSumOfResidentActivitiesByTypeLast30Days': function (residentId, activityTypeId) {
    var activities = Meteor.call('getResidentActivitiesByTypeLast30Days', residentId, activityTypeId);

    // Placeholder for sum of activities
    var sumOfActivities = 0;

    if (activities) {
      // Count each activity
      activities.forEach(function (activity) {
        // Count the resident activity
        sumOfActivities += 1;
      });
    };

    return sumOfActivities;
  },
  'getSumOfAllResidentRecentActivitiesByType': function (residentId) {
    // Get all activity type IDs
    var activityTypeIds = Meteor.call('getAllActivityTypeIds');

    // Placeholder for resident activity sums
    var residentActivitySumsByType = [];

    activityTypeIds.forEach(function (activityTypeId) {
      // Get the activity type
      var activityType = ActivityTypes.findOne(activityTypeId);

      // Get the resident
      var resident = Residents.findOne(residentId);

      // Get sum of activity type for the current resident
      var activitySum = Meteor.call('getSumOfResidentRecentActivitiesByType', residentId, activityTypeId);

      // Create an object with the activity type name and sum
      var activityTypeSum = {
        residentName: resident.fullName(),
        activityTypeName: activityType.name,
        sum: activitySum
      }

      // Add the resident activity type sum to the resident activity sums array
      residentActivitySumsByType.push(activityTypeSum);
    });

    return residentActivitySumsByType;
  },
  'getAllResidentsActivitySumsByType': function () {
    // Get all resident IDs
    var residentIds = Meteor.call('getCurrentResidentIds');

    // Placeholder for all resident activity sums by type
    var allResidentActivitySumsByType = [];

    // Iterate through all residents and get sum of resident recent activities by type
    residentIds.forEach(function (residentId) {
      // Get the sum of all activities by type for a given resident
       var residentActivitiesSumByType = Meteor.call('getSumOfAllResidentRecentActivitiesByType', residentId);

      // Add the resident activity sums to all resident activity sums array
      allResidentActivitySumsByType.push(residentActivitiesSumByType);
    });

    allResidentActivitySumsByTypeFlattened = _.flatten(allResidentActivitySumsByType)

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


<commit_before>import { Class } from 'orbit/lib/objects';
import Orbit from 'orbit/main';
import { assert } from 'orbit/lib/assert';
import { isArray, isObject, expose } from 'orbit/lib/objects';
import Source from 'orbit-common/source';
import { pluck, map } from 'orbit-firebase/lib/array-utils';

import Operation from 'orbit/operation';

import FirebaseClient from './firebase-client';
import FirebaseRequester from './firebase-requester';
import FirebaseTransformer from './firebase-transformer';
import FirebaseSerializer from './firebase-serializer';
import FirebaseListener from './firebase-listener';
import CacheSource from './cache-source';
import OperationMatcher from './operation-matcher';
import OperationDecomposer from './operation-decomposer';
import OperationSequencer from './operation-sequencer';
import SchemaUtils from './lib/schema-utils';
import { fop } from './lib/operation-utils';

export default Source.extend({
	notifierName: "firebase-source",

	init: function(schema, options){
		var _this = this;
		options = options || {};

		this._super.apply(this, arguments);
		this._cache.maintainInverseLinks = false;

		assert('FirebaseSource requires Orbit.Promise be defined', Orbit.Promise);
		assert('FirebaseSource requires Orbit.all be defined', Orbit.all);
		assert('FirebaseSource requires Orbit.allSettled be defined', Orbit.allSettled);
		assert('FirebaseSource requires Orbit.map be defined', Orbit.map);
		assert('FirebaseSource requires Orbit.resolve be defined', Orbit.resolve);
		assert('FirebaseSource requires firebaseRef be defined', options.firebaseRef);

		var firebaseRef = options.firebaseRef;
		var serializer = new FirebaseSerializer(schema);
		var firebaseClient = new FirebaseClient(firebaseRef);

		this._schemaUtils = new SchemaUtils(this.schema);
		this._firebaseTransformer = new FirebaseTransformer(firebaseClient, schema, serializer);
		this._firebaseRequester = new FirebaseRequester(firebaseClient, schema, serializer);
		this._firebaseListener = new FirebaseListener(firebaseRef, schema, serializer);

		var cacheSource = new CacheSource(this._cache);
		this._operationSequencer = new OperationSequencer(this._cache, schema);

		this._firebaseListener.on('didTransform', function(operation){
			_this._operationSequencer.process(operation);
		});

		this.on("didTransform", function(operation){
			// console.log("fb.transmitting", operation.path.join("/"), operation.value);
		});
	},

	disconnect: function(){
		return this._firebaseListener.unsubscribeAll();
	},

	_transform: function(operation){
		// console.log("fb.transform", operation.serialize());
		var _this = this;

		return this._firebaseTransformer.transform(operation).then(function(result){

			if(operation.op === "add" && operation.path.length === 2){
				var type = operation.path[0];
				var allLinks = _this._schemaUtils.linksFor(type);
				return _this._subscribeToRecords(type, result, {include: allLinks});
			}

			else if(operation.op !== "remove" && operation.path.length === 2){
				operation.value = _this.schema.normalize(operation.path[0], operation.value);
			}

		}).then(function(){
			_this._operationSequencer.process(operation);
		});
	},

	_find: function(type, id, options){
		var _this = this;
		return this._firebaseRequester.find(type, id).then(function(records){
			if(!id) _this._firebaseListener.subscribeToType(type, null, options);
			_this._subscribeToRecords(type, records, options);

      return _this._firebaseListener.then(function(){
        return _this.settleTransforms();
      })
      .then(function(){
        return records;

      });
		});
	},

	_findLink: function(type, id, link){
		// todo - why are no subscriptions created? maybe irrelevant
		return this._firebaseRequester.findLink(type, id, link);
	},

	_findLinked: function(type, id, link, options){
		// console.log("fb._findLinked", arguments);
		var _this = this;
		var linkedType = this.schema.models[type].links[link].model;

		return this._firebaseRequester.findLinked(type, id, link).then(function(records){
			_this._firebaseListener.subscribeToLink(type, id, link, options);
			return _this._firebaseListener.then(function(){
				return _this.settleTransforms();
			})
			.then(function(){
				return records;

			});
		});
	},

	_subscribeToRecords: function(type, records, options){
		records = isArray(records) ? records : [records];
		return this._firebaseListener.subscribeToRecords(type, pluck(records, 'id'), options);
	}
});
<commit_msg>Wait for firebaseListener to settle before returning from transform<commit_after>import { Class } from 'orbit/lib/objects';
import Orbit from 'orbit/main';
import { assert } from 'orbit/lib/assert';
import { isArray, isObject, expose } from 'orbit/lib/objects';
import Source from 'orbit-common/source';
import { pluck, map } from 'orbit-firebase/lib/array-utils';

import Operation from 'orbit/operation';

import FirebaseClient from './firebase-client';
import FirebaseRequester from './firebase-requester';
import FirebaseTransformer from './firebase-transformer';
import FirebaseSerializer from './firebase-serializer';
import FirebaseListener from './firebase-listener';
import CacheSource from './cache-source';
import OperationMatcher from './operation-matcher';
import OperationDecomposer from './operation-decomposer';
import OperationSequencer from './operation-sequencer';
import SchemaUtils from './lib/schema-utils';
import { fop } from './lib/operation-utils';

export default Source.extend({
	notifierName: "firebase-source",

	init: function(schema, options){
		var _this = this;
		options = options || {};

		this._super.apply(this, arguments);
		this._cache.maintainInverseLinks = false;

		assert('FirebaseSource requires Orbit.Promise be defined', Orbit.Promise);
		assert('FirebaseSource requires Orbit.all be defined', Orbit.all);
		assert('FirebaseSource requires Orbit.allSettled be defined', Orbit.allSettled);
		assert('FirebaseSource requires Orbit.map be defined', Orbit.map);
		assert('FirebaseSource requires Orbit.resolve be defined', Orbit.resolve);
		assert('FirebaseSource requires firebaseRef be defined', options.firebaseRef);

		var firebaseRef = options.firebaseRef;
		var serializer = new FirebaseSerializer(schema);
		var firebaseClient = new FirebaseClient(firebaseRef);

		this._schemaUtils = new SchemaUtils(this.schema);
		this._firebaseTransformer = new FirebaseTransformer(firebaseClient, schema, serializer);
		this._firebaseRequester = new FirebaseRequester(firebaseClient, schema, serializer);
		this._firebaseListener = new FirebaseListener(firebaseRef, schema, serializer);

		var cacheSource = new CacheSource(this._cache);
		this._operationSequencer = new OperationSequencer(this._cache, schema);

		this._firebaseListener.on('didTransform', function(operation){
			_this._operationSequencer.process(operation);
		});

		this.on("didTransform", function(operation){
			// console.log("fb.transmitting", operation.path.join("/"), operation.value);
		});
	},

	disconnect: function(){
		return this._firebaseListener.unsubscribeAll();
	},

	_transform: function(operation){
		// console.log("fb.transform", operation.serialize());
		var _this = this;

		return this._firebaseTransformer.transform(operation).then(function(result){

			if(operation.op === "add" && operation.path.length === 2){
				var type = operation.path[0];
				var allLinks = _this._schemaUtils.linksFor(type);
				_this._subscribeToRecords(type, result, {include: allLinks});
				return _this._firebaseListener.then(function(){
					console.log("transform complete");
				});
			}

			else if(operation.op !== "remove" && operation.path.length === 2){
				operation.value = _this.schema.normalize(operation.path[0], operation.value);
			}

		}).then(function(){
			_this._operationSequencer.process(operation);
		});
	},

	_find: function(type, id, options){
		var _this = this;
		return this._firebaseRequester.find(type, id).then(function(records){
			if(!id) _this._firebaseListener.subscribeToType(type, null, options);
			_this._subscribeToRecords(type, records, options);

      return _this._firebaseListener.then(function(){
        return _this.settleTransforms();
      })
      .then(function(){
        return records;

      });
		});
	},

	_findLink: function(type, id, link){
		// todo - why are no subscriptions created? maybe irrelevant
		return this._firebaseRequester.findLink(type, id, link);
	},

	_findLinked: function(type, id, link, options){
		// console.log("fb._findLinked", arguments);
		var _this = this;
		var linkedType = this.schema.models[type].links[link].model;

		return this._firebaseRequester.findLinked(type, id, link).then(function(records){
			_this._firebaseListener.subscribeToLink(type, id, link, options);
			return _this._firebaseListener.then(function(){
				return _this.settleTransforms();
			})
			.then(function(){
				return records;

			});
		});
	},

	_subscribeToRecords: function(type, records, options){
		records = isArray(records) ? records : [records];
		return this._firebaseListener.subscribeToRecords(type, pluck(records, 'id'), options);
	}
});
<|endoftext|>


<commit_before>class QuoteCard extends React.Component {
    timestampToDate(timestamp) {
        var date = new Date(timestamp);
        var dd = date.getDate();
        var mm = date.getMonth() + 1;
        var yyyy = date.getFullYear();

        if (dd < 10)
            dd = "0" + dd;

        if (mm < 10)
            mm = "0" + mm;

        return mm + "/" + dd + "/" + yyyy;
    }

    render() {
        return (

                                    {this.props.children}

                            {this.props.author}

                                {this.timestampToDate(this.props.timestamp)}

        );
    }
}

class QuoteList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            quotes: [],
            page: 0,
            endOfData: false
        };
    }

    componentDidMount() {
        this.fetch();

        var page = $(document);
        $(window).scroll(() => {
            if (this.state.endOfData)
                return;

            if (page.scrollTop() + $(document.body).height() >= page.height())
                this.fetch();
        }.bind(this));
    }

    // Views
    renderEndOfDataView(){
        return (

                You've seen it all.

        );
    }

    renderQuoteView(quoteKey, quote){
        return (
            <QuoteCard key={quoteKey} author={quote.author} timestamp={quote.timestamp} bgColor1={quote.bgColor1} bgColor2={quote.bgColor2}>
                {quote.quote}
            </QuoteCard>
        );
    }

    render() {
        if (this.state.quotes.length == 0)
            return (

                    Loading...

            );

        if (this.state.endOfData)
            return (

{this.state.quotes}

                    {this.renderEndOfDataView()}

            );

        return (

{this.state.quotes}

        );
    }

    // Utils
    fetch() {
        var fetchSize = this.props.pageSize * (this.state.page + 1);

        firebase.database().ref("/quotes").limitToLast(fetchSize).once("value").then(data => {
            if (this.state.quotes.length === data.numChildren()){
                this.setState({endOfData: true});
                return;
            }

            data = data.val();
            if (data == null)
                console.log("error");

            this.addQuotes(data);
        }.bind(this));
    }

    addQuotes(data){
        var i = 0,
            page = this.state.page + 1,
            newQuotes = [];

        // Order quotes from newest to oldest
        for (var quoteKey in data){
            if (i == this.props.pageSize)
                break;

            data[quoteKey].bgColor1 = this.props.quoteColors[Math.floor(Math.random() * colors.length)];
            data[quoteKey].bgColor2 = this.props.quoteColors[Math.floor(Math.random() * colors.length)];

            newQuotes.unshift(this.renderQuoteView(quoteKey, data[quoteKey]));
            i++;
        }

        var quotes = this.state.quotes;
        quotes.push(...newQuotes);
        this.setState({quotes: quotes, page: page++});
    }
}

QuoteList.propTypes = {
    pageSize: React.PropTypes.number.isRequired,
    quoteColors: React.PropTypes.array.isRequired,
};

var colors = ["#b71c1c", "#c62828", "#d32f2f", "#e53935", "#d81b60",
              "#c2185b", "#ad1457", "#880e4f", "#8e24aa", "#7b1fa2",
              "#6a1b9a", "#4a148c"];
ReactDOM.render(<QuoteList pageSize={2} quoteColors={colors} />, document.getElementById("quote-app"));
<commit_msg>fixing EndOfData<commit_after>class QuoteCard extends React.Component {
    timestampToDate(timestamp) {
        var date = new Date(timestamp);
        var dd = date.getDate();
        var mm = date.getMonth() + 1;
        var yyyy = date.getFullYear();

        if (dd < 10)
            dd = "0" + dd;

        if (mm < 10)
            mm = "0" + mm;

        return mm + "/" + dd + "/" + yyyy;
    }

    render() {
        return (

                                    {this.props.children}

                            {this.props.author}

                                {this.timestampToDate(this.props.timestamp)}

        );
    }
}

class QuoteList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            quotes: [],
            page: 0,
            endOfData: false
        };
    }

    componentDidMount() {
        this.fetch();

        var page = $(document);
        $(window).scroll(() => {
            if (this.state.endOfData)
                return;

            if (page.scrollTop() + $(document.body).height() >= page.height())
                this.fetch();
        }.bind(this));
    }

    // Views
    renderEndOfDataView(){
        return (

                You've seen it all.

        );
    }

    renderQuoteView(quoteKey, quote){
        return (
            <QuoteCard key={quoteKey} author={quote.author} timestamp={quote.timestamp} bgColor1={quote.bgColor1} bgColor2={quote.bgColor2}>
                {quote.quote}
            </QuoteCard>
        );
    }

    render() {
        if (this.state.quotes.length == 0)
            return (

                    Loading...

            );

        if (this.state.endOfData)
            return (

{this.state.quotes}

                    {this.renderEndOfDataView()}

            );

        return (

{this.state.quotes}

        );
    }

    // Utils
    fetch() {
        var fetchSize = this.props.pageSize * (this.state.page + 1);

        firebase.database().ref("/quotes").limitToLast(fetchSize).once("value").then(data => {
            var dataCount = data.numChildren()

            if (this.state.quotes.length === dataCount){
                this.setState({endOfData: true});
                return;
            }

            data = data.val();
            if (data == null)
                console.log("error");

            this.addQuotes(data, dataCount);
        }.bind(this));
    }

    addQuotes(data, dataCount){
        var i = 0,
            page = this.state.page + 1,
            newQuotes = [];

        // Order quotes from newest to oldest
        var newQuotesCount = (dataCount % this.props.pageSize) || this.props.pageSize;
        for (var quoteKey in data){
            if (i == newQuotesCount)
                break;

            data[quoteKey].bgColor1 = this.props.quoteColors[Math.floor(Math.random() * colors.length)];
            data[quoteKey].bgColor2 = this.props.quoteColors[Math.floor(Math.random() * colors.length)];

            newQuotes.unshift(this.renderQuoteView(quoteKey, data[quoteKey]));
            i++;
        }

        var quotes = this.state.quotes;
        quotes.push(...newQuotes);

        this.setState({quotes: quotes, page: page++});
    }
}

QuoteList.propTypes = {
    pageSize: React.PropTypes.number.isRequired,
    quoteColors: React.PropTypes.array.isRequired,
};

var colors = ["#b71c1c", "#c62828", "#d32f2f", "#e53935", "#d81b60",
              "#c2185b", "#ad1457", "#880e4f", "#8e24aa", "#7b1fa2",
              "#6a1b9a", "#4a148c"];
ReactDOM.render(<QuoteList pageSize={10} quoteColors={colors} />, document.getElementById("quote-app"));
<|endoftext|>


<commit_before>//The store is an event emitter.
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var {isArray, isEmpty, isObject} = require('lodash/lang');
var getEntityInformations = require('../definition/entity/builder').getEntityInformations;
var capitalize = require('lodash/string/capitalize');
var Immutable = require('immutable');
var AppDispatcher = require('../dispatcher');
/**
 * @class CoreStore
 */
class CoreStore extends EventEmitter {

  /**
   * Contructor of the store class.
   */
  constructor(config) {
    assign(this, {
      config
    });
    //Initialize the data as immutable map.
    this.data = Immutable.Map({});
    this.status = Immutable.Map({});
    this.error = Immutable.Map({});
    this.customHandler = assign({}, config.customHandler);
    //Register all gernerated methods.
    this.buildDefinition();
    this.buildEachNodeChangeEventListener();
    this.registerDispatcher();
  }

  /**
   * Initialize the store configuration.
   * @param {object} storeConfiguration - The store configuration for the initialization.
   */
  buildDefinition() {
      /**
       * Build the definitions for the entity (may be a subject.)
       * @type {object}
       */
      this.definition = this.config.definition || getEntityInformations(
        this.config.definitionPath,
        this.config.customDefinition
      );
      return this.definition;
  }
  /** Return the status of a definition.
   * @returns {string} - The status of a definition.
   */
  getStatus(def){
    if (this.status.has(def)){
      return this.status.get(def);
    }
    return undefined;
  }
  /**
  * Build a change listener for each property in the definition. (should be macro entities);
  */
  buildEachNodeChangeEventListener() {
    var currentStore = this;
      //Loop through each store properties.
      for (var definition in this.definition) {
        var capitalizeDefinition = capitalize(definition);
        //Creates the change listener
        currentStore[`add${capitalizeDefinition}ChangeListener`] = function(def){
          return function (cb) {
            currentStore.addListener(`${def}:change`, cb);
        }}(definition);
        //Remove the change listener
        currentStore[`remove${capitalizeDefinition}ChangeListener`] = function(def){
          return function (cb) {
            currentStore.removeListener(`${def}:change`, cb);
        }}(definition);
        //Create an update method.
        currentStore[`update${capitalizeDefinition}`] = function(def){
          return function (dataNode, status) {
            var immutableNode = Immutable.fromJS(dataNode);
            currentStore.data = currentStore.data.set(def, immutableNode);
            //Update the status on the data.
            currentStore.status = currentStore.status.set(def, status);
            currentStore.emit(`${def}:change`, {status: status});
        }}(definition);
        //Create a get method.
        currentStore[`get${capitalizeDefinition}`] = function(def){
          return function () {
            var hasData = currentStore.data.has(def);
            if(hasData){
              var rawData = currentStore.data.get(def);
              if (isObject(rawData)) {
                var data = rawData.toJS();
                if(!isEmpty(data)){
                  return data;
                }
              } else {
                return rawData;
              }
            }
            return undefined;
          };
        }(definition);
        //Creates the error change listener
        currentStore[`add${capitalizeDefinition}ErrorListener`] = function(def){
            return function (cb) {
              currentStore.addListener(`${def}:error`, cb);
        }}(definition);
        //Remove the change listener
        currentStore[`remove${capitalizeDefinition}ErrorListener`] = function(def){
            return function (cb) {
              currentStore.removeListener(`${def}:error`, cb);
        }}(definition);
        //Create an update method.
        currentStore[`updateError${capitalizeDefinition}`] = function(def){
            return function (dataNode) {
              //CheckIsObject
              var immutableNode = Immutable[isArray(dataNode) ? "List" : "Map"](dataNode);
              currentStore.error = currentStore.error.set(def, immutableNode);
              currentStore.emit(`${def}:error`);
        }}(definition);
        //Create a get method.
        currentStore[`getError${capitalizeDefinition}`] = function(def){
            return function(){
              var hasData = currentStore.error.has(def);
              return hasData ? currentStore.error.get(def).toJS() : undefined;
            };
        }(definition);
      }
    }
  /**
   * The store registrer itself on the dispatcher.
   */
  registerDispatcher(){
    var currentStore = this;
    this.dispatch = AppDispatcher.register(function(transferInfo) {
      //Complete rewrie by the store.
      //todo: see if this has meaning instead of an override
      if(currentStore.globalCustomHandler){
        return currentStore.globalCustomHandler.call(currentStore, transferInfo);
      }
      var rawData = transferInfo.action.data;
      var status = transferInfo.action.status || {};
      var type = transferInfo.action.type;
      for(var node in rawData){
        if(currentStore.definition[node]){
          //Call a custom handler if this exists.
          if(currentStore.customHandler && currentStore.customHandler[node] && currentStore.customHandler[node][type]){
            currentStore.customHandler[node][type].call(currentStore, rawData[node], status[node]);
          }else {
            //Update the data for the given node. and emit the change/.
            currentStore[`${type}${capitalize(node)}`](rawData[node], status[node]);
          }
        }
      }
      //console.log('dispatchHandler:action', transferInfo);
    });
  }
    /**
     * Add a listener on a store event.
     * @param {string}   eventName - Event name.
     * @param {Function} cb - CallBack to call on the event change name.
     */
  addListener(eventName, cb) {
    this.on(eventName, cb);
  }

}
module.exports = CoreStore;
<commit_msg>[store] Add the definition in the change event.<commit_after>//The store is an event emitter.
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var {isArray, isEmpty, isObject} = require('lodash/lang');
var getEntityInformations = require('../definition/entity/builder').getEntityInformations;
var capitalize = require('lodash/string/capitalize');
var Immutable = require('immutable');
var AppDispatcher = require('../dispatcher');
/**
 * @class CoreStore
 */
class CoreStore extends EventEmitter {

  /**
   * Contructor of the store class.
   */
  constructor(config) {
    assign(this, {
      config
    });
    //Initialize the data as immutable map.
    this.data = Immutable.Map({});
    this.status = Immutable.Map({});
    this.error = Immutable.Map({});
    this.customHandler = assign({}, config.customHandler);
    //Register all gernerated methods.
    this.buildDefinition();
    this.buildEachNodeChangeEventListener();
    this.registerDispatcher();
  }

  /**
   * Initialize the store configuration.
   * @param {object} storeConfiguration - The store configuration for the initialization.
   */
  buildDefinition() {
      /**
       * Build the definitions for the entity (may be a subject.)
       * @type {object}
       */
      this.definition = this.config.definition || getEntityInformations(
        this.config.definitionPath,
        this.config.customDefinition
      );
      return this.definition;
  }
  /** Return the status of a definition.
   * @returns {string} - The status of a definition.
   */
  getStatus(def){
    if (this.status.has(def)){
      return this.status.get(def);
    }
    return undefined;
  }
  /**
  * Build a change listener for each property in the definition. (should be macro entities);
  */
  buildEachNodeChangeEventListener() {
    var currentStore = this;
      //Loop through each store properties.
      for (var definition in this.definition) {
        var capitalizeDefinition = capitalize(definition);
        //Creates the change listener
        currentStore[`add${capitalizeDefinition}ChangeListener`] = function(def){
          return function (cb) {
            currentStore.addListener(`${def}:change`, cb);
        }}(definition);
        //Remove the change listener
        currentStore[`remove${capitalizeDefinition}ChangeListener`] = function(def){
          return function (cb) {
            currentStore.removeListener(`${def}:change`, cb);
        }}(definition);
        //Create an update method.
        currentStore[`update${capitalizeDefinition}`] = function(def){
          return function (dataNode, status) {
            var immutableNode = Immutable.fromJS(dataNode);
            currentStore.data = currentStore.data.set(def, immutableNode);
            //Update the status on the data.
            currentStore.status = currentStore.status.set(def, status);
            currentStore.emit(`${def}:change`, {property: def, status: status});
        }}(definition);
        //Create a get method.
        currentStore[`get${capitalizeDefinition}`] = function(def){
          return function () {
            var hasData = currentStore.data.has(def);
            if(hasData){
              var rawData = currentStore.data.get(def);
              if (isObject(rawData)) {
                var data = rawData.toJS();
                if(!isEmpty(data)){
                  return data;
                }
              } else {
                return rawData;
              }
            }
            return undefined;
          };
        }(definition);
        //Creates the error change listener
        currentStore[`add${capitalizeDefinition}ErrorListener`] = function(def){
            return function (cb) {
              currentStore.addListener(`${def}:error`, cb);
        }}(definition);
        //Remove the change listener
        currentStore[`remove${capitalizeDefinition}ErrorListener`] = function(def){
            return function (cb) {
              currentStore.removeListener(`${def}:error`, cb);
        }}(definition);
        //Create an update method.
        currentStore[`updateError${capitalizeDefinition}`] = function(def){
            return function (dataNode) {
              //CheckIsObject
              var immutableNode = Immutable[isArray(dataNode) ? "List" : "Map"](dataNode);
              currentStore.error = currentStore.error.set(def, immutableNode);
              currentStore.emit(`${def}:error`);
        }}(definition);
        //Create a get method.
        currentStore[`getError${capitalizeDefinition}`] = function(def){
            return function(){
              var hasData = currentStore.error.has(def);
              return hasData ? currentStore.error.get(def).toJS() : undefined;
            };
        }(definition);
      }
    }
  /**
   * The store registrer itself on the dispatcher.
   */
  registerDispatcher(){
    var currentStore = this;
    this.dispatch = AppDispatcher.register(function(transferInfo) {
      //Complete rewrie by the store.
      //todo: see if this has meaning instead of an override
      if(currentStore.globalCustomHandler){
        return currentStore.globalCustomHandler.call(currentStore, transferInfo);
      }
      var rawData = transferInfo.action.data;
      var status = transferInfo.action.status || {};
      var type = transferInfo.action.type;
      for(var node in rawData){
        if(currentStore.definition[node]){
          //Call a custom handler if this exists.
          if(currentStore.customHandler && currentStore.customHandler[node] && currentStore.customHandler[node][type]){
            currentStore.customHandler[node][type].call(currentStore, rawData[node], status[node]);
          }else {
            //Update the data for the given node. and emit the change/.
            currentStore[`${type}${capitalize(node)}`](rawData[node], status[node]);
          }
        }
      }
      //console.log('dispatchHandler:action', transferInfo);
    });
  }
    /**
     * Add a listener on a store event.
     * @param {string}   eventName - Event name.
     * @param {Function} cb - CallBack to call on the event change name.
     */
  addListener(eventName, cb) {
    this.on(eventName, cb);
  }

}
module.exports = CoreStore;
<|endoftext|>


<commit_before>"use strict";

var BlindingInformation = require("./types/blinding_information");
var client = require("./client");
var util = require("./util");

var openpgp = require("openpgp");

module.exports = {

  /// TODO : Avoid blinding and encrpytion in one step!
  blind_message: function(message, blinding_information)
  {
    if (!(util.isString(message) || /^[0-9]+$/.test(message))
      || !BlindingInformation.isValidFullBlindingInformation(blinding_information)) {
      return null;
    }

    var message_as_MPI = util.bytes2MPI(message);

    var m = message_as_MPI.data;
    var r = blinding_information.blinding_factor;
    var e = blinding_information.public_exponent;
    var N = blinding_information.modulus;

    return m.multiply(r.modPow(e, N));
  },

  /// TODO
  unblind_message: function(message, blinding_information)
  {
    if (!(util.isString(message) || /^[0-9]+$/.test(message))
          || !BlindingInformation.isValidFullBlindingInformation(blinding_information)) {
      return null;
    }

    var m = util.str2BigInt(message);
    var N = blinding_information.modulus;
    var r = blinding_information.blinding_factor;

    var r_inv = r.modInverse(N);
    return m.multiply(r_inv);
  },

  /// TODO
  prepareBlindSignature: function ()
  {
    var server_public_key = client.getServerPublicKey();
    var server_public_key_packet = server_public_key.primaryKey;

    var signature_packet = new openpgp.packet.Signature();
    signature_packet.signatureType = openpgp.enums.signature.cert_generic;
    signature_packet.hashAlgorithm = server_public_key.getPreferredHashAlgorithm();
    signature_packet.issuerKeyId = server_public_key_packet.getKeyId();
    signature_packet.publicKeyAlgorithm = openpgp.enums.write(openpgp.enums.publicKey, server_public_key_packet.algorithm);

    //
    // Create random creation time between key creation und expire date
    // if no expire date is available use maximum possible day in the future
    //    - 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC.
    //      http://es5.github.io/#x15.9.1.1
    //

    var public_key = client.getPublicKey();
    var public_key_packet = public_key.primaryKey;

    var key_created = public_key_packet.created.getTime();
    var key_expire = public_key.getExpirationTime();
    if (null === key_expire || 0 === key_expire.getTime()) {
      key_expire = 8640000000000000;
    } else {
      key_expire = key_expire.getTime();
    }

    var signature_created = Math.floor(key_created + Math.random() * (key_expire - key_created));
    signature_packet.created = new Date(signature_created);

    //
    // prepare sign data (@see Timo Engel thesis)
    //
    // <signatureData>  = <sigHashdData> <sigTrailer >
    // <sigHashData>    = <version> <signatureType> <pubAlgorithm>
    //                    <hashAlgorithm> <hashedSubpktsLen>
    //                    <hashedSubpkts>
    // <sigTrailer>     = %x04 %xff <sigHashDataLen>
    // <sigHashDataLen> = 4<OCTET>

    var sig_hash_data_string = String.fromCharCode(signature_packet.version);
    sig_hash_data_string += String.fromCharCode(signature_packet.signatureType);
    sig_hash_data_string += String.fromCharCode(signature_packet.publicKeyAlgorithm);
    sig_hash_data_string += String.fromCharCode(signature_packet.hashAlgorithm);
    sig_hash_data_string += signature_packet.write_all_sub_packets();

    signature_packet.signatureData = sig_hash_data_string;

    //
    // prepare sign data (@see Timo Engel thesis)
    //
    // <signData>   = <pubKeyData> <userIdData> <signatureData>
    // <userIdData> = %xb4 <userIdLen> <userIdPacket>
    // <userIdLen>  = 4<OCTET> ; len(<userIdPacket >)
    // <pubKeyData> = %x99 <pubKeyLen> <publicKeyPacket>
    // <pubKeyLen>  = 2<OCTET> ; len(<publicKeyP
    //

    var public_key_data = public_key_packet.writeOld();

    var user = public_key.getPrimaryUser().user;
    var user_id_packet_string = user.userId.write();
    var user_id_data = "\u00B4" + openpgp.util.writeNumber(user_id_packet_string.length, 4) + user_id_packet_string;

    var sign_data = public_key_data + user_id_data + signature_packet.signatureData + signature_packet.calculateTrailer();

    var target_length = (server_public_key_packet.getBitSize() / 8);
    var hashed_sign_data = openpgp.crypto.pkcs1.emsa.encode(signature_packet.hashAlgorithm, sign_data, target_length);
    var hashed_sign_data_string = util.bigInt2Bytes(hashed_sign_data);

    signature_packet.signedHashValue = hashed_sign_data_string.substr(0, 2);

    return {
      "signature_packet": signature_packet,
      "message": hashed_sign_data_string
    };
  }
};<commit_msg>Client Blinding: improves input check for unblind_message<commit_after>"use strict";

var BlindingInformation = require("./types/blinding_information");
var client = require("./client");
var util = require("./util");

var openpgp = require("openpgp");

module.exports = {

  /// TODO : Avoid blinding and encrpytion in one step!
  blind_message: function(message, blinding_information)
  {
    if (!(util.isString(message) || /^[0-9]+$/.test(message))
      || !BlindingInformation.isValidFullBlindingInformation(blinding_information)) {
      return null;
    }

    var message_as_MPI = util.bytes2MPI(message);

    var m = message_as_MPI.data;
    var r = blinding_information.blinding_factor;
    var e = blinding_information.public_exponent;
    var N = blinding_information.modulus;

    return m.multiply(r.modPow(e, N));
  },

  /// TODO
  unblind_message: function(message, blinding_information)
  {
    if (!(util.isString(message) && /^[0-9]+$/.test(message))
          || !BlindingInformation.isValidFullBlindingInformation(blinding_information)) {
      return null;
    }

    var m = util.str2BigInt(message);
    var N = blinding_information.modulus;
    var r = blinding_information.blinding_factor;

    var r_inv = r.modInverse(N);
    return m.multiply(r_inv);
  },

  /// TODO
  prepareBlindSignature: function ()
  {
    var server_public_key = client.getServerPublicKey();
    var server_public_key_packet = server_public_key.primaryKey;

    var signature_packet = new openpgp.packet.Signature();
    signature_packet.signatureType = openpgp.enums.signature.cert_generic;
    signature_packet.hashAlgorithm = server_public_key.getPreferredHashAlgorithm();
    signature_packet.issuerKeyId = server_public_key_packet.getKeyId();
    signature_packet.publicKeyAlgorithm = openpgp.enums.write(openpgp.enums.publicKey, server_public_key_packet.algorithm);

    //
    // Create random creation time between key creation und expire date
    // if no expire date is available use maximum possible day in the future
    //    - 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC.
    //      http://es5.github.io/#x15.9.1.1
    //

    var public_key = client.getPublicKey();
    var public_key_packet = public_key.primaryKey;

    var key_created = public_key_packet.created.getTime();
    var key_expire = public_key.getExpirationTime();
    if (null === key_expire || 0 === key_expire.getTime()) {
      key_expire = 8640000000000000;
    } else {
      key_expire = key_expire.getTime();
    }

    var signature_created = Math.floor(key_created + Math.random() * (key_expire - key_created));
    signature_packet.created = new Date(signature_created);

    //
    // prepare sign data (@see Timo Engel thesis)
    //
    // <signatureData>  = <sigHashdData> <sigTrailer >
    // <sigHashData>    = <version> <signatureType> <pubAlgorithm>
    //                    <hashAlgorithm> <hashedSubpktsLen>
    //                    <hashedSubpkts>
    // <sigTrailer>     = %x04 %xff <sigHashDataLen>
    // <sigHashDataLen> = 4<OCTET>

    var sig_hash_data_string = String.fromCharCode(signature_packet.version);
    sig_hash_data_string += String.fromCharCode(signature_packet.signatureType);
    sig_hash_data_string += String.fromCharCode(signature_packet.publicKeyAlgorithm);
    sig_hash_data_string += String.fromCharCode(signature_packet.hashAlgorithm);
    sig_hash_data_string += signature_packet.write_all_sub_packets();

    signature_packet.signatureData = sig_hash_data_string;

    //
    // prepare sign data (@see Timo Engel thesis)
    //
    // <signData>   = <pubKeyData> <userIdData> <signatureData>
    // <userIdData> = %xb4 <userIdLen> <userIdPacket>
    // <userIdLen>  = 4<OCTET> ; len(<userIdPacket >)
    // <pubKeyData> = %x99 <pubKeyLen> <publicKeyPacket>
    // <pubKeyLen>  = 2<OCTET> ; len(<publicKeyP
    //

    var public_key_data = public_key_packet.writeOld();

    var user = public_key.getPrimaryUser().user;
    var user_id_packet_string = user.userId.write();
    var user_id_data = "\u00B4" + openpgp.util.writeNumber(user_id_packet_string.length, 4) + user_id_packet_string;

    var sign_data = public_key_data + user_id_data + signature_packet.signatureData + signature_packet.calculateTrailer();

    var target_length = (server_public_key_packet.getBitSize() / 8);
    var hashed_sign_data = openpgp.crypto.pkcs1.emsa.encode(signature_packet.hashAlgorithm, sign_data, target_length);
    var hashed_sign_data_string = util.bigInt2Bytes(hashed_sign_data);

    signature_packet.signedHashValue = hashed_sign_data_string.substr(0, 2);

    return {
      "signature_packet": signature_packet,
      "message": hashed_sign_data_string
    };
  }
};<|endoftext|>


<commit_before>/*jshint laxcomma: true, smarttabs: true, node: true*/
'use strict';
/**
 * Default querystring parameter validator for API Endpoints
 * @module tastypie/lib/resource/validator/querystring
 * @author Eric Satterwhite
 * @since 0.0.1
 * @requires joi
 */

var joi = require( 'joi' );

module.exports = {
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {Number} limit Limits the number for results per page of data. Default is `25`
	 **/
	limit:joi.number().min(0).default(25).description("the number of records to return"),
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {Number} offset starting page number for listing endpoints Default is `0`
	 **/
	offset:joi.number().min(0).default(0).description("the starting page number"),
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {String}  format ad hoc serialization formats. Allows `json`, `xml`, `jsonp`
	 **/
	format:joi.string().alphanum().allow('json','xml','jsonp'),
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {String}  callback Used for jsonp callback methods
	**/
	callback:joi.string().alphanum().description('query parameter used to force a jsonp response'),

	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {String}  order used to sort collections of resources
	 **/
	orderby: joi.alternatives().try(
		joi.string().optional().description('name of a field to sort the results by')
		,joi.array(  ).items( joi.string() ).optional().description('name of a field to sort the results by')
	)
};
<commit_msg>Fix querystring validation<commit_after>/*jshint laxcomma: true, smarttabs: true, node: true*/
'use strict';
/**
 * Default querystring parameter validator for API Endpoints
 * @module tastypie/lib/resource/validator/querystring
 * @author Eric Satterwhite
 * @since 0.0.1
 * @requires joi
 */

var joi = require( 'joi' );

module.exports = joi.object().keys({
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {Number} limit Limits the number for results per page of data. Default is `25`
	 **/
	limit:joi.number().min(0).default(25).description("the number of records to return"),
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {Number} offset starting page number for listing endpoints Default is `0`
	 **/
	offset:joi.number().min(0).default(0).description("the starting page number"),
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {String}  format ad hoc serialization formats. Allows `json`, `xml`, `jsonp`
	 **/
	format:joi.string().alphanum().allow('json','xml','jsonp'),
	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {String}  callback Used for jsonp callback methods
	**/
	callback:joi.string().alphanum().description('query parameter used to force a jsonp response'),

	/**
	 * @readonly
	 * @memberof module:tastypie/lib/resource/validator/querystring
	 * @property {String}  order used to sort collections of resources
	 **/
	orderby: joi.alternatives().try(
		joi.string().optional().description('name of a field to sort the results by')
		,joi.array(  ).items( joi.string() ).optional().description('name of a field to sort the results by')
	)
}).unknown();
<|endoftext|>


<commit_before><commit_msg>clean up<commit_after><|endoftext|>


<commit_before>/**
 * The default implementation of authen service
 */

var Q = require("q");

var jwt = require('jsonwebtoken');

module.exports = AuthenticationService;

function AuthenticationService($resolveFx, $config, $logger) {
    //--------------------------------------------------------------------------
    //  Method binding

    var jwtOptions = {
        expiresIn: $config.channelAuthentication.jwt.expiresIn,
        algorithm: $config.channelAuthentication.jwt.algorithm
    };

    var userService = null;

    /**
     * Check authentication info
     * @param {type} userId
     * @param {type} token
     * @returns {Q@call;defer.promise}
     */
    this.check = function (userId, token) {
        var retVal = Q.defer();

        isValidUserId(userId)
                .then(function (ok) {
                    if (!ok) {
                        $logger.debug("User not found. Given Id: " + userId);
                        retVal.resolve(false);
                    } else {
                        jwt.verify(token, $config.channelAuthentication.jwt.secretKey, jwtOptions,
                                function (error, decoded) {
                                    if (error || decoded.data != userId) {
                                        retVal.resolve(false);
                                        //debug
                                        if (error != null) {
                                            $logger.debug("Verify token with jwt fail. UserId: " + userId + "; token: " + token + ". Reason: " + error);
                                        }
                                    } else {
                                        retVal.resolve(true);
                                    }
                                });
                    }
                })
                .catch(function (error) {
                    retVal.reject(error);
                });

        return retVal.promise;
    };

    this.generateToken = function (userId) {
        var retVal = Q.defer();
        isValidUserId(userId)
                .then(function (ok) {
                    if (ok) {
                        var token = jwt.sign({data: userId}, $config.channelAuthentication.jwt.secretKey, jwtOptions);
                        retVal.resolve(token);
                    } else {
                        retVal.reject(new Error("Invalid user: " + userId));
                    }
                })
                .catch(function (error) {
                    retVal.reject(error);
                });

        //return
        return retVal.promise;
    };

    //--------------------------------------------------------------------------
    //  Utils

    var cachedUserIds = {};

    function isValidUserId(userId) {
        var retVal = Q.defer();
        if (cachedUserIds[userId] != null) {
            retVal.resolve(true);
        } else {
            if (userService == null) {
                userService = $resolveFx("userService");
            }
            if (userService == null) {
                throw new Error("AuthenticationService cannot work because of missing userService");
            }
            userService.get(userId)
                    .then(function (user) {
                        if (user == null) {
                            retVal.resolve(false);
                        } else {
                            retVal.resolve(true);
                            cachedUserIds[userId] = true;
                        }
                    })
                    .catch(function (error) {
                        retVal.reject(error);
                        //debug
                        $logger.debug("Error while getting user by id: " + userId + ". Reason: " + error);
                    });
        }
        return retVal.promise;
    }
}

<commit_msg>Update authentication-service, replace Q by BlueBird<commit_after>/**
 * The default implementation of authen service
 */

var Promise = require("bluebird");

var jwt = require('jsonwebtoken');

module.exports = AuthenticationService;

function AuthenticationService($resolveFx, $config, $logger) {
    //--------------------------------------------------------------------------
    //  Method binding

    var jwtOptions = {
        expiresIn: $config.channelAuthentication.jwt.expiresIn,
        algorithm: $config.channelAuthentication.jwt.algorithm
    };

    var userService = null;

    /**
     * Check authentication info
     * @param {type} userId
     * @param {type} token
     * @returns {Q@call;defer.promise}
     */
    this.check = function (userId, token) {

        return new Promise(function (resolve, reject) {
            isValidUserId(userId)
                    .then(function (ok) {
                        if (!ok) {
                            $logger.debug("User not found. Given Id: " + userId);
                            resolve(false);
                        } else {
                            jwt.verify(token, $config.channelAuthentication.jwt.secretKey, jwtOptions,
                                    function (error, decoded) {
                                        if (error || decoded.data != userId) {
                                            resolve(false);
                                            //debug
                                            if (error != null) {
                                                $logger.debug("Verify token with jwt fail. UserId: " + userId + "; token: " + token + ". Reason: " + error);
                                            }
                                        } else {
                                            resolve(true);
                                        }
                                    });
                        }
                    })
                    .catch(function (error) {
                        reject(error);
                    });
        });
    };

    this.generateToken = function (userId) {
        return new Promise(function (resolve, reject) {
            isValidUserId(userId)
                    .then(function (ok) {
                        if (ok) {
                            var token = jwt.sign({data: userId}, $config.channelAuthentication.jwt.secretKey, jwtOptions);
                            resolve(token);
                        } else {
                            reject(new Error("Invalid user: " + userId));
                        }
                    })
                    .catch(function (error) {
                        reject(error);
                    });
        });
    };

    //--------------------------------------------------------------------------
    //  Utils

    var cachedUserIds = {};

    function isValidUserId(userId) {
        return new Promise(function (resolve, reject) {
            if (cachedUserIds[userId] != null) {
                resolve(true);
            } else {
                if (userService == null) {
                    userService = $resolveFx("userService");
                }
                if (userService == null) {
                    throw new Error("AuthenticationService cannot work because of missing userService");
                }
                userService.get(userId)
                        .then(function (user) {
                            if (user == null) {
                                resolve(false);
                            } else {
                                resolve(true);
                                cachedUserIds[userId] = true;
                            }
                        })
                        .catch(function (error) {
                            reject(error);
                            //debug
                            $logger.debug("Error while getting user by id: " + userId + ". Reason: " + error);
                        });
            }
        });
    }
}

<|endoftext|>