diff --git a/config/config.js b/config/config.js
index f2db078212..624cf2ce3f 100644
--- a/config/config.js
+++ b/config/config.js
@@ -19,7 +19,7 @@ var getGlobbedPaths = function (globPatterns, excludes) {
// The output array
var output = [];
- // If glob pattern is array so we use each pattern in a recursive way, otherwise we use glob
+ // If glob pattern is array then we use each pattern in a recursive way, otherwise we use glob
if (_.isArray(globPatterns)) {
globPatterns.forEach(function (globPattern) {
output = _.union(output, getGlobbedPaths(globPattern, excludes));
@@ -49,7 +49,7 @@ var getGlobbedPaths = function (globPatterns, excludes) {
};
/**
- * Validate NODE_ENV existance
+ * Validate NODE_ENV existence
*/
var validateEnvironmentVariable = function () {
var environmentFiles = glob.sync('./config/env/' + process.env.NODE_ENV + '.js');
@@ -127,10 +127,10 @@ var initGlobalConfigFiles = function (config, assets) {
config.files.server.policies = getGlobbedPaths(assets.server.policies);
// Setting Globbed js files
- config.files.client.js = getGlobbedPaths(assets.client.lib.js, 'public/').concat(getGlobbedPaths(assets.client.js, ['client/', 'public/']));
+ config.files.client.js = getGlobbedPaths(assets.client.lib.js, 'public/').concat(getGlobbedPaths(assets.client.js, ['public/']));
// Setting Globbed css files
- config.files.client.css = getGlobbedPaths(assets.client.lib.css, 'public/').concat(getGlobbedPaths(assets.client.css, ['client/', 'public/']));
+ config.files.client.css = getGlobbedPaths(assets.client.lib.css, 'public/').concat(getGlobbedPaths(assets.client.css, ['public/']));
// Setting Globbed test files
config.files.client.tests = getGlobbedPaths(assets.client.tests);
@@ -140,7 +140,7 @@ var initGlobalConfigFiles = function (config, assets) {
* Initialize global configuration
*/
var initGlobalConfig = function () {
- // Validate NDOE_ENV existance
+ // Validate NODE_ENV existence
validateEnvironmentVariable();
// Get the default assets
diff --git a/config/env/default.js b/config/env/default.js
index bc3e6e6010..cc09ea42f6 100644
--- a/config/env/default.js
+++ b/config/env/default.js
@@ -9,7 +9,14 @@ module.exports = {
},
port: process.env.PORT || 3000,
templateEngine: 'swig',
+ // Session details
+ // session expiration is set by default to 24 hours
+ sessionExpiration: 24 * (60 * 1000),
+ // sessionSecret should be changed for security measures and concerns
sessionSecret: 'MEAN',
+ // sessionKey is set to the generic sessionId key used by PHP applications
+ // for obsecurity reasons
+ sessionKey: 'sessionId',
sessionCollection: 'sessions',
logo: 'modules/core/img/brand/logo.png',
favicon: 'modules/core/img/brand/favicon.ico'
diff --git a/config/env/development.js b/config/env/development.js
index 1f31ec53f6..39659d564d 100644
--- a/config/env/development.js
+++ b/config/env/development.js
@@ -65,5 +65,6 @@ module.exports = {
}
}
},
- livereload: true
+ livereload: true,
+ seedDB: process.env.MONGO_SEED || false
};
diff --git a/config/env/production.js b/config/env/production.js
index 3bf482cc85..63c7f3dc45 100644
--- a/config/env/production.js
+++ b/config/env/production.js
@@ -61,5 +61,6 @@ module.exports = {
pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD'
}
}
- }
+ },
+ seedDB: process.env.MONGO_SEED || false
};
diff --git a/config/env/test.js b/config/env/test.js
index cbd9821795..2efb791e64 100644
--- a/config/env/test.js
+++ b/config/env/test.js
@@ -56,5 +56,6 @@ module.exports = {
pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD'
}
}
- }
+ },
+ seedDB: process.env.MONGO_SEED || false
};
diff --git a/config/lib/app.js b/config/lib/app.js
index 1feede39ed..76c0bf779c 100644
--- a/config/lib/app.js
+++ b/config/lib/app.js
@@ -11,6 +11,11 @@ var config = require('../config'),
// Initialize Models
mongoose.loadModels();
+//SeedDB
+if (config.seedDB) {
+ require('./seed');
+}
+
module.exports.loadModels = function loadModels() {
mongoose.loadModels();
};
diff --git a/config/lib/express.js b/config/lib/express.js
index d7f0729c46..f2152c4d55 100644
--- a/config/lib/express.js
+++ b/config/lib/express.js
@@ -115,6 +115,10 @@ module.exports.initSession = function (app, db) {
saveUninitialized: true,
resave: true,
secret: config.sessionSecret,
+ cookie: {
+ maxAge: config.sessionExpiration
+ },
+ key: config.sessionKey,
store: new MongoStore({
mongooseConnection: db.connection,
collection: config.sessionCollection
@@ -158,7 +162,7 @@ module.exports.initModulesClientRoutes = function (app) {
// Globbing static routing
config.folders.client.forEach(function (staticPath) {
- app.use(staticPath.replace('/client', ''), express.static(path.resolve('./' + staticPath)));
+ app.use(staticPath, express.static(path.resolve('./' + staticPath)));
});
};
diff --git a/config/lib/seed.js b/config/lib/seed.js
new file mode 100644
index 0000000000..f75db3a0bf
--- /dev/null
+++ b/config/lib/seed.js
@@ -0,0 +1,85 @@
+'use strict';
+
+var mongoose = require('mongoose'),
+ chalk = require('chalk'),
+ crypto = require('crypto'),
+ User = mongoose.model('User');
+
+console.log(chalk.bold.red('Warning: Database seeding is turned on'));
+
+//If production only seed admin if it does not exist
+if (process.env.NODE_ENV === 'production') {
+ //Add Local Admin
+ User.find({username: 'admin'}, function (err, users) {
+ if (users.length === 0) {
+ var password = crypto.randomBytes(64).toString('hex').slice(1, 20);
+ var user = new User({
+ username: 'admin',
+ password: password,
+ provider: 'local',
+ email: 'admin@localhost.com',
+ firstName: 'Admin',
+ lastName: 'Local',
+ displayName: 'Admin Local',
+ roles: ['user', 'admin']
+ });
+ // Then save the user
+ user.save(function (err) {
+ if (err) {
+ console.log('Failed to add local admin');
+ } else {
+ console.log(chalk.bold.red('Local admin added with password set to ' + password));
+ }
+ });
+ } else {
+ console.log('Admin user exists');
+ }
+ });
+} else {
+ //Add Local User
+ User.find({username: 'user'}).remove(function () {
+ var password = crypto.randomBytes(64).toString('hex').slice(1, 20);
+ var user = new User({
+ username: 'user',
+ password: password,
+ provider: 'local',
+ email: 'user@localhost.com',
+ firstName: 'User',
+ lastName: 'Local',
+ displayName: 'User Local',
+ roles: ['user']
+ });
+ // Then save the user
+ user.save(function (err) {
+ if (err) {
+ console.log('Failed to add local user');
+ } else {
+ console.log(chalk.bold.red('Local user added with password set to ' + password));
+ }
+ });
+ });
+
+
+ //Add Local Admin
+ User.find({username: 'admin'}).remove(function () {
+ var password = crypto.randomBytes(64).toString('hex').slice(1, 20);
+ var user = new User({
+ username: 'admin',
+ password: password,
+ provider: 'local',
+ email: 'admin@localhost.com',
+ firstName: 'Admin',
+ lastName: 'Local',
+ displayName: 'Admin Local',
+ roles: ['user', 'admin']
+ });
+ // Then save the user
+ user.save(function (err) {
+ if (err) {
+ console.log('Failed to add local admin');
+ } else {
+ console.log(chalk.bold.red('Local admin added with password set to ' + password));
+ }
+ });
+ });
+}
diff --git a/config/lib/socket.io.js b/config/lib/socket.io.js
index aa613c267c..a7bbc7b5c0 100644
--- a/config/lib/socket.io.js
+++ b/config/lib/socket.io.js
@@ -71,10 +71,15 @@ module.exports = function (app, db) {
// Use the 'cookie-parser' module to parse the request cookies
cookieParser(config.sessionSecret)(socket.request, {}, function (err) {
// Get the session id from the request cookies
- var sessionId = socket.request.signedCookies['connect.sid'];
+ var sessionId = socket.request.signedCookies ? socket.request.signedCookies[config.sessionKey] : undefined;
+
+ if (!sessionId) return next(new Error('sessionId was not found in socket.request'), false);
// Use the mongoStorage instance to get the Express session information
mongoStore.get(sessionId, function (err, session) {
+ if (err) return next(err, false);
+ if (!session) return next(new Error('session was not found for ' + sessionId), false);
+
// Set the Socket.io session information
socket.request.session = session;
diff --git a/karma.conf.js b/karma.conf.js
index cdf1cd2421..2002bb3f7e 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -21,7 +21,7 @@ module.exports = function (karmaConfig) {
moduleName: 'mean',
cacheIdFromPath: function (filepath) {
- return filepath.replace('/client', '');
+ return filepath;
},
},
diff --git a/modules/articles/client/config/articles.client.config.js b/modules/articles/client/config/articles.client.config.js
index 5ad71e82dd..c44990dc9e 100644
--- a/modules/articles/client/config/articles.client.config.js
+++ b/modules/articles/client/config/articles.client.config.js
@@ -7,7 +7,8 @@ angular.module('articles').run(['Menus',
Menus.addMenuItem('topbar', {
title: 'Articles',
state: 'articles',
- type: 'dropdown'
+ type: 'dropdown',
+ roles: ['*']
});
// Add the dropdown list item
@@ -19,7 +20,8 @@ angular.module('articles').run(['Menus',
// Add the dropdown create item
Menus.addSubMenuItem('topbar', 'articles', {
title: 'Create Articles',
- state: 'articles.create'
+ state: 'articles.create',
+ roles: ['user']
});
}
]);
diff --git a/modules/articles/client/config/articles.client.routes.js b/modules/articles/client/config/articles.client.routes.js
index 0b90b2dfef..e687d8601e 100644
--- a/modules/articles/client/config/articles.client.routes.js
+++ b/modules/articles/client/config/articles.client.routes.js
@@ -8,31 +8,84 @@ angular.module('articles').config(['$stateProvider',
.state('articles', {
abstract: true,
url: '/articles',
- template: '',
- controller: 'ArticlesController'
+ template: ''
})
.state('articles.list', {
url: '',
- templateUrl: 'modules/articles/views/list-articles.client.view.html',
- controller: 'ArticlesListController'
+ templateUrl: 'modules/articles/client/views/list-articles.client.view.html',
+ controller: 'ArticlesListController',
+ resolve:{
+ articles: function (Articles, $stateParams, $state) {
+ return Articles.query().$promise.then(
+ function (articles) {
+ //success
+ return articles;
+ },
+ function () {
+ //fail
+ $state.go('not-found');
+ }
+ );
+ }
+ }
})
.state('articles.create', {
url: '/create',
- templateUrl: 'modules/articles/views/create-article.client.view.html',
- controller: 'ArticlesCreateController',
+ templateUrl: 'modules/articles/client/views/create-article.client.view.html',
+ controller: 'ArticlesController',
data: {
roles: ['user', 'admin']
+ },
+ resolve: {
+ article: function () {
+ return { mock: 'mock' };
+ }
}
})
.state('articles.view', {
url: '/:articleId',
- templateUrl: 'modules/articles/views/view-article.client.view.html',
- controller: 'ArticlesViewController'
+ templateUrl: 'modules/articles/client/views/view-article.client.view.html',
+ controller: 'ArticlesController',
+ resolve: {
+ article: function (Articles, $stateParams, $state) {
+ return Articles.get({
+ articleId: $stateParams.articleId
+ }).$promise.then(
+ function (article) {
+ //success
+ return article;
+ },
+ function () {
+ //fail
+ $state.go('not-found');
+ }
+ );
+ }
+ }
})
.state('articles.edit', {
url: '/:articleId/edit',
- templateUrl: 'modules/articles/views/edit-article.client.view.html',
- controller: 'ArticlesEditController',
+ templateUrl: 'modules/articles/client/views/edit-article.client.view.html',
+ controller: 'ArticlesController',
+ resolve: {
+ article: function (Articles, $stateParams, $state) {
+ return Articles.get({
+ articleId: $stateParams.articleId
+ }).$promise.then(
+ function (article) {
+ //Auth Check
+ if (article === undefined || typeof article !== 'object' || article._id === undefined) {
+ $state.go('unauthorized');
+ }
+ return article;
+ },
+ function () {
+ //fail
+ $state.go('not-found');
+ }
+ );
+ }
+ },
data: {
roles: ['user', 'admin']
}
diff --git a/modules/articles/client/controllers/articles.client.controller.js b/modules/articles/client/controllers/articles.client.controller.js
index 65a0c2c9a3..d62d6c7121 100644
--- a/modules/articles/client/controllers/articles.client.controller.js
+++ b/modules/articles/client/controllers/articles.client.controller.js
@@ -2,58 +2,10 @@
// Articles controller
angular.module('articles')
-.controller('ArticlesListController', ['$scope', '$state', 'Articles',
- function ($scope, $stateParams, Articles) {
- //Query Articles
- $scope.articles = Articles.query();
- }
-])
-.controller('ArticlesViewController', ['$scope', '$state', '$stateParams', 'Articles',
- function ($scope, $state, $stateParams, Articles) {
- //Check if article is loaded if not load it
- if ($scope.article === undefined || typeof $scope.article !== 'object' || $scope.article._id === undefined || $scope.article._id !== $stateParams.articleId) {
- $scope.loadArticleById($stateParams.articleId);
- }
-
- // Remove existing Article
- $scope.remove = function () {
- $scope.authCheck();
- if (confirm('Are you sure you want to delete?')) {
- $scope.article.$remove(function (article) {
- if ($scope.articles !== undefined && $scope.articles.length > 0) {
- $scope.articles.splice($scope.articles.indexOf($scope.article), 1);
- }
- $state.go('articles.list');
- });
- }
- };
- }
-])
-.controller('ArticlesEditController', ['$scope', '$state', '$stateParams', 'Authentication', 'Articles',
- function ($scope, $state, $stateParams, Authentication, Articles) {
+.controller('ArticlesController', ['$scope', 'article', '$stateParams', '$state', 'Authentication', 'Articles',
+ function ($scope, article, $stateParams, $state, Authentication, Articles) {
+ $scope.article = article;
- //Check if article is loaded if not load it
- if ($scope.article === undefined || typeof $scope.article !== 'object' || $scope.article._id === undefined || $scope.article._id !== $stateParams.articleId) {
- $scope.loadArticleById($stateParams.articleId);
- }
-
- //Auth Check on Edit Route
- $scope.authCheck();
-
- $scope.update = function () {
- var article = $scope.article;
-
- article.$update(function () {
- $state.go('articles.view',{articleId: article._id});
- }, function (errorResponse) {
- $scope.error = errorResponse.data.message;
- });
- };
- }
-])
-.controller('ArticlesCreateController', ['$scope', '$state', '$stateParams', 'Authentication', 'Articles',
- function ($scope, $state, $stateParams, Authentication, Articles) {
- // Create new Article
$scope.create = function () {
// Create new Article object
var article = new Articles({
@@ -72,32 +24,27 @@ angular.module('articles')
$scope.error = errorResponse.data.message;
});
};
- }
-])
-.controller('ArticlesController', ['$scope', '$stateParams', '$state', 'Authentication', 'Articles',
- function ($scope, $stateParams, $state, Authentication, Articles) {
- $scope.loadArticleById = function (id) {
- $scope.article = Articles.get({
- articleId: id
- });
+ $scope.update = function () {
+ var article = $scope.article;
- $scope.article.$promise.then(function (article) {
- if (article === undefined || typeof article !== 'object' || article._id === undefined) {
- //Article not found
- $state.go('not-found');
- }
+ article.$update(function () {
+ $state.go('articles.view',{articleId: article._id});
+ }, function (errorResponse) {
+ $scope.error = errorResponse.data.message;
});
};
- $scope.authCheck = function () {
- $scope.article.$promise.then(function (article) {
- //Make sure user is authorized if not on the view state
- if ($scope.article.user._id !== Authentication.user._id) {
- //TODO Change to unauthorized when that PR is merged
+ // Remove existing Article
+ $scope.remove = function () {
+ if (confirm('Are you sure you want to delete?')) {
+ $scope.article.$remove(function (article) {
+ if ($scope.articles !== undefined && $scope.articles.length > 0) {
+ $scope.articles.splice($scope.articles.indexOf($scope.article), 1);
+ }
$state.go('articles.list');
- }
- });
+ });
+ }
};
//Not sure if this is needed anymore?
diff --git a/modules/articles/client/controllers/articles.client.list.controller.js b/modules/articles/client/controllers/articles.client.list.controller.js
new file mode 100644
index 0000000000..5384b4b7c0
--- /dev/null
+++ b/modules/articles/client/controllers/articles.client.list.controller.js
@@ -0,0 +1,10 @@
+'use strict';
+
+// Articles List controller
+angular.module('articles')
+.controller('ArticlesListController', ['$scope', 'articles',
+ function ($scope, articles) {
+ //Query Articles
+ $scope.articles = articles;
+ }
+]);
diff --git a/modules/chat/client/config/chat.client.routes.js b/modules/chat/client/config/chat.client.routes.js
index d289e22d01..38649c6802 100644
--- a/modules/chat/client/config/chat.client.routes.js
+++ b/modules/chat/client/config/chat.client.routes.js
@@ -6,7 +6,7 @@ angular.module('chat').config(['$stateProvider',
$stateProvider
.state('chat', {
url: '/chat',
- templateUrl: 'modules/chat/views/chat.client.view.html',
+ templateUrl: 'modules/chat/client/views/chat.client.view.html',
data: {
roles: ['user', 'admin']
}
diff --git a/modules/core/client/config/core.client.routes.js b/modules/core/client/config/core.client.routes.js
index e9e64c82cf..a0e383a67d 100644
--- a/modules/core/client/config/core.client.routes.js
+++ b/modules/core/client/config/core.client.routes.js
@@ -11,11 +11,11 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider',
$stateProvider
.state('home', {
url: '/',
- templateUrl: 'modules/core/views/home.client.view.html'
+ templateUrl: 'modules/core/client/views/home.client.view.html'
})
.state('not-found', {
url: '/not-found',
- templateUrl: 'modules/core/views/404.client.view.html'
+ templateUrl: 'modules/core/client/views/404.client.view.html'
});
}
]);
diff --git a/modules/core/client/services/menus.client.service.js b/modules/core/client/services/menus.client.service.js
index df9b5eafe2..7d18f0cc10 100644
--- a/modules/core/client/services/menus.client.service.js
+++ b/modules/core/client/services/menus.client.service.js
@@ -4,27 +4,26 @@
angular.module('core').service('Menus', [
function () {
// Define a set of default roles
- this.defaultRoles = ['*'];
+ this.defaultRoles = ['user', 'admin'];
// Define the menus object
this.menus = {};
// A private function for rendering decision
var shouldRender = function (user) {
- if (user) {
- if (!!~this.roles.indexOf('*')) {
- return true;
- } else {
- for (var userRoleIndex in user.roles) {
- for (var roleIndex in this.roles) {
- if (this.roles[roleIndex] === user.roles[userRoleIndex]) {
- return true;
- }
+ if (!!~this.roles.indexOf('*')) {
+ return true;
+ } else {
+ 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;
}
}
}
- } else {
- return this.isPublic;
}
return false;
@@ -60,7 +59,6 @@ angular.module('core').service('Menus', [
// Create the new menu
this.menus[menuId] = {
- isPublic: ((options.isPublic === null || typeof options.isPublic === 'undefined') ? true : options.isPublic),
roles: options.roles || this.defaultRoles,
items: options.items || [],
shouldRender: shouldRender
@@ -92,8 +90,7 @@ angular.module('core').service('Menus', [
state: options.state || '',
type: options.type || 'item',
class: options.class,
- isPublic: ((options.isPublic === null || typeof options.isPublic === 'undefined') ? this.menus[menuId].isPublic : options.isPublic),
- roles: ((options.roles === null || typeof options.roles === 'undefined') ? this.menus[menuId].roles : options.roles),
+ roles: ((options.roles === null || typeof options.roles === 'undefined') ? this.defaultRoles : options.roles),
position: options.position || 0,
items: [],
shouldRender: shouldRender
@@ -102,7 +99,7 @@ angular.module('core').service('Menus', [
// Add submenu items
if (options.items) {
for (var i in options.items) {
- this.addSubMenuItem(menuId, options.link, options.items[i]);
+ this.addSubMenuItem(menuId, options.state, options.items[i]);
}
}
@@ -124,7 +121,6 @@ angular.module('core').service('Menus', [
this.menus[menuId].items[itemIndex].items.push({
title: options.title || '',
state: options.state || '',
- isPublic: ((options.isPublic === null || typeof options.isPublic === 'undefined') ? this.menus[menuId].items[itemIndex].isPublic : options.isPublic),
roles: ((options.roles === null || typeof options.roles === 'undefined') ? this.menus[menuId].items[itemIndex].roles : options.roles),
position: options.position || 0,
shouldRender: shouldRender
@@ -137,13 +133,13 @@ angular.module('core').service('Menus', [
};
// Remove existing menu object by menu id
- this.removeMenuItem = function (menuId, menuItemURL) {
+ this.removeMenuItem = function (menuId, menuItemState) {
// Validate that the menu exists
this.validateMenuExistance(menuId);
// Search for menu item to remove
for (var itemIndex in this.menus[menuId].items) {
- if (this.menus[menuId].items[itemIndex].link === menuItemURL) {
+ if (this.menus[menuId].items[itemIndex].state === menuItemState) {
this.menus[menuId].items.splice(itemIndex, 1);
}
}
@@ -153,14 +149,14 @@ angular.module('core').service('Menus', [
};
// Remove existing menu object by menu id
- this.removeSubMenuItem = function (menuId, submenuItemURL) {
+ this.removeSubMenuItem = function (menuId, submenuItemState) {
// Validate that the menu exists
this.validateMenuExistance(menuId);
// 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].link === submenuItemURL) {
+ if (this.menus[menuId].items[itemIndex].items[subitemIndex].state === submenuItemState) {
this.menus[menuId].items[itemIndex].items.splice(subitemIndex, 1);
}
}
@@ -172,7 +168,7 @@ angular.module('core').service('Menus', [
//Adding the topbar menu
this.addMenu('topbar', {
- isPublic: false
+ roles: ['*']
});
}
]);
diff --git a/modules/core/client/views/home.client.view.html b/modules/core/client/views/home.client.view.html
index b34905cdfc..ddba60a490 100644
--- a/modules/core/client/views/home.client.view.html
+++ b/modules/core/client/views/home.client.view.html
@@ -2,7 +2,7 @@
-
+
diff --git a/modules/core/server/views/layout.server.view.html b/modules/core/server/views/layout.server.view.html
index 7f8c83934f..590776071e 100644
--- a/modules/core/server/views/layout.server.view.html
+++ b/modules/core/server/views/layout.server.view.html
@@ -36,7 +36,7 @@
-
+
{% block content %}{% endblock %}
diff --git a/modules/core/tests/client/menus.client.service.tests.js b/modules/core/tests/client/menus.client.service.tests.js
index e693eae448..5bded019be 100644
--- a/modules/core/tests/client/menus.client.service.tests.js
+++ b/modules/core/tests/client/menus.client.service.tests.js
@@ -17,12 +17,8 @@
expect(Menus.menus.topbar).toBeDefined();
});
- it('should have private topbar', function() {
- expect(Menus.menus.topbar.isPublic).toBeFalsy();
- });
-
- it('should have default roles to *', function() {
- expect(Menus.defaultRoles).toEqual(['*']);
+ it('should have default roles to user and admin', function() {
+ expect(Menus.defaultRoles).toEqual(['user', 'admin']);
});
describe('addMenu', function() {
@@ -45,12 +41,8 @@
expect(menu.items).toEqual([]);
});
- it('should be public by default', function() {
- expect(menu.isPublic).toBeTruthy();
- });
-
it('should set shouldRender to shouldRender function handle', function() {
- expect(menu.shouldRender()).toBeTruthy();
+ expect(menu.shouldRender()).toBeFalsy();
});
});
@@ -64,17 +56,6 @@
menu = Menus.addMenu('menu1', options);
});
- it('should set isPublic to true if options.isPublic equal to null', function() {
- var menu = Menus.addMenu('menu1', {
- isPublic: null
- });
- expect(menu.isPublic).toBeTruthy();
- });
-
- it('should set isPublic to true if options.isPublic equal to undefined', function() {
- expect(menu.isPublic).toBeTruthy();
- });
-
it('should set items to options.items list', function() {
expect(menu.items).toBe(options.items);
});
@@ -200,7 +181,6 @@
class: 'class',
isPublic: false,
roles: ['a', 'b'],
- link: 'link',
position: 2,
items: [subMenuItem1, subMenuItem2]
},
@@ -250,17 +230,13 @@
expect(menuItem.class).toBe(menuItemOptions.class);
});
- it('should set menu item isPublic to options isPublic', function() {
- expect(menuItem.isPublic).toBe(menuItemOptions.isPublic);
- });
-
it('should set menu item position to options position', function() {
expect(menuItem.position).toBe(menuItemOptions.position);
});
it('should call addSubMenuItem for each item in options', function() {
- expect(Menus.addSubMenuItem).toHaveBeenCalledWith(menuId, menuItemOptions.link, subMenuItem1);
- expect(Menus.addSubMenuItem).toHaveBeenCalledWith(menuId, menuItemOptions.link, subMenuItem2);
+ expect(Menus.addSubMenuItem).toHaveBeenCalledWith(menuId, menuItemOptions.state, subMenuItem1);
+ expect(Menus.addSubMenuItem).toHaveBeenCalledWith(menuId, menuItemOptions.state, subMenuItem2);
});
});
@@ -278,12 +254,12 @@
expect(menuItem.title).toBe('');
});
- it('should set menu item isPublic to menu.isPublic', function() {
- expect(menuItem.isPublic).toBe(menu.isPublic);
+ it('should set menu item isPublic to false', function() {
+ expect(menuItem.isPublic).toBeFalsy();
});
- it('should set menu item roles to menu roles', function() {
- expect(menuItem.roles).toEqual(menu.roles);
+ it('should set menu item roles to default roles', function() {
+ expect(menuItem.roles).toEqual(Menus.defaultRoles);
});
it('should set menu item position to 0', function() {
@@ -294,22 +270,16 @@
describe('removeMenuItem', function() {
var menuId = 'menuId',
- menuItemURL = 'url',
- menuItem1 = {
- link: menuItemURL
- },
- menuItem2 = {
- link: ''
- },
- newMenu = {
- items: [menuItem1, menuItem2]
- },
- menu = null;
+ menuItemState = 'menu.state1',
+ menuItemState2 = 'menu.state2',
+ menu;
beforeEach(function() {
- Menus.menus.menuId = newMenu;
+ Menus.addMenu(menuId);
+ Menus.addMenuItem(menuId, { state: menuItemState });
+ Menus.addMenuItem(menuId, { state: menuItemState2 });
Menus.validateMenuExistance = jasmine.createSpy();
- menu = Menus.removeMenuItem(menuId, menuItemURL);
+ menu = Menus.removeMenuItem(menuId, menuItemState);
});
it('should return menu object', function() {
@@ -320,55 +290,60 @@
expect(Menus.validateMenuExistance).toHaveBeenCalledWith(menuId);
});
- it('should remove sub menu items with same link', function() {
+ it('should remove sub menu items with same state', function() {
expect(menu.items.length).toBe(1);
- expect(menu.items[0]).toBe(menuItem2);
+ expect(menu.items[0].state).toBe(menuItemState2);
});
});
describe('addSubMenuItem', function() {
var subItemOptions = {
title: 'title',
- state: 'state',
+ state: 'sub.state',
isPublic: false,
roles: ['a', 'b'],
position: 4
};
var menuId = 'menu1',
- menuItem1 = {
- state: 'state',
+ menuItem1Options = {
+ state: 'item1.state',
items: [],
isPublic: false
},
- menuItem2 = {
- state: 'state2',
+ menuItem2Options = {
+ state: 'item2.state2',
items: [],
isPublic: true,
roles: ['a']
},
- menuItem3 = {
- state: 'state3',
- items: []
- },
- newMenu = {
- items: [menuItem1, menuItem2, menuItem3]
- },
+ menuItem1,
+ menuItem2,
+ menuItem3,
+ subItem1,
+ subItem2,
menu;
beforeEach(function() {
Menus.validateMenuExistance = jasmine.createSpy();
- Menus.menus[menuId] = newMenu;
- Menus.addSubMenuItem(menuId, menuItem1.state, subItemOptions);
- menu = Menus.addSubMenuItem(menuId, menuItem2.state);
+ Menus.addMenu(menuId);
+ Menus.addMenuItem(menuId, menuItem1Options);
+ Menus.addMenuItem(menuId, menuItem2Options);
+ Menus.addMenuItem(menuId, {state:'something.else'});
+ Menus.addSubMenuItem(menuId, menuItem1Options.state, subItemOptions);
+ menu = Menus.addSubMenuItem(menuId, menuItem1Options.state);
+ menuItem1 = menu.items[0];
+ menuItem2 = menu.items[1];
+ menuItem3 = menu.items[2];
+ subItem1 = menuItem1.items[0];
+ subItem2 = menuItem1.items[1];
});
afterEach(function() {
- menuItem1.items = [];
- menuItem2.items = [];
+ Menus.removeMenu(menuId);
});
it('should return menu object', function() {
- expect(menu).toEqual(newMenu);
+ expect(menu).not.toBeNull();
});
it('should validate menu existance', function() {
@@ -380,109 +355,75 @@
});
it('should set shouldRender', function() {
- expect(menuItem1.items[0].shouldRender).toBeDefined();
+ expect(subItem1.shouldRender).toBeDefined();
});
describe('with options set', function() {
- var subMenuItem;
- beforeEach(function() {
- subMenuItem = menuItem1.items[0];
- });
-
it('should add sub menu item to menu item', function() {
- expect(menuItem1.items.length).toBe(1);
- });
-
- it('should set isPublic to options isPublic', function() {
- expect(subMenuItem.isPublic).toBe(subItemOptions.isPublic);
+ expect(subItem1).toBeDefined();
});
it('should set title to options title', function() {
- expect(subMenuItem.title).toBe(subItemOptions.title);
+ expect(subItem1.title).toBe(subItemOptions.title);
});
it('should set state to options state', function() {
- expect(subMenuItem.state).toBe(subItemOptions.state);
+ expect(subItem1.state).toBe(subItemOptions.state);
});
it('should set roles to options roles', function() {
- expect(subMenuItem.roles).toEqual(subItemOptions.roles);
+ expect(subItem1.roles).toEqual(subItemOptions.roles);
});
it('should set position to options position', function() {
- expect(subMenuItem.position).toEqual(subItemOptions.position);
+ expect(subItem1.position).toEqual(subItemOptions.position);
});
});
describe('without optoins set', function() {
- var subMenuItem;
- beforeEach(function() {
- subMenuItem = menuItem2.items[0];
- });
-
it('should add sub menu item to menu item', function() {
- expect(menuItem2.items.length).toBe(1);
+ expect(subItem2).toBeDefined();
});
it('should set isPublic to parent isPublic', function() {
- expect(subMenuItem.isPublic).toBe(menuItem2.isPublic);
+ expect(subItem2.isPublic).toBe(menuItem1.isPublic);
});
it('should set title to blank', function() {
- expect(subMenuItem.title).toBe('');
+ expect(subItem2.title).toBe('');
});
it('should set state to blank', function() {
- expect(subMenuItem.state).toBe('');
+ expect(subItem2.state).toBe('');
});
it('should set roles to parent roles', function() {
- expect(subMenuItem.roles).toEqual(menuItem2.roles);
+ expect(subItem2.roles).toEqual(menuItem1.roles);
});
it('should set position to 0', function() {
- expect(subMenuItem.position).toBe(0);
+ expect(subItem2.position).toBe(0);
});
});
- });
-
- describe('removeSubMenuItem', function() {
- var menuId = 'menu1',
- subMenuItem1 = {
- link: 'link1'
- },
- subMenuItem2 = {
- link: 'link2'
- },
- menuItem1 = {
- state: 'state',
- items: [subMenuItem1, subMenuItem2],
- },
- menuItem2 = {
- state: 'state2',
- items: [],
- },
- newMenu = {
- items: [menuItem1, menuItem2]
- },
- menu;
- beforeEach(function() {
- Menus.validateMenuExistance = jasmine.createSpy();
- Menus.menus[menuId] = newMenu;
- menu = Menus.removeSubMenuItem(menuId, subMenuItem1.link);
- });
-
- it('should validate menu existance', function() {
- expect(Menus.validateMenuExistance).toHaveBeenCalledWith(menuId);
- });
-
- it('should return menu object', function() {
- expect(menu).toEqual(newMenu);
- });
-
- it('should remove sub menu item', function() {
- expect(menuItem1.items.length).toBe(1);
- expect(menuItem1.items[0]).toEqual(subMenuItem2);
+
+ 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);
+ });
});
});
});
diff --git a/modules/users/client/config/users-admin.client.routes.js b/modules/users/client/config/users-admin.client.routes.js
index fc9cb42d23..b15154e95f 100644
--- a/modules/users/client/config/users-admin.client.routes.js
+++ b/modules/users/client/config/users-admin.client.routes.js
@@ -6,12 +6,12 @@ angular.module('users.admin.routes').config(['$stateProvider',
$stateProvider
.state('admin.users', {
url: '/users',
- templateUrl: 'modules/users/views/admin/user-list.client.view.html',
+ templateUrl: 'modules/users/client/views/admin/user-list.client.view.html',
controller: 'UserListController'
})
.state('admin.user', {
url: '/users/:userId',
- templateUrl: 'modules/users/views/admin/user.client.view.html',
+ templateUrl: 'modules/users/client/views/admin/user.client.view.html',
controller: 'UserController',
resolve: {
userResolve: ['$stateParams', 'Admin', function ($stateParams, Admin) {
@@ -23,7 +23,7 @@ angular.module('users.admin.routes').config(['$stateProvider',
})
.state('admin.user-edit', {
url: '/users/:userId/edit',
- templateUrl: 'modules/users/views/admin/user-edit.client.view.html',
+ templateUrl: 'modules/users/client/views/admin/user-edit.client.view.html',
controller: 'UserController',
resolve: {
userResolve: ['$stateParams', 'Admin', function ($stateParams, Admin) {
diff --git a/modules/users/client/config/users.client.routes.js b/modules/users/client/config/users.client.routes.js
index b5c9efa9b9..36ef995c55 100644
--- a/modules/users/client/config/users.client.routes.js
+++ b/modules/users/client/config/users.client.routes.js
@@ -8,39 +8,39 @@ angular.module('users').config(['$stateProvider',
.state('settings', {
abstract: true,
url: '/settings',
- templateUrl: 'modules/users/views/settings/settings.client.view.html',
+ templateUrl: 'modules/users/client/views/settings/settings.client.view.html',
data: {
roles: ['user', 'admin']
}
})
.state('settings.profile', {
url: '/profile',
- templateUrl: 'modules/users/views/settings/edit-profile.client.view.html'
+ templateUrl: 'modules/users/client/views/settings/edit-profile.client.view.html'
})
.state('settings.password', {
url: '/password',
- templateUrl: 'modules/users/views/settings/change-password.client.view.html'
+ templateUrl: 'modules/users/client/views/settings/change-password.client.view.html'
})
.state('settings.accounts', {
url: '/accounts',
- templateUrl: 'modules/users/views/settings/manage-social-accounts.client.view.html'
+ templateUrl: 'modules/users/client/views/settings/manage-social-accounts.client.view.html'
})
.state('settings.picture', {
url: '/picture',
- templateUrl: 'modules/users/views/settings/change-profile-picture.client.view.html'
+ templateUrl: 'modules/users/client/views/settings/change-profile-picture.client.view.html'
})
.state('authentication', {
abstract: true,
url: '/authentication',
- templateUrl: 'modules/users/views/authentication/authentication.client.view.html'
+ templateUrl: 'modules/users/client/views/authentication/authentication.client.view.html'
})
.state('authentication.signup', {
url: '/signup',
- templateUrl: 'modules/users/views/authentication/signup.client.view.html'
+ templateUrl: 'modules/users/client/views/authentication/signup.client.view.html'
})
.state('authentication.signin', {
url: '/signin?err',
- templateUrl: 'modules/users/views/authentication/signin.client.view.html'
+ templateUrl: 'modules/users/client/views/authentication/signin.client.view.html'
})
.state('password', {
abstract: true,
@@ -49,7 +49,7 @@ angular.module('users').config(['$stateProvider',
})
.state('password.forgot', {
url: '/forgot',
- templateUrl: 'modules/users/views/password/forgot-password.client.view.html'
+ templateUrl: 'modules/users/client/views/password/forgot-password.client.view.html'
})
.state('password.reset', {
abstract: true,
@@ -58,15 +58,15 @@ angular.module('users').config(['$stateProvider',
})
.state('password.reset.invalid', {
url: '/invalid',
- templateUrl: 'modules/users/views/password/reset-password-invalid.client.view.html'
+ templateUrl: 'modules/users/client/views/password/reset-password-invalid.client.view.html'
})
.state('password.reset.success', {
url: '/success',
- templateUrl: 'modules/users/views/password/reset-password-success.client.view.html'
+ templateUrl: 'modules/users/client/views/password/reset-password-success.client.view.html'
})
.state('password.reset.form', {
url: '/:token',
- templateUrl: 'modules/users/views/password/reset-password.client.view.html'
+ templateUrl: 'modules/users/client/views/password/reset-password.client.view.html'
});
}
]);
diff --git a/modules/users/client/views/admin/user-edit.client.view.html b/modules/users/client/views/admin/user-edit.client.view.html
index 54f4a60ff8..46c8e349f2 100644
--- a/modules/users/client/views/admin/user-edit.client.view.html
+++ b/modules/users/client/views/admin/user-edit.client.view.html
@@ -1,6 +1,6 @@