diff --git a/bower.json b/bower.json
index 951e48aaac..38be8f6194 100644
--- a/bower.json
+++ b/bower.json
@@ -11,6 +11,7 @@
"angular-bootstrap": "~0.11.0",
"angular-ui-utils": "~0.1.1",
"angular-ui-router": "~0.2.10",
- "angular-file-upload": "~1.1.5"
+ "angular-file-upload": "~1.1.5",
+ "angular-json-tree": "*"
}
}
diff --git a/config/assets/default.js b/config/assets/default.js
index 42f1b1062a..4377b7fd1c 100644
--- a/config/assets/default.js
+++ b/config/assets/default.js
@@ -5,7 +5,8 @@ module.exports = {
lib: {
css: [
'public/lib/bootstrap/dist/css/bootstrap.css',
- 'public/lib/bootstrap/dist/css/bootstrap-theme.css'
+ 'public/lib/bootstrap/dist/css/bootstrap-theme.css',
+ 'public/lib/angular-json-tree/build/angular-json-tree.css'
],
js: [
'public/lib/angular/angular.js',
@@ -14,7 +15,8 @@ module.exports = {
'public/lib/angular-ui-router/release/angular-ui-router.js',
'public/lib/angular-ui-utils/ui-utils.js',
'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
- 'public/lib/angular-file-upload/angular-file-upload.js'
+ 'public/lib/angular-file-upload/angular-file-upload.js',
+ 'public/lib/angular-json-tree/build/angular-json-tree.min.js'
],
tests: ['public/lib/angular-mocks/angular-mocks.js']
},
diff --git a/config/env/development.js b/config/env/development.js
index 310189454b..abf0ff9afe 100644
--- a/config/env/development.js
+++ b/config/env/development.js
@@ -6,30 +6,30 @@ module.exports = {
title: 'MEAN.JS - Development Environment'
},
facebook: {
- clientID: process.env.FACEBOOK_ID || 'APP_ID',
- clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
- callbackURL: '/api/auth/facebook/callback'
- },
- twitter: {
- clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
- clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
- callbackURL: '/api/auth/twitter/callback'
- },
- google: {
- clientID: process.env.GOOGLE_ID || 'APP_ID',
- clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
- callbackURL: '/api/auth/google/callback'
- },
- linkedin: {
- clientID: process.env.LINKEDIN_ID || 'APP_ID',
- clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
- callbackURL: '/api/auth/linkedin/callback'
- },
- github: {
- clientID: process.env.GITHUB_ID || 'APP_ID',
- clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
- callbackURL: '/api/auth/github/callback'
- },
+ clientID: process.env.FACEBOOK_ID || 'APP_ID',
+ clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
+ callbackURL: '/api/auth/facebook/callback'
+ },
+ twitter: {
+ clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
+ clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
+ callbackURL: '/api/auth/twitter/callback'
+ },
+ google: {
+ clientID: process.env.GOOGLE_ID || 'APP_ID',
+ clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
+ callbackURL: '/api/auth/google/callback'
+ },
+ linkedin: {
+ clientID: process.env.LINKEDIN_ID || 'APP_ID',
+ clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
+ callbackURL: '/api/auth/linkedin/callback'
+ },
+ github: {
+ clientID: process.env.GITHUB_ID || 'APP_ID',
+ clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
+ callbackURL: '/api/auth/github/callback'
+ },
mailer: {
from: process.env.MAILER_FROM || 'MAILER_FROM',
options: {
diff --git a/gruntfile.js b/gruntfile.js
index e8abfe71ab..584cf1331e 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -138,8 +138,8 @@ module.exports = function (grunt) {
expand: true,
src: defaultAssets.client.sass,
ext: '.css',
- rename: function(base, src) {
- return src.replace('/scss/', '/css/');
+ rename: function (base, src) {
+ return src.replace('/scss/', '/css/');
}
}]
}
@@ -150,8 +150,8 @@ module.exports = function (grunt) {
expand: true,
src: defaultAssets.client.less,
ext: '.css',
- rename: function(base, src) {
- return src.replace('/less/', '/css/');
+ rename: function (base, src) {
+ return src.replace('/less/', '/css/');
}
}]
}
@@ -203,14 +203,14 @@ module.exports = function (grunt) {
}
});
- // Load NPM tasks
+ // Load NPM tasks
require('load-grunt-tasks')(grunt);
// Making grunt default to force in order not to break the project.
grunt.option('force', true);
// Connect to the MongoDB instance and load the models
- grunt.task.registerTask('mongoose', 'Task that connects to the MongoDB instance and loads the application models.', function() {
+ grunt.task.registerTask('mongoose', 'Task that connects to the MongoDB instance and loads the application models.', function () {
// Get the callback
var done = this.async();
@@ -218,7 +218,7 @@ module.exports = function (grunt) {
var mongoose = require('./config/lib/mongoose.js');
// Connect to database
- mongoose.connect(function(db) {
+ mongoose.connect(function (db) {
done();
});
});
diff --git a/modules/core/server/controllers/errors.server.controller.js b/modules/core/server/controllers/errors.server.controller.js
index db81a8ec86..ae1497c274 100644
--- a/modules/core/server/controllers/errors.server.controller.js
+++ b/modules/core/server/controllers/errors.server.controller.js
@@ -3,14 +3,14 @@
/**
* Get unique error field name
*/
-var getUniqueErrorMessage = function(err) {
+var getUniqueErrorMessage = function (err) {
var output;
try {
var fieldName = err.err.substring(err.err.lastIndexOf('.$') + 2, err.err.lastIndexOf('_1'));
output = fieldName.charAt(0).toUpperCase() + fieldName.slice(1) + ' already exist';
- } catch(ex) {
+ } catch (ex) {
output = 'Unique field already exist';
}
@@ -20,9 +20,9 @@ var getUniqueErrorMessage = function(err) {
/**
* Get the error message from error object
*/
-exports.getErrorMessage = function(err) {
+exports.getErrorMessage = function (err) {
var message = '';
-
+
if (err.code) {
switch (err.code) {
case 11000:
@@ -33,6 +33,9 @@ exports.getErrorMessage = function(err) {
message = 'Something went wrong';
}
} else {
+ if (!err.errors && err.message) {
+ return err.message;
+ }
for (var errName in err.errors) {
if (err.errors[errName].message) message = err.errors[errName].message;
}
diff --git a/modules/users/client/config/users.client.routes.js b/modules/users/client/config/users.client.routes.js
index 9b0546360e..71e2300f6f 100644
--- a/modules/users/client/config/users.client.routes.js
+++ b/modules/users/client/config/users.client.routes.js
@@ -64,6 +64,15 @@ angular.module('users').config(['$stateProvider',
state('password.reset.form', {
url: '/:token',
templateUrl: 'modules/users/views/password/reset-password.client.view.html'
+ }).
+ state('admin', {
+ abstract: true,
+ url: '/admin',
+ template: ''
+ }).
+ state('admin.users', {
+ url: '/users',
+ templateUrl: 'modules/users/views/admin/users.list.client.view.html'
});
}
]);
diff --git a/modules/users/client/controllers/admin/users.client.controller.js b/modules/users/client/controllers/admin/users.client.controller.js
new file mode 100644
index 0000000000..d1266e4c3c
--- /dev/null
+++ b/modules/users/client/controllers/admin/users.client.controller.js
@@ -0,0 +1,13 @@
+'use strict';
+
+angular.module('users').controller('AdminUsersController', ['$scope', 'Users', 'Authentication',
+ function ($scope, Users, Authentication) {
+
+ $scope.rows = Users.query();
+
+ $scope.identityToLink = function (identity) {
+ return 'noneYet';
+ };
+
+ }
+]);
diff --git a/modules/users/client/controllers/settings.client.controller.js b/modules/users/client/controllers/settings.client.controller.js
index 70b16c5151..2cbb830f05 100644
--- a/modules/users/client/controllers/settings.client.controller.js
+++ b/modules/users/client/controllers/settings.client.controller.js
@@ -1,14 +1,49 @@
'use strict';
angular.module('users').controller('SettingsController', ['$scope', '$http', '$location', 'Users', 'Authentication',
- function($scope, $http, $location, Users, Authentication) {
+ function ($scope, $http, $location, Users, Authentication) {
$scope.user = Authentication.user;
+ $scope.linkedProviders = [];
// If user is not signed in then redirect back home
if (!$scope.user) $location.path('/');
+ $scope.user.identities.forEach(function (identity) {
+ if (identity.provider === 'username') {
+ $scope.user.username = identity.id;
+ }
+ });
+
+ $scope.identitiesToEmails = function () {
+ $scope.user.emails = [];
+ if ($scope.user.identities) {
+ $scope.user.identities.forEach(function (identity, idx) {
+ if (identity.provider === 'email') {
+ $scope.user.identities.splice(idx, 1);
+ $scope.user.emails.push(identity);
+ }
+ });
+ }
+ };
+ $scope.identitiesToEmails();
+
+ $scope.removeEmail = function (emailIndex) {
+ $scope.user.emails.splice(emailIndex, 1);
+ return false;
+ };
+
+ $scope.addEmail = function () {
+ if (!$scope.user.identities) {
+ $scope.user.identities = [];
+ }
+ $scope.user.emails.push({
+ provider: 'email',
+ id: ''
+ });
+ };
+
// Check if there are additional accounts
- $scope.hasConnectedAdditionalSocialAccounts = function(provider) {
+ $scope.hasConnectedAdditionalSocialAccounts = function (provider) {
for (var i in $scope.user.additionalProvidersData) {
return true;
}
@@ -17,37 +52,51 @@ angular.module('users').controller('SettingsController', ['$scope', '$http', '$l
};
// Check if provider is already in use with current user
- $scope.isConnectedSocialAccount = function(provider) {
- return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]);
+ $scope.isConnectedSocialAccount = function (provider) {
+ var connected = false;
+ angular.forEach($scope.user.identities, function (identity) {
+ if (identity.provider === provider) {
+ connected = true;
+ $scope.linkedProviders.push(provider);
+ }
+ });
+ return connected;
};
// Remove a user social account
- $scope.removeUserSocialAccount = function(provider) {
+ $scope.removeUserSocialAccount = function (provider) {
$scope.success = $scope.error = null;
$http.delete('/api/users/accounts', {
params: {
provider: provider
}
- }).success(function(response) {
+ }).success(function (response) {
// If successful show success message and clear form
$scope.success = true;
$scope.user = Authentication.user = response;
- }).error(function(response) {
+ }).error(function (response) {
$scope.error = response.message;
});
};
// Update a user profile
- $scope.updateUserProfile = function(isValid) {
- if (isValid){
+ $scope.updateUserProfile = function (isValid) {
+ if (isValid) {
$scope.success = $scope.error = null;
+
+ $scope.user.emails.forEach(function (email) {
+ $scope.user.identities.push(email);
+ });
+ delete $scope.user.emails;
+
var user = new Users($scope.user);
-
- user.$update(function(response) {
+
+ user.$update(function (response) {
$scope.success = true;
Authentication.user = response;
- }, function(response) {
+ $scope.identitiesToEmails();
+ }, function (response) {
$scope.error = response.data.message;
});
} else {
@@ -56,14 +105,14 @@ angular.module('users').controller('SettingsController', ['$scope', '$http', '$l
};
// Change user password
- $scope.changeUserPassword = function() {
+ $scope.changeUserPassword = function () {
$scope.success = $scope.error = null;
- $http.post('/api/users/password', $scope.passwordDetails).success(function(response) {
+ $http.post('/api/users/password', $scope.passwordDetails).success(function (response) {
// If successful show success message and clear form
$scope.success = true;
$scope.passwordDetails = null;
- }).error(function(response) {
+ }).error(function (response) {
$scope.error = response.message;
});
};
diff --git a/modules/users/client/controllers/settings/edit-profile.client.controller.js b/modules/users/client/controllers/settings/edit-profile.client.controller.js
index 8e1d423819..5f6da1e258 100644
--- a/modules/users/client/controllers/settings/edit-profile.client.controller.js
+++ b/modules/users/client/controllers/settings/edit-profile.client.controller.js
@@ -1,24 +1,52 @@
'use strict';
angular.module('users').controller('EditProfileController', ['$scope', '$http', '$location', 'Users', 'Authentication',
- function($scope, $http, $location, Users, Authentication) {
+ function ($scope, $http, $location, Users, Authentication) {
$scope.user = Authentication.user;
// Update a user profile
- $scope.updateUserProfile = function(isValid) {
- if (isValid){
+ $scope.updateUserProfile = function (isValid) {
+ if (isValid) {
$scope.success = $scope.error = null;
var user = new Users($scope.user);
- user.$update(function(response) {
+ user.$update(function (response) {
$scope.success = true;
Authentication.user = response;
- }, function(response) {
+ }, function (response) {
$scope.error = response.data.message;
});
} else {
$scope.submitted = true;
}
};
+
+ $scope.identitiesToEmails = function () {
+ $scope.user.emails = [];
+ if ($scope.user.identities) {
+ $scope.user.identities.forEach(function (identity, idx) {
+ if (identity.provider === 'email') {
+ $scope.user.identities.splice(idx, 1);
+ $scope.user.emails.push(identity);
+ }
+ });
+ }
+ };
+ $scope.identitiesToEmails();
+
+ $scope.removeEmail = function (emailIndex) {
+ $scope.user.emails.splice(emailIndex, 1);
+ return false;
+ };
+
+ $scope.addEmail = function () {
+ if (!$scope.user.identities) {
+ $scope.user.identities = [];
+ }
+ $scope.user.emails.push({
+ provider: 'email',
+ id: ''
+ });
+ };
}
]);
diff --git a/modules/users/client/controllers/settings/manage-social-accounts.client.controller.js b/modules/users/client/controllers/settings/manage-social-accounts.client.controller.js
index 74774f06d1..35ba8f93e8 100644
--- a/modules/users/client/controllers/settings/manage-social-accounts.client.controller.js
+++ b/modules/users/client/controllers/settings/manage-social-accounts.client.controller.js
@@ -1,36 +1,39 @@
'use strict';
angular.module('users').controller('SocialAccountsController', ['$scope', '$http', '$location', 'Users', 'Authentication',
- function($scope, $http, $location, Users, Authentication) {
+ function ($scope, $http, $location, Users, Authentication) {
$scope.user = Authentication.user;
// Check if there are additional accounts
- $scope.hasConnectedAdditionalSocialAccounts = function(provider) {
- for (var i in $scope.user.additionalProvidersData) {
- return true;
- }
-
- return false;
+ $scope.hasConnectedAdditionalSocialAccounts = function (provider) {
+ return true;
};
// Check if provider is already in use with current user
- $scope.isConnectedSocialAccount = function(provider) {
- return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]);
+ $scope.isConnectedSocialAccount = function (provider) {
+ var has = false;
+ angular.forEach($scope.user.identities, function (identity) {
+ if (identity.provider === provider) {
+ has = true;
+ }
+ });
+ return has;
};
// Remove a user social account
- $scope.removeUserSocialAccount = function(provider) {
+ $scope.removeUserSocialAccount = function (provider, id) {
$scope.success = $scope.error = null;
$http.delete('/api/users/accounts', {
params: {
- provider: provider
+ provider: provider,
+ id: id
}
- }).success(function(response) {
+ }).success(function (response) {
// If successful show success message and clear form
$scope.success = true;
$scope.user = Authentication.user = response;
- }).error(function(response) {
+ }).error(function (response) {
$scope.error = response.message;
});
};
diff --git a/modules/users/client/controllers/settings/settings.client.controller.js b/modules/users/client/controllers/settings/settings.client.controller.js
index 25af58435f..524cdcbc96 100644
--- a/modules/users/client/controllers/settings/settings.client.controller.js
+++ b/modules/users/client/controllers/settings/settings.client.controller.js
@@ -1,7 +1,7 @@
'use strict';
angular.module('users').controller('SettingsController', ['$scope', '$http', '$location', 'Users', 'Authentication',
- function($scope, $http, $location, Users, Authentication) {
+ function ($scope, $http, $location, Users, Authentication) {
$scope.user = Authentication.user;
// If user is not signed in then redirect back home
diff --git a/modules/users/client/users.client.module.js b/modules/users/client/users.client.module.js
index 569aba8c16..5d3164a205 100644
--- a/modules/users/client/users.client.module.js
+++ b/modules/users/client/users.client.module.js
@@ -1,4 +1,4 @@
'use strict';
// Use Applicaion configuration module to register a new module
-ApplicationConfiguration.registerModule('users');
+ApplicationConfiguration.registerModule('users', ['angular-json-tree']);
diff --git a/modules/users/client/views/admin/users.list.client.view.html b/modules/users/client/views/admin/users.list.client.view.html
new file mode 100644
index 0000000000..1c0966c995
--- /dev/null
+++ b/modules/users/client/views/admin/users.list.client.view.html
@@ -0,0 +1,34 @@
+
+
Browse Users
+
+
+
+
+
+ ID |
+ User Name |
+ Data |
+ Accounts |
+
+
+
+
+ {{ row._id | limitTo : 6 }} |
+ {{ row.displayName }} |
+
+
+ |
+
+
+ |
+
+
+
+
+
diff --git a/modules/users/client/views/settings/edit-profile.client.view.html b/modules/users/client/views/settings/edit-profile.client.view.html
index ae8cd30327..3e6f877918 100644
--- a/modules/users/client/views/settings/edit-profile.client.view.html
+++ b/modules/users/client/views/settings/edit-profile.client.view.html
@@ -1,22 +1,43 @@