diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..69bd6355e5 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,76 @@ +module.exports = { + extends: [ + 'airbnb/legacy' + ], + rules: { + camelcase: 0, + 'comma-dangle': [2, 'never'], + 'comma-spacing': [2, { before: false, after: true }], + 'consistent-return': 0, + curly: 0, + 'default-case': 0, + eqeqeq: [2, 'smart'], + 'func-names': 0, + 'guard-for-in': 2, + indent: [2, 2, { SwitchCase: 1, VariableDeclarator: { var: 2, let: 2, const: 3 } }], + 'key-spacing': [2, { beforeColon: false, afterColon: true }], + 'keyword-spacing': [2, { before: true, after: true }], + 'max-len': 0, + 'new-cap': [2, { newIsCapExceptions: ['acl.memoryBackend', 'acl'] }], + 'no-bitwise': 0, + 'no-caller': 2, + 'no-console': 0, + 'no-else-return': 0, + 'no-empty-class': 0, + 'no-multi-spaces': 2, + 'no-param-reassign': 0, + 'no-shadow': 0, + 'no-spaced-func': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-unneeded-ternary': 2, + 'no-unreachable': 2, + 'no-underscore-dangle': 0, + 'no-unused-expressions': 0, + 'no-unused-vars': 0, + 'no-use-before-define': [1, 'nofunc'], + 'no-var': 0, + 'object-curly-spacing': [2, 'always'], + 'one-var': [0, 'never'], + 'one-var-declaration-per-line': [2, 'always'], + 'padded-blocks': 0, + 'space-before-function-paren': 0, + 'space-in-parens': [2, 'never'], + 'spaced-comment': [2, 'always'], + strict: 0, + 'quote-props': 0, + quotes: [1, 'single'], + 'wrap-iife': [2, 'outside'], + 'vars-on-top': 0 + }, + env: { + node: true, + browser: true, + jasmine: true, + mocha: true, + jquery: true + }, + globals: { + angular: true, + PruneCluster: true, + PruneClusterForLeaflet: true, + PhusionPassenger: true, + L: true, + by: true, + browser: true, + element: true, + inject: true, + io: true, + moment: true, + Promise: true, + __TESTING__: true, + _: false, + AppConfig: true + } +}; diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 9e2a51568f..0000000000 --- a/.jshintrc +++ /dev/null @@ -1,43 +0,0 @@ -{ - "node": true, // Enable globals available when code is running inside of the NodeJS runtime environment. - "mocha": true, // Enable globals available when code is running inside of the Mocha tests. - "jasmine": true, // Enable globals available when code is running inside of the Jasmine tests. - "browser": true, // Standard browser globals e.g. `window`, `document`. - "esnext": true, // Allow ES.next specific features such as `const` and `let`. - "bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.). - "camelcase": false, // Permit only camelcase for `var` and `object indexes`. - "curly": false, // Require {} for every new block or scope. - "eqeqeq": true, // Require triple equals i.e. `===`. - "immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` - "latedef": false, // Prohibit variable use before definition. - "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. - "quotmark": "single", // Define quotes to string values. - "regexp": true, // Prohibit `.` and `[^...]` in regular expressions. - "undef": true, // Require all non-global variables be declared before they are used. - "unused": false, // Warn unused variables. - "strict": true, // Require `use strict` pragma in every file. - "trailing": true, // Prohibit trailing whitespaces. - "smarttabs": false, // Suppresses warnings about mixed tabs and spaces - "globals": { // Globals variables. - "jQuery": true, - "angular": true, - "io": true, - "PruneCluster": true, - "PruneClusterForLeaflet": true, - "L": true, // Leaflet - "moment": true, - "AppConfig": true, - "ga": true, // Google Analytics - "PhusionPassenger": true, - "FastClick": true - }, - "predef": [ // Extra globals. - "inject", - "by", - "browser", - "element" - ], - "indent": 2, // Specify indentation spacing - "devel": true, // Allow development statements e.g. `console.log();` and `alert`. - "noempty": true // Prohibit use of empty blocks. -} diff --git a/.travis.yml b/.travis.yml index 48be5ac9c9..db60f71a18 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,7 @@ language: node_js node_js: - - 4 - 5 - 6 -matrix: - allow_failures: - - node_js: 4 # NodeJS v4 requires gcc 4.8 env: - NODE_ENV=travis CXX="g++-4.8" CC="gcc-4.8" diff --git a/config/assets/default.js b/config/assets/default.js index 1fcb399821..05ca681c1f 100644 --- a/config/assets/default.js +++ b/config/assets/default.js @@ -18,7 +18,7 @@ module.exports = { 'modules/core/client/fonts/fontello/css/tricons-codes.css', 'public/lib/angular-ui-bootstrap/src/position/position.css', 'public/lib/angular-ui-bootstrap/src/typeahead/typeahead.css', - 'public/lib/angular-ui-bootstrap/src/tooltip/tooltip.css', + 'public/lib/angular-ui-bootstrap/src/tooltip/tooltip.css' ], js: [ // Non minified versions @@ -115,12 +115,12 @@ module.exports = { // Reset and dependencies 'public/lib/bootstrap/less/normalize.less', 'public/lib/bootstrap/less/print.less', - //'public/lib/bootstrap/less/glyphicons.less', + // 'public/lib/bootstrap/less/glyphicons.less', // Core CSS 'public/lib/bootstrap/less/scaffolding.less', 'public/lib/bootstrap/less/type.less', - //'public/lib/bootstrap/less/code.less', + // 'public/lib/bootstrap/less/code.less', 'public/lib/bootstrap/less/grid.less', 'public/lib/bootstrap/less/tables.less', 'public/lib/bootstrap/less/forms.less', @@ -133,27 +133,27 @@ module.exports = { 'public/lib/bootstrap/less/input-groups.less', 'public/lib/bootstrap/less/navs.less', 'public/lib/bootstrap/less/navbar.less', - //'public/lib/bootstrap/less/breadcrumbs.less', - //'public/lib/bootstrap/less/pagination.less', - //'public/lib/bootstrap/less/pager.less', + // 'public/lib/bootstrap/less/breadcrumbs.less', + // 'public/lib/bootstrap/less/pagination.less', + // 'public/lib/bootstrap/less/pager.less', 'public/lib/bootstrap/less/labels.less', 'public/lib/bootstrap/less/badges.less', - //'public/lib/bootstrap/less/jumbotron.less', - //'public/lib/bootstrap/less/thumbnails.less', + // 'public/lib/bootstrap/less/jumbotron.less', + // 'public/lib/bootstrap/less/thumbnails.less', 'public/lib/bootstrap/less/alerts.less', 'public/lib/bootstrap/less/progress-bars.less', 'public/lib/bootstrap/less/media.less', 'public/lib/bootstrap/less/list-group.less', 'public/lib/bootstrap/less/panels.less', - //'public/lib/bootstrap/less/responsive-embed.less', - //'public/lib/bootstrap/less/wells.less', + // 'public/lib/bootstrap/less/responsive-embed.less', + // 'public/lib/bootstrap/less/wells.less', 'public/lib/bootstrap/less/close.less', // Components w/ JavaScript 'public/lib/bootstrap/less/modals.less', 'public/lib/bootstrap/less/tooltip.less', 'public/lib/bootstrap/less/popovers.less', - //'public/lib/bootstrap/less/carousel.less', + // 'public/lib/bootstrap/less/carousel.less', // Utility classes 'public/lib/bootstrap/less/utilities.less', diff --git a/config/assets/development.js b/config/assets/development.js index 5f64512693..602a3add26 100644 --- a/config/assets/development.js +++ b/config/assets/development.js @@ -19,5 +19,5 @@ module.exports = { less: defaultAssets.client.less, js: defaultAssets.client.js, views: defaultAssets.client.views - }, + } }; diff --git a/config/assets/production.js b/config/assets/production.js index e6f1fc68c9..c8e3cd2b6c 100644 --- a/config/assets/production.js +++ b/config/assets/production.js @@ -19,8 +19,8 @@ module.exports = { less: defaultAssets.client.less, js: _.union(defaultAssets.client.js, [ 'public/dist/uib-templates.js', - 'public/dist/templates.js', + 'public/dist/templates.js' ]), views: defaultAssets.client.views - }, + } }; diff --git a/config/config.js b/config/config.js index 0b6b117f7c..157ad3c0f8 100644 --- a/config/config.js +++ b/config/config.js @@ -33,7 +33,9 @@ var getGlobbedPaths = function(globPatterns, excludes) { files = files.map(function(file) { if (_.isArray(excludes)) { for (var i in excludes) { - file = file.replace(excludes[i], ''); + if (excludes.hasOwnProperty(i)) { + file = file.replace(excludes[i], ''); + } } } else { file = file.replace(excludes, ''); @@ -80,7 +82,7 @@ var initGlobalConfigFolders = function(config, assets) { }; // Setting globbed client paths - config.folders.client = getGlobbedPaths(path.join(process.cwd(), 'modules/*/client/'), process.cwd().replace(new RegExp(/\\/g),'/')); + config.folders.client = getGlobbedPaths(path.join(process.cwd(), 'modules/*/client/'), process.cwd().replace(new RegExp(/\\/g), '/')); }; /** @@ -108,7 +110,7 @@ var initGlobalConfigFiles = function(config, assets) { config.files.server.policies = getGlobbedPaths(assets.server.policies); // Setting Globbed js files - if(process.env.NODE_ENV === 'production') { + if (process.env.NODE_ENV === 'production') { // In production mode assets.client.lib.js are combined into client.js already config.files.client.js = getGlobbedPaths(assets.client.js, ['client/', 'public/']); config.files.client.lib.js = getGlobbedPaths(assets.client.lib.js, 'public/'); @@ -117,7 +119,7 @@ var initGlobalConfigFiles = function(config, assets) { } // Setting Globbed css files - if(process.env.NODE_ENV === 'production') { + if (process.env.NODE_ENV === 'production') { // In production mode assets.client.lib.css are combined into client.css already config.files.client.css = getGlobbedPaths(assets.client.css, ['client/', 'public/']); } else { diff --git a/config/env/default.js b/config/env/default.js index c3146fa767..f961f3f290 100644 --- a/config/env/default.js +++ b/config/env/default.js @@ -15,7 +15,7 @@ module.exports = { title: 'Trustroots', description: 'Travellers community for sharing, hosting and getting people together. We want a world that encourages trust and adventure.' }, - maxUploadSize: process.env.MAX_UPLOAD_SIZE || 10*1024*1024, // 10MB. Remember to change this to Nginx configs as well + maxUploadSize: process.env.MAX_UPLOAD_SIZE || 10 * 1024 * 1024, // 10MB. Remember to change this to Nginx configs as well imageProcessor: 'graphicsmagick', // graphicsmagick|imagemagick uploadTmpDir: './tmp/', uploadDir: './modules/users/client/img/profile/uploads/', @@ -59,7 +59,7 @@ module.exports = { map: 'outdoors-v9', user: 'mapbox', legacy: false - }, + } }, user: process.env.MAPBOX_USERNAME || false, publicKey: process.env.MAPBOX_ACCESS_TOKEN || false @@ -77,7 +77,7 @@ module.exports = { callbackURL: '/api/auth/twitter/callback' }, google: { - page: process.env.GOOGLE_PAGE || '', + page: process.env.GOOGLE_PAGE || '' }, github: { clientID: process.env.GITHUB_ID || 'APP_ID', diff --git a/config/env/development.js b/config/env/development.js index 9a1d097e88..257b7e1e00 100644 --- a/config/env/development.js +++ b/config/env/development.js @@ -17,8 +17,8 @@ module.exports = { auth: { authMechanism: '' } - //user: '', - //pass: '' + // user: '', + // pass: '' }, // Enable mongoose debug mode debug: process.env.MONGODB_DEBUG || false diff --git a/config/env/production.js b/config/env/production.js index f70e378646..84acb6ab14 100644 --- a/config/env/production.js +++ b/config/env/production.js @@ -17,8 +17,8 @@ module.exports = { auth: { authMechanism: '' } - //user: '', - //pass: '' + // user: '', + // pass: '' }, // Enable mongoose debug mode debug: process.env.MONGODB_DEBUG || false diff --git a/config/env/test.js b/config/env/test.js index a73f9e297f..82c5b07388 100644 --- a/config/env/test.js +++ b/config/env/test.js @@ -17,8 +17,8 @@ module.exports = { auth: { authMechanism: '' } - //user: '', - //pass: '' + // user: '', + // pass: '' }, // Enable mongoose debug mode debug: process.env.MONGODB_DEBUG || false diff --git a/config/lib/express.js b/config/lib/express.js index 5407ab0d9d..b9d47dc11f 100644 --- a/config/lib/express.js +++ b/config/lib/express.js @@ -23,7 +23,6 @@ var _ = require('lodash'), path = require('path'), paginate = require('express-paginate'), seo = require('mean-seo'), - path = require('path'), Agenda = require('agenda'); /** @@ -146,7 +145,7 @@ module.exports.initSession = function (app, db) { secret: config.sessionSecret, cookie: { // If secure is true, and you access your site over HTTP, the cookie will not be set. - secure: false,//config.https, + secure: false, // ...or you could use `config.https`, but it screws things up with Nginx proxy. // By default cookie.maxAge is null, meaning no "expires" parameter is // set so the cookie becomes a browser-session cookie. When the user @@ -205,7 +204,7 @@ module.exports.initHelmetHeaders = function (app) { module.exports.initSEO = function (app) { app.use(seo({ cacheClient: 'disk', // Can be 'disk' or 'redis' - cacheDuration: 2 * 60 * 60 * 24 * 1000, // In milliseconds for disk cache + cacheDuration: 2 * 60 * 60 * 24 * 1000 // In milliseconds for disk cache })); }; @@ -218,7 +217,7 @@ module.exports.initAgenda = function (app, db) { // Don't launch Agenda on test environment // @todo: make it possible to launch this manually with very small interwalls for testing // @todo: similarly for testing purposes, write a stopAgenda() method - if(process.env.NODE_ENV === 'test') { + if (process.env.NODE_ENV === 'test') { return; } @@ -290,19 +289,6 @@ module.exports.initErrorRoutes = function (app) { app.use(errorHandler.errorResponse); }; -/** - * Configure Socket.io - */ -/* -module.exports.configureSocketIO = function (app, db) { - // Load the Socket.io configuration - var server = require('./socket.io')(app, db); - - // Return server object - return server; -}; -*/ - /** * Initialize the Express application */ @@ -346,8 +332,5 @@ module.exports.init = function (db) { // Initialize Agenda ("cron" jobs) this.initAgenda(app, db); - // Configure Socket.io - //app = this.configureSocketIO(app, db); - return app; }; diff --git a/gulpfile.js b/gulpfile.js index 749e8854bb..f9c7d52e1c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -29,7 +29,7 @@ var changedTestFiles = []; var environmentAssets, assets, config; gulp.task('bower', function(done) { - if(argv.skipBower) { + if (argv.skipBower) { plugins.util.log('Bower task skipped.'); return done(); } @@ -53,7 +53,7 @@ gulp.task('env:prod', function() { // Make sure local config file exists gulp.task('copyConfig', function(done) { - if(!fs.existsSync('config/env/local.js') ) { + if (!fs.existsSync('config/env/local.js') ) { gulp .src('config/env/local.sample.js') .pipe(plugins.rename('local.js')) @@ -68,13 +68,13 @@ gulp.task('copyConfig', function(done) { // Load config + assets // Loading config before `env:*` and `copyConfig` tasks would load configs with wrong environment gulp.task('loadConfig', function(done) { - if(!config) { + if (!config) { config = require('./config/config'); } - if(!environmentAssets) { + if (!environmentAssets) { environmentAssets = require('./config/assets/' + process.env.NODE_ENV || 'development') || {}; } - if(!assets) { + if (!assets) { assets = _.extend(defaultAssets, environmentAssets); } done(); @@ -104,17 +104,17 @@ gulp.task('watch', function() { // Add watch rules gulp.watch(defaultAssets.server.views).on('change', plugins.livereload.changed); - gulp.watch(defaultAssets.server.allJS, ['jshint']).on('change', plugins.livereload.changed); + gulp.watch(defaultAssets.server.allJS, ['eslint']).on('change', plugins.livereload.changed); gulp.watch(defaultAssets.server.fontelloConfig, ['fontello']); gulp.watch(defaultAssets.client.less, ['clean:css', 'styles']); if (process.env.NODE_ENV === 'production') { - gulp.watch(defaultAssets.client.js, ['jshint', 'clean:js', 'scripts']); - gulp.watch(defaultAssets.server.gulpConfig, ['jshint']); + gulp.watch(defaultAssets.client.js, ['eslint', 'clean:js', 'scripts']); + gulp.watch(defaultAssets.server.gulpConfig, ['eslint']); gulp.watch(defaultAssets.client.views, ['clean:js', 'scripts']).on('change', plugins.livereload.changed); } else { - gulp.watch(defaultAssets.client.js, ['jshint']).on('change', plugins.livereload.changed); - gulp.watch(defaultAssets.server.gulpConfig, ['jshint']); + gulp.watch(defaultAssets.client.js, ['eslint']).on('change', plugins.livereload.changed); + gulp.watch(defaultAssets.server.gulpConfig, ['eslint']); gulp.watch(defaultAssets.client.views).on('change', plugins.livereload.changed); } }); @@ -144,8 +144,8 @@ gulp.task('watch:server:run-tests', function () { }); }); -// JS linting task -gulp.task('jshint', function() { +// ESLint JS linting task +gulp.task('eslint', function() { var assets = _.union( defaultAssets.server.gulpConfig, defaultAssets.server.allJS, @@ -156,9 +156,11 @@ gulp.task('jshint', function() { ); return gulp.src(assets) - .pipe(plugins.jshint()) - .pipe(plugins.jshint.reporter('default')) - .pipe(plugins.jshint.reporter('fail')); + .pipe(plugins.eslint()) + .pipe(plugins.eslint.format()) + // To have the process exit with an error code (1) on + // lint error, return the stream and pipe to failAfterError last. + .pipe(plugins.eslint.failAfterError()); }); // JavaScript task @@ -233,7 +235,7 @@ gulp.task('uibTemplatecache', function() { .pipe(plugins.templateCache('uib-templates-' + uibModule + '.js', { root: 'uib/template/' + uibModule + '/', module: 'core', - templateHeader: '(function(){ \'use strict\'; angular.module(\'<%= module %>\'<%= standalone %>).run(templates); templates.$inject = [\'$templateCache\']; function templates($templateCache) {', + templateHeader: '(function() { \'use strict\'; angular.module(\'<%= module %>\'<%= standalone %>).run(templates); templates.$inject = [\'$templateCache\']; function templates($templateCache) {', templateBody: '$templateCache.put(\'<%= url %>\', \'<%= contents %>\');', templateFooter: '} })();' })); @@ -259,7 +261,7 @@ gulp.task('templatecache', function() { return url.replace('/client', ''); }, module: 'core', - templateHeader: '(function(){ \'use strict\'; angular.module(\'<%= module %>\'<%= standalone %>).run(templates); templates.$inject = [\'$templateCache\']; function templates($templateCache) {', + templateHeader: '(function() { \'use strict\'; angular.module(\'<%= module %>\'<%= standalone %>).run(templates); templates.$inject = [\'$templateCache\']; function templates($templateCache) {', templateBody: '$templateCache.put(\'<%= url %>\', \'<%= contents %>\');', templateFooter: '} })();' })) @@ -343,12 +345,12 @@ gulp.task('karma:watch', function(done) { // Build assets for development mode gulp.task('build:dev', function(done) { - runSequence('env:dev', 'bower', 'jshint', 'clean', ['uibTemplatecache', 'styles'], done); + runSequence('env:dev', 'bower', 'eslint', 'clean', ['uibTemplatecache', 'styles'], done); }); // Build assets for production mode gulp.task('build:prod', function(done) { - runSequence('env:prod', 'bower', 'jshint', 'clean', ['styles', 'scripts'], done); + runSequence('env:prod', 'bower', 'eslint', 'clean', ['styles', 'scripts'], done); }); // Clean dist css and js files @@ -358,11 +360,11 @@ gulp.task('clean', function(done) { // Run the project tests gulp.task('test', function(done) { - runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'jshint', ['karma', 'mocha'], done); + runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'eslint', ['karma', 'mocha'], done); }); gulp.task('test:server', function(done) { - runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'jshint', 'mocha', done); + runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'eslint', 'mocha', done); }); // Watch all server files for changes & run server tests (test:server) task on changes @@ -371,11 +373,11 @@ gulp.task('test:server:watch', function(done) { }); gulp.task('test:client', function(done) { - runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'jshint', 'karma', done); + runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'eslint', 'karma', done); }); gulp.task('test:client:watch', function(done) { - runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'jshint', 'karma:watch', done); + runSequence('env:test', 'copyConfig', 'makeUploadsDir', 'eslint', 'karma:watch', done); }); // Run the project in development mode diff --git a/modules/contacts/client/config/contacts.client.routes.js b/modules/contacts/client/config/contacts.client.routes.js index 23fb54478c..778c657553 100644 --- a/modules/contacts/client/config/contacts.client.routes.js +++ b/modules/contacts/client/config/contacts.client.routes.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -54,4 +54,4 @@ } -})(); +}()); diff --git a/modules/contacts/client/controllers/add-contact.client.controller.js b/modules/contacts/client/controllers/add-contact.client.controller.js index 3b4bdf9d2b..eb9a47d5ae 100644 --- a/modules/contacts/client/controllers/add-contact.client.controller.js +++ b/modules/contacts/client/controllers/add-contact.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -32,7 +32,7 @@ function init() { // Prevent connecting with yourself - if($stateParams.userId === Authentication.user._id) { + if ($stateParams.userId === Authentication.user._id) { vm.isConnected = true; vm.error = 'You cannot connect with yourself. That is just silly!'; } @@ -50,7 +50,7 @@ // If contact already exists, stop here existingContact.$promise.then(function(response) { - if(response) { + if (response) { vm.isConnected = true; vm.success = (response.confirmed) ? 'You two are already connected. Great!' : 'Connection already initiated; now it has to be confirmed.'; } @@ -80,4 +80,4 @@ } -})(); +}()); diff --git a/modules/contacts/client/controllers/confirm-contact.client.controller.js b/modules/contacts/client/controllers/confirm-contact.client.controller.js index 2641276928..76017480aa 100644 --- a/modules/contacts/client/controllers/confirm-contact.client.controller.js +++ b/modules/contacts/client/controllers/confirm-contact.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -26,12 +26,10 @@ // Got contact function(contact) { vm.isLoading = false; - if(vm.contact.confirmed === true) { + if (vm.contact.confirmed === true) { vm.isConnected = true; vm.success = 'You two are already connected. Great!'; - } - // [0] contains contact requester's id, [1] is the receiver - else if (vm.contact.users[0]._id !== Authentication.user._id) { + } else if (vm.contact.users[0]._id !== Authentication.user._id) { // [0] contains contact requester's id, [1] is the receiver vm.error = 'You must wait until he/she confirms your connection.'; } }, @@ -57,4 +55,4 @@ } -})(); +}()); diff --git a/modules/contacts/client/controllers/list-contacts.client.controller.js b/modules/contacts/client/controllers/list-contacts.client.controller.js index d86b60051b..53dce0d885 100644 --- a/modules/contacts/client/controllers/list-contacts.client.controller.js +++ b/modules/contacts/client/controllers/list-contacts.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -41,11 +41,9 @@ if (value === 'displayName') { return other.displayName; - } - else if (value === 'username') { + } else if (value === 'username') { return other.username; - } - else { + } else { // User object return other; } @@ -53,4 +51,4 @@ } -})(); +}()); diff --git a/modules/contacts/client/controllers/remove-contact.client.controller.js b/modules/contacts/client/controllers/remove-contact.client.controller.js index aa75a6bd72..d8737dca59 100644 --- a/modules/contacts/client/controllers/remove-contact.client.controller.js +++ b/modules/contacts/client/controllers/remove-contact.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -10,7 +10,10 @@ var contactToRemove = $scope.contactToRemove; + // ViewModel var vm = this; + + // Exposed to the view vm.isLoading = false; vm.contact = contactToRemove; vm.removeContact = removeContact; @@ -18,20 +21,18 @@ // Different confirm button label and modal title depending on situation - // User is cancelling a request - if(angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false && Authentication.user._id === contactToRemove.users[1]._id) { + if (angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false && Authentication.user._id === contactToRemove.users[1]._id) { + // User is cancelling a request vm.labelConfirm = 'Yes, revoke request'; vm.labelTitle = 'Revoke contact request?'; vm.labelTime = 'Requested'; - } - // Decline received request - else if(angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false) { + } else if (angular.isDefined(contactToRemove.confirmed) && contactToRemove.confirmed === false) { + // Decline received request vm.labelConfirm = 'Yes, decline request'; vm.labelTitle = 'Decline contact request?'; vm.labelTime = 'Requested'; - } - // Removing confirmed contact - else { + } else { + // Removing confirmed contact vm.labelConfirm = 'Yes, remove contact'; vm.labelTitle = 'Remove contact?'; vm.labelTime = 'Connected since'; @@ -41,7 +42,7 @@ vm.isLoading = true; // contact comes from the parent link() - Contact.delete({contactId: contactToRemove._id}, + Contact.delete({ contactId: contactToRemove._id }, // Success function() { @@ -66,4 +67,4 @@ } -})(); +}()); diff --git a/modules/contacts/client/directives/tr-contact-remove.client.directive.js b/modules/contacts/client/directives/tr-contact-remove.client.directive.js index a01f3fb04c..cf1241ad50 100644 --- a/modules/contacts/client/directives/tr-contact-remove.client.directive.js +++ b/modules/contacts/client/directives/tr-contact-remove.client.directive.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; /** @@ -32,4 +32,5 @@ } }; } -})(); + +}()); diff --git a/modules/contacts/client/services/contact-by.client.service.js b/modules/contacts/client/services/contact-by.client.service.js index 7590ff9439..db8bc4c111 100644 --- a/modules/contacts/client/services/contact-by.client.service.js +++ b/modules/contacts/client/services/contact-by.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; // ContactBy factory used for communicating with the contacts REST endpoints @@ -18,4 +18,4 @@ }); } -})(); +}()); diff --git a/modules/contacts/client/services/contact.client.service.js b/modules/contacts/client/services/contact.client.service.js index e6e10c8634..4bcc198ff2 100644 --- a/modules/contacts/client/services/contact.client.service.js +++ b/modules/contacts/client/services/contact.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; // Contact factory used for communicating with the contacts REST endpoints @@ -24,4 +24,4 @@ }); } -})(); +}()); diff --git a/modules/contacts/client/services/contacts-list.client.service.js b/modules/contacts/client/services/contacts-list.client.service.js index 9e5f74d6a4..021b45b995 100644 --- a/modules/contacts/client/services/contacts-list.client.service.js +++ b/modules/contacts/client/services/contacts-list.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; // ContactsList factory used for communicating with the contacts REST endpoints @@ -14,4 +14,4 @@ }); } -})(); +}()); diff --git a/modules/contacts/server/controllers/contacts.server.controller.js b/modules/contacts/server/controllers/contacts.server.controller.js index 87428e5f1c..9e5da8fe1f 100644 --- a/modules/contacts/server/controllers/contacts.server.controller.js +++ b/modules/contacts/server/controllers/contacts.server.controller.js @@ -42,7 +42,7 @@ exports.add = function(req, res) { function(done) { // Not a valid ObjectId - if(!mongoose.Types.ObjectId.isValid(req.body.friendUserId)) { + if (!mongoose.Types.ObjectId.isValid(req.body.friendUserId)) { return res.status(400).json({ message: errorHandler.getErrorMessageByKey('invalid-id') }); @@ -51,8 +51,8 @@ exports.add = function(req, res) { // Check if contact already exists Contact.findOne({ $or: [ - { users: [ req.body.friendUserId, req.user._id ] }, - { users: [ req.user._id, req.body.friendUserId ] } + { users: [req.body.friendUserId, req.user._id] }, + { users: [req.user._id, req.body.friendUserId] } ] }).exec(function(err, existingContact) { if (err) return done(err); @@ -75,9 +75,9 @@ exports.add = function(req, res) { // Catch message separately var messageHTML = false; var messagePlain = false; - if(req.body.message && req.body.message !== '') { + if (req.body.message && req.body.message !== '') { messageHTML = sanitizeHtml(req.body.message, textProcessor.sanitizeOptions); - messagePlain = htmlToText.fromString(req.body.message, {wordwrap: 80}); + messagePlain = htmlToText.fromString(req.body.message, { wordwrap: 80 }); } delete req.body.message; @@ -123,28 +123,28 @@ exports.add = function(req, res) { urlConfirm = url + '/contact-confirm/' + contact._id; var renderVars = emailsHandler.addEmailBaseTemplateParams( - req.headers.host, - { - name: friend.displayName, - message: messageHTML, - meName: req.user.displayName, - meURLPlainText: meURL, - meURL: analyticsHandler.appendUTMParams(meURL, { - source: 'transactional-email', - medium: 'email', - campaign: 'confirm-contact', - content: 'profile' - }), - urlConfirmPlainText: urlConfirm, - urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { - source: 'transactional-email', - medium: 'email', - campaign: 'confirm-contact', - content: 'confirm-contact' - }) - }, - 'confirm-contact' - ); + req.headers.host, + { + name: friend.displayName, + message: messageHTML, + meName: req.user.displayName, + meURLPlainText: meURL, + meURL: analyticsHandler.appendUTMParams(meURL, { + source: 'transactional-email', + medium: 'email', + campaign: 'confirm-contact', + content: 'profile' + }), + urlConfirmPlainText: urlConfirm, + urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { + source: 'transactional-email', + medium: 'email', + campaign: 'confirm-contact', + content: 'confirm-contact' + }) + }, + 'confirm-contact' + ); res.render(path.resolve('./modules/core/server/views/email-templates/confirm-contact'), renderVars, function(err, emailHTML) { done(err, emailHTML, messagePlain, friend, renderVars); @@ -189,7 +189,7 @@ exports.add = function(req, res) { ], function(err) { if (err) { if (contact) { - contact.remove(function(){ + contact.remove(function() { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); @@ -209,17 +209,17 @@ exports.add = function(req, res) { * Disconnect contact */ exports.remove = function(req, res) { - var contact = req.contact; - - contact.remove(function(err) { - if (err) { - return res.status(400).send({ - message: errorHandler.getErrorMessage(err) - }); - } else { - res.json(contact); - } - }); + var contact = req.contact; + + contact.remove(function(err) { + if (err) { + return res.status(400).send({ + message: errorHandler.getErrorMessage(err) + }); + } else { + res.json(contact); + } + }); }; @@ -229,7 +229,7 @@ exports.remove = function(req, res) { exports.confirm = function(req, res) { // Only receiving user can confirm user connections - if(!req.contact || !req.contact.users[0]._id.equals(req.user._id.valueOf())) { + if (!req.contact || !req.contact.users[0]._id.equals(req.user._id.valueOf())) { return res.status(403).json({ message: errorHandler.getErrorMessageByKey('forbidden') }); @@ -237,17 +237,17 @@ exports.confirm = function(req, res) { // Ta'da! var contact = req.contact; - contact.confirmed = true; - - contact.save(function(err) { - if(err) { - return res.status(400).send({ - message: errorHandler.getErrorMessage(err) - }); - } else { - res.json(contact); - } - }); + contact.confirmed = true; + + contact.save(function(err) { + if (err) { + return res.status(400).send({ + message: errorHandler.getErrorMessage(err) + }); + } else { + res.json(contact); + } + }); }; /** @@ -261,7 +261,7 @@ exports.list = function(req, res) { * Single contact */ exports.get = function(req, res) { - res.json(req.contact || {}); + res.json(req.contact || {}); }; /** @@ -272,31 +272,31 @@ exports.get = function(req, res) { exports.contactByUserId = function(req, res, next, userId) { // Not a valid ObjectId - if(!mongoose.Types.ObjectId.isValid(userId)) { + if (!mongoose.Types.ObjectId.isValid(userId)) { return res.status(400).json({ message: errorHandler.getErrorMessageByKey('invalid-id') }); } // User's own profile, don't bother hitting the DB - if(req.user && req.user._id === userId) { + if (req.user && req.user._id === userId) { return res.status(400).json({ message: errorHandler.getErrorMessageByKey('invalid-id') }); } - if(req.user && req.user.public) { + if (req.user && req.user.public) { Contact.findOne({ $or: [ - { users: [ userId, req.user._id ] }, - { users: [ req.user._id, userId ] } + { users: [userId, req.user._id] }, + { users: [req.user._id, userId] } ] }) .populate('users', userHandler.userMiniProfileFields) .exec(function(err, contact) { - if(err) return next(err); - if(!contact) { + if (err) return next(err); + if (!contact) { return res.status(404).json({ message: errorHandler.getErrorMessageByKey('not-found') }); @@ -305,8 +305,7 @@ exports.contactByUserId = function(req, res, next, userId) { req.contact = contact; next(); }); - } - else { + } else { next(); } }; @@ -318,7 +317,7 @@ exports.contactByUserId = function(req, res, next, userId) { exports.contactById = function(req, res, next, contactId) { // Not a valid ObjectId - if(!mongoose.Types.ObjectId.isValid(contactId)) { + if (!mongoose.Types.ObjectId.isValid(contactId)) { return res.status(400).json({ message: errorHandler.getErrorMessageByKey('invalid-id') }); @@ -331,7 +330,7 @@ exports.contactById = function(req, res, next, contactId) { if (err) return next(err); // If nothing was found or neither of the user ID's match currently authenticated user's id, return 404 - if(!contact || !req.user || ( + if (!contact || !req.user || ( !contact.users[0]._id.equals(req.user._id.valueOf()) && !contact.users[1]._id.equals(req.user._id.valueOf()) )) { @@ -354,7 +353,7 @@ exports.contactById = function(req, res, next, contactId) { exports.contactListByUser = function(req, res, next, listUserId) { // Not a valid ObjectId - if(!mongoose.Types.ObjectId.isValid(listUserId)) { + if (!mongoose.Types.ObjectId.isValid(listUserId)) { return res.status(400).json({ message: errorHandler.getErrorMessageByKey('invalid-id') }); @@ -363,7 +362,7 @@ exports.contactListByUser = function(req, res, next, listUserId) { var contactQuery = { users: listUserId, confirmed: true }; // Remove 'confirmed=true' from queries if showing currently logged in user's listing - if(req.user && req.user._id.equals(listUserId)) { + if (req.user && req.user._id.equals(listUserId)) { delete contactQuery.confirmed; } @@ -373,12 +372,12 @@ exports.contactListByUser = function(req, res, next, listUserId) { .populate({ path: 'users', // ...except don't populate user's own info for confirmed contacts. We don't need it dozen times there: - //match: { _id: { $ne: listUserId } }, + // match: { _id: { $ne: listUserId } }, select: userHandler.userMiniProfileFields }) .exec(function(err, contacts) { - if(err) return next(err); - if(!contacts) return next(new Error('Failed to load contacts.')); + if (err) return next(err); + if (!contacts) return next(new Error('Failed to load contacts.')); req.contacts = contacts; next(); diff --git a/modules/contacts/server/policies/contacts.server.policy.js b/modules/contacts/server/policies/contacts.server.policy.js index 2113b41f7e..486bf25f9d 100644 --- a/modules/contacts/server/policies/contacts.server.policy.js +++ b/modules/contacts/server/policies/contacts.server.policy.js @@ -54,7 +54,7 @@ exports.invokeRolesPolicies = function() { exports.isAllowed = function(req, res, next) { // No contacts for un-published users - if(req.user && req.user.public !== true) { + if (req.user && req.user.public !== true) { return res.status(403).json({ message: errorHandler.getErrorMessageByKey('forbidden') }); @@ -62,7 +62,7 @@ exports.isAllowed = function(req, res, next) { // If an contact is being processed and the current user owns it, then allow any manipulation // 'Delete' gets allowed here - if(req.contact && req.user && + if (req.contact && req.user && ( req.contact.users[0]._id.equals(req.user._id.valueOf()) || req.contact.users[1]._id.equals(req.user._id.valueOf()) diff --git a/modules/contacts/server/routes/contacts.server.routes.js b/modules/contacts/server/routes/contacts.server.routes.js index 240d9a4be3..fe1c8b68cc 100644 --- a/modules/contacts/server/routes/contacts.server.routes.js +++ b/modules/contacts/server/routes/contacts.server.routes.js @@ -12,12 +12,12 @@ module.exports = function(app) { .post(contacts.add); app.route('/api/contact-by/:contactUserId').all(contactsPolicy.isAllowed) - .get(contacts.get); //contacts.hasAuthorization, + .get(contacts.get); app.route('/api/contact/:contactId').all(contactsPolicy.isAllowed) - .get(contacts.get) //contacts.hasAuthorization, - .put(contacts.confirm) //contacts.receiverHasAuthorization, - .delete(contacts.remove); //contacts.hasAuthorization, + .get(contacts.get) + .put(contacts.confirm) + .delete(contacts.remove); // Contact list app.route('/api/contacts/:listUserId').all(contactsPolicy.isAllowed) diff --git a/modules/contacts/tests/client/add-contact.client.controller.tests.js b/modules/contacts/tests/client/add-contact.client.controller.tests.js index b0cda8f7c3..a4ddc3f593 100644 --- a/modules/contacts/tests/client/add-contact.client.controller.tests.js +++ b/modules/contacts/tests/client/add-contact.client.controller.tests.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; describe('ContactAddController', function() { @@ -28,7 +28,7 @@ // Load the main application module beforeEach(module(AppConfig.appModuleName)); - beforeEach(inject(function($templateCache, _$httpBackend_, _Authentication_, _UsersMini_, _ContactByService_){ + beforeEach(inject(function($templateCache, _$httpBackend_, _Authentication_, _UsersMini_, _ContactByService_) { $httpBackend = _$httpBackend_; Authentication = _Authentication_; UsersMini = _UsersMini_; @@ -37,15 +37,15 @@ $templateCache.put('/modules/core/views/404.client.view.html', ''); })); - afterEach(function(){ + afterEach(function() { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); - describe('logged in', function(){ + describe('logged in', function() { - beforeEach(function(done){ - inject(function($controller){ + beforeEach(function(done) { + inject(function($controller) { Authentication.user = user1; @@ -60,66 +60,66 @@ }); }); - describe('when user does not exist', function(){ + describe('when user does not exist', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('GET', '/api/users/mini/user2').respond(404); $httpBackend.expect('GET', '/api/contact-by/user2').respond(404); }); - it('displays an error message', function(){ + it('displays an error message', function() { $httpBackend.flush(); expect(ContactAddController.error).toBe('User does not exist.'); }); }); - describe('when user exists', function(){ + describe('when user exists', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('GET', '/api/users/mini/user2').respond(200, user2); }); - describe('when unconfirmed contact exists', function(){ + describe('when unconfirmed contact exists', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('GET', '/api/contact-by/user2').respond(200, { confirmed: false }); }); - it('displays a success message', function(){ + it('displays a success message', function() { $httpBackend.flush(); expect(ContactAddController.success).toBe('Connection already initiated; now it has to be confirmed.'); }); }); - describe('when confirmed contact exists', function(){ + describe('when confirmed contact exists', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('GET', '/api/contact-by/user2').respond(200, { confirmed: true }); }); - it('Shows a nice message when the contact is confirmed', function(){ + it('Shows a nice message when the contact is confirmed', function() { $httpBackend.flush(); expect(ContactAddController.success).toBe('You two are already connected. Great!'); }); }); - describe('when no contact exists', function(){ + describe('when no contact exists', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('GET', '/api/contact-by/user2').respond(404); }); - it('will make contact request', function(){ + it('will make contact request', function() { $httpBackend.expect('POST', '/api/contact', contactRequest).respond(200); ContactAddController.add(); $httpBackend.flush(); expect(ContactAddController.success).toBe('Done! We sent an email to your contact and he/she still needs to confirm it.'); }); - it('will make contact request with custom message', function(){ + it('will make contact request with custom message', function() { var customMessage = 'my custom message'; ContactAddController.contact.message = customMessage; $httpBackend.expect('POST', '/api/contact', { friendUserId: user2._id, message: customMessage }).respond(200); @@ -129,13 +129,13 @@ }); - describe('when unconfirmed contact conflict', function(){ + describe('when unconfirmed contact conflict', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('POST', '/api/contact', contactRequest).respond(409, { confirmed: false }); }); - it('displays a confirmation waiting success message', function(){ + it('displays a confirmation waiting success message', function() { ContactAddController.add(); $httpBackend.flush(); expect(ContactAddController.success).toBe('Connection already initiated; now it has to be confirmed.'); @@ -143,13 +143,13 @@ }); - describe('with confirmed contact conflict', function(){ + describe('with confirmed contact conflict', function() { - beforeEach(function(){ + beforeEach(function() { $httpBackend.expect('POST', '/api/contact', contactRequest).respond(409, { confirmed: true }); }); - it('displays an already connected success message', function(){ + it('displays an already connected success message', function() { ContactAddController.add(); $httpBackend.flush(); expect(ContactAddController.success).toBe('You two are already connected. Great!'); @@ -164,4 +164,5 @@ }); }); + }()); diff --git a/modules/contacts/tests/client/contacts.client.routes.tests.js b/modules/contacts/tests/client/contacts.client.routes.tests.js index 851fd7b864..d340c181ca 100644 --- a/modules/contacts/tests/client/contacts.client.routes.tests.js +++ b/modules/contacts/tests/client/contacts.client.routes.tests.js @@ -52,7 +52,7 @@ $httpBackend.when('GET', '/api/users/mini/123').respond(200, ''); $httpBackend.expectGET('/api/users/mini/123'); - $state.go('contactAdd', { userId: '123'}); + $state.go('contactAdd', { userId: '123' }); $rootScope.$digest(); })); @@ -96,7 +96,7 @@ $httpBackend.when('GET', '/api/contact/123').respond(200, ''); $httpBackend.expectGET('/api/contact/123'); - $state.go('contactConfirm', { contactId: '123'}); + $state.go('contactConfirm', { contactId: '123' }); $rootScope.$digest(); })); @@ -112,4 +112,5 @@ }); -})(); + +}()); diff --git a/modules/contacts/tests/client/remove-contact.client.controller.tests.js b/modules/contacts/tests/client/remove-contact.client.controller.tests.js index 5d54556b55..82341f9d5b 100644 --- a/modules/contacts/tests/client/remove-contact.client.controller.tests.js +++ b/modules/contacts/tests/client/remove-contact.client.controller.tests.js @@ -24,7 +24,7 @@ // Load the main application module beforeEach(module(AppConfig.appModuleName)); - beforeEach(inject(function($templateCache, _$httpBackend_, _Authentication_, _$rootScope_, _messageCenterService_){ + beforeEach(inject(function($templateCache, _$httpBackend_, _Authentication_, _$rootScope_, _messageCenterService_) { $httpBackend = _$httpBackend_; Authentication = _Authentication_; @@ -42,15 +42,15 @@ $templateCache.put('/modules/pages/views/home.client.view.html', ''); })); - afterEach(function(){ + afterEach(function() { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); - describe('logged in', function(){ + describe('logged in', function() { - beforeEach(function(done){ - inject(function($controller){ + beforeEach(function(done) { + inject(function($controller) { Authentication.user = user1; ContactRemoveController = $controller('ContactRemoveController', { $scope: $scope, diff --git a/modules/contacts/tests/server/contact.server.model.tests.js b/modules/contacts/tests/server/contact.server.model.tests.js index 4488e07716..0c68ddeaf4 100644 --- a/modules/contacts/tests/server/contact.server.model.tests.js +++ b/modules/contacts/tests/server/contact.server.model.tests.js @@ -11,7 +11,11 @@ var should = require('should'), /** * Globals */ -var user1, user2, user1Id, user2Id, contact; +var user1, + user2, + user1Id, + user2Id, + contact; /** * Unit tests diff --git a/modules/contacts/tests/server/contact.server.routes.tests.js b/modules/contacts/tests/server/contact.server.routes.tests.js index b6d6eef768..ad27618e85 100644 --- a/modules/contacts/tests/server/contact.server.routes.tests.js +++ b/modules/contacts/tests/server/contact.server.routes.tests.js @@ -14,11 +14,23 @@ var should = require('should'), /** * Globals */ -var app, agent, credentials, - user1, user2, user3, user4, - user1Id, user2Id, user3Id, user4Id, - contact1, contact2, contact3, - contact1Id, contact2Id, contact3Id; +var app, + agent, + credentials, + user1, + user2, + user3, + user4, + user1Id, + user2Id, + user3Id, + user4Id, + contact1, + contact2, + contact3, + contact1Id, + contact2Id, + contact3Id; /** * Contact routes tests @@ -178,9 +190,9 @@ describe('Contact CRUD tests', function() { }); }); - context('logged in', function(){ + context('logged in', function() { - beforeEach(function(done){ + beforeEach(function(done) { agent.post('/api/auth/signin') .send(credentials) // = user 1 @@ -191,11 +203,11 @@ describe('Contact CRUD tests', function() { }); - it('should be able to get a contact by user id', function(done){ + it('should be able to get a contact by user id', function(done) { // Get the contact for User1 -> User2 : Contact1 agent.get('/api/contact-by/' + user2Id) .expect(200) - .end(function(contactByErr, contactByRes){ + .end(function(contactByErr, contactByRes) { // Handle contact by error if (contactByErr) return done(contactByErr); @@ -270,12 +282,12 @@ describe('Contact CRUD tests', function() { }); }); - it('should be able to create a new unconfirmed contact', function(done){ + it('should be able to create a new unconfirmed contact', function(done) { // Create a contact User1 -> User4 agent.post('/api/contact') .send({ friendUserId: user4Id }) .expect(200) - .end(function(contactAddErr, contactAddRes){ + .end(function(contactAddErr, contactAddRes) { // Handle contact add error if (contactAddErr) return done(contactAddErr); @@ -284,7 +296,7 @@ describe('Contact CRUD tests', function() { // Get the contact for User4 that we just created agent.get('/api/contact-by/' + user4Id) .expect(200) - .end(function(contactByErr, contactByRes){ + .end(function(contactByErr, contactByRes) { // Handle contact by error if (contactByErr) return done(contactByErr); @@ -304,23 +316,23 @@ describe('Contact CRUD tests', function() { }); }); - it('should not be able to create a duplicate contact', function(done){ + it('should not be able to create a duplicate contact', function(done) { // Try and create a contact User1 -> User2 agent.post('/api/contact') .send({ friendUserId: user2Id }) .expect(409) - .end(function(contactAddErr, contactAddRes){ + .end(function(contactAddErr, contactAddRes) { // Handle contact add error if (contactAddErr) return done(contactAddErr); return done(); }); }); - it('should be able to confirm a contact', function(done){ + it('should be able to confirm a contact', function(done) { // Confirm the un-confirmed Contact1 between User1 -> User2 agent.put('/api/contact/' + contact1Id) .expect(200) - .end(function(contactConfirmErr, contactConfirmRes){ + .end(function(contactConfirmErr, contactConfirmRes) { // Handle contact confirm error if (contactConfirmErr) return done(contactConfirmErr); @@ -348,7 +360,7 @@ describe('Contact CRUD tests', function() { // The contact should be gone now agent.get('/api/contact-by/' + user2Id) .expect(404) - .end(function(contactByErr, contactByRes){ + .end(function(contactByErr, contactByRes) { // Handle contact by error if (contactByErr) return done(contactByErr); @@ -361,11 +373,11 @@ describe('Contact CRUD tests', function() { }); }); - context('with email sending error', function(){ + context('with email sending error', function() { var originalMailerOptions; - beforeEach(function(){ + beforeEach(function() { // Set the mail sending to fail originalMailerOptions = config.mailer.options; config.mailer.options = stubTransport({ @@ -373,16 +385,16 @@ describe('Contact CRUD tests', function() { }); }); - afterEach(function(){ + afterEach(function() { config.mailer.options = originalMailerOptions; }); - it('should fail to create contact', function(done){ + it('should fail to create contact', function(done) { // Try and create a contact User1 -> User4 agent.post('/api/contact') .send({ friendUserId: user4Id }) .expect(400) - .end(function(contactAddErr, contactAddRes){ + .end(function(contactAddErr, contactAddRes) { // Handle contact add error if (contactAddErr) return done(contactAddErr); diff --git a/modules/core/client/app/config.js b/modules/core/client/app/config.js index 9e2f983e84..133a4043ec 100644 --- a/modules/core/client/app/config.js +++ b/modules/core/client/app/config.js @@ -1,49 +1,50 @@ 'use strict'; // Init the application configuration module for AngularJS application -var AppConfig = (function() { +var AppConfig = (function () { // Init module configuration options var appEnv = window.env || 'production'; var appModuleName = 'trustroots'; var appModuleVendorDependencies = [ - 'ngResource', - 'ngAnimate', - 'ngTouch', - 'ngSanitize', - 'ngMessageFormat', - 'angulartics', - 'ui.router', - 'ui.bootstrap.dateparser', - 'ui.bootstrap.buttons', - 'ui.bootstrap.collapse', - 'ui.bootstrap.dropdown', - 'ui.bootstrap.modal', - 'ui.bootstrap.popover', - 'ui.bootstrap.progressbar', - 'ui.bootstrap.tabs', - 'ui.bootstrap.tooltip', - 'ui.bootstrap.typeahead', - 'angularMoment', - 'nemLogging', - 'ui-leaflet', - 'ngFileUpload', - 'zumba.angular-waypoints', - 'MessageCenterModule', - 'localytics.directives', - 'angular-loading-bar', - 'trTrustpass', - 'angular-mailcheck', - 'angular-locker', - 'angular-confirm', - 'angularGrid' - ]; + 'ngResource', + 'ngAnimate', + 'ngTouch', + 'ngSanitize', + 'ngMessageFormat', + 'angulartics', + 'ui.router', + 'ui.bootstrap.dateparser', + 'ui.bootstrap.buttons', + 'ui.bootstrap.collapse', + 'ui.bootstrap.dropdown', + 'ui.bootstrap.modal', + 'ui.bootstrap.popover', + 'ui.bootstrap.progressbar', + 'ui.bootstrap.tabs', + 'ui.bootstrap.tooltip', + 'ui.bootstrap.typeahead', + 'angularMoment', + 'nemLogging', + 'ui-leaflet', + 'ngFileUpload', + 'zumba.angular-waypoints', + 'MessageCenterModule', + 'localytics.directives', + 'angular-loading-bar', + 'trTrustpass', + 'angular-mailcheck', + 'angular-locker', + 'angular-confirm', + 'angularGrid' + ]; - // Load different service dependency for Angulartics depending on environment - // @link https://github.com/angulartics/angulartics - if(appEnv === 'production') { + /** + * Load different service dependency for Angulartics depending on environment + * @link https://github.com/angulartics/angulartics + */ + if (appEnv === 'production') { appModuleVendorDependencies.push('angulartics.google.analytics'); - } - else { + } else { appModuleVendorDependencies.push('angulartics.debug'); } @@ -62,4 +63,4 @@ var AppConfig = (function() { appModuleVendorDependencies: appModuleVendorDependencies, registerModule: registerModule }; -})(); +}()); diff --git a/modules/core/client/app/init.js b/modules/core/client/app/init.js index b4b819e28e..525fae3d5f 100644 --- a/modules/core/client/app/init.js +++ b/modules/core/client/app/init.js @@ -1,5 +1,5 @@ -(function() { - 'use strict'; +(function () { + 'use strict'; // Start by defining the main module and adding the module dependencies angular @@ -41,11 +41,11 @@ }); // Default timeout for success, error etc messages - $messageCenterServiceProvider.setGlobalOptions({timeout: 6000}); + $messageCenterServiceProvider.setGlobalOptions({ timeout: 6000 }); // Disabling Debug Data for production environment // @link https://docs.angularjs.org/guide/production - if(AppConfig.appEnv === 'production') { + if (AppConfig.appEnv === 'production') { $compileProvider.debugInfoEnabled(false); } @@ -64,4 +64,4 @@ }); }); -})(); +}()); diff --git a/modules/core/client/config/core.client.routes.js b/modules/core/client/config/core.client.routes.js index 8f93639e3b..1e21e9887d 100644 --- a/modules/core/client/config/core.client.routes.js +++ b/modules/core/client/config/core.client.routes.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -35,4 +35,4 @@ }); } -})(); +}()); diff --git a/modules/core/client/controllers/app.client.controller.js b/modules/core/client/controllers/app.client.controller.js index b2c2907de5..49f55f4b48 100644 --- a/modules/core/client/controllers/app.client.controller.js +++ b/modules/core/client/controllers/app.client.controller.js @@ -1,4 +1,4 @@ -(function(){ +(function() { 'use strict'; /** @@ -50,24 +50,24 @@ autoLink: false, // automatically turns URLs entered into the text field into HTML anchor tags toolbar: { buttons: [{ - name: 'bold', - contentDefault: '' - }, { - name: 'italic', - contentDefault: '' - }, { - name: 'underline', - contentDefault: '' - }, { - name: 'anchor', - contentDefault: '' - }, { - name: 'quote', - contentDefault: '' - }, { - name: 'unorderedlist', - contentDefault: '' - }] + name: 'bold', + contentDefault: '' + }, { + name: 'italic', + contentDefault: '' + }, { + name: 'underline', + contentDefault: '' + }, { + name: 'anchor', + contentDefault: '' + }, { + name: 'quote', + contentDefault: '' + }, { + name: 'unorderedlist', + contentDefault: '' + }] } }; @@ -91,7 +91,7 @@ $scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { // Redirect to login page if no user - if(toState.requiresAuth && !Authentication.user) { + if (toState.requiresAuth && !Authentication.user) { // Cancel stateChange event.preventDefault(); @@ -102,15 +102,13 @@ // Show a special signup ad for certain pages if user isn't authenticated // (Normally we just splash a signup page at this point) - if(toState.name === 'profile') { + if (toState.name === 'profile') { $state.go('profile-signup'); - } - else if(toState.name === 'search') { + } else if (toState.name === 'search') { $state.go('search-signin', toParams || {}); - } - // Or just continue to the signup page - else { - $state.go('signin', {'continue': true}); + } else { + // Or just continue to the signup page... + $state.go('signin', { 'continue': true }); } } @@ -130,7 +128,7 @@ vm.photoCreditsCount = 0; // Reset page scroll on page change - $window.scrollTo(0,0); + $window.scrollTo(0, 0); }); /** @@ -147,10 +145,9 @@ * Determine where to direct user from "home" links */ function goHome() { - if(Authentication.user) { + if (Authentication.user) { $state.go('search'); - } - else { + } else { $state.go('home'); } } @@ -159,7 +156,7 @@ * Sign out authenticated user */ function signout($event) { - if($event) { + if ($event) { $event.preventDefault(); } @@ -173,10 +170,10 @@ locker.clean(); // Do the signout and refresh the page - $window.top.location.href = '/api/auth/signout'; + $window.top.location.href = '/api/auth/signout'; } } -})(); +}()); diff --git a/modules/core/client/controllers/footer.client.controller.js b/modules/core/client/controllers/footer.client.controller.js index ce9afcaf57..d17f7b1fbe 100644 --- a/modules/core/client/controllers/footer.client.controller.js +++ b/modules/core/client/controllers/footer.client.controller.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; angular @@ -19,14 +19,14 @@ $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) { // Footer is transparent on these pages - vm.isTransparent = (angular.isDefined(toState.footerTransparent) && toState.footerTransparent === true) ? true : false; + vm.isTransparent = (angular.isDefined(toState.footerTransparent) && toState.footerTransparent === true); // Footer is hidden on these pages - vm.isHidden = (angular.isDefined(toState.footerHidden) && toState.footerHidden === true) ? true : false; + vm.isHidden = (angular.isDefined(toState.footerHidden) && toState.footerHidden === true); }); } -})(); +}()); diff --git a/modules/core/client/controllers/header.client.controller.js b/modules/core/client/controllers/header.client.controller.js index 7de6399d73..6442674826 100644 --- a/modules/core/client/controllers/header.client.controller.js +++ b/modules/core/client/controllers/header.client.controller.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; angular @@ -32,10 +32,10 @@ vm.isCollapsed = false; // Hide header at certain pages - vm.isHidden = (angular.isDefined(toState.headerHidden) && toState.headerHidden === true) ? true : false; + vm.isHidden = (angular.isDefined(toState.headerHidden) && toState.headerHidden === true); }); } } -})(); +}()); diff --git a/modules/core/client/directives/tr-board-credits.client.directive.js b/modules/core/client/directives/tr-board-credits.client.directive.js index 088c04b010..6f5f6d602e 100644 --- a/modules/core/client/directives/tr-board-credits.client.directive.js +++ b/modules/core/client/directives/tr-board-credits.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -14,16 +14,16 @@ replace: true, template: '' + - 'Photo by' + - 'Photos by' + - ' ' + - '' + - ' ()' + - ', ' + - '' + + ' Photo by' + + ' Photos by' + + ' ' + + ' ' + + ' ()' + + ' , ' + + ' ' + '', restrict: 'A' }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-boards.client.directive.js b/modules/core/client/directives/tr-boards.client.directive.js index 7aff48ed9b..df231aa6ec 100644 --- a/modules/core/client/directives/tr-boards.client.directive.js +++ b/modules/core/client/directives/tr-boards.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -36,14 +36,14 @@ 'file': 'flickr-bokeh.jpg' }, 'forestpath': { - 'name': 'Johnson', //Johnson Cameraface + 'name': 'Johnson', // Johnson Cameraface 'url': 'https://www.flickr.com/photos/54459164@N00/15506455245', 'license': 'CC', 'license_url': 'https://creativecommons.org/licenses/by-nc-sa/2.0/', 'file': 'flickr-forestpath.jpg' }, 'forestpath-toned': { - 'name': 'Johnson', //Johnson Cameraface + 'name': 'Johnson', // Johnson Cameraface 'url': 'https://www.flickr.com/photos/54459164@N00/15506455245', 'license': 'CC', 'license_url': 'https://creativecommons.org/licenses/by-nc-sa/2.0/', @@ -123,7 +123,7 @@ 'url': 'https://unsplash.com/sveninho', 'file': 'ss-mountainforest.jpg', 'license': 'CC', - 'license_url': 'https://creativecommons.org/publicdomain/zero/1.0/', // https://unsplash.com/license + 'license_url': 'https://creativecommons.org/publicdomain/zero/1.0/' // https://unsplash.com/license }, 'tribes-1': { // Permission granted for Trustroots (asked by Mikael Korpela) @@ -152,7 +152,6 @@ elem.addClass('board-' + key); elem.css({ 'background-image': 'url(/modules/core/img/board/' + photo.file + ')' - //'background-position': (photo.position ? photo.position : '50% 50%') }); // To prevent key being literally `key`: `{key: ...}`, we want it to be actual keyname such as `hitchroad`. @@ -166,4 +165,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-editor.client.directive.js b/modules/core/client/directives/tr-editor.client.directive.js index 255258068f..4b143abb96 100644 --- a/modules/core/client/directives/tr-editor.client.directive.js +++ b/modules/core/client/directives/tr-editor.client.directive.js @@ -1,5 +1,5 @@ -/*global MediumEditor */ -(function(){ +/* global MediumEditor */ +(function () { 'use strict'; /** @@ -106,9 +106,9 @@ }); // On ctrl+enter - if(iAttrs.trEditorOnCtrlEnter) { + if (iAttrs.trEditorOnCtrlEnter) { ngModel.editor.subscribe('editableKeydownEnter', function (event, editable) { - if(event.ctrlKey) { + if (event.ctrlKey) { event.preventDefault(); // Apply linked function $parse(iAttrs.trEditorOnCtrlEnter)(scope.$parent); @@ -123,4 +123,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-flashcards.client.directive.js b/modules/core/client/directives/tr-flashcards.client.directive.js index 4f27e87163..185b2378f9 100644 --- a/modules/core/client/directives/tr-flashcards.client.directive.js +++ b/modules/core/client/directives/tr-flashcards.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -21,34 +21,28 @@ return { restrict: 'A', template: '' + - 'Tip' + - '

' + - '

' + + ' Tip' + + '

' + + '

' + '
', link: function(scope, iElement, iAttrs) { - var flashcards = [ - { - title: 'Make sure your profile is complete', - content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.' - }, - { - title: 'Tell a little bit about yourself', - content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.' - }, - { - title: 'Explain them why you are choosing them', - content: '...explaining that you are interested in meeting them, not just looking for free accommodation.' - }, - { - title: 'Tell your host why you\'re on a trip', - content: 'What are your expectations in regards with going through their town?' - }, - { - title: 'Trustroots is very much about spontaneous travel', - content: 'Don\'t write to people 2 months ahead.' - } - ]; + var flashcards = [{ + title: 'Make sure your profile is complete', + content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.' + }, { + title: 'Tell a little bit about yourself', + content: 'You\'re much more likely to get a positive response if you have written a bit about yourself.' + }, { + title: 'Explain them why you are choosing them', + content: '...explaining that you are interested in meeting them, not just looking for free accommodation.' + }, { + title: 'Tell your host why you\'re on a trip', + content: 'What are your expectations in regards with going through their town?' + }, { + title: 'Trustroots is very much about spontaneous travel', + content: 'Don\'t write to people 2 months ahead.' + }]; var randomFlashcard = flashcards[Math.floor(Math.random() * flashcards.length)]; @@ -59,4 +53,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-focustip.client.directive.js b/modules/core/client/directives/tr-focustip.client.directive.js index 2fe1f012a3..0e65a9257b 100644 --- a/modules/core/client/directives/tr-focustip.client.directive.js +++ b/modules/core/client/directives/tr-focustip.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -21,14 +21,15 @@ scope: { trFocustip: '=' }, - link: function(scope, el, attrs, ctrl) { + link: function(scope, element, attrs, ctrl) { // Compiled template // after() requires jQuery var template = $compile('
' + scope.trFocustip + '
')(scope); - el.after(template); + element.after(template); - el.bind('focus', function() { + element + .bind('focus', function() { // Enable only if there's some text to show scope.enabled = (angular.isString(scope.trFocustip) && scope.trFocustip !== ''); scope.$apply(); @@ -42,4 +43,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-location.client.directive.js b/modules/core/client/directives/tr-location.client.directive.js index 37dd5dd6a6..4a34d304c2 100644 --- a/modules/core/client/directives/tr-location.client.directive.js +++ b/modules/core/client/directives/tr-location.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -31,21 +31,21 @@ scope: { value: '=ngModel', trLocationCenter: '=?', // `?` makes this optional - trLocationBounds: '=?', // `?` makes this optional + trLocationBounds: '=?' // `?` makes this optional }, replace: false, link: function (scope, element, attr, ngModel) { // Event handler to stop submitting the surrounding form element.bind('keydown keypress', function($event) { - if ($event.which === 13) { - $event.preventDefault(); - } + if ($event.which === 13) { + $event.preventDefault(); + } }); // Attach Angular UI Bootstrap TypeAhead - element.attr('typeahead-min-length', attr.typeaheadMinLength ? parseInt(attr.typeaheadMinLength) : 3); - element.attr('typeahead-wait-ms', attr.typeaheadWaitMs ? parseInt(attr.typeaheadWaitMs) : 300); + element.attr('typeahead-min-length', attr.typeaheadMinLength ? parseInt(attr.typeaheadMinLength, 10) : 3); + element.attr('typeahead-wait-ms', attr.typeaheadWaitMs ? parseInt(attr.typeaheadWaitMs, 10) : 300); element.attr('typeahead-on-select', 'trLocation.onSelect($item, $model, $label, $event)'); element.attr('uib-typeahead', 'trTitle as address.trTitle for address in trLocation.searchSuggestions($viewValue)'); @@ -89,14 +89,14 @@ // Set center bounds for (Angular-UI-Leaflet) model // Bounds is prioritized over center var bounds = LocationService.getBounds($item); - if(angular.isObject($scope.trLocationBounds) && bounds) { + + if (angular.isObject($scope.trLocationBounds) && bounds) { $scope.trLocationBounds = bounds; - } - // If no bounds was found, check `center` - // Set center coordinates for (Angular-UI-Leaflet) model - else if(angular.isObject($scope.trLocationCenter)) { + } else if (angular.isObject($scope.trLocationCenter)) { + // If no bounds was found, check `center` + // Set center coordinates for (Angular-UI-Leaflet) model var center = LocationService.getCenter($item); - if(center) { + if (center) { angular.extend($scope.trLocationCenter, center); } } @@ -107,4 +107,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-spinner.client.directive.js b/modules/core/client/directives/tr-spinner.client.directive.js index ef2ee9fe6c..c4922a07dd 100644 --- a/modules/core/client/directives/tr-spinner.client.directive.js +++ b/modules/core/client/directives/tr-spinner.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; angular @@ -10,9 +10,9 @@ restrict: 'E', link: function(scope, element, attrs) { - function generateSVG(size, square, stroke) { + function generateSVGMarkup(size, square, stroke) { return '' + - '' + + ' ' + ''; } @@ -21,30 +21,30 @@ square, stroke; - if(size === 'lg') { + if (size === 'lg') { square = 85; stroke = 4; - } - else if(size === 'md') { + } else if (size === 'md') { square = 65; stroke = 3; - } - else if(size === 'sm') { + } else if (size === 'sm') { square = 35; stroke = 2; - } - else if(size === 'xs') { + } else if (size === 'xs') { square = 25; stroke = 1; } - element.html( generateSVG(size, square, stroke) ); + var svg = generateSVGMarkup(size, square, stroke); + + element.html(svg); } + // Initialize svg renderSVG(); } }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-time.client.directive.js b/modules/core/client/directives/tr-time.client.directive.js index 383e85ac32..2db6251446 100644 --- a/modules/core/client/directives/tr-time.client.directive.js +++ b/modules/core/client/directives/tr-time.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -41,7 +41,7 @@ }, link: function(scope, el, attrs, ctrl) { - if(!scope.trTime) { + if (!scope.trTime) { $log.warn('No time passed for tr-time directive.'); return; } @@ -59,7 +59,7 @@ // Sync mode if other directive changes time mode scope.$on('timeModeAgoChanged', timeModeAgoChanged); function timeModeAgoChanged($event, newTimeModeAgo) { - if(scope.timeModeAgo !== newTimeModeAgo) { + if (scope.timeModeAgo !== newTimeModeAgo) { scope.timeModeAgo = newTimeModeAgo; } } @@ -73,7 +73,7 @@ scope.timeModeAgo = !scope.timeModeAgo; // Save setting to cache - if(locker.supported()) { + if (locker.supported()) { locker.put('timeAgo', scope.timeModeAgo); } @@ -85,4 +85,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/directives/tr-window-blur.client.directive.js b/modules/core/client/directives/tr-window-blur.client.directive.js index f6e39c1a7d..2e35f04340 100644 --- a/modules/core/client/directives/tr-window-blur.client.directive.js +++ b/modules/core/client/directives/tr-window-blur.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -15,35 +15,35 @@ .module('core') .directive('trWindowBlur', trWindowBlurDirective); - /* @ngInject */ - function trWindowBlurDirective($window) { - var directive = { - link: link, - restrict: 'A' - }; + /* @ngInject */ + function trWindowBlurDirective($window) { + var directive = { + link: link, + restrict: 'A' + }; - return directive; + return directive; - function link(scope, element, attributes) { + function link(scope, element, attributes) { - // Hook up blur-handler - var win = angular.element($window).on('blur', handleBlur); + // Hook up blur-handler + var win = angular.element($window).on('blur', handleBlur); - // When the scope is destroyed, we have to make sure to teardown - // the event binding so we don't get a leak. - scope.$on('$destroy', handleDestroy); + // When the scope is destroyed, we have to make sure to teardown + // the event binding so we don't get a leak. + scope.$on('$destroy', handleDestroy); - // Handle the blur event on the Window. - function handleBlur() { - scope.$apply(attributes.trWindowBlur); - } - - // Teardown the directive. - function handleDestroy() { - win.off('blur', handleBlur); - } + // Handle the blur event on the Window. + function handleBlur() { + scope.$apply(attributes.trWindowBlur); + } + // Teardown the directive. + function handleDestroy() { + win.off('blur', handleBlur); } + } + } -})(); +}()); diff --git a/modules/core/client/directives/tr-window-focus.client.directive.js b/modules/core/client/directives/tr-window-focus.client.directive.js index 08b02ff3e9..26614b7b8a 100644 --- a/modules/core/client/directives/tr-window-focus.client.directive.js +++ b/modules/core/client/directives/tr-window-focus.client.directive.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -15,35 +15,35 @@ .module('core') .directive('trWindowFocus', trWindowFocusDirective); - /* @ngInject */ - function trWindowFocusDirective($window) { - var directive = { - link: link, - restrict: 'A' - }; + /* @ngInject */ + function trWindowFocusDirective($window) { + var directive = { + link: link, + restrict: 'A' + }; - return directive; + return directive; - function link(scope, element, attributes) { + function link(scope, element, attributes) { - // Hook up focus-handler - var win = angular.element($window).on('focus', handleFocus); + // Hook up focus-handler + var win = angular.element($window).on('focus', handleFocus); - // When the scope is destroyed, we have to make sure to teardown - // the event binding so we don't get a leak. - scope.$on('$destroy', handleDestroy); + // When the scope is destroyed, we have to make sure to teardown + // the event binding so we don't get a leak. + scope.$on('$destroy', handleDestroy); - // Handle the focus event on the Window - function handleFocus() { - scope.$apply(attributes.trWindowFocus); - } - - // Teardown the directive - function handleDestroy() { - win.off('focus', handleFocus); - } + // Handle the focus event on the Window + function handleFocus() { + scope.$apply(attributes.trWindowFocus); + } + // Teardown the directive + function handleDestroy() { + win.off('focus', handleFocus); } + } + } -})(); +}()); diff --git a/modules/core/client/filters/age.client.filter.js b/modules/core/client/filters/age.client.filter.js index 56368d2ebd..1c49372c4a 100644 --- a/modules/core/client/filters/age.client.filter.js +++ b/modules/core/client/filters/age.client.filter.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -17,7 +17,7 @@ /* @ngInject */ function ageYearsFilter($filter) { return function(dateStringOrDate) { - var dateObj = new Date( $filter('date')(dateStringOrDate, 'yyyy-MM-dd') ), + var dateObj = new Date($filter('date')(dateStringOrDate, 'yyyy-MM-dd')), ageDifMs = Date.now() - dateObj.getTime(), ageDate = new Date(ageDifMs); // miliseconds from epoch @@ -25,4 +25,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/filters/plain-text-length.client.filter.js b/modules/core/client/filters/plain-text-length.client.filter.js index 80fe16f8d8..787ef9864b 100644 --- a/modules/core/client/filters/plain-text-length.client.filter.js +++ b/modules/core/client/filters/plain-text-length.client.filter.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; /** @@ -24,4 +24,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/filters/trusted-html.client.filter.js b/modules/core/client/filters/trusted-html.client.filter.js index 9d856c5680..25c365ae8d 100644 --- a/modules/core/client/filters/trusted-html.client.filter.js +++ b/modules/core/client/filters/trusted-html.client.filter.js @@ -1,4 +1,4 @@ -(function(){ +(function () { 'use strict'; angular @@ -12,4 +12,4 @@ }; } -})(); +}()); diff --git a/modules/core/client/services/languages.client.service.js b/modules/core/client/services/languages.client.service.js index a0dff9557c..1f85535a71 100644 --- a/modules/core/client/services/languages.client.service.js +++ b/modules/core/client/services/languages.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -17,9 +17,11 @@ function get(type) { if (type === 'array') { var langsArr = []; - for (var key in $window.languages) { - langsArr[langsArr.length] = {key: key, name: $window.languages[key]}; - } + + angular.forEach($window.languages, function(value, key) { + this.push({ key: key, name: value }); + }, langsArr); + return langsArr; } @@ -27,8 +29,6 @@ return $window.languages; } - return service; - } -})(); +}()); diff --git a/modules/core/client/services/location.client.service.js b/modules/core/client/services/location.client.service.js index 3d9b687154..45485d2d51 100644 --- a/modules/core/client/services/location.client.service.js +++ b/modules/core/client/services/location.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; /** @@ -25,7 +25,7 @@ getBounds: getBounds, getCenter: getCenter, shortTitle: shortTitle, - suggestions: suggestions, + suggestions: suggestions }; /** @@ -43,7 +43,7 @@ return { lat: defaultLocation.lat, lng: defaultLocation.lng, - zoom: parseInt(zoom) || defaultLocation.zoom, + zoom: parseInt(zoom || defaultLocation.zoom, 10) }; } @@ -64,7 +64,7 @@ * } */ function getBounds(geolocation) { - if(!geolocation || !geolocation.bbox || !angular.isArray(geolocation.bbox) || geolocation.bbox.length !== 4) { + if (!geolocation || !geolocation.bbox || !angular.isArray(geolocation.bbox) || geolocation.bbox.length !== 4) { return false; } return { @@ -93,15 +93,14 @@ function getCenter(geolocation) { var coords; - if(geolocation.center) { + if (geolocation.center) { coords = geolocation.center; - } - else if(geolocation.geometry && geolocation.geometry.coordinates) { + } else if (geolocation.geometry && geolocation.geometry.coordinates) { coords = geolocation.geometry.coordinates; } // Nothing found, return old or false - if(!coords || !angular.isArray(coords) || coords.length !== 2) { + if (!coords || !angular.isArray(coords) || coords.length !== 2) { return false; } @@ -124,29 +123,28 @@ * Defaults to `country,region,place,locality,neighborhood` */ function suggestions(val, types) { - if(!appSettings.mapbox || !appSettings.mapbox.publicKey) { + if (!appSettings.mapbox || !appSettings.mapbox.publicKey) { return []; } - return $http - .get( - '//api.mapbox.com/geocoding/v5/mapbox.places/' + val + '.json' + - '?access_token=' + appSettings.mapbox.publicKey + - '&types=' + (types || 'country,region,place,locality,neighborhood'), - { - // Tells Angular-Loading-Bar to ignore this http request - // @link https://github.com/chieffancypants/angular-loading-bar#ignoring-particular-xhr-requests - ignoreLoadingBar: true - } - ) + return $http.get( + '//api.mapbox.com/geocoding/v5/mapbox.places/' + val + '.json' + + '?access_token=' + appSettings.mapbox.publicKey + + '&types=' + (types || 'country,region,place,locality,neighborhood'), + { + // Tells Angular-Loading-Bar to ignore this http request + // @link https://github.com/chieffancypants/angular-loading-bar#ignoring-particular-xhr-requests + ignoreLoadingBar: true + }) .then(function(response) { - if(response.status === 200 && response.data.features && response.data.features.length > 0) { + if (response.status === 200 && response.data.features && response.data.features.length > 0) { return response.data.features.map(function(geolocation) { geolocation.trTitle = shortTitle(geolocation); return geolocation; }); + } else { + return []; } - else return []; }); } @@ -162,24 +160,22 @@ var title = '', titlePostfix = null; - if(geolocation.text) { + if (geolocation.text) { title = geolocation.text; // Relevant context strings - if(geolocation.context) { + if (geolocation.context) { var contextLength = geolocation.context.length; for (var i = 0; i < contextLength; i++) { - if(geolocation.context[i].id.substring(0, 6) === 'place.') { + if (geolocation.context[i].id.substring(0, 6) === 'place.') { title += ', ' + geolocation.context[i].text; - } - else if(geolocation.context[i].id.substring(0, 8) === 'country.') { + } else if (geolocation.context[i].id.substring(0, 8) === 'country.') { title += ', ' + geolocation.context[i].text; } } } - } - else if(geolocation.place_name) { + } else if (geolocation.place_name) { title = geolocation.place_name; } @@ -190,4 +186,4 @@ return service; } -})(); +}()); diff --git a/modules/core/client/services/maplayers.client.service.js b/modules/core/client/services/maplayers.client.service.js index 72d68037f5..e4cb48550d 100644 --- a/modules/core/client/services/maplayers.client.service.js +++ b/modules/core/client/services/maplayers.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; /** @@ -36,7 +36,7 @@ */ function getMapboxLayer(label, TRStyle, layerConf) { - if(!isMapboxAvailable || !layerConf) return; + if (!isMapboxAvailable || !layerConf) return; var layer = { name: label || 'Mapbox', @@ -53,12 +53,11 @@ } }; - // Legacy tiles - if(layerConf.legacy) { + if (layerConf.legacy) { + // Legacy tiles URL layer.url = 'https://{s}.tiles.mapbox.com/v4/{user}.{map}/{z}/{x}/{y}.png?access_token={token}&secure=1'; - } - // Publicly available Mapbox styles - else { + } else { + // Publicly available Mapbox styles URL layer.url = 'https://api.mapbox.com/styles/v1/{user}/{map}/tiles/{z}/{x}/{y}?access_token={token}'; } @@ -66,10 +65,9 @@ var feedbackLayer = appSettings.mapbox.user + '.' + layerConf.map; // These feedback layer id's are required for public styles - if(!layerConf.legacy && TRStyle === 'satellite') { + if (!layerConf.legacy && TRStyle === 'satellite') { feedbackLayer = 'mapbox.satellite'; - } - else if(!layerConf.legacy) { + } else if (!layerConf.legacy) { feedbackLayer = 'mapbox.streets'; } @@ -100,7 +98,7 @@ }, options || {}); // Streets - if(options.streets && isMapboxAvailable && appSettings.mapbox.maps.streets) { + if (options.streets && isMapboxAvailable && appSettings.mapbox.maps.streets) { // Streets: Mapbox layers.streets = getMapboxLayer( 'Streets', @@ -108,7 +106,7 @@ appSettings.mapbox.maps.streets ); // Streets fallback - } else if(options.streets) { + } else if (options.streets) { // Streets: OpenStreetMap layers.streets = { name: 'Streets', @@ -124,17 +122,15 @@ } // Satellite - if(options.satellite && isMapboxAvailable && appSettings.mapbox.maps.satellite) { - // Satellite: Mapbox + if (options.satellite && isMapboxAvailable && appSettings.mapbox.maps.satellite) { + // Satellite: Mapbox layers.satellite = getMapboxLayer( 'Satellite', 'satellite', appSettings.mapbox.maps.satellite ); - } - // Satellite fallback - else if(options.satellite) { - // Satellite: MapQuest + } else if (options.satellite) { + // Satellite fallback: MapQuest layers.satellite = { name: 'Satellite', type: 'xyz', @@ -149,7 +145,7 @@ } // Outdoors (without fallback) - if(options.outdoors && isMapboxAvailable && appSettings.mapbox.maps.outdoors) { + if (options.outdoors && isMapboxAvailable && appSettings.mapbox.maps.outdoors) { // Outdoors: Mapbox layers.outdoors = getMapboxLayer( 'Outdoors', @@ -163,4 +159,4 @@ } -})(); +}()); diff --git a/modules/core/client/services/settings.client.service.js b/modules/core/client/services/settings.client.service.js index be7fde84c1..c2926af7f5 100644 --- a/modules/core/client/services/settings.client.service.js +++ b/modules/core/client/services/settings.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -23,7 +23,7 @@ } } -})(); +}()); // TODO: Clean this out (deprecated) @@ -59,4 +59,4 @@ } } -})(); +}()); diff --git a/modules/core/server/controllers/analytics.server.controller.js b/modules/core/server/controllers/analytics.server.controller.js index cd5cd7ff2f..52d963286a 100644 --- a/modules/core/server/controllers/analytics.server.controller.js +++ b/modules/core/server/controllers/analytics.server.controller.js @@ -50,13 +50,13 @@ var url = require('url'); * */ exports.appendUTMParams = function(trackUrl, utmParams) { - if(!trackUrl || !utmParams || !utmParams.source || !utmParams.medium || !utmParams.campaign) { + if (!trackUrl || !utmParams || !utmParams.source || !utmParams.medium || !utmParams.campaign) { console.error('utmTrackify() missing one of the required variables:'); console.error('- trackUrl: ' + trackUrl); console.error('- utmParams.source: ' + utmParams.source); console.error('- utmParams.medium: ' + utmParams.medium); console.error('- utmParams.campaign: ' + utmParams.campaign); - return (trackUrl) ? trackUrl : ''; + return trackUrl || ''; } // Append required UTM parameters @@ -66,10 +66,10 @@ exports.appendUTMParams = function(trackUrl, utmParams) { obj.query.utm_campaign = String(utmParams.campaign); // Optional UTM parameters - if(utmParams.term) { + if (utmParams.term) { obj.query.utm_term = String(utmParams.term); } - if(utmParams.content) { + if (utmParams.content) { obj.query.utm_content = String(utmParams.content); } diff --git a/modules/core/server/controllers/core.server.controller.js b/modules/core/server/controllers/core.server.controller.js index 1c9561a009..569362a638 100644 --- a/modules/core/server/controllers/core.server.controller.js +++ b/modules/core/server/controllers/core.server.controller.js @@ -14,12 +14,12 @@ exports.renderIndex = function(req, res) { }; // Expose user - if(req.user) { + if (req.user) { renderVars.user = usersHandler.sanitizeProfile(req.user, req.user); } // Expose tribe (when browsing `/tribes/tribe-name`) - if(req.tribe) { + if (req.tribe) { renderVars.tribe = req.tribe; } @@ -39,7 +39,7 @@ exports.renderNotFound = function(req, res) { res.json({ message: errorHandler.getErrorMessageByKey('not-found') }); }, 'default': function() { - res.send( errorHandler.getErrorMessageByKey('not-found') ); + res.send(errorHandler.getErrorMessageByKey('not-found')); } }); }; diff --git a/modules/core/server/controllers/emails.server.controller.js b/modules/core/server/controllers/emails.server.controller.js index 07baa91047..9464da953c 100644 --- a/modules/core/server/controllers/emails.server.controller.js +++ b/modules/core/server/controllers/emails.server.controller.js @@ -18,12 +18,12 @@ var path = require('path'), * @returns {Object[]} - Returns object with supportUrl, footerUrl and headerUrl parameters. */ exports.addEmailBaseTemplateParams = function(host, params, utmCampaign) { - if(params === null || typeof params !== 'object') { + if (params === null || typeof params !== 'object') { console.error('appendUrlParams: requires param to be Object. No URL parameters added.'); return {}; } - if(!host) { + if (!host) { console.error('appendUrlParams: requires host.'); return params; } diff --git a/modules/core/server/controllers/errors.server.controller.js b/modules/core/server/controllers/errors.server.controller.js index 371d8d2e64..2d0f543cb1 100644 --- a/modules/core/server/controllers/errors.server.controller.js +++ b/modules/core/server/controllers/errors.server.controller.js @@ -13,14 +13,14 @@ var defaultErrorMessage = 'Snap! Something went wrong. If this keeps happening, exports.getErrorMessageByKey = function(key) { var errorMessages = { - 'not-found': 'Not found.', - 'forbidden': 'Forbidden.', - 'invalid-id': 'Cannot interpret id.', - 'unprocessable-entity': 'Unprocessable Entity.', // Status 422, @link http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity + 'not-found': 'Not found.', + 'forbidden': 'Forbidden.', + 'invalid-id': 'Cannot interpret id.', + 'unprocessable-entity': 'Unprocessable Entity.', // Status 422, @link http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity 'unsupported-media-type': 'Unsupported Media Type.', // Status 415 - 'bad-request': 'Bad request.', // Status 400 - 'conflict': 'Conflict.', // Status 409 - 'default': defaultErrorMessage + 'bad-request': 'Bad request.', // Status 400 + 'conflict': 'Conflict.', // Status 409 + 'default': defaultErrorMessage }; return (key && errorMessages[key]) ? errorMessages[key] : defaultErrorMessage; @@ -38,7 +38,7 @@ exports.getNewError = function(key, status) { var message = this.getErrorMessageByKey(key), err = new Error(message); - if(status) err.status = status; + if (status) err.status = status; return err; }; diff --git a/modules/core/server/controllers/text-processor.server.controller.js b/modules/core/server/controllers/text-processor.server.controller.js index b0410c6386..454fe66122 100644 --- a/modules/core/server/controllers/text-processor.server.controller.js +++ b/modules/core/server/controllers/text-processor.server.controller.js @@ -15,16 +15,16 @@ var Autolinker = require('autolinker'), * @link https://github.com/punkave/sanitize-html */ exports.sanitizeOptions = { - allowedTags: [ 'p', 'br', 'b', 'i', 'em', 'strong', 'u', 'a', 'li', 'ul', 'blockquote' ], + allowedTags: ['p', 'br', 'b', 'i', 'em', 'strong', 'u', 'a', 'li', 'ul', 'blockquote'], allowedAttributes: { - 'a': [ 'href' ], + 'a': ['href'] // We don't currently allow img itself, but this would make sense if we did: - //'img': [ 'src' ] + // 'img': [ 'src' ] }, // If we would allow class attributes, you can limit which classes are allowed: - //allowedClasses: { - // 'a': [ 'classname' ] - //}, + // allowedClasses: { + // 'a': [ 'classname' ] + // }, // Convert these tags to unify html transformTags: { 'strong': 'b', @@ -34,9 +34,9 @@ exports.sanitizeOptions = { exclusiveFilter: function(frame) { return frame.tag === 'a' && !frame.text.trim(); }, - selfClosing: [ 'img', 'br' ], + selfClosing: ['img', 'br'], // URL schemes we permit - allowedSchemes: [ 'http', 'https', 'ftp', 'mailto', 'tel', 'irc' ] + allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'tel', 'irc'] }; @@ -49,7 +49,7 @@ exports.sanitizeOptions = { */ exports.html = function (content) { - if(typeof content === 'string' && content.length > 0) { + if (typeof content === 'string' && content.length > 0) { // Replace " ", "


" and trim content = content.replace(/ /g, ' ').replace(/


<\/p>/g, ' ').trim(); @@ -60,33 +60,33 @@ exports.html = function (content) { // Turn URLs/emails/phonenumbers into links // @link https://github.com/gregjacobs/Autolinker.js content = Autolinker.link(content, { - // Don't auto-link Twitter handles (@username) - twitter: false, + // Don't auto-link Twitter handles (@username) + twitter: false, - // Auto-link emails - email: true, + // Auto-link emails + email: true, - // Auto-link URLs - urls: true, + // Auto-link URLs + urls: true, - // Auto-link phone numbers - phone: true, + // Auto-link phone numbers + phone: true, - // A number for how many characters long URLs/emails/Twitter handles/Twitter hashtags should be truncated to - // inside the text of a link. If the match is over the number of characters, it will be truncated to this length - // by replacing the end of the string with a two period ellipsis ('..'). - truncate: { - length: 150, - location: 'middle' // end|middle|smart - }, + // A number for how many characters long URLs/emails/Twitter handles/Twitter hashtags should be truncated to + // inside the text of a link. If the match is over the number of characters, it will be truncated to this length + // by replacing the end of the string with a two period ellipsis ('..'). + truncate: { + length: 150, + location: 'middle' // end|middle|smart + }, - // Strip 'http://' or 'https://' and/or the 'www.' from the beginning of links. - // I.e.: `https://www.wikipedia.org/` => `wikipedia.org` - stripPrefix: true, + // Strip 'http://' or 'https://' and/or the 'www.' from the beginning of links. + // I.e.: `https://www.wikipedia.org/` => `wikipedia.org` + stripPrefix: true, - // Don't add target="_blank" because of https://mathiasbynens.github.io/rel-noopener/ attack. - newWindow: false - }); + // Don't add target="_blank" because of https://mathiasbynens.github.io/rel-noopener/ attack. + newWindow: false + }); } @@ -103,7 +103,7 @@ exports.isEmpty = function (content) { return ( typeof content !== 'string' || content.length === 0 || - sanitizeHtml(content, {allowedTags: []}).replace(/ /g, ' ').trim() === '' + sanitizeHtml(content, { allowedTags: [] }).replace(/ /g, ' ').trim() === '' ); }; @@ -115,13 +115,13 @@ exports.isEmpty = function (content) { */ exports.plainText = function (content, cleanWhitespace) { - if(typeof content === 'string' && content.length > 0) { + if (typeof content === 'string' && content.length > 0) { // No HTML allowed - content = sanitizeHtml(content, {allowedTags: []}); + content = sanitizeHtml(content, { allowedTags: [] }); // Remove white space. Matches a single white space character, including space, tab, form feed, line feed. - if(cleanWhitespace === true) { + if (cleanWhitespace === true) { content = content.replace(/\s/g, ' '); } diff --git a/modules/core/server/views/layout.server.view.html b/modules/core/server/views/layout.server.view.html index 1cb934de4b..0b5253fb47 100644 --- a/modules/core/server/views/layout.server.view.html +++ b/modules/core/server/views/layout.server.view.html @@ -96,7 +96,7 @@ {# Google Analytics #} {% if googleAnalytics.enabled === true %} + diff --git a/modules/tags/server/controllers/tags.server.controller.js b/modules/tags/server/controllers/tags.server.controller.js index 8d7322061f..c5f03deaf6 100644 --- a/modules/tags/server/controllers/tags.server.controller.js +++ b/modules/tags/server/controllers/tags.server.controller.js @@ -10,17 +10,17 @@ var path = require('path'), // Publicly exposed fields from tags exports.tagFields = [ - '_id', - 'slug', - 'label', - 'count' - ].join(' '); + '_id', + 'slug', + 'label', + 'count' +].join(' '); /** * Crate a tag */ exports.createTag = function(req, res) { - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); diff --git a/modules/tags/server/controllers/tribes.server.controller.js b/modules/tags/server/controllers/tribes.server.controller.js index 0288e20bf9..a6622d81f8 100644 --- a/modules/tags/server/controllers/tribes.server.controller.js +++ b/modules/tags/server/controllers/tribes.server.controller.js @@ -12,24 +12,24 @@ var path = require('path'), // Publicly exposed fields from tribes exports.tribeFields = [ - '_id', - 'slug', - 'label', - 'count', - 'color', - 'image_UUID', - 'attribution', - 'attribution_url' - ].join(' '); + '_id', + 'slug', + 'label', + 'count', + 'color', + 'image_UUID', + 'attribution', + 'attribution_url' +].join(' '); /** * Constructs link headers for pagination */ var setLinkHeader = function(req, res, pageCount) { - if(paginate.hasNextPages(req)(pageCount)) { + if (paginate.hasNextPages(req)(pageCount)) { var nextPage = { page: req.query.page + 1 }; - var linkHead = '<' + req.protocol + ':' + res.locals.url.slice(0,-1) + res.locals.paginate.href(nextPage) + '>; rel="next"'; - res.set('Link',linkHead); + var linkHead = '<' + req.protocol + ':' + res.locals.url.slice(0, -1) + res.locals.paginate.href(nextPage) + '>; rel="next"'; + res.set('Link', linkHead); } }; @@ -44,8 +44,8 @@ exports.listTribes = function(req, res) { tribe: true }, { - page: parseInt(req.query.page) || 1, // Note: `parseInt('0')` will return `NaN`, `page` will be set to `1` in such case. - limit: parseInt(req.query.limit) || 0, // `0` for infinite + page: parseInt(req.query.page, 10) || 1, // Note: `parseInt('0')` will return `NaN`, `page` will be set to `1` in such case. + limit: parseInt(req.query.limit, 10) || 0, // `0` for infinite sort: { count: 'desc' }, diff --git a/modules/tags/server/models/tag.server.model.js b/modules/tags/server/models/tag.server.model.js index 6260670cf9..fa82aea66a 100644 --- a/modules/tags/server/models/tag.server.model.js +++ b/modules/tags/server/models/tag.server.model.js @@ -9,7 +9,7 @@ var path = require('path'), mongoosePaginate = require('mongoose-paginate'), uniqueValidation = require('mongoose-beautiful-unique-validation'), integerValidator = require('mongoose-integer'), - URLSlugs = require('mongoose-url-slugs'), + urlslugs = require('mongoose-url-slugs'), randomColor = require('randomcolor'), speakingurl = require('speakingurl'), validator = require('validator'), @@ -46,7 +46,7 @@ var validateLabel = function(label) { */ var validateURL = function(url) { return !url || validator.isURL(url, { - protocols: ['http','https'], + protocols: ['http', 'https'], require_tld: true, require_protocol: true, require_valid_protocol: true, @@ -145,13 +145,13 @@ var TagSchema = new Schema({ * @link https://npmjs.org/package/speakingurl * @link https://github.com/mindblaze/mongoose-url-slugs/issues/17 */ -TagSchema.plugin(URLSlugs('label', { +TagSchema.plugin(urlslugs('label', { field: 'slug', generator: function(string) { return speakingurl(string, { separator: '-', // char that replaces the whitespaces maintainCase: false, // maintain case (true, convert all chars to lower case (false) - truncate: 255 // trim to max length ({number}), don't truncate (0) + truncate: 255 // trim to max length ({number}), don't truncate (0) }); } })); diff --git a/modules/tags/server/policies/tags.server.policy.js b/modules/tags/server/policies/tags.server.policy.js index 1fcd23a1f6..78b9bf39b1 100644 --- a/modules/tags/server/policies/tags.server.policy.js +++ b/modules/tags/server/policies/tags.server.policy.js @@ -70,7 +70,7 @@ exports.isAllowed = function(req, res, next) { // No tags/tribes for non-authenticated users /* - if(!req.user || (req.user && !req.user.public)) { + if (!req.user || (req.user && !req.user.public)) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); @@ -81,13 +81,13 @@ exports.isAllowed = function(req, res, next) { var roles = (req.user && req.user.roles) ? req.user.roles : ['guest']; acl.areAnyRolesAllowed(roles, req.route.path, req.method.toLowerCase(), function(err, isAllowed) { - if(err) { + if (err) { // An authorization error occurred. return res.status(500).send({ message: 'Unexpected authorization error' }); } else { - if(isAllowed) { + if (isAllowed) { // Access granted! Invoke next middleware return next(); } else { diff --git a/modules/tags/tests/server/tags.server.model.tests.js b/modules/tags/tests/server/tags.server.model.tests.js index be4ef18377..23aa50283c 100644 --- a/modules/tags/tests/server/tags.server.model.tests.js +++ b/modules/tags/tests/server/tags.server.model.tests.js @@ -13,7 +13,9 @@ var path = require('path'), /** * Globals */ -var tag, tag2, tag3; +var tag, + tag2, + tag3; /** * Unit tests diff --git a/modules/tags/tests/server/tags.server.routes.test.js b/modules/tags/tests/server/tags.server.routes.test.js index 6e94c1173d..b6bd0225a9 100644 --- a/modules/tags/tests/server/tags.server.routes.test.js +++ b/modules/tags/tests/server/tags.server.routes.test.js @@ -12,7 +12,17 @@ var should = require('should'), /** * Globals */ -var app, agent, credentials, user, _user, tag, _tag, tribe, _tribe, tribeNonPublic, _tribeNonPublic; +var app, + agent, + credentials, + user, + _user, + tag, + _tag, + tribe, + _tribe, + tribeNonPublic, + _tribeNonPublic; /** * User routes tests @@ -59,7 +69,7 @@ describe('Tag CRUD tests', function () { attribution: 'Photo credits', attribution_url: 'http://www.trustroots.org/team', image_UUID: '3c8bb9f1-e313-4baa-bf4c-1d8994fd6c6c', - tribe: true, + tribe: true }; // Create a new non-public tribe diff --git a/modules/users/client/config/users.client.config.js b/modules/users/client/config/users.client.config.js index 4c6755832d..7b033adb1f 100644 --- a/modules/users/client/config/users.client.config.js +++ b/modules/users/client/config/users.client.config.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -34,4 +34,4 @@ ]); } -})(); +}()); diff --git a/modules/users/client/config/users.client.routes.js b/modules/users/client/config/users.client.routes.js index c72a42a574..2e48deb2ea 100644 --- a/modules/users/client/config/users.client.routes.js +++ b/modules/users/client/config/users.client.routes.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -36,7 +36,7 @@ templateUrl: '/modules/users/views/profile/profile-edit.client.view.html', abstract: true, controller: 'ProfileEditController', - controllerAs : 'profileEdit' + controllerAs: 'profileEdit' }). state('profile-edit.about', { url: '', @@ -105,12 +105,11 @@ // Contact is loaded only after profile is loaded, because we need the profile ID contact: function(ContactByService, profile, Authentication) { return profile.$promise.then(function(profile) { - // No profile found or looking at own profile: no need to load contact - if(Authentication.user && Authentication.user._id === profile._id) { + if (Authentication.user && Authentication.user._id === profile._id) { + // No profile found or looking at own profile: no need to load contact return; - } - // Load contact - else { + } else { + // Load contact return ContactByService.get({ userId: profile._id }); @@ -160,7 +159,7 @@ state('profile-signup', { url: '/profile-signup', title: 'Trustroots profile', - templateUrl: '/modules/users/views/profile/profile-signup.client.view.html', + templateUrl: '/modules/users/views/profile/profile-signup.client.view.html' }). // Auth routes @@ -238,4 +237,4 @@ }); } -})(); +}()); diff --git a/modules/users/client/controllers/authentication.client.controller.js b/modules/users/client/controllers/authentication.client.controller.js index a967871355..f118f7e994 100644 --- a/modules/users/client/controllers/authentication.client.controller.js +++ b/modules/users/client/controllers/authentication.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -42,15 +42,14 @@ // Redirect to where we were left off before sign-in page // See modules/core/client/controllers/main.client.controller.js - if(vm.continue) { + if (vm.continue) { var stateTo = $rootScope.signinState || 'search', stateToParams = $rootScope.signinStateParams || {}; delete $rootScope.signinState; delete $rootScope.signinStateParams; $state.go(stateTo, stateToParams); - } - // Redirect to the search page - else { + } else { + // Redirect to the search page $state.go('search'); } }).error(function(error) { @@ -65,4 +64,4 @@ } -})(); +}()); diff --git a/modules/users/client/controllers/avatar-editor.client.controller.js b/modules/users/client/controllers/avatar-editor.client.controller.js index e1ddf455f9..fc809c70f4 100644 --- a/modules/users/client/controllers/avatar-editor.client.controller.js +++ b/modules/users/client/controllers/avatar-editor.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -34,7 +34,7 @@ function saveAvatar() { // Uploaded new file - if(vm.user.avatarSource === 'local' && vm.avatarPreview === true) { + if (vm.user.avatarSource === 'local' && vm.avatarPreview === true) { // Upload the new file vm.avatarUploading = true; vm.upload = Upload.upload({ @@ -52,27 +52,22 @@ }).error(function(data, status, headers, config) { messageCenterService.add('danger', 'Oops! Something went wrong. Try again later.'); vm.avatarUploading = false; - //$uibModalInstance.dismiss('close'); }); - } - - // Changed avatar selection (but didn't upload new file) - else if(lastAvatarSource !== vm.user.avatarSource) { + } else if (lastAvatarSource !== vm.user.avatarSource) { + // Close modal due user changed avatar selection (but didn't upload a new file) $uibModalInstance.close(vm.user); - } - - // No changes, just dismiss... - else { + } else { + // No changes, just dismiss... dismissModal(); } } /** - * Process preview after file is selected/dropped/received from camera + * Process preview after file is selected via fileinput / dropped to window / received from camera */ function fileSelected($files, $event) { // Too early - if($files && $files.length === 0) { + if ($files && $files.length === 0) { return; } @@ -82,14 +77,11 @@ vm.user.avatarSource = 'local'; // Validate file - if(file.type.indexOf('jpeg') === -1 && file.type.indexOf('gif') === -1 && file.type.indexOf('png') === -1) { - messageCenterService.add('danger', 'Please give a jpg, gif, or png image.'); - } - else if(file.size > appSettings.maxUploadSize) { - messageCenterService.add('danger', 'Whoops, your file is too big. Please keep it up to ' + bytesToSize(appSettings.maxUploadSize) + '. Sorry!'); - } - // Upload file - else { + if (file.type.indexOf('jpeg') === -1 && file.type.indexOf('gif') === -1 && file.type.indexOf('png') === -1) { + messageCenterService.add('danger', 'Please give a jpg, gif, or png image.'); + } else if (file.size > appSettings.maxUploadSize) { + messageCenterService.add('danger', 'Whoops, your file is too big. Please keep it up to ' + bytesToSize(appSettings.maxUploadSize) + '. Sorry!'); + } else { vm.avatarUploading = true; // Show the local file as a preview @@ -114,10 +106,10 @@ function bytesToSize(bytes) { var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; if (bytes === 0) return '0 Byte'; - var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); + var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10); return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]; } } -})(); +}()); diff --git a/modules/users/client/controllers/confirm-email.client.controller.js b/modules/users/client/controllers/confirm-email.client.controller.js index 4f6e9b8c8b..a4f4309094 100644 --- a/modules/users/client/controllers/confirm-email.client.controller.js +++ b/modules/users/client/controllers/confirm-email.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -18,7 +18,7 @@ vm.isLoading = false; // Is ?signup at the url (set only for first email confirms) - vm.signup = ($stateParams.signup) ? true : false; + vm.signup = angular.isDefined($stateParams.signup); // Change user password function confirmEmail() { @@ -32,12 +32,11 @@ Authentication.user = response.user; $rootScope.$broadcast('userUpdated'); - // If successful and this was user's first confirm, welcome them to the community - if(response.profileMadePublic) { + if (response.profileMadePublic) { + // If successful and this was user's first confirm, welcome them to the community $state.go('welcome'); - } - // If succesfull and wasn't first time, say yay! - else { + } else { + // If succesfull and wasn't first time, say yay! vm.success = true; } @@ -49,4 +48,4 @@ } -})(); +}()); diff --git a/modules/users/client/controllers/password-forgot.client.controller.js b/modules/users/client/controllers/password-forgot.client.controller.js index dacaddca45..d36006f548 100644 --- a/modules/users/client/controllers/password-forgot.client.controller.js +++ b/modules/users/client/controllers/password-forgot.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -37,4 +37,4 @@ } } -})(); +}()); diff --git a/modules/users/client/controllers/password-reset.client.controller.js b/modules/users/client/controllers/password-reset.client.controller.js index 63a5c76ff0..d0da7833c7 100644 --- a/modules/users/client/controllers/password-reset.client.controller.js +++ b/modules/users/client/controllers/password-reset.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -43,4 +43,4 @@ } } -})(); +}()); diff --git a/modules/users/client/controllers/profile-edit-about.client.controller.js b/modules/users/client/controllers/profile-edit-about.client.controller.js index 0a45bf502e..3ea249ad1f 100644 --- a/modules/users/client/controllers/profile-edit-about.client.controller.js +++ b/modules/users/client/controllers/profile-edit-about.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -43,15 +43,15 @@ */ function decodeUserLanguages() { var langs_arr = []; - if(vm.user && vm.user.languages) { + if (vm.user && vm.user.languages) { vm.user.languages.forEach(function(key) { - langs_arr[langs_arr.length] = {key: key, name: vm.languages[key]}; + langs_arr[langs_arr.length] = { key: key, name: vm.languages[key] }; }); } vm.userLanguages = langs_arr; } function encodeUserLanguages() { - if(!vm.user) return; + if (!vm.user) return; var langs_arr = []; vm.userLanguages.forEach(function(lang) { @@ -65,21 +65,20 @@ */ function updateUserProfile(isValid) { encodeUserLanguages(); - if(isValid) { + if (isValid) { vm.user.$update(function(response) { Authentication.user = response; $scope.$emit('userUpdated'); messageCenterService.add('success', 'Profile updated.'); }, function(response) { - messageCenterService.add('danger', response.data.message || 'Something went wrong. Please try again!' , { timeout: 10000 }); + messageCenterService.add('danger', response.data.message || 'Something went wrong. Please try again!', { timeout: 10000 }); }); - } - else { - messageCenterService.add('danger', 'Please fix errors from your profile and try again.' , { timeout: 10000 }); + } else { + messageCenterService.add('danger', 'Please fix errors from your profile and try again.', { timeout: 10000 }); } } } -})(); +}()); diff --git a/modules/users/client/controllers/profile-edit-account.client.controller.js b/modules/users/client/controllers/profile-edit-account.client.controller.js index 6a8cbf35d1..0de127c95d 100644 --- a/modules/users/client/controllers/profile-edit-account.client.controller.js +++ b/modules/users/client/controllers/profile-edit-account.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -48,8 +48,8 @@ * Resend confirmation email for already sent email */ function resendUserEmailConfirm($event) { - if($event) $event.preventDefault(); - if(vm.user.emailTemporary) { + if ($event) $event.preventDefault(); + if (vm.user.emailTemporary) { vm.user.email = vm.user.emailTemporary; updateUserEmail(); } @@ -86,7 +86,7 @@ vm.currentPassword = ''; vm.newPassword = ''; vm.verifyPassword = ''; - angular.element('#newPassword').val(''); //Fix to bypass password verification directive + angular.element('#newPassword').val(''); // Fix to bypass password verification directive vm.changeUserPasswordLoading = false; vm.user = Authentication.user = response.user; messageCenterService.add('success', 'Your password is now changed. Have a nice day!'); @@ -99,4 +99,4 @@ } -})(); +}()); diff --git a/modules/users/client/controllers/profile-edit-networks.client.controller.js b/modules/users/client/controllers/profile-edit-networks.client.controller.js index c2675e1ae2..9229b981f5 100644 --- a/modules/users/client/controllers/profile-edit-networks.client.controller.js +++ b/modules/users/client/controllers/profile-edit-networks.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -35,11 +35,8 @@ /** * Check if there are additional accounts */ - function hasConnectedAdditionalSocialAccounts(provider) { - for (var i in vm.user.additionalProvidersData) { - return true; - } - return false; + function hasConnectedAdditionalSocialAccounts() { + return (vm.user.additionalProvidersData && Object.keys(vm.user.additionalProvidersData).length); } /** @@ -59,7 +56,7 @@ vm.user = Authentication.user = response; $scope.$emit('userUpdated'); }).error(function(response) { - messageCenterService.add('danger', response.message || 'Something went wrong. Try again or contact us to disconnect your profile.' , { timeout: 10000 }); + messageCenterService.add('danger', response.message || 'Something went wrong. Try again or contact us to disconnect your profile.', { timeout: 10000 }); }); } @@ -67,20 +64,19 @@ * Update a user profile */ function updateUserProfile(isValid) { - if(isValid) { + if (isValid) { vm.user.$update(function(response) { Authentication.user = response; $scope.$emit('userUpdated'); messageCenterService.add('success', 'Hospitality networks updated.'); }, function(response) { - messageCenterService.add('danger', response.data.message || 'Something went wrong. Please try again!' , { timeout: 10000 }); + messageCenterService.add('danger', response.data.message || 'Something went wrong. Please try again!', { timeout: 10000 }); }); - } - else { - messageCenterService.add('danger', 'Please fix errors from your profile and try again.' , { timeout: 10000 }); + } else { + messageCenterService.add('danger', 'Please fix errors from your profile and try again.', { timeout: 10000 }); } } } -})(); +}()); diff --git a/modules/users/client/controllers/profile-edit-photo.client.controller.js b/modules/users/client/controllers/profile-edit-photo.client.controller.js index 12880e4f1f..16afa94c46 100644 --- a/modules/users/client/controllers/profile-edit-photo.client.controller.js +++ b/modules/users/client/controllers/profile-edit-photo.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -54,7 +54,7 @@ */ function saveAvatar() { // Uploaded new file - if(vm.user.avatarSource === 'local' && vm.avatarPreview === true) { + if (vm.user.avatarSource === 'local' && vm.avatarPreview === true) { // Upload the new file vm.avatarUploading = true; vm.upload = Upload.upload({ @@ -73,16 +73,14 @@ // Default error var saveAvatarErr = 'Oops! Something went wrong. Try again later.'; - // Could not process file - if(status === 422) { + if (status === 422) { + // Could not process file saveAvatarErr = 'Sorry, we could not process this file.'; - } - // File too large - else if(status === 413) { + } else if (status === 413) { + // File too large saveAvatarErr = 'Whoops, your file is too big. Please keep it up to ' + bytesToSize(appSettings.maxUploadSize) + '.'; - } - // Unsupported media type - else if(status === 415) { + } else if (status === 415) { + // Unsupported media type saveAvatarErr = 'Sorry, we do not support this type of file.'; } @@ -95,11 +93,11 @@ } /** - * Process preview after file is selected/dropped/received from camera + * Process preview after file is selected via fileinput / dropped to window / received from camera */ function fileSelected($files, $event) { // Too early - if($files && $files.length === 0) { + if ($files && $files.length === 0) { return; } @@ -109,15 +107,14 @@ vm.user.avatarSource = 'local'; vm.user.avatarUploaded = true; - // Validate file - if(file.type.indexOf('jpeg') === -1 && file.type.indexOf('gif') === -1 && file.type.indexOf('png') === -1) { - messageCenterService.add('danger', 'Please give a jpg, gif, or png image.'); - } - else if(file.size > appSettings.maxUploadSize) { - messageCenterService.add('danger', 'Whoops, your file is too big. Please keep it up to ' + bytesToSize(appSettings.maxUploadSize) + '.'); - } - // Upload file - else { + // Validate filetype + if (file.type.indexOf('jpeg') === -1 && file.type.indexOf('gif') === -1 && file.type.indexOf('png') === -1) { + messageCenterService.add('danger', 'Please give a jpg, gif, or png image.'); + // Validate filesize + } else if (file.size > appSettings.maxUploadSize) { + messageCenterService.add('danger', 'Whoops, your file is too big. Please keep it up to ' + bytesToSize(appSettings.maxUploadSize) + '.'); + // All good, uploading file... + } else { vm.avatarUploading = true; // Show the local file as a preview @@ -161,11 +158,11 @@ function bytesToSize(bytes) { var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; if (bytes === 0) return '0 Byte'; - var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); + var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10); return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]; } } -})(); +}()); diff --git a/modules/users/client/controllers/profile-edit-tags.client.controller.js b/modules/users/client/controllers/profile-edit-tags.client.controller.js index 38e05e318a..2fb9ac87f8 100644 --- a/modules/users/client/controllers/profile-edit-tags.client.controller.js +++ b/modules/users/client/controllers/profile-edit-tags.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -22,20 +22,19 @@ * Update a user profile */ function updateUserProfile(isValid) { - if(isValid) { + if (isValid) { vm.user.$update(function(response) { Authentication.user = response; $scope.$emit('userUpdated'); messageCenterService.add('success', 'Hospitality networks updated.'); }, function(response) { - messageCenterService.add('danger', response.data.message || 'Something went wrong. Please try again!' , { timeout: 10000 }); + messageCenterService.add('danger', response.data.message || 'Something went wrong. Please try again!', { timeout: 10000 }); }); - } - else { - messageCenterService.add('danger', 'Please fix errors from your profile and try again.' , { timeout: 10000 }); + } else { + messageCenterService.add('danger', 'Please fix errors from your profile and try again.', { timeout: 10000 }); } } } -})(); +}()); diff --git a/modules/users/client/controllers/profile-edit.client.controller.js b/modules/users/client/controllers/profile-edit.client.controller.js index a3debd22f7..b7eeb7956e 100644 --- a/modules/users/client/controllers/profile-edit.client.controller.js +++ b/modules/users/client/controllers/profile-edit.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -21,7 +21,7 @@ // React when state changes and there are unsaved modifications $scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options) { - if(vm.unsavedModifications) { + if (vm.unsavedModifications) { // Cancel original $state transition // transitionTo() promise will be rejected with // a 'transition prevented' error @@ -29,19 +29,19 @@ // Ask for confirmation $confirm({ - title: 'Are you sure?', - text: 'Your changes would be lost. Return and press "Save" to keep the changes, or press "Continue" to discard them.', - ok: 'Continue', - cancel: 'Cancel' - }) - // If user pressed "continue", create another state go - .then(function() { - vm.unsavedModifications = false; - $state.go(toState.name, toParams); - }); + title: 'Are you sure?', + text: 'Your changes would be lost. Return and press "Save" to keep the changes, or press "Continue" to discard them.', + ok: 'Continue', + cancel: 'Cancel' + }) + // If user pressed "continue", create another state go + .then(function() { + vm.unsavedModifications = false; + $state.go(toState.name, toParams); + }); } }); } -})(); +}()); diff --git a/modules/users/client/controllers/profile.client.controller.js b/modules/users/client/controllers/profile.client.controller.js index e24ac8c6f0..2f371629f8 100644 --- a/modules/users/client/controllers/profile.client.controller.js +++ b/modules/users/client/controllers/profile.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -9,8 +9,8 @@ function ProfileController($scope, $stateParams, $state, $location, $uibModal, $filter, $window, Languages, Users, Contact, Authentication, $timeout, messageCenterService, profile, contact, appSettings) { // No user defined at URL, just redirect to user's own profile - if(!$stateParams.username) { - $state.go('profile.about', {username: Authentication.user.username}); + if (!$stateParams.username) { + $state.go('profile.about', { username: Authentication.user.username }); } // ViewModel @@ -40,24 +40,23 @@ initMemberships(); // When on small screen... - if(angular.element('body').width() <= 480) { + if (angular.element('body').width() <= 480) { // By default we land to `about` tab of this controller // If we're on small screens, direct to `overview` tab instead - if($state.current.name === 'profile.about') { + if ($state.current.name === 'profile.about') { // Timeout ensures `ui-sref-active=""` gets updated at the templates $timeout(function() { $state.go('profile.overview', { username: profile.username }); }); } - } // When on bigger screen... // Redirect "mobile only" tabs to about tab - else if(['profile.overview', 'profile.accommodation'].indexOf($state.current.name) > -1) { + } else if (['profile.overview', 'profile.accommodation'].indexOf($state.current.name) > -1) { $state.go('profile.about', { username: profile.username }); } // If this is authenticated user's own profile, measure profile description length - if(Authentication.user._id === profile._id) { + if (Authentication.user._id === profile._id) { vm.profileDescriptionLength = Authentication.user.description ? $filter('plainTextLength')(Authentication.user.description) : 0; } @@ -84,20 +83,22 @@ */ function initMemberships() { var memberships = { - 'tribes': { - 'is': [], - 'likes': [] - }, - 'tags': { - 'is': [], - 'likes': [] - } - }; + 'tribes': { + 'is': [], + 'likes': [] + }, + 'tags': { + 'is': [], + 'likes': [] + } + }; // Construct tribes & tags - if(profile && profile.member && profile.member.length > 0) { + if (profile && profile.member && profile.member.length > 0) { for (var i = 0, len = profile.member.length; i < len; i++) { - // Sort to right category... - memberships[ (profile.member[i].tag.tribe ? 'tribes' : 'tags') ][ profile.member[i].relation ].push(profile.member[i].tag); + // Sort to the right category... + var tribeOrTag = (profile.member[i].tag.tribe ? 'tribes' : 'tags'), + relation = profile.member[i].relation; + memberships[tribeOrTag][relation].push(profile.member[i].tag); } } vm.memberships = memberships; @@ -130,11 +131,8 @@ /** * Check if there are additional accounts */ - function hasConnectedAdditionalSocialAccounts(provider) { - for (var i in vm.profile.additionalProvidersData) { - return true; - } - return false; + function hasConnectedAdditionalSocialAccounts() { + return (vm.profile.additionalProvidersData && Object.keys(vm.profile.additionalProvidersData).length); } /** @@ -149,18 +147,17 @@ * Ensure these values are published at users.profile.server.controller.js */ function socialAccountLink(providerName, providerData) { - if(providerName === 'facebook' && providerData.id) { + if (providerName === 'facebook' && providerData.id) { return 'https://www.facebook.com/app_scoped_user_id/' + providerData.id; - } - else if(providerName === 'twitter' && providerData.screen_name) { + } else if (providerName === 'twitter' && providerData.screen_name) { return 'https://twitter.com/' + providerData.screen_name; - } - else if(providerName === 'github' && providerData.login) { + } else if (providerName === 'github' && providerData.login) { return 'https://github.com/' + providerData.login; + } else { + return '#'; } - else return '#'; } } -})(); +}()); diff --git a/modules/users/client/controllers/signup.client.controller.js b/modules/users/client/controllers/signup.client.controller.js index 22e564daa2..2a6a4c2d70 100644 --- a/modules/users/client/controllers/signup.client.controller.js +++ b/modules/users/client/controllers/signup.client.controller.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -30,20 +30,20 @@ function activate() { // If user is already signed in then redirect to search page - if(Authentication.user) { + if (Authentication.user) { $state.go('search'); return; } // Fetch information about referred tribe - if($stateParams.tribe && $stateParams.tribe !== '') { + if ($stateParams.tribe && $stateParams.tribe !== '') { TribeService.get({ tribeSlug: $stateParams.tribe }) .then(function(tribe) { // Got it - if(tribe._id) { + if (tribe._id) { vm.tribe = tribe; // Show one less suggestion since we have referred tribe vm.suggestionsLimit--; @@ -53,8 +53,7 @@ getSuggestedTribes(tribe._id || null); }); - } - else { + } else { getSuggestedTribes(); } } @@ -67,22 +66,21 @@ function getSuggestedTribes(withoutTribeId) { TribesService.query({ // If we have referred tribe, load one extra suggestion in case we load referred tribe among suggestions - limit: (vm.tribe ? (parseInt(vm.suggestionsLimit + 1)) : vm.suggestionsLimit) + limit: (vm.tribe ? (parseInt(vm.suggestionsLimit + 1, 10)) : vm.suggestionsLimit) }, function(tribes) { var suggestedTribes = []; // Make sure to remove referred tribe from suggested tribes so that we won't have dublicates // We'll always show 2 or 3 of these at the frontend depending on if referred tribe is shown. - if(withoutTribeId) { + if (withoutTribeId) { angular.forEach(tribes, function(suggestedTribe) { - if(suggestedTribe._id !== withoutTribeId) { + if (suggestedTribe._id !== withoutTribeId) { this.push(suggestedTribe); } }, suggestedTribes); vm.suggestedTribes = suggestedTribes; - } - else { + } else { vm.suggestedTribes = tribes; } }); @@ -99,7 +97,7 @@ .success(function(newUser) { // If there is referred tribe, add user to that next up - if(vm.tribe && vm.tribe._id) { + if (vm.tribe && vm.tribe._id) { UserTagsService.post({ id: vm.tribe._id, relation: 'is' @@ -109,9 +107,8 @@ vm.isLoading = false; vm.step = 2; }); - } - // No tribe to join, just continue - else { + } else { + // No tribe to join, just continue updateUser(newUser); vm.isLoading = false; vm.step = 2; @@ -138,7 +135,7 @@ * Open rules modal */ function openRules($event) { - if($event) { + if ($event) { $event.preventDefault(); } $uibModal.open({ @@ -153,4 +150,4 @@ } -})(); +}()); diff --git a/modules/users/client/directives/tr-avatar.client.directive.js b/modules/users/client/directives/tr-avatar.client.directive.js index 0fc0ccc544..996630b8ad 100644 --- a/modules/users/client/directives/tr-avatar.client.directive.js +++ b/modules/users/client/directives/tr-avatar.client.directive.js @@ -1,41 +1,42 @@ -'use strict'; - -/** - * @ngdoc directive - * - * @name trustroots:trAvatar - * - * @param {object} user User object - * @param {int} size Size of the image . Supported values are 2048, 1024, 512, 256, 128, 64, 36, 32, 24 and 16. See avatar.less for details. Defaults to 256. - * @param {string} source Leave empty to use user's selected source. Values "none", "facebook", "local", "gravatar". - * @param {boolean} link Link to user's profile. Defaults to true. - * - * @description - * - * Use this directive to produce user's avatar - * - * @example - * - *

- * Basic:
- * 
- * - * Advanced: - *
- *
- */ -angular.module('users').directive('trAvatar', ['$location', - function($location) { - - // Options - var defaultSize = 256, - defaultAvatar = '/modules/users/img/avatar.png'; - - return { +(function () { + 'use strict'; + + /** + * @ngdoc directive + * + * @name trustroots:trAvatar + * + * @param {object} user User object + * @param {int} size Size of the image . Supported values are 2048, 1024, 512, 256, 128, 64, 36, 32, 24 and 16. See avatar.less for details. Defaults to 256. + * @param {string} source Leave empty to use user's selected source. Values "none", "facebook", "local", "gravatar". + * @param {boolean} link Link to user's profile. Defaults to true. + * + * @description + * + * Use this directive to produce user's avatar + * + * @example + * + *
+   * Basic:
+   * 
+ * + * Advanced: + *
+ *
+ */ + angular.module('users').directive('trAvatar', ['$location', + function($location) { + + // Options + var defaultSize = 256, + defaultAvatar = '/modules/users/img/avatar.png'; + + return { template: '
' + - '' + - '' + + ' ' + + ' ' + '
', restrict: 'A', scope: { @@ -48,80 +49,61 @@ angular.module('users').directive('trAvatar', ['$location', function determineSource() { - // Determine source for avatar - if($scope.fixedSource) { - $scope.source = $scope.fixedSource; + // Determine source for avatar + if ($scope.fixedSource) { + $scope.source = $scope.fixedSource; + } else if ($scope.user && $scope.user.avatarSource) { + $scope.source = $scope.user.avatarSource; + } else { + $scope.source = 'none'; + } + + // Avatar via FB + // @link https://developers.facebook.com/docs/graph-api/reference/user/picture/ + if ($scope.source === 'facebook') { + if ($scope.user && + $scope.user.additionalProvidersData && + $scope.user.additionalProvidersData.facebook && + $scope.user.additionalProvidersData.facebook.id) { + $scope.avatar = $location.protocol() + '://graph.facebook.com/' + $scope.user.additionalProvidersData.facebook.id + '/picture/?width=' + ($scope.size || defaultSize) + '&height=' + ($scope.size || defaultSize); + } else { + $scope.avatar = defaultAvatar; } - else if($scope.user && $scope.user.avatarSource) { - $scope.source = $scope.user.avatarSource; + // Avatar via Gravatar + // @link https://en.gravatar.com/site/implement/images/ + } else if ($scope.source === 'gravatar') { + if ($scope.user.emailHash) { + $scope.avatar = $location.protocol() + '://gravatar.com/avatar/' + $scope.user.emailHash + '?s=' + ($scope.size || defaultSize); + + // This fallback image won't work via localhost since Gravatar fallback is required to be online. + $scope.avatar += '&d=' + encodeURIComponent($location.protocol() + '://' + $location.host() + ':' + $location.port() + defaultAvatar); + } else { + $scope.avatar = defaultAvatar; } - else { - $scope.source = 'none'; + // Locally uploaded avatar + } else if ($scope.source === 'local') { + if ($scope.user.avatarUploaded) { + // Cache buster + var timestamp = new Date($scope.user.updated).getTime(); + + // 32 is the smallest and 2048 biggest file size we're generating. + var fileSize = ($scope.size < 32) ? 32 : $scope.size; + + $scope.avatar = '/modules/users/img/profile/uploads/' + $scope.user._id + '/avatar/' + fileSize + '.jpg?' + timestamp; + } else { + $scope.avatar = defaultAvatar; } + // Dummy avatar + } else { + $scope.avatar = defaultAvatar + '?none'; + } + } // determineSource() - /** - * Avatar via FB - * @link https://developers.facebook.com/docs/graph-api/reference/user/picture/ - */ - if($scope.source === 'facebook' ) { - if($scope.user && - $scope.user.additionalProvidersData && - $scope.user.additionalProvidersData.facebook && - $scope.user.additionalProvidersData.facebook.id) { - $scope.avatar = $location.protocol() + '://graph.facebook.com/' + $scope.user.additionalProvidersData.facebook.id + '/picture/?width=' + ($scope.size || defaultSize) + '&height=' + ($scope.size || defaultSize); - } - else { - $scope.avatar = defaultAvatar; - } - } - - /** - * Avatar via Gravatar - * @link https://en.gravatar.com/site/implement/images/ - */ - else if($scope.source === 'gravatar') { - if($scope.user.emailHash) { - $scope.avatar = $location.protocol() + '://gravatar.com/avatar/' + $scope.user.emailHash + '?s=' + ($scope.size || defaultSize); - - // This fallback image won't work via localhost since Gravatar fallback is required to be online. - $scope.avatar += '&d=' + encodeURIComponent( $location.protocol() + '://' + $location.host() + ':' + $location.port() + defaultAvatar ); - } - else { - $scope.avatar = defaultAvatar; - } - } - - /** - * Locally uploaded image - * @todo: implement this, duhh - */ - else if($scope.source === 'local') { - if($scope.user.avatarUploaded) { - - // Cache buster - var timestamp = new Date($scope.user.updated).getTime(); - - // 32 is the smallest and 2048 biggest file size we're generating. - var fileSize = ($scope.size < 32) ? 32 : $scope.size; - - $scope.avatar = '/modules/users/img/profile/uploads/' + $scope.user._id + '/avatar/' + fileSize + '.jpg?' + timestamp; - } - else { - $scope.avatar = defaultAvatar; - } - } - - // Dummy - else { - $scope.avatar = defaultAvatar + '?none'; - } - }// determineSource() - - $scope.$watch('user.avatarSource',function() { + $scope.$watch('user.avatarSource', function() { determineSource(); }); - $scope.$watch('user.updated',function() { + $scope.$watch('user.updated', function() { determineSource(); }); @@ -129,7 +111,7 @@ angular.module('users').directive('trAvatar', ['$location', link: function (scope, element, attr, ctrl) { // Make sure source won't change dynamicly when user changes - if(attr.source) { + if (attr.source) { scope.source = attr.source; scope.fixedSource = attr.source; } @@ -138,9 +120,11 @@ angular.module('users').directive('trAvatar', ['$location', scope.size = attr.size || defaultSize; // By default show the link - scope.link = (attr.link !== 'false') ? true : false; + scope.link = attr.link !== 'false'; } - }; - } -]); + }; + } + ]); + +}()); diff --git a/modules/users/client/directives/tr-date-select.client.directive.js b/modules/users/client/directives/tr-date-select.client.directive.js index 04803a1f28..1d731ef424 100644 --- a/modules/users/client/directives/tr-date-select.client.directive.js +++ b/modules/users/client/directives/tr-date-select.client.directive.js @@ -1,142 +1,149 @@ -'use strict'; - -/** - * @ngdoc directive - * - * @name trustroots:trDateSelect - * - * Fork of https://github.com/sambs/angular-sb-date-select with additional features: - * - allows choosing empty values - * - allows passing our own templates - * - * Relies on MomentJS - * @link http://momentjs.com/ - * - */ -angular.module('users') - - .run(['$templateCache', function ($templateCache) { - - var template = [ - '
', - '', - '', - '', - '
' - ]; - - $templateCache.put('tr-date-select.html', template.join('')); - - }]) - - .directive('trDateSelect', [function () { - - return { - restrict: 'A', - replace: true, - templateUrl: function ($element, $attrs) { - return $attrs.templateUrl || 'tr-date-select.html'; - }, - require: 'ngModel', - scope: { - selectClass: '@trSelectClass' - }, - - link: function(scope, elem, attrs, ngModel) { - scope.val = {}; - - var min = scope.min = moment(attrs.min || '1900-01-01'); - var max = scope.max = moment(attrs.max); // Defaults to now - - scope.years = []; - - for (var i=max.year(); i>=min.year(); i--) { - scope.years.push(i); - } - - scope.$watch('val.year', function () { - updateMonthOptions(); - }); - - scope.$watchCollection('[val.month, val.year]', function () { - updateDateOptions(); - }); +(function () { + 'use strict'; + + /** + * @ngdoc directive + * + * @name trustroots:trDateSelect + * + * Fork of https://github.com/sambs/angular-sb-date-select with additional features: + * - allows choosing empty values + * - allows passing our own templates + * + * Relies on MomentJS + * @link http://momentjs.com/ + * + */ + angular.module('users') + + .run(['$templateCache', function ($templateCache) { + + var template = [ + '
', + ' ', + ' ', + ' ', + '
' + ]; + + $templateCache.put('tr-date-select.html', template.join('')); + + }]) + + .directive('trDateSelect', [function () { + + return { + restrict: 'A', + replace: true, + templateUrl: function ($element, $attrs) { + return $attrs.templateUrl || 'tr-date-select.html'; + }, + require: 'ngModel', + scope: { + selectClass: '@trSelectClass' + }, + + link: function(scope, elem, attrs, ngModel) { + scope.val = {}; + + var min = scope.min = moment(attrs.min || '1900-01-01'); + var max = scope.max = moment(attrs.max); // Defaults to now + + scope.years = []; + + for (var i = max.year(); i >= min.year(); i--) { + scope.years.push(i); + } - scope.$watchCollection('[val.date, val.month, val.year]', function (newDate, oldDate) { - if (scope.val.year && scope.val.month && scope.val.date) { - if(!angular.equals(newDate, oldDate)) { - var m = moment([scope.val.year, scope.val.month-1, scope.val.date]); - ngModel.$setViewValue(m.format('YYYY-MM-DD')); + scope.$watch('val.year', function () { + updateMonthOptions(); + }); + + scope.$watchCollection('[val.month, val.year]', function () { + updateDateOptions(); + }); + + scope.$watchCollection('[val.date, val.month, val.year]', function (newDate, oldDate) { + if (scope.val.year && scope.val.month && scope.val.date) { + if (!angular.equals(newDate, oldDate)) { + var m = moment([scope.val.year, scope.val.month - 1, scope.val.date]); + ngModel.$setViewValue(m.format('YYYY-MM-DD')); + } + } else { + ngModel.$setViewValue(); } - } - else { - ngModel.$setViewValue(); - } - }); + }); - function updateMonthOptions () { - // Values begin at 1 to permit easier boolean testing - scope.months = []; + function updateMonthOptions () { + // Values begin at 1 to permit easier boolean testing + scope.months = []; - var minMonth = scope.val.year && min.isSame([scope.val.year], 'year') ? min.month() : 0; - var maxMonth = scope.val.year && max.isSame([scope.val.year], 'year') ? max.month() : 11; + var minMonth = scope.val.year && min.isSame([scope.val.year], 'year') ? min.month() : 0; + var maxMonth = scope.val.year && max.isSame([scope.val.year], 'year') ? max.month() : 11; - var monthNames = moment.months(); + var monthNames = moment.months(); - for (var j=minMonth; j<=maxMonth; j++) { - scope.months.push({ - name: monthNames[j], - value: j+1 - }); - } + for (var j = minMonth; j <= maxMonth; j++) { + scope.months.push({ + name: monthNames[j], + value: j + 1 + }); + } - if (scope.val.month-1 > maxMonth || scope.val.month-1 < minMonth) delete scope.val.month; - } + if (scope.val.month - 1 > maxMonth || scope.val.month - 1 < minMonth) { + delete scope.val.month; + } + } - function updateDateOptions (year, month) { - var minDate, maxDate; + function updateDateOptions (year, month) { + var minDate, + maxDate; - if (scope.val.year && scope.val.month && min.isSame([scope.val.year, scope.val.month-1], 'month')) { - minDate = min.date(); - } else { - minDate = 1; - } + if (scope.val.year && scope.val.month && min.isSame([scope.val.year, scope.val.month - 1], 'month')) { + minDate = min.date(); + } else { + minDate = 1; + } - if (scope.val.year && scope.val.month && max.isSame([scope.val.year, scope.val.month-1], 'month')) { - maxDate = max.date(); - } else if (scope.val.year && scope.val.month) { - maxDate = moment([scope.val.year, scope.val.month-1]).daysInMonth(); - } else { - maxDate = 31; - } + if (scope.val.year && scope.val.month && max.isSame([scope.val.year, scope.val.month - 1], 'month')) { + maxDate = max.date(); + } else if (scope.val.year && scope.val.month) { + maxDate = moment([scope.val.year, scope.val.month - 1]).daysInMonth(); + } else { + maxDate = 31; + } - scope.dates = []; + scope.dates = []; - for (var i=minDate; i<=maxDate; i++) { - scope.dates.push(i); + for (var i = minDate; i <= maxDate; i++) { + scope.dates.push(i); + } + if (scope.val.date < minDate || scope.val.date > maxDate) { + delete scope.val.date; + } } - if (scope.val.date < minDate || scope.val.date > maxDate) delete scope.val.date; - } - // ngModel -> view - ngModel.$render = function() { - if (!ngModel.$viewValue) return; + // ngModel -> view + ngModel.$render = function() { + if (!ngModel.$viewValue) return; - var m = moment(new Date(ngModel.$viewValue)); + var m = moment(new Date(ngModel.$viewValue)); - // Always use a dot in ng-model attrs... - scope.val = { - year: m.year(), - month: m.month()+1, - date: m.date() + // Always use a dot in ng-model attrs... + scope.val = { + year: m.year(), + month: m.month() + 1, + date: m.date() + }; }; - }; - } - }; - }]); + } + }; + }]); + +}()); diff --git a/modules/users/client/directives/tr-monkeybox.client.directive.js b/modules/users/client/directives/tr-monkeybox.client.directive.js index 694615a8db..f28842e6fa 100644 --- a/modules/users/client/directives/tr-monkeybox.client.directive.js +++ b/modules/users/client/directives/tr-monkeybox.client.directive.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; /** @@ -24,4 +24,4 @@ }] }; } -})(); +}()); diff --git a/modules/users/client/services/authentication.client.service.js b/modules/users/client/services/authentication.client.service.js index 08601d11dc..984c132d48 100644 --- a/modules/users/client/services/authentication.client.service.js +++ b/modules/users/client/services/authentication.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; // Authentication service for user variables @@ -8,10 +8,10 @@ /* @ngInject */ function Authentication($window) { - var auth = { - user: $window.user - }; - return auth; + var auth = { + user: $window.user + }; + return auth; } -})(); +}()); diff --git a/modules/users/client/services/users-mini.client.service.js b/modules/users/client/services/users-mini.client.service.js index 3dea804df0..6fc034118f 100644 --- a/modules/users/client/services/users-mini.client.service.js +++ b/modules/users/client/services/users-mini.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; // Used to receive basic info to show avatars etc... @@ -9,7 +9,7 @@ /* @ngInject */ function UsersMiniFactory($resource) { return $resource('/api/users/mini/:userId', { - userId:'@id' + userId: '@id' }, { get: { method: 'GET' @@ -17,4 +17,4 @@ }); } -})(); +}()); diff --git a/modules/users/client/services/users-profile.client.service.js b/modules/users/client/services/users-profile.client.service.js index 49171cf9f1..49e027808c 100644 --- a/modules/users/client/services/users-profile.client.service.js +++ b/modules/users/client/services/users-profile.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -16,4 +16,4 @@ }); } -})(); +}()); diff --git a/modules/users/client/services/users-tags.client.service.js b/modules/users/client/services/users-tags.client.service.js index 98117c7f25..2b21845eaf 100644 --- a/modules/users/client/services/users-tags.client.service.js +++ b/modules/users/client/services/users-tags.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; angular @@ -20,4 +20,4 @@ }); } -})(); +}()); diff --git a/modules/users/client/services/users.client.service.js b/modules/users/client/services/users.client.service.js index 9d7b644004..4f530b3a74 100644 --- a/modules/users/client/services/users.client.service.js +++ b/modules/users/client/services/users.client.service.js @@ -1,4 +1,4 @@ -(function() { +(function () { 'use strict'; // Users service used for communicating with the users REST endpoint @@ -18,4 +18,4 @@ }); } -})(); +}()); diff --git a/modules/users/server/config/strategies/facebook.js b/modules/users/server/config/strategies/facebook.js index b8aea345c3..2c0e90c2c7 100644 --- a/modules/users/server/config/strategies/facebook.js +++ b/modules/users/server/config/strategies/facebook.js @@ -10,32 +10,31 @@ var passport = require('passport'), module.exports = function(config) { // Use facebook strategy passport.use(new FacebookStrategy({ - clientID: config.facebook.clientID, - clientSecret: config.facebook.clientSecret, - callbackURL: config.facebook.callbackURL, - profileFields: ['id', 'name', 'displayName', 'emails', 'photos'], - passReqToCallback: true, - enableProof: false - }, - function(req, accessToken, refreshToken, profile, done) { - // Set the provider data and include tokens - var providerData = profile._json; - providerData.accessToken = accessToken; - providerData.refreshToken = refreshToken; + clientID: config.facebook.clientID, + clientSecret: config.facebook.clientSecret, + callbackURL: config.facebook.callbackURL, + profileFields: ['id', 'name', 'displayName', 'emails', 'photos'], + passReqToCallback: true, + enableProof: false + }, + function(req, accessToken, refreshToken, profile, done) { + // Set the provider data and include tokens + var providerData = profile._json; + providerData.accessToken = accessToken; + providerData.refreshToken = refreshToken; - // Create the user OAuth profile - var providerUserProfile = { - firstName: profile.name.givenName, - lastName: profile.name.familyName, - displayName: profile.displayName, - email: profile.emails[0].value, - provider: 'facebook', - providerIdentifierField: 'id', - providerData: providerData - }; + // Create the user OAuth profile + var providerUserProfile = { + firstName: profile.name.givenName, + lastName: profile.name.familyName, + displayName: profile.displayName, + email: profile.emails[0].value, + provider: 'facebook', + providerIdentifierField: 'id', + providerData: providerData + }; - // Save the user OAuth profile - users.saveOAuthUserProfile(req, providerUserProfile, done); - } - )); + // Save the user OAuth profile + users.saveOAuthUserProfile(req, providerUserProfile, done); + })); }; diff --git a/modules/users/server/config/strategies/github.js b/modules/users/server/config/strategies/github.js index 4e3d6d8136..0b078ea3cd 100644 --- a/modules/users/server/config/strategies/github.js +++ b/modules/users/server/config/strategies/github.js @@ -10,29 +10,28 @@ var passport = require('passport'), module.exports = function(config) { // Use github strategy passport.use(new GithubStrategy({ - clientID: config.github.clientID, - clientSecret: config.github.clientSecret, - callbackURL: config.github.callbackURL, - passReqToCallback: true - }, - function(req, accessToken, refreshToken, profile, done) { - // Set the provider data and include tokens - var providerData = profile._json; - providerData.accessToken = accessToken; - providerData.refreshToken = refreshToken; + clientID: config.github.clientID, + clientSecret: config.github.clientSecret, + callbackURL: config.github.callbackURL, + passReqToCallback: true + }, + function(req, accessToken, refreshToken, profile, done) { + // Set the provider data and include tokens + var providerData = profile._json; + providerData.accessToken = accessToken; + providerData.refreshToken = refreshToken; - // Create the user OAuth profile - var providerUserProfile = { - displayName: profile.displayName || profile.username, - email: profile.emails[0].value, - username: profile.username, - provider: 'github', - providerIdentifierField: 'id', - providerData: providerData - }; + // Create the user OAuth profile + var providerUserProfile = { + displayName: profile.displayName || profile.username, + email: profile.emails[0].value, + username: profile.username, + provider: 'github', + providerIdentifierField: 'id', + providerData: providerData + }; - // Save the user OAuth profile - users.saveOAuthUserProfile(req, providerUserProfile, done); - } - )); + // Save the user OAuth profile + users.saveOAuthUserProfile(req, providerUserProfile, done); + })); }; diff --git a/modules/users/server/config/strategies/local.js b/modules/users/server/config/strategies/local.js index 17abab054f..771afc715c 100644 --- a/modules/users/server/config/strategies/local.js +++ b/modules/users/server/config/strategies/local.js @@ -10,27 +10,26 @@ var passport = require('passport'), module.exports = function() { // Use local strategy passport.use(new LocalStrategy({ - usernameField: 'username', - passwordField: 'password' - }, - function(username, password, done) { - User.findOne({ - $or: [ - { username: username.toLowerCase() }, - { email: username.toLowerCase() } - ] - }, function(err, user) { - if (err) { - return done(err); - } - if (!user || !user.authenticate(password)) { - return done(null, false, { - message: 'Unknown user or invalid password' - }); - } + usernameField: 'username', + passwordField: 'password' + }, + function(username, password, done) { + User.findOne({ + $or: [ + { username: username.toLowerCase() }, + { email: username.toLowerCase() } + ] + }, function(err, user) { + if (err) { + return done(err); + } + if (!user || !user.authenticate(password)) { + return done(null, false, { + message: 'Unknown user or invalid password' + }); + } - return done(null, user); - }); - } - )); + return done(null, user); + }); + })); }; diff --git a/modules/users/server/config/strategies/twitter.js b/modules/users/server/config/strategies/twitter.js index 1f903780d9..88b51df286 100644 --- a/modules/users/server/config/strategies/twitter.js +++ b/modules/users/server/config/strategies/twitter.js @@ -10,28 +10,27 @@ var passport = require('passport'), module.exports = function(config) { // Use twitter strategy passport.use(new TwitterStrategy({ - consumerKey: config.twitter.clientID, - consumerSecret: config.twitter.clientSecret, - callbackURL: config.twitter.callbackURL, - passReqToCallback: true - }, - function(req, token, tokenSecret, profile, done) { - // Set the provider data and include tokens - var providerData = profile._json; - providerData.token = token; - providerData.tokenSecret = tokenSecret; + consumerKey: config.twitter.clientID, + consumerSecret: config.twitter.clientSecret, + callbackURL: config.twitter.callbackURL, + passReqToCallback: true + }, + function(req, token, tokenSecret, profile, done) { + // Set the provider data and include tokens + var providerData = profile._json; + providerData.token = token; + providerData.tokenSecret = tokenSecret; - // Create the user OAuth profile - var providerUserProfile = { - displayName: profile.displayName, - username: profile.username, - provider: 'twitter', - providerIdentifierField: 'id_str', - providerData: providerData - }; + // Create the user OAuth profile + var providerUserProfile = { + displayName: profile.displayName, + username: profile.username, + provider: 'twitter', + providerIdentifierField: 'id_str', + providerData: providerData + }; - // Save the user OAuth profile - users.saveOAuthUserProfile(req, providerUserProfile, done); - } - )); + // Save the user OAuth profile + users.saveOAuthUserProfile(req, providerUserProfile, done); + })); }; diff --git a/modules/users/server/controllers/users/users.authentication.server.controller.js b/modules/users/server/controllers/users/users.authentication.server.controller.js index aa007cb40d..27f414fd95 100644 --- a/modules/users/server/controllers/users/users.authentication.server.controller.js +++ b/modules/users/server/controllers/users/users.authentication.server.controller.js @@ -35,7 +35,7 @@ exports.signup = function(req, res) { // Check if we have the required data before hitting more strict validations at Mongo function(done) { - if(!req.body.firstName || !req.body.lastName || !req.body.username || !req.body.password || !req.body.email) { + if (!req.body.firstName || !req.body.lastName || !req.body.username || !req.body.password || !req.body.email) { return res.status(400).send({ message: 'Please provide required fields.' }); @@ -102,20 +102,20 @@ exports.signup = function(req, res) { urlConfirm = url + '/confirm-email/' + user.emailToken + '?signup'; var renderVars = emailsHandler.addEmailBaseTemplateParams( - req.headers.host, - { - name: user.displayName, - email: user.email, - ourMail: config.mailer.from, - urlConfirmPlainText: urlConfirm, - urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { - source: 'transactional-email', - medium: 'email', - campaign: 'confirm-email' - }) - }, - 'confirm-email' - ); + req.headers.host, + { + name: user.displayName, + email: user.email, + ourMail: config.mailer.from, + urlConfirmPlainText: urlConfirm, + urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { + source: 'transactional-email', + medium: 'email', + campaign: 'confirm-email' + }) + }, + 'confirm-email' + ); res.render(path.resolve('./modules/core/server/views/email-templates/signup'), renderVars, function(err, emailHTML) { done(err, emailHTML, user, renderVars, url); @@ -261,14 +261,14 @@ exports.saveOAuthUserProfile = function(req, providerUserProfile, done) { exports.removeOAuthProvider = function(req, res, next) { // Return error if no user - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); } // Return error if no provider or wrong provider - if(!req.params.provider || !_.includes(['github', 'facebook', 'twitter'], req.params.provider)) { + if (!req.params.provider || !_.includes(['github', 'facebook', 'twitter'], req.params.provider)) { return res.status(400).send({ message: 'No provider defined.' }); @@ -277,9 +277,9 @@ exports.removeOAuthProvider = function(req, res, next) { var user = req.user; var provider = req.params.provider; - if(user && provider) { + if (user && provider) { // Delete the additional provider - if(user.additionalProvidersData[provider]) { + if (user.additionalProvidersData[provider]) { delete user.additionalProvidersData[provider]; // Then tell mongoose that we've updated the additionalProvidersData field @@ -287,7 +287,7 @@ exports.removeOAuthProvider = function(req, res, next) { } user.save(function(err) { - if(err) { + if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) }); @@ -312,7 +312,7 @@ exports.validateEmailToken = function(req, res) { User.findOne({ emailToken: req.params.token }, function(err, user) { - if(!user) { + if (!user) { return res.redirect('/confirm-email-invalid'); } res.redirect('/confirm-email/' + req.params.token); @@ -366,7 +366,7 @@ exports.confirmEmail = function(req, res, next) { // Replace old email with new one email: user.emailTemporary, // @todo: this should be done at user.server.model.js - emailHash: crypto.createHash('md5').update( user.emailTemporary.trim().toLowerCase() ).digest('hex') + emailHash: crypto.createHash('md5').update(user.emailTemporary.trim().toLowerCase()).digest('hex') } }, { diff --git a/modules/users/server/controllers/users/users.password.server.controller.js b/modules/users/server/controllers/users/users.password.server.controller.js index 3a2833ff0a..90e4c36efe 100644 --- a/modules/users/server/controllers/users/users.password.server.controller.js +++ b/modules/users/server/controllers/users/users.password.server.controller.js @@ -77,20 +77,20 @@ exports.forgot = function(req, res, next) { urlConfirm = url + '/api/auth/reset/' + token; var renderVars = emailsHandler.addEmailBaseTemplateParams( - req.headers.host, - { - name: user.displayName, - email: user.email, - ourMail: config.mailer.from, - urlConfirmPlainText: urlConfirm, - urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { - source: 'transactional-email', - medium: 'email', - campaign: 'reset-password' - }) - }, - 'reset-password' - ); + req.headers.host, + { + name: user.displayName, + email: user.email, + ourMail: config.mailer.from, + urlConfirmPlainText: urlConfirm, + urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { + source: 'transactional-email', + medium: 'email', + campaign: 'reset-password' + }) + }, + 'reset-password' + ); res.render(path.resolve('./modules/core/server/views/email-templates/reset-password'), renderVars, function(err, emailHTML) { done(err, emailHTML, user, renderVars); @@ -155,7 +155,7 @@ exports.validateResetToken = function(req, res) { var passwordResetUrl = '/password/reset/' + req.params.token; // Re-apply possible UTM variables to the redirect URL - if(req.query && req.query.utm_source && req.query.utm_medium && req.query.utm_campaign) { + if (req.query && req.query.utm_source && req.query.utm_medium && req.query.utm_campaign) { passwordResetUrl = analyticsHandler.appendUTMParams(passwordResetUrl, { source: req.query.utm_source, medium: req.query.utm_medium, @@ -221,12 +221,12 @@ exports.reset = function(req, res, next) { function(user, done) { var renderVars = emailsHandler.addEmailBaseTemplateParams( - req.headers.host, - { - name: user.displayName - }, - 'reset-password-confirm' - ); + req.headers.host, + { + name: user.displayName + }, + 'reset-password-confirm' + ); res.render(path.resolve('./modules/core/server/views/email-templates/reset-password-confirm'), renderVars, function(err, emailHTML) { done(err, emailHTML, user, renderVars); @@ -284,7 +284,7 @@ exports.changePassword = function(req, res) { function(done) { // Return error if no user - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); @@ -350,12 +350,12 @@ exports.changePassword = function(req, res) { function(user, done) { var renderVars = emailsHandler.addEmailBaseTemplateParams( - req.headers.host, - { - name: user.displayName - }, - 'reset-password-confirm' - ); + req.headers.host, + { + name: user.displayName + }, + 'reset-password-confirm' + ); res.render(path.resolve('./modules/core/server/views/email-templates/reset-password-confirm'), renderVars, function(err, emailHTML) { done(err, emailHTML, user, renderVars); diff --git a/modules/users/server/controllers/users/users.profile.server.controller.js b/modules/users/server/controllers/users/users.profile.server.controller.js index e036d2046e..dfecefe727 100644 --- a/modules/users/server/controllers/users/users.profile.server.controller.js +++ b/modules/users/server/controllers/users/users.profile.server.controller.js @@ -38,50 +38,50 @@ if (process.env.NODE_ENV === 'test') { // Load either ImageMagick or GraphicsMagick as an image processor // Defaults to GraphicsMagick // @link https://github.com/aheckmann/gm#use-imagemagick-instead-of-gm -var imageProcessor = (config.imageProcessor === 'imagemagic') ? require('gm').subClass({imageMagick: true}) : require('gm'); +var imageProcessor = (config.imageProcessor === 'imagemagic') ? require('gm').subClass({ imageMagick: true }) : require('gm'); // Fields to send publicly about any user profile // to make sure we're not sending unsecure content (eg. passwords) // Pick here fields to send exports.userProfileFields = [ - 'id', - 'displayName', - 'username', - 'displayUsername', - 'gender', - 'tagline', - 'description', - 'locationFrom', - 'locationLiving', - 'languages', - 'birthdate', - 'seen', - 'created', - 'updated', - 'avatarSource', - 'avatarUploaded', - 'member', - 'extSitesBW', // BeWelcome username - 'extSitesCS', // CouchSurfing username - 'extSitesWS', // WarmShowers username - 'emailHash', // MD5 hashed email to use with Gravatars - 'additionalProvidersData.facebook.id', // For FB avatars and profile links - 'additionalProvidersData.twitter.screen_name', // For Twitter profile links - 'additionalProvidersData.github.login' // For GitHub profile links - ].join(' '); + 'id', + 'displayName', + 'username', + 'displayUsername', + 'gender', + 'tagline', + 'description', + 'locationFrom', + 'locationLiving', + 'languages', + 'birthdate', + 'seen', + 'created', + 'updated', + 'avatarSource', + 'avatarUploaded', + 'member', + 'extSitesBW', // BeWelcome username + 'extSitesCS', // CouchSurfing username + 'extSitesWS', // WarmShowers username + 'emailHash', // MD5 hashed email to use with Gravatars + 'additionalProvidersData.facebook.id', // For FB avatars and profile links + 'additionalProvidersData.twitter.screen_name', // For Twitter profile links + 'additionalProvidersData.github.login' // For GitHub profile links +].join(' '); // Restricted set of profile fields when only really "miniprofile" is needed exports.userMiniProfileFields = [ - 'id', - 'updated', // Used as local-avatar cache buster - 'displayName', - 'username', - 'displayUsername', - 'avatarSource', - 'avatarUploaded', - 'emailHash', - 'additionalProvidersData.facebook.id' // For FB avatars - ].join(' '); + 'id', + 'updated', // Used as local-avatar cache buster + 'displayName', + 'username', + 'displayUsername', + 'avatarSource', + 'avatarUploaded', + 'emailHash', + 'additionalProvidersData.facebook.id' // For FB avatars +].join(' '); // Mini + a few fields we'll need at listings exports.userListingProfileFields = exports.userMiniProfileFields + ' birthdate gender tagline'; @@ -97,12 +97,12 @@ exports.avatarUploadField = function (req, res, next) { // random data as a hex-string (e.g. a087fda2cf19f341ddaeacacab285acc) // without file-extension. var upload = multer({ - dest: config.uploadTmpDir || os.tmpdir(), - limits: { - fileSize: config.maxUploadSize // max file size in bytes - }, - fileFilter: multerConfig.uploadFileFilter - }).single('avatar'); + dest: config.uploadTmpDir || os.tmpdir(), + limits: { + fileSize: config.maxUploadSize // max file size in bytes + }, + fileFilter: multerConfig.uploadFileFilter + }).single('avatar'); upload(req, res, function (err) { @@ -111,26 +111,25 @@ exports.avatarUploadField = function (req, res, next) { // @link https://github.com/expressjs/multer/blob/master/lib/make-error.js if (err) { - var errorMessage, errorStatus; + var errorMessage, + errorStatus; - // Unsupported media type -error - // This error is generated from ./config/lib/multer.js - if(err.code && err.code === 'UNSUPPORTED_MEDIA_TYPE') { + if (err.code && err.code === 'UNSUPPORTED_MEDIA_TYPE') { + // Unsupported media type -error + // This error is generated from ./config/lib/multer.js errorMessage = errorHandler.getErrorMessageByKey('unsupported-media-type'); errorStatus = 415; - } - // Too big file - // 413: "Request Entity Too Large" - else if(err.code && err.code === 'LIMIT_FILE_SIZE') { - errorMessage = 'Image too big. Please maximum ' + (config.maxUploadSize / (1024*1024)).toFixed(2) + ' Mb files.'; + } else if (err.code && err.code === 'LIMIT_FILE_SIZE') { + // Too big file + // 413: "Request Entity Too Large" + errorMessage = 'Image too big. Please maximum ' + (config.maxUploadSize / (1024 * 1024)).toFixed(2) + ' Mb files.'; errorStatus = 413; - } - // Field doesn't exist -error - else if(err.code && err.code === 'LIMIT_UNEXPECTED_FILE') { + } else if (err.code && err.code === 'LIMIT_UNEXPECTED_FILE') { + // Field doesn't exist -error errorMessage = 'Missing `avatar` field from the API call.'; errorStatus = 400; - } - else { + } else { + // Any other error errorMessage = errorHandler.getErrorMessageByKey('default'); errorStatus = 400; } @@ -151,7 +150,7 @@ exports.avatarUploadField = function (req, res, next) { */ exports.avatarUpload = function (req, res) { - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); @@ -159,7 +158,7 @@ exports.avatarUpload = function (req, res) { // `req.file` is placed there by Multer middleware. // See `users.server.routes.js` for more details. - if(!req.file || !req.file.path) { + if (!req.file || !req.file.path) { return res.status(422).send({ message: errorHandler.getErrorMessageByKey('unprocessable-entity') }); @@ -204,55 +203,51 @@ exports.avatarUpload = function (req, res) { // Create a queue worker // @link https://github.com/caolan/async#queueworker-concurrency var q = async.queue(function (thumbSize, callback) { - /** - * Create thumbnail size - * Images are resized following quality/size -optimization tips from this article: - * @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/ - */ - imageProcessor(req.file.path) - //.in('jpeg:fancy-upsampling=false') // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#resampling - .autoOrient() - .noProfile() // No color profile - .colorspace('rgb') // Not sRGB @link https://ehc.ac/p/graphicsmagick/bugs/331/?limit=25 - .interlace('None') // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#progressive-rendering - .filter('Triangle') // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#resampling - .resize(thumbSize, thumbSize+'^') // ^ = Dimensions are treated as minimum rather than maximum values. @link http://www.graphicsmagick.org/Magick++/Geometry.html - .gravity('Center') - .extent(thumbSize, thumbSize) - .unsharp(0.25, 0.25, 8, 0.065) // radius [, sigma, amount, threshold] - @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#sharpening - .quality(82) // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#quality-and-compression - .write(uploadDir + '/' + thumbSize + '.jpg', function (err) { - - // Something's wrong with the file, stop here. - if(err) { - if (process.env.NODE_ENV === 'development') { - console.error('Error while generating thumbnail ' + thumbSize); - console.error(err); - } - - // This stops us sending res multiple times since tasks are running paraller - if(!asyncQueueErrorHappened) { - asyncQueueErrorHappened = true; - - // Stop the queue - q.pause(); - - // Attempt to delete tmp file - fs.unlink(req.file.path, function (err) { - // @link http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity - return res.status(422).send({ - message: 'Failed to process image, please try again.' - }); - }); - } - else { - callback(err, thumbSize); - } + // Create thumbnail size + // Images are resized following quality/size -optimization tips from this article: + // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/ + imageProcessor(req.file.path) + // .in('jpeg:fancy-upsampling=false') // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#resampling + .autoOrient() + .noProfile() // No color profile + .colorspace('rgb') // Not sRGB @link https://ehc.ac/p/graphicsmagick/bugs/331/?limit=25 + .interlace('None') // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#progressive-rendering + .filter('Triangle') // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#resampling + .resize(thumbSize, thumbSize + '^') // ^ = Dimensions are treated as minimum rather than maximum values. @link http://www.graphicsmagick.org/Magick++/Geometry.html + .gravity('Center') + .extent(thumbSize, thumbSize) + .unsharp(0.25, 0.25, 8, 0.065) // radius [, sigma, amount, threshold] - @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#sharpening + .quality(82) // @link https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/#quality-and-compression + .write(uploadDir + '/' + thumbSize + '.jpg', function (err) { + + // Something's wrong with the file, stop here. + if (err) { + if (process.env.NODE_ENV === 'development') { + console.error('Error while generating thumbnail ' + thumbSize); + console.error(err); } - else { + + // This stops us sending res multiple times since tasks are running paraller + if (!asyncQueueErrorHappened) { + asyncQueueErrorHappened = true; + + // Stop the queue + q.pause(); + + // Attempt to delete tmp file + fs.unlink(req.file.path, function (err) { + // @link http://www.restpatterns.org/HTTP_Status_Codes/422_-_Unprocessable_Entity + return res.status(422).send({ + message: 'Failed to process image, please try again.' + }); + }); + } else { callback(err, thumbSize); } - }); + } else { + callback(err, thumbSize); + } + }); }, 3); // How many thumbnails to process simultaneously? // Start processing these sizes @@ -272,30 +267,25 @@ exports.avatarUpload = function (req, res) { // Catch errors ], function(err) { - if(err) { + if (err) { return res.status(400).send({ message: errorHandler.getErrorMessage(err) || 'Failed to process image, please try again.' }); - } - else { + } else { // All Done! return res.send({ message: 'Avatar image uploaded.' }); } }); - - }; - - /** * Update */ exports.update = function(req, res) { - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); @@ -303,215 +293,206 @@ exports.update = function(req, res) { async.waterfall([ - // If user is changing email, check if it's available - function(done) { - - // Check if email changed and proceed with extra checks if so - if(req.body.email && req.body.email !== req.user.email) { - User.findOne({ - $or: [ - { emailTemporary: req.body.email.toLowerCase() }, - { email: req.body.email.toLowerCase() } - ] - }, 'emailTemporary email', function(err, emailUser) { - // Not free - if(emailUser) { - // If the user we found with this email is currently authenticated user, let user pass to resend confirmation email - if(emailUser._id.equals(req.user._id)) { + // If user is changing email, check if it's available + function(done) { + + // Check if email changed and proceed with extra checks if so + if (req.body.email && req.body.email !== req.user.email) { + User.findOne({ + $or: [ + { emailTemporary: req.body.email.toLowerCase() }, + { email: req.body.email.toLowerCase() } + ] + }, 'emailTemporary email', function(err, emailUser) { + // Not free + if (emailUser) { + // If the user we found with this email is currently authenticated user, let user pass to resend confirmation email + if (emailUser._id.equals(req.user._id)) { + done(null); + } else { + // Otherwise it was someone else's email. Block the way. + return res.status(403).send({ + message: 'This email is already in use. Please use another one.' + }); + } + } else { + // Free, proceed generating the token done(null); } - // Otherwise it was someone else's email. Block the way. - else { - return res.status(403).send({ - message: 'This email is already in use. Please use another one.' - }); - } - } - // Free, proceed generating the token - else { - done(null); - } - }); - } - // Email didn't change, just continue - else { - done(null); - } - }, - - // Check if we should generate new email token - function(done) { - - // Generate only if email changed - if(req.body.email && req.body.email !== req.user.email) { - crypto.randomBytes(20, function(err, buffer) { - var token = buffer.toString('hex'); - done(err, token, req.body.email); - }); - } - // Email didn't change, just continue - else { - done(null, false, false); - } - }, - - // Update user - function(token, email, done) { - - // For security measurement do not use _id from the req.body object - delete req.body._id; - - // For security measurement remove these from the req.body object - // Users aren't allowed to modify these directly - delete req.body.member; - delete req.body.public; - delete req.body.created; - delete req.body.seen; - delete req.body.roles; - delete req.body.email; - delete req.body.emailHash; - delete req.body.emailToken; - delete req.body.emailTemporary; - delete req.body.provider; - delete req.body.username; - delete req.body.displayUsername; - delete req.body.salt; - delete req.body.password; - delete req.body.resetPasswordToken; - delete req.body.resetPasswordExpires; - delete req.body.additionalProvidersData; - - // Merge existing user - var user = req.user; - user = _.extend(user, req.body); - user.updated = Date.now(); - - // This is set only if user edited email - if(token && email) { - user.emailToken = token; - user.emailTemporary = email; - } - - // Sanitize string contents - // `description` field is allowed to contain some html - ['description', - 'tagline', - 'firstName', - 'lastName', - 'locationLiving', - 'locationFrom', - 'extSitesBW', - 'extSitesCS', - 'extSitesWS' - ].forEach(function(key) { - if(user[key] && key === 'description') { - // Allow some HTML - user[key] = textProcessor.html(user[key]); - } - // Clean out all HTML - else if(user[key]) { - user[key] = textProcessor.plainText(user[key], true); + }); + } else { + // Email didn't change, just continue + done(null); } - }); + }, - // Generate display name - user.displayName = user.firstName + ' ' + user.lastName; + // Check if we should generate new email token + function(done) { - user.save(function(err) { - if (!err) { - req.login(user, function(err) { - if (err) { - done(err); - } else { - done(null, token, user); - } + // Generate only if email changed + if (req.body.email && req.body.email !== req.user.email) { + crypto.randomBytes(20, function(err, buffer) { + var token = buffer.toString('hex'); + done(err, token, req.body.email); }); + } else { + // Email didn't change, just continue + done(null, false, false); } - else { - done(err, token, user); + }, + + // Update user + function(token, email, done) { + + // For security measurement do not use _id from the req.body object + delete req.body._id; + + // For security measurement remove these from the req.body object + // Users aren't allowed to modify these directly + delete req.body.member; + delete req.body.public; + delete req.body.created; + delete req.body.seen; + delete req.body.roles; + delete req.body.email; + delete req.body.emailHash; + delete req.body.emailToken; + delete req.body.emailTemporary; + delete req.body.provider; + delete req.body.username; + delete req.body.displayUsername; + delete req.body.salt; + delete req.body.password; + delete req.body.resetPasswordToken; + delete req.body.resetPasswordExpires; + delete req.body.additionalProvidersData; + + // Merge existing user + var user = req.user; + user = _.extend(user, req.body); + user.updated = Date.now(); + + // This is set only if user edited email + if (token && email) { + user.emailToken = token; + user.emailTemporary = email; } - }); - }, + // Sanitize string contents + // `description` field is allowed to contain some html + ['description', + 'tagline', + 'firstName', + 'lastName', + 'locationLiving', + 'locationFrom', + 'extSitesBW', + 'extSitesCS', + 'extSitesWS' + ].forEach(function(key) { + if (user[key] && key === 'description') { + // Allow some HTML + user[key] = textProcessor.html(user[key]); + } else if (user[key]) { + // Clean out all HTML + user[key] = textProcessor.plainText(user[key], true); + } + }); - // Prepare TEXT mail - function(token, user, done) { + // Generate display name + user.displayName = user.firstName + ' ' + user.lastName; - // If no token, user didn't change email = pass this phase - if(token) { + user.save(function(err) { + if (!err) { + req.login(user, function(err) { + if (err) { + done(err); + } else { + done(null, token, user); + } + }); + } else { + done(err, token, user); + } + }); - var url = (config.https ? 'https' : 'http') + '://' + req.headers.host, - urlConfirm = url + '/confirm-email/' + token; + }, - var renderVars = emailsHandler.addEmailBaseTemplateParams( - req.headers.host, - { - name: user.displayName, - email: user.emailTemporary, - urlConfirmPlainText: urlConfirm, - urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { - source: 'transactional-email', - medium: 'email', - campaign: 'reset-password' - }) - }, - 'reset-password' - ); + // Prepare TEXT mail + function(token, user, done) { + + // If no token, user didn't change email = pass this phase + if (token) { + + var url = (config.https ? 'https' : 'http') + '://' + req.headers.host, + urlConfirm = url + '/confirm-email/' + token; + + var renderVars = emailsHandler.addEmailBaseTemplateParams( + req.headers.host, + { + name: user.displayName, + email: user.emailTemporary, + urlConfirmPlainText: urlConfirm, + urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, { + source: 'transactional-email', + medium: 'email', + campaign: 'reset-password' + }) + }, + 'reset-password' + ); + + res.render(path.resolve('./modules/core/server/views/email-templates-text/email-confirmation'), renderVars, function(err, emailPlain) { + done(err, emailPlain, user, renderVars); + }); + } else { + done(null, false, user, false); + } + }, - res.render(path.resolve('./modules/core/server/views/email-templates-text/email-confirmation'), renderVars, function(err, emailPlain) { - done(err, emailPlain, user, renderVars); - }); - } - else { - done(null, false, user, false); - } - }, + // Prepare HTML mail + function(emailPlain, user, renderVars, done) { - // Prepare HTML mail - function(emailPlain, user, renderVars, done) { + // If no emailPlain, user didn't change email = pass this phase + if (emailPlain) { + res.render(path.resolve('./modules/core/server/views/email-templates/email-confirmation'), renderVars, function(err, emailHTML) { + done(err, emailHTML, emailPlain, user); + }); + } else { + done(null, false, false, user); + } + }, - // If no emailPlain, user didn't change email = pass this phase - if(emailPlain) { - res.render(path.resolve('./modules/core/server/views/email-templates/email-confirmation'), renderVars, function(err, emailHTML) { - done(err, emailHTML, emailPlain, user); - }); - } - else { - done(null, false, false, user); - } - }, - - // If valid email, send confirm email using service - function(emailHTML, emailPlain, user, done) { - - // If no emailHTML, user didn't change email = pass this phase - if(emailHTML) { - var smtpTransport = nodemailer.createTransport(config.mailer.options); - var mailOptions = { - to: { - name: user.displayName, - address: user.emailTemporary - }, - from: 'Trustroots <' + config.mailer.from + '>', - subject: 'Confirm email change', - text: emailPlain, - html: emailHTML - }; - smtpTransport.sendMail(mailOptions, function(err) { - smtpTransport.close(); // close the connection pool - done(err, user); - }); - } - else { - done(null, user); - } - }, + // If valid email, send confirm email using service + function(emailHTML, emailPlain, user, done) { - // Return user - function(user, done) { - user = exports.sanitizeProfile(user); - return res.json(user); - }, + // If no emailHTML, user didn't change email = pass this phase + if (emailHTML) { + var smtpTransport = nodemailer.createTransport(config.mailer.options); + var mailOptions = { + to: { + name: user.displayName, + address: user.emailTemporary + }, + from: 'Trustroots <' + config.mailer.from + '>', + subject: 'Confirm email change', + text: emailPlain, + html: emailHTML + }; + smtpTransport.sendMail(mailOptions, function(err) { + smtpTransport.close(); // close the connection pool + done(err, user); + }); + } else { + done(null, user); + } + }, + + // Return user + function(user, done) { + user = exports.sanitizeProfile(user); + return res.json(user); + } ], function(err) { if (err) { @@ -527,16 +508,15 @@ exports.update = function(req, res) { */ exports.getUser = function(req, res) { // Not a profile of currently authenticated user: - if( req.profile && !req.user._id.equals(req.profile._id) ) { + if (req.profile && !req.user._id.equals(req.profile._id)) { // 'public' isn't needed at frontend. // We had to bring it until here trough // ACL policy since it's needed there. // `req.profile.toObject()` is done at sanitizeProfile() before this. delete req.profile.public; res.json(req.profile); - } - // Profile of currently authenticated user: - else { + } else { + // Profile of currently authenticated user: res.json(req.profile || {}); } }; @@ -546,15 +526,14 @@ exports.getUser = function(req, res) { */ exports.getMiniUser = function(req, res) { - if(req.profile) { + if (req.profile) { // 'public' isn't needed at frontend. // We had to bring it until here trough // ACL policy since it's needed there. var profile = req.profile.toObject(); delete profile.public; res.json(profile); - } - else { + } else { res.json({}); } @@ -567,7 +546,7 @@ exports.getMiniUser = function(req, res) { exports.userMiniByID = function(req, res, next, userId) { // Not a valid ObjectId - if(!mongoose.Types.ObjectId.isValid(userId)) { + if (!mongoose.Types.ObjectId.isValid(userId)) { return res.status(400).send({ message: errorHandler.getErrorMessageByKey('invalid-id') }); @@ -576,12 +555,12 @@ exports.userMiniByID = function(req, res, next, userId) { User.findById(userId, exports.userMiniProfileFields + ' public').exec(function(err, profile) { // Something went wrong - if(err) { + if (err) { return next(err); } // No such user - if(!profile || !profile.public) { + if (!profile || !profile.public) { return res.status(404).send({ message: errorHandler.getErrorMessageByKey('not-found') }); @@ -601,14 +580,14 @@ exports.userByUsername = function(req, res, next, username) { var query; // Require user - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); } // Proper 'username' value required - if(typeof username !== 'string' || username.trim() === '' || username.length < 3) { + if (typeof username !== 'string' || username.trim() === '' || username.length < 3) { return res.status(400).send({ message: 'Valid username required.' }); @@ -620,44 +599,37 @@ exports.userByUsername = function(req, res, next, username) { function(done) { User .findOne({ - username: username.toLowerCase() - }, - exports.userProfileFields + ' public' - ) + username: username.toLowerCase() + }, + exports.userProfileFields + ' public') .populate({ path: 'member.tag', select: tribesHandler.tribeFields + ' tribe', // Loads `tribe` fields for both `tribe:true` and `tribe:false` objects model: 'Tag', - options: { sort: { count: -1 }} + options: { sort: { count: -1 } } }) .exec(function(err, profile) { - - // Something went wrong - if (err) { - done(err); - } - // No such user - else if(!profile) { - return res.status(404).send({ - message: errorHandler.getErrorMessageByKey('not-found') - }); - } - // User's own profile, okay to send with public value in it - else if( (profile && req.user) && req.user._id.equals(profile._id) ) { - done(err, profile); - } - // Not own profile and not public - else if( (profile && req.user) && (!req.user._id.equals(profile._id) && !profile.public) ) { - return res.status(404).send({ - message: errorHandler.getErrorMessageByKey('not-found') - }); - } - else { - // Transform profile into object so that we can add new fields to it - done(err, profile); - } - - }); + if (err) { + // Something went wrong + done(err); + } else if (!profile) { + // No such user + return res.status(404).send({ + message: errorHandler.getErrorMessageByKey('not-found') + }); + } else if ((profile && req.user) && req.user._id.equals(profile._id)) { + // User's own profile, okay to send with public value in it + done(err, profile); + } else if ((profile && req.user) && (!req.user._id.equals(profile._id) && !profile.public)) { + // Not own profile and not public + return res.status(404).send({ + message: errorHandler.getErrorMessageByKey('not-found') + }); + } else { + // Transform profile into object so that we can add new fields to it + done(err, profile); + } + }); }, // Sanitize & return profile @@ -681,7 +653,7 @@ exports.userByUsername = function(req, res, next, username) { * - Sanitize description in case */ exports.sanitizeProfile = function(profile, authenticatedUser) { - if(!profile) { + if (!profile) { console.warn('sanitizeProfile() needs profile data to sanitize.'); return; } @@ -689,23 +661,22 @@ exports.sanitizeProfile = function(profile, authenticatedUser) { profile = profile.toObject(); // We're sanitizing this already on saving/updating the profile, but here we do it again just in case. - if(profile.description) profile.description = sanitizeHtml(profile.description, textProcessor.sanitizeOptions); + if (profile.description) profile.description = sanitizeHtml(profile.description, textProcessor.sanitizeOptions); // Remove tribes/tags without reference object (= they've been deleted from tags table) - if(profile.member && profile.member.length > 0) { + if (profile.member && profile.member.length > 0) { profile.member = _.reject(profile.member, function(o) { return !o.tag; }); } // Create simple arrays of tag and tribe id's profile.memberIds = []; - if(profile.member && profile.member.length > 0) { + if (profile.member && profile.member.length > 0) { profile.member.forEach(function(obj) { // If profile's `member.tag` path was populated - if(obj.tag && obj.tag._id) { + if (obj.tag && obj.tag._id) { profile.memberIds.push(obj.tag._id.toString()); - } - // If profile's `member.tag` path wasn't populated, tag is ObjectId - else if(obj.tag) { + } else if (obj.tag) { + // If profile's `member.tag` path wasn't populated, tag is ObjectId profile.memberIds.push(obj.tag.toString()); } }); @@ -713,7 +684,7 @@ exports.sanitizeProfile = function(profile, authenticatedUser) { // Profile does not belong to currently authenticated user // Remove data we don't need from other member's profile - if(!authenticatedUser || !authenticatedUser._id.equals(profile._id)) { + if (!authenticatedUser || !authenticatedUser._id.equals(profile._id)) { delete profile.updated; } @@ -739,27 +710,28 @@ exports.sanitizeProfile = function(profile, authenticatedUser) { exports.modifyUserTag = function(req, res) { // Relation (`is`|`likes`|`leave`) should be present - if(!req.body.relation || typeof req.body.relation !== 'string' || ['is', 'likes', 'leave'].indexOf(req.body.relation) === -1) { + if (!req.body.relation || typeof req.body.relation !== 'string' || ['is', 'likes', 'leave'].indexOf(req.body.relation) === -1) { return res.status(400).send({ message: 'Missing relation info.' }); } // Not a valid ObjectId - if(!req.body.id || !mongoose.Types.ObjectId.isValid(req.body.id)) { + if (!req.body.id || !mongoose.Types.ObjectId.isValid(req.body.id)) { return res.status(400).send({ message: errorHandler.getErrorMessageByKey('invalid-id') }); } - if(!req.user) { + if (!req.user) { return res.status(403).send({ message: errorHandler.getErrorMessageByKey('forbidden') }); } - // Joining (is/likes) or leaving? - var joining = (req.body.relation !== 'leave') ? true : false; + // Joining [is/likes] (=true) or leaving (=false)? + // Relation can be "join" or "leave" + var joining = (req.body.relation !== 'leave'); async.waterfall([ @@ -772,12 +744,11 @@ exports.modifyUserTag = function(req, res) { }) : false; // Return error if "is joining + is a member" OR "is leaving + isn't a member" - if((isMember && joining) || (!isMember && !joining)) { + if ((isMember && joining) || (!isMember && !joining)) { return res.status(409).send({ message: errorHandler.getErrorMessageByKey('conflict') }); - } - else { + } else { done(null); } }, @@ -795,7 +766,7 @@ exports.modifyUserTag = function(req, res) { .exec(function(err, tag) { // Tag by id `req.body.id` didn't exist - if(!tag || !tag._id) { + if (!tag || !tag._id) { return res.status(400).send({ message: errorHandler.getErrorMessageByKey('bad-request') }); @@ -808,10 +779,11 @@ exports.modifyUserTag = function(req, res) { // Add tribe/tag to user's object function(tag, done) { - // Mongo query to perform - var query = (joining) ? - // When joining: - { + // Mongo query to perform... + var query; + if (joining) { + // When joining... + query = { $push: { member: { tag: tag._id, @@ -819,15 +791,17 @@ exports.modifyUserTag = function(req, res) { since: Date.now() } } - } : - // When leaving: - { + }; + } else { + // When leaving... + query = { $pull: { member: { tag: tag._id } } }; + } User.findByIdAndUpdate(req.user._id, query, { safe: true, // @link http://stackoverflow.com/a/4975054/1984644 @@ -862,7 +836,7 @@ exports.modifyUserTag = function(req, res) { // Catch errors ], function(err) { - if(err) { + if (err) { return res.status(400).send({ message: 'Failed to join tribe/tag.' }); diff --git a/modules/users/server/models/user.server.model.js b/modules/users/server/models/user.server.model.js index 9cdaeba934..3c2a6f7440 100755 --- a/modules/users/server/models/user.server.model.js +++ b/modules/users/server/models/user.server.model.js @@ -47,11 +47,11 @@ var validatePassword = function(password) { var validateUsername = function(username) { var usernameRegex = /^(?=.*[0-9a-z])[0-9a-z.\-_]{3,34}$/, dotsRegex = /^[^.](?!.*(\.)\1).*[^.]$/; - return (this.provider !== 'local' || ( username && - usernameRegex.test(username) && - config.illegalStrings.indexOf(username) < 0) && - dotsRegex.test(username) - ); + return ( + this.provider !== 'local' || + (username && usernameRegex.test(username) && config.illegalStrings.indexOf(username) < 0) && + dotsRegex.test(username) + ); }; /** @@ -59,7 +59,7 @@ var validateUsername = function(username) { * This could be defined directly under `UserSchema` as well, * but then we'd have extra `_id`'s hanging around. */ -var UserMemberSchema = mongoose.Schema({ +var UserMemberSchema = new Schema({ tag: { type: Schema.Types.ObjectId, ref: 'Tag', @@ -76,7 +76,7 @@ var UserMemberSchema = mongoose.Schema({ default: Date.now, required: true } -}, { _id : false }); +}, { _id: false }); /** * User Schema @@ -130,7 +130,7 @@ var UserSchema = new Schema({ }, gender: { type: String, - enum: ['','male','female','other'], + enum: ['', 'male', 'female', 'other'], default: '' }, languages: { @@ -253,14 +253,14 @@ var UserSchema = new Schema({ * Hook a pre save method to hash the password */ UserSchema.pre('save', function(next) { - if(this.password && this.isModified('password') && this.password.length >= passwordMinLength) { + if (this.password && this.isModified('password') && this.password.length >= passwordMinLength) { this.salt = crypto.randomBytes(16).toString('base64'); this.password = this.hashPassword(this.password); } // Pre-cached email hash to use with Gravatar - if(this.email && this.isModified('email') && this.email !== '') { - this.emailHash = crypto.createHash('md5').update( this.email.trim().toLowerCase() ).digest('hex'); + if (this.email && this.isModified('email') && this.email !== '') { + this.emailHash = crypto.createHash('md5').update(this.email.trim().toLowerCase()).digest('hex'); } next(); diff --git a/modules/users/server/policies/users.server.policy.js b/modules/users/server/policies/users.server.policy.js index b2edbcbfa1..63a6c23ee4 100644 --- a/modules/users/server/policies/users.server.policy.js +++ b/modules/users/server/policies/users.server.policy.js @@ -90,14 +90,14 @@ exports.invokeRolesPolicies = function() { exports.isAllowed = function(req, res, next) { // Non-public profiles are invisible - if(req.profile && !req.profile.public && req.user && !req.profile._id.equals(req.user._id)) { + if (req.profile && !req.profile.public && req.user && !req.profile._id.equals(req.user._id)) { return res.status(404).json({ message: errorHandler.getErrorMessageByKey('not-found') }); } // No profile browsing for non-public users - if(req.profile && req.user && !req.user.public && !req.profile._id.equals(req.user._id)) { + if (req.profile && req.user && !req.user.public && !req.profile._id.equals(req.user._id)) { return res.status(403).json({ message: errorHandler.getErrorMessageByKey('forbidden') }); diff --git a/modules/users/tests/client/password-forgot.client.controller.tests.js b/modules/users/tests/client/password-forgot.client.controller.tests.js index 51ec633949..58f3fac29f 100644 --- a/modules/users/tests/client/password-forgot.client.controller.tests.js +++ b/modules/users/tests/client/password-forgot.client.controller.tests.js @@ -5,12 +5,12 @@ describe('ForgotPasswordController', function() { // Initialize global variables var ForgotPasswordController, - $scope, - $httpBackend, - $stateParams, - $location, - $window, - Authentication; + $scope, + $httpBackend, + $stateParams, + $location, + $window, + Authentication; // The $resource service augments the response object with methods for updating and deleting the resource. // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match diff --git a/modules/users/tests/client/password-reset.client.controller.tests.js b/modules/users/tests/client/password-reset.client.controller.tests.js index 36dc22a248..a98ebb65de 100644 --- a/modules/users/tests/client/password-reset.client.controller.tests.js +++ b/modules/users/tests/client/password-reset.client.controller.tests.js @@ -5,12 +5,12 @@ describe('ResetPasswordController', function() { // Initialize global variables var ResetPasswordController, - $scope, - $httpBackend, - $stateParams, - $location, - $window, - Authentication; + $scope, + $httpBackend, + $stateParams, + $location, + $window, + Authentication; // The $resource service augments the response object with methods for updating and deleting the resource. // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match diff --git a/modules/users/tests/server/user.server.model.tests.js b/modules/users/tests/server/user.server.model.tests.js index 1417cdb091..45b683fdbc 100644 --- a/modules/users/tests/server/user.server.model.tests.js +++ b/modules/users/tests/server/user.server.model.tests.js @@ -12,7 +12,9 @@ var path = require('path'), /** * Globals */ -var user, user2, user3; +var user, + user2, + user3; /** * Unit tests diff --git a/modules/users/tests/server/user.server.routes.tests.js b/modules/users/tests/server/user.server.routes.tests.js index d51521acec..c46ea328b0 100644 --- a/modules/users/tests/server/user.server.routes.tests.js +++ b/modules/users/tests/server/user.server.routes.tests.js @@ -13,7 +13,12 @@ var should = require('should'), /** * Globals */ -var app, agent, credentials, user, _user, admin; +var app, + agent, + credentials, + user, + _user, + admin; /** * User routes tests @@ -148,8 +153,8 @@ describe('User CRUD tests', function () { return done(); }); - }); - }); + }); + }); }); }); @@ -204,8 +209,8 @@ describe('User CRUD tests', function () { return done(); }); - }); - }); + }); + }); }); }); @@ -641,12 +646,12 @@ describe('User CRUD tests', function () { var userUpdate = { firstName: 'user_update_first', - lastName: 'user_update_last', + lastName: 'user_update_last' }; agent.put('/api/users') .send(userUpdate) - //.expect(200) + // .expect(200) .end(function (userInfoErr, userInfoRes) { if (userInfoErr) { return done(userInfoErr); @@ -769,7 +774,7 @@ describe('User CRUD tests', function () { var userUpdate = { firstName: 'user_update_first', - lastName: 'user_update_last', + lastName: 'user_update_last' }; agent.put('/api/users') @@ -1040,7 +1045,7 @@ describe('User CRUD tests', function () { return done(userInfoErr); } - userInfoRes.body.message.should.equal('Image too big. Please maximum ' + (config.maxUploadSize / (1024*1024)).toFixed(2) + ' Mb files.'); + userInfoRes.body.message.should.equal('Image too big. Please maximum ' + (config.maxUploadSize / (1024 * 1024)).toFixed(2) + ' Mb files.'); return done(); }); @@ -1450,4 +1455,4 @@ function redirectMessage(url) { } else { return 'Moved Temporarily. Redirecting to ' + url; } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 97d590284a..c1b1f3bb5b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/Trustroots/trustroots" }, "engines": { - "node": "~4.2.0", + "node": ">=5.0.0", "npm": ">=2.0.0" }, "scripts": { @@ -46,6 +46,8 @@ "consolidate": "~0.14.0", "cookie-parser": "~1.4.0", "del": "~2.2.0", + "eslint": "~2.2.0", + "eslint-config-airbnb": "~6.0.2", "express": "~4.14.0", "express-paginate": "~0.2.0", "express-session": "~1.14.0", @@ -59,9 +61,9 @@ "gulp-concat": "~2.6.0", "gulp-csslint": "~0.3.0", "gulp-csso": "~2.0.0", + "gulp-eslint": "~2.0.0", "gulp-fontello": "~0.4.5", "gulp-htmlmin": "~2.0.0", - "gulp-jshint": "~2.0.0", "gulp-less": "~3.1.0", "gulp-livereload": "~3.8.1", "gulp-load-plugins": "~1.2.0", @@ -77,7 +79,6 @@ "gulp-util": "~3.0.7", "helmet": "~2.1.0", "html-to-text": "~2.1.0", - "jshint": "~2.9.1", "lodash": "~4.13.1", "mean-seo": "~0.0.8", "merge-stream": "~1.0.0", diff --git a/scripts/export-newsletter-subscribers.js b/scripts/export-newsletter-subscribers.js index 1d1d38fa5f..78e7f2b3e2 100644 --- a/scripts/export-newsletter-subscribers.js +++ b/scripts/export-newsletter-subscribers.js @@ -30,7 +30,7 @@ console.log(chalk.white('--')); // Export file is required -if(process.argv[2] == null) { +if (process.argv[2] == null) { console.log(chalk.red('Please give export file path!')); console.log('Example:'); console.log('node export-newsletter-subscribers.js ~/emails.csv'); @@ -45,7 +45,7 @@ else { // Bootstrap db connection var db = mongoose.connect(config.db.uri, function(err) { - if(err) { + if (err) { console.error(chalk.red('Could not connect to MongoDB!')); console.log(err); process.exit(0); @@ -58,11 +58,11 @@ else { User.find({newsletter:true}, {email: 1, firstName: 1, lastName: 1}) .exec(function(err, users) { console.log('Found ' + users.length + ' users.'); - if(err) { + if (err) { console.error(chalk.red('Error:')); console.log(err); process.exit(0); - } else if(users.length <= 0) { + } else if (users.length <= 0) { console.error(chalk.red('Could not find any users!')); console.log(err); process.exit(0); @@ -77,7 +77,7 @@ else { // Write contents console.log('Writing content to ' + csvFile); fs.writeFile(csvFile, data, function(err) { - if(err) { + if (err) { console.error(chalk.red('Error while saving the file!')); console.error(err); } diff --git a/scripts/fillTestData.js b/scripts/fillTestData.js index 9849097566..92b4a5c245 100644 --- a/scripts/fillTestData.js +++ b/scripts/fillTestData.js @@ -27,7 +27,7 @@ var random = function (max) { var randomizeLoaction = function () { var random = Math.random(); - if(random > 0.98) { + if (random > 0.98) { random = ((Math.random()-0.5)*Math.random()*4)-1; } else { @@ -59,12 +59,12 @@ var addUsers = function (index, max) { user.username = index+user.firstName.toLowerCase().replace('\'', ''); user.save(function(err) { - if(err != null) console.log(err); + if (err != null) console.log(err); }); index++; addOffer(user._id, index, max); - if(index <= max) { + if (index <= max) { addUsers(index, max); } @@ -86,10 +86,10 @@ var addOffer = function (id, index, max) { offer.locationFuzzy = location; offer.save(function(err) { - if(err != null) console.log(err); + if (err != null) console.log(err); else { savedCounter++; - if(savedCounter >= max) { + if (savedCounter >= max) { console.log(chalk.green('Done with ' + max + ' test users!')); console.log(chalk.white(''));// Reset to white process.exit(0); @@ -102,14 +102,14 @@ var addOffer = function (id, index, max) { var adminUsername = (process.argv[3] == null) ? false : process.argv[3]; // Number of users is required -if(process.argv[2] == null) { +if (process.argv[2] == null) { console.log(chalk.red('Please give a number of users to add.')); } else { var numberOfUsers = process.argv[2]; // Create admin user + regular users - if(adminUsername !== false) { + if (adminUsername !== false) { var adminUser = new User(); adminUser.firstName = faker.name.firstName(); @@ -124,7 +124,7 @@ else { adminUser.avatarUploaded = false; adminUser.save(function(err) { - if(!err) { + if (!err) { console.log('Created admin user. Login with: ' + adminUsername + ' / password'); } else { console.log(chalk.red('Could not add admin user ' + adminUsername)); @@ -133,7 +133,7 @@ else { // Add regular users console.log('Generating ' + numberOfUsers + ' users...'); - if(numberOfUsers > 2000) { + if (numberOfUsers > 2000) { console.log('...this might really take a while... go grab some coffee!'); } addUsers(1, numberOfUsers); @@ -142,7 +142,7 @@ else { else { // Add regular users console.log('Generating ' + numberOfUsers + ' users...'); - if(numberOfUsers > 2000) { + if (numberOfUsers > 2000) { console.log('...this might really take a while... go grab some coffee!'); } addUsers(0, numberOfUsers); diff --git a/server.js b/server.js index 0cecdc0049..129c4e44d1 100755 --- a/server.js +++ b/server.js @@ -7,7 +7,7 @@ // Debug Node.js C/C++ native code modules on dev mode // @link https://www.npmjs.com/package/segfault-handler -if(process.env.NODE_ENV === 'development') { +if (process.env.NODE_ENV === 'development') { var SegfaultHandler = require('segfault-handler'); SegfaultHandler.registerHandler('segfault.log'); console.log('Logging possible segfault errors to ./segfault.log'); @@ -29,7 +29,7 @@ mongoose.connect(function(db) { app.listen(config.port); // Check in case mailer config is still set to default values (a common problem) - if(config.mailer.service && config.mailer.service === 'MAILER_SERVICE_PROVIDER') { + if (config.mailer.service && config.mailer.service === 'MAILER_SERVICE_PROVIDER') { console.warn(chalk.red('Remember to setup mailer from ./config/env/local.js - some features won\'t work without it.')); }