From 7c6b09634ef6e6b46e9192d8bea50b18d245cc7e Mon Sep 17 00:00:00 2001 From: Mihai Cucicea Date: Fri, 19 Jan 2018 10:45:40 +0200 Subject: [PATCH 1/3] Implementation for Group And User Management. https://www.topcoder.com/challenges/30061947/?type=develop --- src/app/groups/groups.list.controller.js | 15 +- src/app/groups/groups.list.html | 3 + src/app/groups/groups.service.js | 59 ++++ .../users/sso-user-edit-dialog.controller.js | 87 ++++++ src/app/users/sso-user-edit-dialog.html | 38 +++ src/app/users/users.controller.js | 11 + src/app/users/users.html | 285 +++++++++--------- src/app/users/users.service.js | 119 ++------ src/app/utils/helper.js | 39 +++ 9 files changed, 425 insertions(+), 231 deletions(-) create mode 100644 src/app/users/sso-user-edit-dialog.controller.js create mode 100644 src/app/users/sso-user-edit-dialog.html create mode 100644 src/app/utils/helper.js diff --git a/src/app/groups/groups.list.controller.js b/src/app/groups/groups.list.controller.js index 2501efa..1d536eb 100644 --- a/src/app/groups/groups.list.controller.js +++ b/src/app/groups/groups.list.controller.js @@ -3,8 +3,8 @@ var module = angular.module('supportAdminApp'); module.controller('permissionmanagement.GroupsListController', [ - '$scope', '$rootScope', 'GroupService', 'UserService', 'IdResolverService', 'Alert', '$timeout', - function ($scope, $rootScope, GroupService, UserService, IdResolverService, $alert, $timeout) { + '$scope', '$rootScope', 'GroupService', 'UserService', 'IdResolverService', 'Alert', '$timeout', '$uibModal', + function ($scope, $rootScope, GroupService, UserService, IdResolverService, $alert, $timeout, $modal) { // true data is loading $scope.isLoading = false; @@ -51,5 +51,16 @@ module.controller('permissionmanagement.GroupsListController', [ // load the groups on controller init $scope.fetch(); + + $scope.openGroupEditDialog = function(index) { + var modalInstance = $modal.open({ + size: 'sm', + templateUrl: 'app/groups/group-edit-dialog.html', + controller: 'groups.GroupEditDialogController', + resolve: { + parentScope: function(){ return $scope; } + } + }); + }; } ]); diff --git a/src/app/groups/groups.list.html b/src/app/groups/groups.list.html index a800759..1e3760c 100644 --- a/src/app/groups/groups.list.html +++ b/src/app/groups/groups.list.html @@ -6,6 +6,9 @@
+
diff --git a/src/app/groups/groups.service.js b/src/app/groups/groups.service.js index 9576dd0..e9f7f2b 100644 --- a/src/app/groups/groups.service.js +++ b/src/app/groups/groups.service.js @@ -79,6 +79,65 @@ angular.module('supportAdminApp') }).catch(GroupService.handleError); }; + /** + * Creates a group + * @param {Object} group The group. + */ + GroupService.create = function(group) { + var request = $http({ + method: 'POST', + url: GroupService.getBasePath() + '/groups', + headers: { + "Content-Type":"application/json" + }, + data: JSON.stringify({ param: group }) + }); + + return request.then( + function(response) { + if (response && response.data && response.data.result) { + var newGroup = response.data.result.content; + var securityGroup = {id: newGroup.id, name: newGroup.name}; + return GroupService.createSecurityGroup(securityGroup) + .then(function(response){}, GroupService.handleError); + } else { + return $q.reject({ + error : 'Cannot find data in response' + }) + } + }, + GroupService.handleError + ); + }; + + /** + * Creates a security group + * @param {Object} group The security group. + */ + GroupService.createSecurityGroup = function(group) { + var request = $http({ + method: 'POST', + url: GroupService.getBasePath() + '/groups/securityGroups', + headers: { + "Content-Type":"application/json" + }, + data: JSON.stringify({ param: group }) + }); + + return request.then( + function(response) { + if (response && response.data && response.data.result) { + return response.data.result.content; + } else { + return $q.reject({ + error : 'Cannot find data in response' + }) + } + }, + GroupService.handleError + ); + }; + /** * Handle API response error * diff --git a/src/app/users/sso-user-edit-dialog.controller.js b/src/app/users/sso-user-edit-dialog.controller.js new file mode 100644 index 0000000..e200e49 --- /dev/null +++ b/src/app/users/sso-user-edit-dialog.controller.js @@ -0,0 +1,87 @@ +module.controller('users.SsoUserEditDialogController', [ + '$scope', + '$uibModalInstance', + 'UserService', + 'Alert', + 'user', + '$q', + function ($scope, $modalInstance, UserService, $alert, user, $q) { + + // currently selected user object + $scope.user = user; + + // These are the provider types accepted in the API. + $scope.providerTypes = [ + 'ad', + 'adfs', + 'auth0', + 'behance', + 'bitbucket', + 'dribbble', + 'facebook', + 'github', + 'google-oauth2', + 'linkedin', + 'samlp', + 'sfdc', + 'stackoverflow', + 'twitter' + ]; + + // true if details are being loaded/saved + $scope.isLoading = false; + + /** + * Close dialog + */ + $scope.close = function () { + $modalInstance.close(); + }; + + /** + * Load user profile. + */ + $scope.loadData = function () { + $scope.isLoading = true; + UserService + .findById($scope.user.id) + .then(function (data) { + $scope.user.profile = {}; + if (data.profile) { + // we can't have all properties form profile as saving will fail. + $scope.user.profile = { + userId: data.profile.userId, + providerType: data.profile.providerType, + provider: data.profile.provider + } + } + }) + .catch(function (error) { + $alert.error(error.error, $scope); + }) + . finally(function () { + $scope.isLoading = false; + }); + } + + /** + * Create or updates the user SSO profile. + */ + $scope.save = function () { + $scope.isLoading = true; + UserService + .createOrUpdateSSOUserLogin($scope.user.id, $scope.user.profile) + .then(function (data) { + $scope.close(); + }) + .catch(function (error) { + $alert.error(error.error, $scope); + }) + . finally(function () { + $scope.isLoading = false; + }); + } + + $scope.loadData(); + } +]); diff --git a/src/app/users/sso-user-edit-dialog.html b/src/app/users/sso-user-edit-dialog.html new file mode 100644 index 0000000..0a14e5f --- /dev/null +++ b/src/app/users/sso-user-edit-dialog.html @@ -0,0 +1,38 @@ +
+ + + +
+ +
+
\ No newline at end of file diff --git a/src/app/users/users.controller.js b/src/app/users/users.controller.js index 5942817..424907f 100644 --- a/src/app/users/users.controller.js +++ b/src/app/users/users.controller.js @@ -199,6 +199,17 @@ module.controller('users.UserSearchController', [ }); }; + $scope.openSsoUserEditDialog = function(index) { + var modalInstance = $modal.open({ + size: 'sm', + templateUrl: 'app/users/sso-user-edit-dialog.html', + controller: 'users.SsoUserEditDialogController', + resolve: { + user: function(){ return $scope.users[index]; } + } + }); + }; + } ]); diff --git a/src/app/users/users.html b/src/app/users/users.html index 32766e7..7099e1b 100644 --- a/src/app/users/users.html +++ b/src/app/users/users.html @@ -1,142 +1,143 @@ - -
-
-

Users

-
-
-
-
- -
-
-
-
-
-
-
-
-
- - -
-
- - -
-
- - -
-
-

- Tips:
- - Wildcard(*) is available for partial matching. (e.g. ChrisB*, chris*@appirio.com)
- - Maximum number of searched results is 500. -

-
-
- -
- - -
-
-
-
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
User IDHandlePrimary EmailNameUser StatusEmail StatusCreated atModified atActivation CodeUser ActiveAction
{{user.id}}{{user.handle}}{{user.email}}{{user.firstName}} {{user.lastName}} - {{user.statusDesc()}} - - - - {{user.emailStatusDesc()}}{{user.createdAtLabel()}}{{user.modifiedAtLabel()}} - {{user.credential.activationCode}} -
- - - - - - -
-
- - -
- - -
- - Activate - - - Deactivate - -
-
    -
    -
    - - - - - + +
    +
    +

    Users

    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    + Tips:
    + - Wildcard(*) is available for partial matching. (e.g. ChrisB*, chris*@appirio.com)
    + - Maximum number of searched results is 500. +

    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    User IDHandlePrimary EmailNameUser StatusEmail StatusCreated atModified atActivation CodeUser ActiveAction
    {{user.id}}{{user.handle}}{{user.email}}{{user.firstName}} {{user.lastName}} + {{user.statusDesc()}} + + + + {{user.emailStatusDesc()}}{{user.createdAtLabel()}}{{user.modifiedAtLabel()}} + {{user.credential.activationCode}} +
    + + + + + + +
    +
    + + +
    + + +
    + + Activate + + + Deactivate + +
    +
      +
      +
      + +
      +
      +
      +
      diff --git a/src/app/users/users.service.js b/src/app/users/users.service.js index 50cc8f1..25c51c0 100644 --- a/src/app/users/users.service.js +++ b/src/app/users/users.service.js @@ -1,8 +1,8 @@ 'use strict'; angular.module('supportAdminApp') - .factory('UserService', ['$log', '$q','$http', 'User', 'API_URL', 'API_VERSION_PATH', - function ($log, $q, $http, User, API_URL, API_VERSION_PATH) { + .factory('UserService', ['$log', '$q','$http', 'User', 'API_URL', 'API_VERSION_PATH', 'helper', + function ($log, $q, $http, User, API_URL, API_VERSION_PATH, helper) { // local dev //var API_URL = 'http://local.topcoder-dev.com:8080'; @@ -27,23 +27,7 @@ angular.module('supportAdminApp') $log.debug(response); return UserService.createUser(response.data.result.content); }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); - } + helper.handleError ); }; // findById() @@ -77,23 +61,7 @@ angular.module('supportAdminApp') $log.debug(response); return UserService.createUser(response.data.result.content); }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); - } + helper.handleError ); }; // find() @@ -155,23 +123,7 @@ angular.module('supportAdminApp') $log.debug(response); return UserService.createUser(response.data.result.content); }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); - } + helper.handleError ); }; // updateHandle() @@ -191,23 +143,7 @@ angular.module('supportAdminApp') $log.debug(response); return UserService.createUser(response.data.result.content); }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); - } + helper.handleError ); }, // updateEmail() @@ -232,23 +168,7 @@ angular.module('supportAdminApp') $log.debug(response); return UserService.createUser(response.data.result.content); }, - function(error) { - $log.error(error); - var err; - if(error && error.data && error.data.result) { - err = { - status: error.status, - error : error.data.result.content - }; - } - if(!err) { - err = { - status: error.status, - error : error.statusText - }; - } - return $q.reject(err); - } + helper.handleError ); }; // updateStatus() @@ -349,6 +269,31 @@ angular.module('supportAdminApp') UserService.getProfileEndpoint = function(handle) { return API_URL + '/'+API_VERSION_PATH+'/members/' + handle; } + + /** + * Creates or updates the user SSO profile + * @param {Integer} userId The userId + * @param {Object} profile The user SSO profile. + */ + UserService.createOrUpdateSSOUserLogin = function(userId, profile) { + var payload = JSON.stringify({ param: profile }); + var request = $http({ + method: 'POST', + url: API_URL + '/v3/users/'+userId+'/createOrUpdateSSOUserLogin', + headers: { + "Content-Type":"application/json" + }, + data: payload + }); + + return request.then( + function(response) { + $log.debug(response); + return response.data; + }, + helper.handleError + ); + }; return UserService; }]); diff --git a/src/app/utils/helper.js b/src/app/utils/helper.js new file mode 100644 index 0000000..fda8a6b --- /dev/null +++ b/src/app/utils/helper.js @@ -0,0 +1,39 @@ +'use strict'; + +angular + .module('supportAdminApp') + .factory('helper', [ + '$log', + '$q', + function ($log, $q) { + var helper = {}; + + /** + * Handles an API error response. + * @param {Object} error The error + */ + helper.handleError = function (error) { + $log.error(error); + var err; + if (error && error.data) { + err = { + status: error.status + }; + err.error = error.data.result + ? error.data.result.content + : error.data.message; + + } + if (!err) { + err = { + status: error.status, + error: error.statusText + }; + } + + return $q.reject(err); + } + + return helper; + } + ]); \ No newline at end of file From 38c0e9c4bdf050b62bb38aa1cad041150ab30c8b Mon Sep 17 00:00:00 2001 From: Mihai Cucicea Date: Fri, 19 Jan 2018 10:54:00 +0200 Subject: [PATCH 2/3] Adding missing group-edit. --- .../groups/group-edit-dialog.controller.js | 38 +++++++++++++++++++ src/app/groups/group-edit-dialog.html | 33 ++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/app/groups/group-edit-dialog.controller.js create mode 100644 src/app/groups/group-edit-dialog.html diff --git a/src/app/groups/group-edit-dialog.controller.js b/src/app/groups/group-edit-dialog.controller.js new file mode 100644 index 0000000..14473ad --- /dev/null +++ b/src/app/groups/group-edit-dialog.controller.js @@ -0,0 +1,38 @@ +module.controller('groups.GroupEditDialogController', [ + '$scope', + '$uibModalInstance', + 'GroupService', + 'Alert', + 'parentScope', + function ($scope, $modalInstance, GroupService, $alert, parentScope) { + $scope.group = {}; + // true if group is being saved. + $scope.isLoading = false; + + /** + * Close dialog + */ + $scope.close = function () { + $modalInstance.close(); + }; + + /** + * Create or updates the user SSO profile. + */ + $scope.save = function () { + $scope.isLoading = true; + GroupService + .create($scope.group) + .then(function (data) { + parentScope.fetch(); + $scope.close(); + }) + .catch(function (error) { + $alert.error(error.error, $scope); + }) + . finally(function () { + $scope.isLoading = false; + }); + } + } +]); diff --git a/src/app/groups/group-edit-dialog.html b/src/app/groups/group-edit-dialog.html new file mode 100644 index 0000000..a914d30 --- /dev/null +++ b/src/app/groups/group-edit-dialog.html @@ -0,0 +1,33 @@ +
      + + + +
      + +
      +
      From 2d96ade3963694214dbac078517e873f0b48a4f7 Mon Sep 17 00:00:00 2001 From: Mihai Cucicea Date: Thu, 25 Jan 2018 11:03:01 +0200 Subject: [PATCH 3/3] make provider type read-only --- src/app/users/sso-user-edit-dialog.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/users/sso-user-edit-dialog.html b/src/app/users/sso-user-edit-dialog.html index 0a14e5f..aad8596 100644 --- a/src/app/users/sso-user-edit-dialog.html +++ b/src/app/users/sso-user-edit-dialog.html @@ -15,7 +15,7 @@
      - +