feat(config): Deprecate JSHint in favor of ESLint

Add basic ESLint setup extending well-known Airbnb code style.

Fixes #1072, #1097
This commit is contained in:
Marek Grzybek
2015-12-10 20:31:51 +01:00
parent 4e9ad81ad2
commit d14d5130af
76 changed files with 266 additions and 255 deletions

View File

@@ -1,37 +0,0 @@
{
rules: {
indent: [2, 2, {"SwitchCase": 1}],
no-multi-spaces: 2,
no-underscore-dangle: 0,
no-use-before-define: [1, "nofunc"],
no-unused-expressions: 0,
no-empty-class: 0,
object-curly-spacing: [2, "always"],
quotes: [1, "single"],
space-in-parens: [2, "never"]
},
env: {
node: true
},
globals: {
angular: true,
$: true,
jQuery: true,
moment: true,
window: true,
document: true,
Modernizr: true,
__TESTING__: true,
beforeEach: true,
expect: true,
describe: true,
it: true,
element: true,
by: true,
browser: true,
inject: true,
register: true,
sinon: true,
_: false
}
}

72
.eslintrc.js Normal file
View File

@@ -0,0 +1,72 @@
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 }],
'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-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,
by: true,
browser: true,
element: true,
inject: true,
io: true,
moment: true,
Modernizr: true,
Promise: true,
__TESTING__: true,
_: false,
ApplicationConfiguration: true
}
};

View File

@@ -1,27 +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.).
"curly": false, // Require {} for every new block or scope.
"eqeqeq": true, // Require triple equals i.e. `===`.
"latedef": "nofunc", // Prohibit variable use before definition.
"noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`.
"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.
"globals": { // Globals variables.
"angular": true,
"io": true,
"ApplicationConfiguration": true
},
"predef": [ // Extra globals.
"inject",
"by",
"browser",
"element"
],
"devel": true // Allow development statements e.g. `console.log();`.
}

View File

@@ -6,7 +6,7 @@ module.exports = {
css: [
// bower:css
'public/lib/bootstrap/dist/css/bootstrap.min.css',
'public/lib/bootstrap/dist/css/bootstrap-theme.min.css',
'public/lib/bootstrap/dist/css/bootstrap-theme.min.css'
// endbower
],
js: [

View File

@@ -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, '');

View File

@@ -74,9 +74,9 @@ module.exports = {
}
},
seedDB: {
seed: process.env.MONGO_SEED === 'true' ? true : false,
seed: process.env.MONGO_SEED === 'true',
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true,
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
username: process.env.MONGO_SEED_USER_USERNAME || 'user',
provider: 'local',

View File

@@ -47,7 +47,7 @@ module.exports = {
profileUpload: {
dest: './modules/users/client/img/profile/uploads/', // Profile upload destination path
limits: {
fileSize: 1*1024*1024 // Max file size in bytes (1 MB)
fileSize: 1 * 1024 * 1024 // Max file size in bytes (1 MB)
}
}
}

View File

@@ -19,16 +19,16 @@ module.exports = {
options: {
// Stream defaults to process.stdout
// Uncomment/comment to toggle the logging to a log on the file system
//stream: {
// stream: {
// directoryPath: process.cwd(),
// fileName: 'access.log',
// rotatingLogs: { // for more info on rotating logs - https://github.com/holidayextras/file-stream-rotator#usage
// active: false, // activate to use rotating logs
// active: false, // activate to use rotating logs
// fileName: 'access-%DATE%.log', // if rotating logs are active, this fileName setting will be used
// frequency: 'daily',
// verbose: false
// }
//}
// }
}
},
app: {
@@ -77,9 +77,9 @@ module.exports = {
},
livereload: true,
seedDB: {
seed: process.env.MONGO_SEED === 'true' ? true : false,
seed: process.env.MONGO_SEED === 'true',
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true,
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
username: process.env.MONGO_SEED_USER_USERNAME || 'user',
provider: 'local',

View File

@@ -5,7 +5,7 @@
// Use it for your API keys, passwords, etc.
// WARNING: When using this example for multiple NODE_ENV's concurrently, make sure you update the 'db' settings appropriately.
// You do not want to accidentally overwrite/lose any data. For instance, if you create a file for 'test' and don't change the
// You do not want to accidentally overwrite/lose any data. For instance, if you create a file for 'test' and don't change the
// database name in the setting below, running the tests will drop all the data from the specified database.
//
// You may end up with a list of files, that will be used with their corresponding NODE_ENV:

View File

@@ -29,10 +29,10 @@ module.exports = {
directoryPath: process.env.LOG_DIR_PATH || process.cwd(),
fileName: process.env.LOG_FILE || 'access.log',
rotatingLogs: { // for more info on rotating logs - https://github.com/holidayextras/file-stream-rotator#usage
active: process.env.LOG_ROTATING_ACTIVE === 'true' ? true : false, // activate to use rotating logs
active: process.env.LOG_ROTATING_ACTIVE === 'true', // activate to use rotating logs
fileName: process.env.LOG_ROTATING_FILE || 'access-%DATE%.log', // if rotating logs are active, this fileName setting will be used
frequency: process.env.LOG_ROTATING_FREQUENCY || 'daily',
verbose: process.env.LOG_ROTATING_VERBOSE === 'true' ? true : false
verbose: process.env.LOG_ROTATING_VERBOSE === 'true'
}
}
}
@@ -79,9 +79,9 @@ module.exports = {
}
},
seedDB: {
seed: process.env.MONGO_SEED === 'true' ? true : false,
seed: process.env.MONGO_SEED === 'true',
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true,
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
username: process.env.MONGO_SEED_USER_USERNAME || 'user',
provider: 'local',

6
config/env/test.js vendored
View File

@@ -23,7 +23,7 @@ module.exports = {
directoryPath: process.cwd(),
fileName: 'access.log',
rotatingLogs: { // for more info on rotating logs - https://github.com/holidayextras/file-stream-rotator#usage
active: false, // activate to use rotating logs
active: false, // activate to use rotating logs
fileName: 'access-%DATE%.log', // if rotating logs are active, this fileName setting will be used
frequency: 'daily',
verbose: false
@@ -77,9 +77,9 @@ module.exports = {
}
},
seedDB: {
seed: process.env.MONGO_SEED === 'true' ? true : false,
seed: process.env.MONGO_SEED === 'true',
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true,
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
username: process.env.MONGO_SEED_USER_USERNAME || 'user',
provider: 'local',

View File

@@ -120,8 +120,8 @@ module.exports.start = function start(options) {
seedOptions.logResults = options.logResults;
}
if (_.has(options, 'seedUser')) {
seedOptions.seedUser = options.seedUser;
if (_.has(options, 'seedUser')) {
seedOptions.seedUser = options.seedUser;
}
if (_.has(options, 'seedAdmin')) {
@@ -134,7 +134,7 @@ module.exports.start = function start(options) {
var adminAccount = new User(seedOptions.seedAdmin);
var userAccount = new User(seedOptions.seedUser);
//If production only seed admin if it does not exist
// If production only seed admin if it does not exist
if (process.env.NODE_ENV === 'production') {
User.generateRandomPassphrase()
.then(seedTheUser(adminAccount))

View File

@@ -34,7 +34,7 @@ module.exports = function (grunt) {
},
serverJS: {
files: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS),
tasks: ['jshint'],
tasks: ['eslint'],
options: {
livereload: true
}
@@ -47,7 +47,7 @@ module.exports = function (grunt) {
},
clientJS: {
files: defaultAssets.client.js,
tasks: ['jshint'],
tasks: ['eslint'],
options: {
livereload: true
}
@@ -91,17 +91,6 @@ module.exports = function (grunt) {
logConcurrentOutput: true
}
},
jshint: {
all: {
src: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS, defaultAssets.client.js, testAssets.tests.server, testAssets.tests.client, testAssets.tests.e2e),
options: {
jshintrc: true,
node: true,
mocha: true,
jasmine: true
}
}
},
eslint: {
options: {},
target: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS, defaultAssets.client.js, testAssets.tests.server, testAssets.tests.client, testAssets.tests.e2e)
@@ -190,7 +179,7 @@ module.exports = function (grunt) {
coverage: true,
require: 'test.js',
coverageFolder: 'coverage/server',
reportFormats: ['cobertura','lcovonly'],
reportFormats: ['cobertura', 'lcovonly'],
check: {
lines: 40,
statements: 40
@@ -297,7 +286,7 @@ module.exports = function (grunt) {
});
// Lint CSS and JavaScript files.
grunt.registerTask('lint', ['sass', 'less', 'jshint', 'eslint', 'csslint']);
grunt.registerTask('lint', ['sass', 'less', 'eslint', 'csslint']);
// Lint project files and minify them into two production files.
grunt.registerTask('build', ['env:dev', 'lint', 'ngAnnotate', 'uglify', 'cssmin']);

View File

@@ -69,24 +69,24 @@ 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.client.js, ['jshint']).on('change', plugins.livereload.changed);
gulp.watch(defaultAssets.server.allJS, ['eslint']).on('change', plugins.livereload.changed);
gulp.watch(defaultAssets.client.js, ['eslint']).on('change', plugins.livereload.changed);
gulp.watch(defaultAssets.client.css, ['csslint']).on('change', plugins.livereload.changed);
gulp.watch(defaultAssets.client.sass, ['sass', 'csslint']).on('change', plugins.livereload.changed);
gulp.watch(defaultAssets.client.less, ['less', 'csslint']).on('change', plugins.livereload.changed);
if (process.env.NODE_ENV === 'production') {
gulp.watch(defaultAssets.server.gulpConfig, ['templatecache', 'jshint']);
gulp.watch(defaultAssets.client.views, ['templatecache', 'jshint']).on('change', plugins.livereload.changed);
gulp.watch(defaultAssets.server.gulpConfig, ['templatecache', 'eslint']);
gulp.watch(defaultAssets.client.views, ['templatecache']).on('change', plugins.livereload.changed);
} else {
gulp.watch(defaultAssets.server.gulpConfig, ['jshint']);
gulp.watch(defaultAssets.server.gulpConfig, ['eslint']);
gulp.watch(defaultAssets.client.views).on('change', plugins.livereload.changed);
}
if (process.env.NODE_ENV === 'test') {
// Add Server Test file rules
gulp.watch([testAssets.tests.server, defaultAssets.server.allJS], ['test:server']).on('change', function (file) {
var runOnlyChangedTestFile = argv.onlyChanged ? true : false;
var runOnlyChangedTestFile = !!argv.onlyChanged;
// check if we should only run a changed test file
if (runOnlyChangedTestFile) {
@@ -125,23 +125,6 @@ gulp.task('csslint', function (done) {
}));
});
// JS linting task
gulp.task('jshint', function () {
var assets = _.union(
defaultAssets.server.gulpConfig,
defaultAssets.server.allJS,
defaultAssets.client.js,
testAssets.tests.server,
testAssets.tests.client,
testAssets.tests.e2e
);
return gulp.src(assets)
.pipe(plugins.jshint())
.pipe(plugins.jshint.reporter('default'))
.pipe(plugins.jshint.reporter('fail'));
});
// ESLint JS linting task
gulp.task('eslint', function () {
var assets = _.union(
@@ -339,7 +322,7 @@ gulp.task('dropdb', function (done) {
mongoose.connect(function (db) {
db.connection.db.dropDatabase(function (err) {
if(err) {
if (err) {
console.log(err);
} else {
console.log('Successfully dropped db: ', db.connection.db.databaseName);
@@ -376,7 +359,7 @@ gulp.task('protractor', ['webdriver_update'], function () {
// Lint CSS and JavaScript files.
gulp.task('lint', function (done) {
runSequence('less', 'sass', ['csslint', 'eslint', 'jshint'], done);
runSequence('less', 'sass', ['csslint', 'eslint'], done);
});
// Lint project files and minify them into two production files.
@@ -394,7 +377,7 @@ gulp.task('test:server', function (done) {
});
// Watch all server files for changes & run server tests (test:server) task on changes
// optional arguments:
// optional arguments:
// --onlyChanged - optional argument for specifying that only the tests in a changed Server Test file will be run
// example usage: gulp test:server:watch --onlyChanged
gulp.task('test:server:watch', function (done) {

View File

@@ -35,7 +35,7 @@ module.exports = function (karmaConfig) {
cacheIdFromPath: function (filepath) {
return filepath;
},
}
},
// List of files / patterns to load in the browser
@@ -47,7 +47,7 @@ module.exports = function (karmaConfig) {
// Configure the coverage reporter
coverageReporter: {
dir : 'coverage/client',
dir: 'coverage/client',
reporters: [
// Reporters not supporting the `file` property
{ type: 'html', subdir: 'report-html' },

View File

@@ -4,4 +4,4 @@
app.registerModule('articles', ['core']);// The core module is required for special route handling; see /core/client/config/core.client.routes
app.registerModule('articles.services');
app.registerModule('articles.routes', ['ui.router', 'articles.services']);
})(ApplicationConfiguration);
}(ApplicationConfiguration));

View File

@@ -28,4 +28,4 @@
roles: ['user']
});
}
})();
}());

View File

@@ -33,7 +33,7 @@
},
data: {
roles: ['user', 'admin'],
pageTitle : 'Articles Create'
pageTitle: 'Articles Create'
}
})
.state('articles.edit', {
@@ -57,7 +57,7 @@
resolve: {
articleResolve: getArticle
},
data:{
data: {
pageTitle: 'Article {{ articleResolve.title }}'
}
});
@@ -76,4 +76,4 @@
function newArticle(ArticlesService) {
return new ArticlesService();
}
})();
}());

View File

@@ -49,4 +49,4 @@
}
}
}
})();
}());

View File

@@ -12,4 +12,4 @@
vm.articles = ArticlesService.query();
}
})();
}());

View File

@@ -16,4 +16,4 @@
}
});
}
})();
}());

View File

@@ -35,7 +35,7 @@ exports.read = function (req, res) {
// Add a custom field to the Article, for determining if the current User is the "owner".
// NOTE: This field is NOT persisted to the database, since it doesn't exist in the Article model.
article.isCurrentUserOwner = req.user && article.user && article.user._id.toString() === req.user._id.toString() ? true : false;
article.isCurrentUserOwner = !!(req.user && article.user && article.user._id.toString() === req.user._id.toString());
res.json(article);
};

View File

@@ -64,7 +64,7 @@
articleResolve: {}
});
//Spy on state go
// Spy on state go
spyOn($state, 'go');
}));
@@ -143,12 +143,12 @@
describe('vm.remove()', function () {
beforeEach(function () {
//Setup articles
// Setup articles
$scope.vm.article = mockArticle;
});
it('should delete the article and redirect to articles', function () {
//Return true on confirm message
// Return true on confirm message
spyOn(window, 'confirm').and.returnValue(true);
$httpBackend.expectDELETE(/api\/articles\/([0-9a-fA-F]{24})$/).respond(204);
@@ -160,7 +160,7 @@
});
it('should should not delete the article and not redirect', function () {
//Return false on confirm message
// Return false on confirm message
spyOn(window, 'confirm').and.returnValue(false);
$scope.vm.remove();
@@ -169,4 +169,4 @@
});
});
});
})();
}());

View File

@@ -6,7 +6,7 @@
var $scope,
ArticlesService;
//We can start by loading the main application module
// We can start by loading the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
@@ -73,7 +73,7 @@
content: 'MEAN rocks!'
});
//Initialize Controller
// Initialize Controller
ArticlesController = $controller('ArticlesController as vm', {
$scope: $scope,
articleResolve: mockArticle
@@ -120,7 +120,7 @@
// create mock article
mockArticle = new ArticlesService();
//Initialize Controller
// Initialize Controller
ArticlesController = $controller('ArticlesController as vm', {
$scope: $scope,
articleResolve: mockArticle
@@ -170,7 +170,7 @@
content: 'MEAN rocks!'
});
//Initialize Controller
// Initialize Controller
ArticlesController = $controller('ArticlesController as vm', {
$scope: $scope,
articleResolve: mockArticle
@@ -226,4 +226,4 @@
});
});
})();
}());

View File

@@ -63,7 +63,7 @@
$scope: $scope
});
//Spy on state go
// Spy on state go
spyOn($state, 'go');
}));
@@ -89,4 +89,4 @@
}));
});
});
})();
}());

View File

@@ -11,7 +11,8 @@ var should = require('should'),
/**
* Globals
*/
var user, article;
var user,
article;
/**
* Unit tests

View File

@@ -11,7 +11,11 @@ var should = require('should'),
/**
* Globals
*/
var app, agent, credentials, user, article;
var app,
agent,
credentials,
user,
article;
/**
* Article routes tests

View File

@@ -3,4 +3,4 @@
app.registerModule('chat', ['core']);
app.registerModule('chat.routes', ['ui.router']);
})(ApplicationConfiguration);
}(ApplicationConfiguration));

View File

@@ -14,4 +14,4 @@
state: 'chat'
});
}
})();
}());

View File

@@ -20,4 +20,4 @@
}
});
}
})();
}());

View File

@@ -52,4 +52,4 @@
vm.messageText = '';
}
}
})();
}());

View File

@@ -5,7 +5,7 @@
'use strict';
describe('ChatController', function () {
//Initialize global variables
// Initialize global variables
var $scope,
Socket,
ChatController,
@@ -91,4 +91,4 @@
});
});
});
})();
}());

View File

@@ -6,7 +6,7 @@
var $scope,
Authentication;
//We can start by loading the main application module
// We can start by loading the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
@@ -60,4 +60,4 @@
});
});
})();
}());

View File

@@ -20,4 +20,4 @@ var ApplicationConfiguration = (function () {
applicationModuleVendorDependencies: applicationModuleVendorDependencies,
registerModule: registerModule
};
})();
}());

View File

@@ -1,6 +1,6 @@
'use strict';
//Start by defining the main module and adding the module dependencies
// Start by defining the main module and adding the module dependencies
angular.module(ApplicationConfiguration.applicationModuleName, ApplicationConfiguration.applicationModuleVendorDependencies);
// Setting HTML5 Location Mode
@@ -45,7 +45,7 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(function ($ro
// Store previous state
function storePreviousState(state, params) {
// only store this state if it shouldn't be ignored
// only store this state if it shouldn't be ignored
if (!state.data || !state.data.ignoreState) {
$state.previous = {
state: state,
@@ -56,9 +56,9 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(function ($ro
}
});
//Then define the init function for starting up the application
// Then define the init function for starting up the application
angular.element(document).ready(function () {
//Fixing facebook bug with redirect
// Fixing facebook bug with redirect
if (window.location.hash && window.location.hash === '#_=_') {
if (window.history && history.pushState) {
window.history.pushState('', document.title, window.location.pathname);
@@ -75,6 +75,6 @@ angular.element(document).ready(function () {
}
}
//Then init the app
// Then init the app
angular.bootstrap(document, [ApplicationConfiguration.applicationModuleName]);
});

View File

@@ -42,4 +42,4 @@
}
})();
}());

View File

@@ -9,7 +9,7 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider',
var hasTrailingSlash = path.length > 1 && path[path.length - 1] === '/';
if (hasTrailingSlash) {
//if last character is a slash, return the same url without the slash
// if last character is a slash, return the same url without the slash
var newPath = path.substr(0, path.length - 1);
$location.replace().path(newPath);
}

View File

@@ -37,4 +37,4 @@
}
}
}
})();
}());

View File

@@ -7,7 +7,12 @@
angular.module('core')
.directive('showErrors', ['$timeout', '$interpolate', function ($timeout, $interpolate) {
var linkFn = function (scope, el, attrs, formCtrl) {
var inputEl, inputName, inputNgEl, options, showSuccess, toggleClasses,
var inputEl,
inputName,
inputNgEl,
options,
showSuccess,
toggleClasses,
initCheck = false,
showValidationMessages = false,
blurred = false;
@@ -19,7 +24,7 @@ angular.module('core')
inputName = $interpolate(inputNgEl.attr('name') || '')(scope);
if (!inputName) {
throw 'show-errors element has no child input elements with a \'name\' attribute class';
throw new Error('show-errors element has no child input elements with a \'name\' attribute class');
}
var reset = function () {
@@ -65,7 +70,7 @@ angular.module('core')
compile: function (elem, attrs) {
if (attrs.showErrors.indexOf('skipFormGroupCheck') === -1) {
if (!(elem.hasClass('form-group') || elem.hasClass('input-group'))) {
throw 'show-errors element does not have the \'form-group\' or \'input-group\' class';
throw new Error('show-errors element does not have the \'form-group\' or \'input-group\' class');
}
}
return linkFn;

View File

@@ -1,6 +1,6 @@
'use strict';
//Menu service used for managing menus
// Menu service used for managing menus
angular.module('core').service('Menus', [
function () {
// Define a set of default roles
@@ -14,13 +14,17 @@ angular.module('core').service('Menus', [
if (!!~this.roles.indexOf('*')) {
return true;
} else {
if(!user) {
if (!user) {
return false;
}
for (var userRoleIndex in user.roles) {
for (var roleIndex in this.roles) {
if (this.roles[roleIndex] === user.roles[userRoleIndex]) {
return true;
if (user.roles.hasOwnProperty(userRoleIndex)) {
for (var roleIndex in this.roles) {
if (this.roles.hasOwnProperty(roleIndex)) {
if (this.roles[roleIndex] === user.roles[userRoleIndex]) {
return true;
}
}
}
}
}
@@ -40,8 +44,6 @@ angular.module('core').service('Menus', [
} else {
throw new Error('MenuId was not provided');
}
return false;
};
// Get the menu object by menu id
@@ -99,7 +101,9 @@ angular.module('core').service('Menus', [
// Add submenu items
if (options.items) {
for (var i in options.items) {
this.addSubMenuItem(menuId, options.state, options.items[i]);
if (options.items.hasOwnProperty(i)) {
this.addSubMenuItem(menuId, options.state, options.items[i]);
}
}
}
@@ -155,9 +159,13 @@ angular.module('core').service('Menus', [
// Search for menu item to remove
for (var itemIndex in this.menus[menuId].items) {
for (var subitemIndex in this.menus[menuId].items[itemIndex].items) {
if (this.menus[menuId].items[itemIndex].items[subitemIndex].state === submenuItemState) {
this.menus[menuId].items[itemIndex].items.splice(subitemIndex, 1);
if (this.menus[menuId].items.hasOwnProperty(itemIndex)) {
for (var subitemIndex in this.menus[menuId].items[itemIndex].items) {
if (this.menus[menuId].items[itemIndex].items.hasOwnProperty(subitemIndex)) {
if (this.menus[menuId].items[itemIndex].items[subitemIndex].state === submenuItemState) {
this.menus[menuId].items[itemIndex].items.splice(subitemIndex, 1);
}
}
}
}
}
@@ -166,7 +174,7 @@ angular.module('core').service('Menus', [
return this.menus[menuId];
};
//Adding the topbar menu
// Adding the topbar menu
this.addMenu('topbar', {
roles: ['*']
});

View File

@@ -2,7 +2,7 @@
(function () {
describe('HeaderController', function () {
//Initialize global variables
// Initialize global variables
var scope,
HeaderController,
$state,
@@ -61,4 +61,4 @@
});
});
});
})();
}());

View File

@@ -2,7 +2,7 @@
(function () {
describe('HomeController', function () {
//Initialize global variables
// Initialize global variables
var scope,
HomeController;
@@ -21,4 +21,4 @@
expect(scope.authentication).toBeTruthy();
});
});
})();
}());

View File

@@ -2,7 +2,7 @@
(function() {
describe('authInterceptor', function() {
//Initialize global variables
// Initialize global variables
var authInterceptor,
$q,
$state,
@@ -12,7 +12,7 @@
// Load the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
//Load httpProvider
// Load httpProvider
beforeEach(module(function($httpProvider) {
httpProvider = $httpProvider;
}));
@@ -22,8 +22,8 @@
$q = _$q_;
$state = _$state_;
Authentication = _Authentication_;
spyOn($q,'reject');
spyOn($state,'transitionTo');
spyOn($q, 'reject');
spyOn($state, 'transitionTo');
}));
it('Auth Interceptor should be object', function() {
@@ -63,4 +63,4 @@
});
});
});
})();
}());

View File

@@ -2,7 +2,7 @@
(function() {
describe('Menus', function() {
//Initialize global variables
// Initialize global variables
var scope,
Menus;
@@ -405,21 +405,21 @@
expect(subItem2.position).toBe(0);
});
});
describe('then removeSubMenuItem', function() {
beforeEach(function() {
Menus.validateMenuExistance = jasmine.createSpy();
menu = Menus.removeSubMenuItem(menuId, subItem1.state);
});
it('should validate menu existance', function() {
expect(Menus.validateMenuExistance).toHaveBeenCalledWith(menuId);
});
it('should return menu object', function() {
expect(menu).toBeDefined();
});
it('should remove sub menu item', function() {
expect(menuItem1.items.length).toBe(1);
expect(menuItem1.items[0].state).toEqual(subItem2.state);
@@ -427,4 +427,4 @@
});
});
});
})();
}());

View File

@@ -40,4 +40,4 @@
};
$window.io = mock;
})();
}());

View File

@@ -17,7 +17,11 @@ var _ = require('lodash'),
/**
* Globals
*/
var user1, admin1, userFromSeedConfig, adminFromSeedConfig, originalLogConfig;
var user1,
admin1,
userFromSeedConfig,
adminFromSeedConfig,
originalLogConfig;
describe('Configuration Tests:', function () {
@@ -308,7 +312,7 @@ describe('Configuration Tests:', function () {
seed
.start({ logResults: false })
.then(function () {
// we don't ever expect to make it here but we don't want to timeout
// we don't ever expect to make it here but we don't want to timeout
User.remove(function(err) {
should.not.exist(err);
// force this test to fail since we should never be here
@@ -461,7 +465,7 @@ describe('Configuration Tests:', function () {
it('should use the default log format of "combined" when an invalid format was provided', function () {
// manually set the config log format to be invalid
config.log = {
format: '_some_invalid_format_'
format: '_some_invalid_format_'
};
var format = logger.getFormat();
@@ -568,7 +572,7 @@ describe('Configuration Tests:', function () {
var _dir = process.cwd() + '/temp-rotating-logs';
var _filename = 'unit-test-rotating-access-%DATE%.log';
// enable rotating logs
// enable rotating logs
config.log = {
format: 'combined',
options: {

View File

@@ -14,4 +14,4 @@
state: 'admin.users'
});
}
})();
}());

View File

@@ -52,4 +52,4 @@
}).$promise;
}
}
})();
}());

View File

@@ -125,4 +125,4 @@
}
});
}
})();
}());

View File

@@ -39,4 +39,4 @@
vm.figureOutItemsToDisplay();
}
}
})();
}());

View File

@@ -47,4 +47,4 @@
});
}
}
})();
}());

View File

@@ -74,4 +74,4 @@
$window.location.href = url;
}
}
})();
}());

View File

@@ -66,4 +66,4 @@
});
}
}
})();
}());

View File

@@ -34,4 +34,4 @@
});
}
}
})();
}());

View File

@@ -83,4 +83,4 @@
vm.imageURL = vm.user.profileImageURL;
}
}
})();
}());

View File

@@ -35,4 +35,4 @@
});
}
}
})();
}());

View File

@@ -16,12 +16,8 @@
vm.removeUserSocialAccount = removeUserSocialAccount;
// Check if there are additional accounts
function hasConnectedAdditionalSocialAccounts(provider) {
for (var i in vm.user.additionalProvidersData) {
return true;
}
return false;
function hasConnectedAdditionalSocialAccounts() {
return ($scope.user.additionalProvidersData && Object.keys($scope.user.additionalProvidersData).length);
}
// Check if provider is already in use with current user
@@ -46,4 +42,4 @@
});
}
}
})();
}());

View File

@@ -12,4 +12,4 @@
vm.user = Authentication.user;
}
})();
}());

View File

@@ -61,4 +61,4 @@
};
}
}
})();
}());

View File

@@ -28,10 +28,10 @@
if (value) {
ngModel.$validators.passwordVerify = function (password) {
var origin = scope.passwordVerify;
return (origin !== password) ? false : true;
return (origin === password);
};
}
});
}
}
})();
}());

View File

@@ -21,4 +21,4 @@
element.css('text-transform', 'lowercase');
}
}
})();
}());

View File

@@ -16,4 +16,4 @@
return auth;
}
})();
}());

View File

@@ -30,4 +30,4 @@
}
}
})();
}());

View File

@@ -16,8 +16,7 @@
});
}
//TODO this should be Users service
// TODO this should be Users service
angular
.module('users.admin.services')
.factory('AdminService', AdminService);
@@ -33,4 +32,4 @@
}
});
}
})();
}());

View File

@@ -7,4 +7,4 @@
app.registerModule('users.admin.services');
app.registerModule('users.routes', ['ui.router']);
app.registerModule('users.admin.routes', ['ui.router', 'users.admin.services']);
})(ApplicationConfiguration);
}(ApplicationConfiguration));

View File

@@ -21,7 +21,7 @@ exports.read = function (req, res) {
exports.update = function (req, res) {
var user = req.model;
//For security purposes only merge these parameters
// For security purposes only merge these parameters
user.firstName = req.body.firstName;
user.lastName = req.body.lastName;
user.displayName = user.firstName + ' ' + user.lastName;

View File

@@ -57,13 +57,13 @@ exports.changeProfilePicture = function (req, res) {
var user = req.user;
var upload = multer(config.uploads.profileUpload).single('newProfilePicture');
var profileUploadFileFilter = require(path.resolve('./config/lib/multer')).profileUploadFileFilter;
// Filtering to upload only images
upload.fileFilter = profileUploadFileFilter;
if (user) {
upload(req, res, function (uploadError) {
if(uploadError) {
if (uploadError) {
return res.status(400).send({
message: 'Error occurred while uploading profile picture'
});

View File

@@ -186,7 +186,7 @@ UserSchema.statics.generateRandomPassphrase = function () {
numbers: true,
symbols: false,
uppercase: true,
excludeSimilarCharacters: true,
excludeSimilarCharacters: true
});
// check if we need to remove any repeating characters

View File

@@ -6,7 +6,7 @@
var $scope,
Authentication;
//We can start by loading the main application module
// We can start by loading the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
@@ -98,4 +98,4 @@
});
});
})();
}());

View File

@@ -6,7 +6,7 @@
var $scope,
Authentication;
//We can start by loading the main application module
// We can start by loading the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
@@ -316,4 +316,4 @@
});
});
})();
}());

View File

@@ -299,9 +299,9 @@ describe('Users E2E Tests:', function () {
describe('Signin Validation', function () {
it('Should report missing credentials', function () {
//Make sure user is signed out first
// Make sure user is signed out first
signout();
//Sign in
// Sign in
browser.get('http://localhost:3001/authentication/signin');
// Click Submit button
element(by.css('button[type="submit"]')).click();
@@ -312,9 +312,9 @@ describe('Users E2E Tests:', function () {
});
it('Verify that the user is logged in', function() {
//Make sure user is signed out first
// Make sure user is signed out first
signout();
//Sign in
// Sign in
browser.get('http://localhost:3001/authentication/signin');
// Enter UserName
element(by.model('vm.credentials.username')).sendKeys(user1.username);
@@ -327,7 +327,7 @@ describe('Users E2E Tests:', function () {
});
describe ('Change Password Settings Validation', function () {
describe('Change Password Settings Validation', function () {
it('Should report missing passwords', function () {
browser.get('http://localhost:3001/settings/password');

View File

@@ -10,7 +10,9 @@ var should = require('should'),
/**
* Globals
*/
var user1, user2, user3;
var user1,
user2,
user3;
/**
* Unit tests

View File

@@ -10,7 +10,12 @@ var should = require('should'),
/**
* Globals
*/
var app, agent, credentials, user, _user, admin;
var app,
agent,
credentials,
user,
_user,
admin;
/**
* User routes tests
@@ -254,7 +259,7 @@ describe('User CRUD tests', function () {
}
agent.delete('/api/users/' + user._id)
//.send(userUpdate)
// .send(userUpdate)
.expect(200)
.end(function (userInfoErr, userInfoRes) {
if (userInfoErr) {
@@ -631,7 +636,7 @@ describe('User CRUD tests', function () {
var userUpdate = {
firstName: 'user_update_first',
lastName: 'user_update_last',
lastName: 'user_update_last'
};
agent.put('/api/users')
@@ -811,7 +816,7 @@ describe('User CRUD tests', function () {
var userUpdate = {
firstName: 'user_update_first',
lastName: 'user_update_last',
lastName: 'user_update_last'
};
agent.put('/api/users')

View File

@@ -68,17 +68,18 @@
},
"devDependencies": {
"coveralls": "~2.11.6",
"eslint": "~2.2.0",
"eslint-config-airbnb": "~6.0.2",
"grunt-concurrent": "~2.0.0",
"grunt-contrib-copy": "~0.8.0",
"grunt-contrib-csslint": "~0.4.0",
"grunt-contrib-cssmin": "~0.12.3",
"grunt-contrib-jshint": "~0.11.2",
"grunt-contrib-less": "~1.0.1",
"grunt-contrib-sass": "~0.9.2",
"grunt-contrib-uglify": "~0.9.1",
"grunt-contrib-watch": "~0.6.1",
"grunt-env": "~0.4.4",
"grunt-eslint": "~17.3.1",
"grunt-eslint": "~18.0.0",
"grunt-karma": "~0.12.1",
"grunt-mocha-istanbul": "~2.4.0",
"grunt-mocha-test": "~0.12.7",
@@ -95,7 +96,6 @@
"gulp-cssmin": "~0.1.7",
"gulp-eslint": "~2.0.0",
"gulp-imagemin": "~2.4.0",
"gulp-jshint": "~2.0.0",
"gulp-less": "~3.0.5",
"gulp-livereload": "~3.8.1",
"gulp-load-plugins": "~1.2.0",
@@ -109,7 +109,6 @@
"gulp-util": "~3.0.7",
"imagemin-pngquant": "~4.2.0",
"istanbul": "~0.4.2",
"jshint": "~2.9.1",
"karma": "~0.13.21",
"karma-chrome-launcher": "~0.2.2",
"karma-coverage": "~0.5.3",

View File

@@ -81,7 +81,14 @@ mg.connect(function (db) {
if (processedCount === 0) {
console.log(chalk.yellow('No users were found.'));
} else {
var alert = (!errorCount) ? chalk.green : ((successCount / processedCount) < 0.8) ? chalk.red : chalk.yellow;
var alert;
if (!errorCount) {
alert = chalk.green;
} else if ((successCount / processedCount) < 0.8) {
alert = chalk.red;
} else {
alert = chalk.yellow;
}
console.log(alert('Sent ' + successCount + ' of ' + processedCount + ' emails successfully.'));
}

View File

@@ -3,7 +3,6 @@
/**
* Module dependencies.
*/
var app;
var path = require('path');
var app = require(path.resolve('./config/lib/app'));