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 @@
- MEAN.JS + MEAN.JS

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 @@
diff --git a/modules/users/client/views/authentication/authentication.client.view.html b/modules/users/client/views/authentication/authentication.client.view.html index af052fad2d..698a4d5199 100644 --- a/modules/users/client/views/authentication/authentication.client.view.html +++ b/modules/users/client/views/authentication/authentication.client.view.html @@ -1,12 +1,12 @@

Sign in using your social accounts

- - - - - - + + + + + +
diff --git a/modules/users/client/views/settings/manage-social-accounts.client.view.html b/modules/users/client/views/settings/manage-social-accounts.client.view.html index f07ad9ca1f..39d9c431b0 100644 --- a/modules/users/client/views/settings/manage-social-accounts.client.view.html +++ b/modules/users/client/views/settings/manage-social-accounts.client.view.html @@ -2,7 +2,7 @@

Connected social accounts: