@@ -53,7 +53,7 @@
Admins / Copilots / Reviewers
diff --git a/src/app/admintool/admintool.service.js b/src/app/admintool/admintool.service.js
index 2cc400b..05f9091 100644
--- a/src/app/admintool/admintool.service.js
+++ b/src/app/admintool/admintool.service.js
@@ -4,7 +4,6 @@ angular.module('supportAdminApp')
.factory('AdminToolService', ['$log', '$q', '$http', 'ADMIN_TOOL_URL', 'API_URL', 'API_VERSION_PATH',
function ($log, $q, $http, ADMIN_TOOL_URL, API_URL, API_VERSION_PATH) {
var service = {
- getV2Token: getV2Token,
findAdmins: findAdmins,
createAdmin: createAdmin,
deleteAdmin: deleteAdmin,
@@ -19,45 +18,6 @@ angular.module('supportAdminApp')
findReviewBoardProjectCategories: findReviewBoardProjectCategories
};
- /**
- * Get v2 token with v3 token
- */
- function getV2Token() {
- return $http({
- method: 'GET',
- url: API_URL + '/' + API_VERSION_PATH + '/authorizations/1'
- }).then(
- function (response) {
- $log.debug(response);
- if (response.data && response.data.result && response.data.result.content
- && response.data.result.content.externalToken) {
- return response.data.result.content.externalToken;
- } else {
- return $q.reject({
- error: 'Cannot find v2 token in response.'
- });
- }
- },
- 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 function to process http request
*/
@@ -105,13 +65,12 @@ angular.module('supportAdminApp')
/**
* Find admins
*/
- function findAdmins(token) {
+ function findAdmins() {
var request = $http({
method: 'GET',
url: ADMIN_TOOL_URL + '/admin/admins',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
}
});
return _processRequest(request, 'allAdmins');
@@ -120,13 +79,12 @@ angular.module('supportAdminApp')
/**
* creates admin user
*/
- function createAdmin(token, data) {
+ function createAdmin(data) {
var request = $http({
method: 'POST',
url: ADMIN_TOOL_URL + '/admin/admins',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
},
data: angular.toJson(data)
});
@@ -136,13 +94,12 @@ angular.module('supportAdminApp')
/**
* Delete an existing admin user
*/
- function deleteAdmin(token, data) {
+ function deleteAdmin(data) {
var request = $http({
method: "DELETE",
url: ADMIN_TOOL_URL + "/admin/admins",
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
},
data: angular.toJson(data)
});
@@ -153,13 +110,12 @@ angular.module('supportAdminApp')
/**
* Find copilots
*/
- function findCopilots(token) {
+ function findCopilots() {
var request = $http({
method: 'GET',
url: ADMIN_TOOL_URL + '/admin/copilots',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
}
});
return _processRequest(request, 'allCopilots');
@@ -168,13 +124,12 @@ angular.module('supportAdminApp')
/**
* creates copilot
*/
- function createCopilot(token, data) {
+ function createCopilot(data) {
var request = $http({
method: 'POST',
url: ADMIN_TOOL_URL + '/admin/copilots',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
},
data: angular.toJson(data)
});
@@ -184,13 +139,12 @@ angular.module('supportAdminApp')
/**
* Delete copilot
*/
- function deleteCopilot(token, data) {
+ function deleteCopilot(data) {
var request = $http({
method: "DELETE",
url: ADMIN_TOOL_URL + "/admin/copilots",
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
},
data: angular.toJson(data)
});
@@ -200,9 +154,9 @@ angular.module('supportAdminApp')
/**
* Update copilot
*/
- function updateCopilot(token, data) {
- return deleteCopilot(token, data).then(function () {
- return createCopilot(token, data);
+ function updateCopilot(data) {
+ return deleteCopilot(data).then(function () {
+ return createCopilot(data);
});
}
@@ -210,7 +164,7 @@ angular.module('supportAdminApp')
/**
* Find Reviewers
*/
- function findReviewers(token, categoryId) {
+ function findReviewers(categoryId) {
var request = $http({
method: 'GET',
url: ADMIN_TOOL_URL + '/admin/reviewers',
@@ -219,7 +173,6 @@ angular.module('supportAdminApp')
},
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
}
});
return _processRequest(request, 'reviewers');
@@ -229,13 +182,12 @@ angular.module('supportAdminApp')
/**
* creates Reviewer
*/
- function createReviewer(token, data) {
+ function createReviewer(data) {
var request = $http({
method: 'POST',
url: ADMIN_TOOL_URL + '/admin/reviewers',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
},
data: angular.toJson(data)
});
@@ -245,13 +197,12 @@ angular.module('supportAdminApp')
/**
* Delete Reviewer
*/
- function deleteReviewer(token, data) {
+ function deleteReviewer(data) {
var request = $http({
method: "DELETE",
url: ADMIN_TOOL_URL + "/admin/reviewers",
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
},
data: angular.toJson(data)
});
@@ -262,10 +213,10 @@ angular.module('supportAdminApp')
/**
* Update Reviewer
*/
- function updateReviewer(token, oldReviewer, newReviewer) {
- var requests = [deleteReviewer(token, oldReviewer)];
+ function updateReviewer(oldReviewer, newReviewer) {
+ var requests = [deleteReviewer(oldReviewer)];
if (oldReviewer.categoryId !== newReviewer.categoryId) {
- requests.push(deleteReviewer(token, {
+ requests.push(deleteReviewer({
username: newReviewer.username,
categoryId: newReviewer.categoryId
}).catch(function (error) {
@@ -277,27 +228,25 @@ angular.module('supportAdminApp')
}
return $q.all(requests).then(function () {
delete newReviewer.id;
- return createReviewer(token, newReviewer)
+ return createReviewer(newReviewer)
});
}
/**
* Find review board project categories
*/
- function findReviewBoardProjectCategories(token) {
+ function findReviewBoardProjectCategories() {
var request = $q.all([$http({
method: 'GET',
url: ADMIN_TOOL_URL + '/develop/challengetypes',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
}
}), $http({
method: 'GET',
url: ADMIN_TOOL_URL + '/design/challengetypes',
headers: {
"Content-Type": "application/json",
- "Authorization": "Bearer " + token
}
})]);
return _processRequest(request);
diff --git a/src/app/app.js b/src/app/app.js
index 831dd10..ab61105 100755
--- a/src/app/app.js
+++ b/src/app/app.js
@@ -4,285 +4,327 @@
* support-admin-app
*/
angular.module('supportAdminApp', [
- 'ngAnimate',
- 'ngCookies',
- 'ngTouch',
- 'ngSanitize',
- 'ngResource',
- 'csvReader',
- 'ui.router',
- 'ui.bootstrap',
- 'app.constants',
- 'appirio-tech-ng-api-services',
- 'appirio-tech-ng-auth',
- 'angular-clipboard',
- 'ng-file-model',
- 'ui.multiselect',
- 'ui.bootstrap.datetimepicker',
- 'angularMoment'])
+ 'ngAnimate',
+ 'ngCookies',
+ 'ngTouch',
+ 'ngSanitize',
+ 'ngResource',
+ 'csvReader',
+ 'ui.router',
+ 'ui.bootstrap',
+ 'app.constants',
+ 'angular-clipboard',
+ 'ng-file-model',
+ 'ui.multiselect',
+ 'ui.bootstrap.datetimepicker',
+ 'angularMoment',
+ 'angular-jwt'])
// In the run phase of your Angular application
- .run(function ($rootScope, $location, AuthService, $state, UserV3Service) {
- // Listen to '$locationChangeSuccess', not '$stateChangeStart'
- $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
- if (toState.name === 'login') {
- return;
- }
- console.log('state changed. loggedIn: ' + AuthService.isLoggedIn()); // debug
- if (!AuthService.isLoggedIn()) {
- $state.go('login');
- } else {
- UserV3Service.loadUser().then(function (currentUser) {
- $rootScope.currentUser = currentUser;
- $state.go(toState, toParams);
- });
- }
- });
+ .run(function (AuthService) {
+ // init AuthService, it has to be done once, when app starts
+ AuthService.init();
})
.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
- $stateProvider
- .state('login', {
- url: '/login',
- templateUrl: 'app/login/login.html',
- data: { pageTitle: 'Login' }
- })
- .state('index', {
- abstract: true,
- url: '/index',
- templateUrl: 'components/common/content.html'
- })
- .state('index.main', {
- url: '/main',
- templateUrl: 'app/main/main.html',
- data: { pageTitle: 'Dashboard' }
- })
- .state('index.users', {
- url: '/users',
- templateUrl: 'app/users/users.html',
- data: { pageTitle: 'User Management' }
- })
- .state('index.admintool', {
- url: '/admintool',
- templateUrl: 'app/admintool/admintool.html',
- data: { pageTitle: 'Admins / Copilots / Reviewers Management' }
- })
- .state('index.sso', {
- url: '/sso',
- templateUrl: 'app/sso/sso.html',
- data: { pageTitle: 'SSO User Management' }
- })
- .state('index.addmembers', {
- url: '/add',
- templateUrl: 'app/addmembers/add.html',
- data: { pageTitle: 'User Management' }
- })
- .state('index.submissions', {
- abstract: true,
- url: '/submissions',
- templateUrl: 'app/submissions/submissions.html',
- data: { pageTitle: 'Submissions' }
- })
- .state('index.submissions.list', {
- url: '/list',
- templateUrl: 'app/submissions/submissions.list.html',
- data: { pageTitle: 'Submissions List' },
- controller: 'SubmissionListCtrl'
- })
- .state('index.submissions.new', {
- url: '/new',
- templateUrl: 'app/submissions/submissions.new.html',
- controller: 'NewSubmissionCtrl',
- data: { pageTitle: 'New Submission' }
- })
- .state('index.tags', {
- abstract: true,
- url: '/tags',
- templateUrl: 'app/tags/tags.html',
- data: { pageTitle: 'Tags' },
- controller: function ($scope, $state, TagService) {
- $scope.$state = $state;
- $scope.tagDomains = [{
- value: 'skills',
- name: 'Skills'
- }, {
- value: 'events',
- name: 'Events'
- }, {
- value: 'technology',
- name: 'Technology'
- }, {
- value: 'platform',
- name: 'Platform'
- }];
+ var authenticate = ['AuthService', '$q', '$state', function(AuthService, $q, $state) {
+ return AuthService.authenticate().catch(function(err) {
+ // if we get error that use doesn't have permissions
+ // then go to auth page, which will show permissions denied error
+ if (err === AuthService.ERROR.NO_PERMISSIONS) {
+ $state.go('auth');
+ }
+ return $q.reject();
+ });
+ }];
- $scope.tagCategories = [{
- value: 'data_science',
- name: 'Data Science'
- }, {
- value: 'develop',
- name: 'Develop'
- },
- {
- value: 'design',
- name: 'Design'
- }];
+ $stateProvider
+ .state('auth', {
+ url: '/auth',
+ templateUrl: 'app/auth/auth.html',
+ data: { pageTitle: 'Authentication' },
+ resolve: {
+ auth: ['AuthService', '$q', function(AuthService, $q) {
+ // for auth state we use another resolver then all other states
+ return AuthService.authenticate().catch(function(err) {
+ // if we get error that use doesn't have permissions
+ // we still resolve the promise and proceed to auth page
+ // which will show permissions denied error
+ // also we keep going if we are in loging out process
+ if (err === AuthService.ERROR.NO_PERMISSIONS || AuthService.logginOut) {
+ return $q.resolve();
+ }
+ return $q.reject();
+ });
+ }]
+ }
+ })
+ .state('index', {
+ abstract: true,
+ url: '/index',
+ templateUrl: 'components/common/content.html'
+ })
+ .state('index.main', {
+ url: '/main',
+ templateUrl: 'app/main/main.html',
+ data: { pageTitle: 'Dashboard' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.users', {
+ url: '/users',
+ templateUrl: 'app/users/users.html',
+ data: { pageTitle: 'User Management' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.admintool', {
+ url: '/admintool',
+ templateUrl: 'app/admintool/admintool.html',
+ data: { pageTitle: 'Admins / Copilots / Reviewers Management' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.sso', {
+ url: '/sso',
+ templateUrl: 'app/sso/sso.html',
+ data: { pageTitle: 'SSO User Management' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.addmembers', {
+ url: '/add',
+ templateUrl: 'app/addmembers/add.html',
+ data: { pageTitle: 'User Management' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.permission_management', {
+ url: '/permission_management',
+ templateUrl: 'app/permission_management/permission_management.html',
+ data: { pageTitle: 'Permission Management' },
+ controller: 'PermissionManagementCtrl',
+ controllerAs: 'ctrl',
+ resolve: { auth: authenticate }
+ })
+ .state('index.submissions', {
+ abstract: true,
+ url: '/submissions',
+ templateUrl: 'app/submissions/submissions.html',
+ data: { pageTitle: 'Submissions' }
+ })
+ .state('index.submissions.list', {
+ url: '/list',
+ templateUrl: 'app/submissions/submissions.list.html',
+ data: { pageTitle: 'Submissions List' },
+ controller: 'SubmissionListCtrl',
+ resolve: { auth: authenticate }
+ })
+ .state('index.submissions.new', {
+ url: '/new',
+ templateUrl: 'app/submissions/submissions.new.html',
+ controller: 'NewSubmissionCtrl',
+ data: { pageTitle: 'New Submission' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.tags', {
+ abstract: true,
+ url: '/tags',
+ templateUrl: 'app/tags/tags.html',
+ data: { pageTitle: 'Tags' },
+ controller: function ($scope, $state, TagService) {
+ $scope.$state = $state;
+ $scope.tagDomains = [{
+ value: 'skills',
+ name: 'Skills'
+ }, {
+ value: 'events',
+ name: 'Events'
+ }, {
+ value: 'technology',
+ name: 'Technology'
+ }, {
+ value: 'platform',
+ name: 'Platform'
+ }];
- $scope.tagStatuses = [{
- value: 'approved',
- name: 'Approved'
- }, {
- value: 'pending',
- name: 'Pending'
+ $scope.tagCategories = [{
+ value: 'data_science',
+ name: 'Data Science'
+ }, {
+ value: 'develop',
+ name: 'Develop'
+ },
+ {
+ value: 'design',
+ name: 'Design'
}];
- TagService.getTechnologyStatuses().then(function(techStatuses) {
- _.forEach(techStatuses, function(status) {
- status.value = _.lowerCase(status.description);
- status.name = status.description;
- });
- $scope.techStatuses = techStatuses;
+ $scope.tagStatuses = [{
+ value: 'approved',
+ name: 'Approved'
+ }, {
+ value: 'pending',
+ name: 'Pending'
+ }];
+
+ TagService.getTechnologyStatuses().then(function(techStatuses) {
+ _.forEach(techStatuses, function(status) {
+ status.value = _.lowerCase(status.description);
+ status.name = status.description;
});
- $scope.getTagStatuses = function(domainType) {
- if (domainType === 'technology') {
- return $scope.techStatuses;
- } else {
- return $scope.tagStatuses;
- }
+ $scope.techStatuses = techStatuses;
+ });
+ $scope.getTagStatuses = function(domainType) {
+ if (domainType === 'technology') {
+ return $scope.techStatuses;
+ } else {
+ return $scope.tagStatuses;
}
}
- })
- .state('index.tags.list', {
- url: '/list',
- templateUrl: 'app/tags/tags.list.html',
- controller: 'TagListCtrl'
- })
- .state('index.tags.new', {
- url: '/new',
- templateUrl: 'app/tags/tags.new.html',
- controller: 'NewTagCtrl',
- data: { pageTitle: 'New Tag' }
- })
- .state('index.tags.edit', {
- url: '/edit/:tagId',
- templateUrl: 'app/tags/tags.edit.html',
- controller: 'EditTagCtrl',
- data: { pageTitle: 'Edit Tag' }
- })
- .state('index.work', {
- abstract: true,
- url: '/work',
- templateUrl: 'app/work/work.html',
- data: { pageTitle: 'Work Items Management' }
- })
- .state('index.work.list', {
- url: '/list/:id',
- views: {
- 'work-details': {
- templateUrl: 'app/work/work.details.html'
- },
- 'work-list': {
- templateUrl: 'app/work/work.list.html',
- data: { pageTitle: 'work List' },
- controller: 'WorkListCtrl',
- params: {
- id: ''
- }
- },
- 'work-messages': {
- templateUrl: 'app/work/work.messages.html',
- controller: 'projectController'
+ }
+ })
+ .state('index.tags.list', {
+ url: '/list',
+ templateUrl: 'app/tags/tags.list.html',
+ controller: 'TagListCtrl',
+ resolve: { auth: authenticate }
+ })
+ .state('index.tags.new', {
+ url: '/new',
+ templateUrl: 'app/tags/tags.new.html',
+ controller: 'NewTagCtrl',
+ data: { pageTitle: 'New Tag' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.tags.edit', {
+ url: '/edit/:tagId',
+ templateUrl: 'app/tags/tags.edit.html',
+ controller: 'EditTagCtrl',
+ data: { pageTitle: 'Edit Tag' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.work', {
+ abstract: true,
+ url: '/work',
+ templateUrl: 'app/work/work.html',
+ data: { pageTitle: 'Work Items Management' }
+ })
+ .state('index.work.list', {
+ url: '/list/:id',
+ views: {
+ 'work-details': {
+ templateUrl: 'app/work/work.details.html'
+ },
+ 'work-list': {
+ templateUrl: 'app/work/work.list.html',
+ data: { pageTitle: 'work List' },
+ controller: 'WorkListCtrl',
+ params: {
+ id: ''
}
+ },
+ 'work-messages': {
+ templateUrl: 'app/work/work.messages.html',
+ controller: 'projectController'
}
- })
- .state('index.workStepEdit', {
- url: '/work/:id/:stepId',
- templateUrl: 'app/work/workStepEdit.html',
- data: { pageTitle: 'Edit Step' },
- controller: 'WorkStepEditCtrl',
- params: {
- id: '',
- stepId: ''
- }
- })
- .state('index.projects', {
- url: '/projects',
- templateUrl: 'app/work/projects.html',
- data: { pageTitle: 'Projects List' },
- controller: 'ProjectListCtrl',
- controllerAs: 'vm'
- })
- .state('index.clients', {
- abstract: true,
- url: '/clients',
- templateUrl: 'app/clients/clients.html',
- data: { pageTitle: 'Clients' },
- controller: 'billingaccount.ClientsController'
- })
- .state('index.clients.list', {
- url: '/list',
- templateUrl: 'app/clients/clients.list.html',
- controller: 'billingaccount.ClientsListController'
- })
- .state('index.clients.new', {
- url: '/new',
- templateUrl: 'app/clients/clients.new.html',
- controller: 'billingaccount.NewClientController',
- data: { pageTitle: 'New Client' }
- })
- .state('index.clients.edit', {
- url: '/edit/:clientId',
- templateUrl: 'app/clients/clients.edit.html',
- controller: 'billingaccount.EditClientController',
- data: { pageTitle: 'Edit Client' }
- })
- .state('index.billingaccounts', {
- abstract: true,
- url: '/billingaccounts',
- templateUrl: 'app/billing_accounts/billingaccounts.html',
- data: { pageTitle: 'Billing Accounts' },
- controller: 'billingaccount.BillingAccountsController'
- })
- .state('index.billingaccounts.list', {
- url: '/list',
- templateUrl: 'app/billing_accounts/billingaccounts.list.html',
- controller: 'billingaccount.BillingAccountsListController'
- })
- .state('index.billingaccounts.new', {
- url: '/new',
- templateUrl: 'app/billing_accounts/billingaccounts.new.html',
- controller: 'billingaccount.NewBillingAccountController',
- data: { pageTitle: 'New Billing Account' }
- })
- .state('index.billingaccounts.edit', {
- url: '/edit/:accountId',
- templateUrl: 'app/billing_accounts/billingaccounts.edit.html',
- controller: 'billingaccount.EditBillingAccountController',
- data: { pageTitle: 'Edit Billing Account' }
- })
- .state('index.billingaccounts.view', {
- url: '/view/:accountId',
- templateUrl: 'app/billing_accounts/billingaccounts.view.html',
- controller: 'billingaccount.ViewBillingAccountController',
- data: { pageTitle: 'Details - Billing Account' }
- })
- .state('index.billingaccountresources', {
- abstract: true,
- url: '/billingaccountresources',
- templateUrl: 'app/billing_account_resources/billingaccountresources.html',
- data: { pageTitle: 'Billing Account Resources' },
- controller: 'billingaccount.BillingAccountResourcesController'
- })
- .state('index.billingaccountresources.list', {
- url: '/list/:accountId',
- templateUrl: 'app/billing_account_resources/billingaccountresources.list.html',
- controller: 'billingaccount.BillingAccountResourcesListController'
- })
- .state('index.billingaccountresources.new', {
- url: '/:accountId/new',
- templateUrl: 'app/billing_account_resources/billingaccountresources.new.html',
- controller: 'billingaccount.NewBillingAccountResourceController',
- data: { pageTitle: 'New Billing Account Resource' }
- });
+ },
+ resolve: { auth: authenticate }
+ })
+ .state('index.workStepEdit', {
+ url: '/work/:id/:stepId',
+ templateUrl: 'app/work/workStepEdit.html',
+ data: { pageTitle: 'Edit Step' },
+ controller: 'WorkStepEditCtrl',
+ params: {
+ id: '',
+ stepId: ''
+ },
+ resolve: { auth: authenticate }
+ })
+ .state('index.projects', {
+ url: '/projects',
+ templateUrl: 'app/work/projects.html',
+ data: { pageTitle: 'Projects List' },
+ controller: 'ProjectListCtrl',
+ controllerAs: 'vm',
+ resolve: { auth: authenticate }
+ })
+ .state('index.clients', {
+ abstract: true,
+ url: '/clients',
+ templateUrl: 'app/clients/clients.html',
+ data: { pageTitle: 'Clients' },
+ controller: 'billingaccount.ClientsController'
+ })
+ .state('index.clients.list', {
+ url: '/list',
+ templateUrl: 'app/clients/clients.list.html',
+ controller: 'billingaccount.ClientsListController',
+ resolve: { auth: authenticate }
+ })
+ .state('index.clients.new', {
+ url: '/new',
+ templateUrl: 'app/clients/clients.new.html',
+ controller: 'billingaccount.NewClientController',
+ data: { pageTitle: 'New Client' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.clients.edit', {
+ url: '/edit/:clientId',
+ templateUrl: 'app/clients/clients.edit.html',
+ controller: 'billingaccount.EditClientController',
+ data: { pageTitle: 'Edit Client' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.billingaccounts', {
+ abstract: true,
+ url: '/billingaccounts',
+ templateUrl: 'app/billing_accounts/billingaccounts.html',
+ data: { pageTitle: 'Billing Accounts' },
+ controller: 'billingaccount.BillingAccountsController'
+ })
+ .state('index.billingaccounts.list', {
+ url: '/list',
+ templateUrl: 'app/billing_accounts/billingaccounts.list.html',
+ controller: 'billingaccount.BillingAccountsListController',
+ resolve: { auth: authenticate }
+ })
+ .state('index.billingaccounts.new', {
+ url: '/new',
+ templateUrl: 'app/billing_accounts/billingaccounts.new.html',
+ controller: 'billingaccount.NewBillingAccountController',
+ data: { pageTitle: 'New Billing Account' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.billingaccounts.edit', {
+ url: '/edit/:accountId',
+ templateUrl: 'app/billing_accounts/billingaccounts.edit.html',
+ controller: 'billingaccount.EditBillingAccountController',
+ data: { pageTitle: 'Edit Billing Account' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.billingaccounts.view', {
+ url: '/view/:accountId',
+ templateUrl: 'app/billing_accounts/billingaccounts.view.html',
+ controller: 'billingaccount.ViewBillingAccountController',
+ data: { pageTitle: 'Details - Billing Account' },
+ resolve: { auth: authenticate }
+ })
+ .state('index.billingaccountresources', {
+ abstract: true,
+ url: '/billingaccountresources',
+ templateUrl: 'app/billing_account_resources/billingaccountresources.html',
+ data: { pageTitle: 'Billing Account Resources' },
+ controller: 'billingaccount.BillingAccountResourcesController'
+ })
+ .state('index.billingaccountresources.list', {
+ url: '/list/:accountId',
+ templateUrl: 'app/billing_account_resources/billingaccountresources.list.html',
+ controller: 'billingaccount.BillingAccountResourcesListController',
+ resolve: { auth: authenticate }
+ })
+ .state('index.billingaccountresources.new', {
+ url: '/:accountId/new',
+ templateUrl: 'app/billing_account_resources/billingaccountresources.new.html',
+ controller: 'billingaccount.NewBillingAccountResourceController',
+ data: { pageTitle: 'New Billing Account Resource' },
+ resolve: { auth: authenticate }
+ });
- $urlRouterProvider.otherwise('/login');
+ $urlRouterProvider.otherwise('/index/main');
// $locationProvider.html5Mode(true).hashPrefix('!');
});
diff --git a/src/app/auth/auth.config.js b/src/app/auth/auth.config.js
new file mode 100644
index 0000000..27496f0
--- /dev/null
+++ b/src/app/auth/auth.config.js
@@ -0,0 +1,65 @@
+'use strict';
+
+/**
+ * Inject JWT token into http requests
+ *
+ * It inject token V2 for requests to API V2
+ * and token V3 for requests to API V3
+ */
+
+angular.module('supportAdminApp')
+ .config(function($httpProvider, jwtInterceptorProvider) {
+ var refreshingToken = null;
+
+ jwtInterceptorProvider.tokenGetter = [
+ 'AuthService', '$http', 'API_URL', 'ADMIN_TOOL_URL', 'config',
+ function($authService, $http, API_URL, ADMIN_TOOL_URL, config) {
+ // token V2 for API V2
+ if (config.url.indexOf(ADMIN_TOOL_URL) > -1) {
+ if ($authService.getTokenV2()) {
+ return $authService.getTokenV2();
+ } else {
+ $authService.login();
+ }
+
+ // token V3 for API V3
+ } else {
+ var currentToken = $authService.getTokenV3();
+
+ function handleRefreshResponse(res) {
+ var newToken, ref, ref1, ref2;
+
+ newToken = (ref = res.data) != null ? (ref1 = ref.result) != null ? (ref2 = ref1.content) != null ? ref2.token : void 0 : void 0 : void 0;
+
+ $authService.setTokenV3(newToken);
+
+ return newToken;
+ };
+
+ function refreshingTokenComplete() {
+ return refreshingToken = null;
+ };
+
+ if ($authService.getTokenV3() && $authService.isTokenV3Expired()) {
+ if (refreshingToken === null) {
+ refreshingToken = $http({
+ method: 'GET',
+ url: API_URL + "/v3/authorizations/1",
+ headers: {
+ 'Authorization': "Bearer " + currentToken
+ }
+ })
+ .then(handleRefreshResponse)["finally"](refreshingTokenComplete)
+ .catch(function() {
+ $authService.login();
+ });
+ }
+ return refreshingToken;
+ } else {
+ return currentToken;
+ }
+ }
+ }];
+
+ return $httpProvider.interceptors.push('jwtInterceptor');
+ });
diff --git a/src/app/auth/auth.controller.js b/src/app/auth/auth.controller.js
new file mode 100644
index 0000000..69a4b7e
--- /dev/null
+++ b/src/app/auth/auth.controller.js
@@ -0,0 +1,42 @@
+'use strict';
+
+angular.module('supportAdminApp')
+ .controller('LoginController', [
+ '$q', '$scope', '$state', 'AuthService',
+ function ($q, $scope, $state, $authService) {
+
+ $scope.logginOut = false;
+ $scope.errorMessage = '';
+
+ function onLogOut() {
+ $authService.login();
+ // we could stop loggin out indicator but we don't do it, because redirecting doesn't happen immediately
+ // so we keep showing loging out indicator even if log out already complete
+ // anyway we go from this page
+ // $scope.logginOut = false;
+ }
+
+ // if we come to this page and user is logged in, and we are not loggin out
+ // then we shouldn't be on this page so we redirect to index
+ if ($authService.isLoggedIn() && !$authService.logginOut) {
+ $state.go('index.users');
+
+ // if we are loggin out currently, then show "loggin out..." message
+ } else if ($authService.logginOut) {
+ $scope.logginOut = true;
+ $authService.logginOut.then(onLogOut);
+
+ // as we come to this page after AuthService.authenticate()
+ // the only one case when we can come to this page now if access was denied for current user
+ // so we show permissions denied error
+ } else {
+ $scope.errorMessage = $authService.ERROR.NO_PERMISSIONS;
+ }
+
+ $scope.logout = function() {
+ $scope.errorMessage = '';
+ $scope.logginOut = true;
+ $authService.logout().then(onLogOut);
+ }
+
+ }]);
diff --git a/src/app/auth/auth.html b/src/app/auth/auth.html
new file mode 100644
index 0000000..b302ab6
--- /dev/null
+++ b/src/app/auth/auth.html
@@ -0,0 +1,23 @@
+
diff --git a/src/app/auth/auth.service.js b/src/app/auth/auth.service.js
new file mode 100644
index 0000000..46dffd4
--- /dev/null
+++ b/src/app/auth/auth.service.js
@@ -0,0 +1,275 @@
+'use strict';
+
+angular.module('supportAdminApp')
+ .factory('AuthService', [
+ '$q', '$log', 'jwtHelper', '$cookies', '$window', '$state', 'AUTH_URL', 'ACCOUNTS_CONNECTOR_URL', 'COOKIES_SECURE', 'JWT_V3_NAME', 'JWT_V2_NAME',
+ function($q, $log, jwtHelper, $cookies, $window, $state, AUTH_URL, ACCOUNTS_CONNECTOR_URL, COOKIES_SECURE, JWT_V3_NAME, JWT_V2_NAME) {
+ // these constants are for AuthService internal usage only
+ // they don't depend on the environment thus don't have to be placed in global config
+ var GET_FRESH_TOKEN_REQUEST = 'GET_FRESH_TOKEN_REQUEST';
+ var GET_FRESH_TOKEN_SUCCESS = 'GET_FRESH_TOKEN_SUCCESS';
+ var GET_FRESH_TOKEN_FAILURE = 'GET_FRESH_TOKEN_FAILURE';
+
+ var LOGOUT_REQUEST = 'LOGOUT_REQUEST';
+ var LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
+ var LOGOUT_FAILURE = 'LOGOUT_FAILURE';
+
+ // local variables
+ var connectorIFrame, url, loading;
+
+ /**
+ * Create invisible iframe and append it to the body
+ *
+ * @param {String} id iframe tag id
+ * @param {String} src iframe source
+ * @return {HTMLElement} dom element of the iframe
+ */
+ function createFrame(id, src) {
+
+ var iframe = document.createElement('iframe');
+
+ iframe.id = id;
+ iframe.src = src;
+ iframe.width = 0;
+ iframe.height = 0;
+ iframe.frameborder = 0;
+
+ // set inline style cross-browser way to make iframe completely invisible
+ angular.element(iframe).css({
+ display: 'block',
+ border: '0'
+ })
+
+ document.body.appendChild(iframe);
+
+ return iframe;
+ }
+
+ /**
+ * Proxies calls to the iframe from main window
+ *
+ * @param {String} REQUEST request id
+ * @param {String} SUCCESS success respond id
+ * @param {String} FAILURE failure respond id
+ * @param {Object} params params of the request
+ * @return {Promise} promise of the request
+ */
+ function proxyCall(REQUEST, SUCCESS, FAILURE, params) {
+ if (!connectorIFrame) {
+ throw new Error('connector has not yet been configured.')
+ }
+
+ var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+
+ function request() {
+ return $q(function(resolve, reject) {
+ function receiveMessage(e) {
+ var safeFormat = e.data.type === SUCCESS || e.data.type === FAILURE
+ if (safeFormat) {
+ window.removeEventListener('message', receiveMessage)
+ if (e.data.type === SUCCESS) resolve(e.data)
+ if (e.data.type === FAILURE) reject(e.error)
+ }
+ }
+
+ window.addEventListener('message', receiveMessage)
+
+ var payload = $.extend({}, { type: REQUEST }, params)
+
+ connectorIFrame.contentWindow.postMessage(payload, url)
+ })
+ }
+
+ return loading.then(request)
+ }
+
+ /**
+ * Create invisible iframe which will be used to retrieve token v3
+ *
+ * @param {Object} options frameId and connectorUrl for the iframe
+ * @return {Promise} promise on iframe load
+ */
+ function configureConnector(options) {
+ if (connectorIFrame) {
+ $log.warn('iframe connector can only be configured once, this request has been ignored.')
+ } else {
+ connectorIFrame = createFrame(options.frameId, options.connectorUrl)
+ url = options.connectorUrl
+
+ loading = $q(function(resolve) {
+ connectorIFrame.onload = function() {
+ resolve()
+ }
+ })
+ }
+ }
+
+ var AuthService = {
+ ERROR: {
+ NO_PERMISSIONS: 'Current user doesn\'t have administrator permissions.'
+ }
+ };
+
+ /**
+ * Returns promise which is resolved when connector iframe is loaded
+ *
+ * @return {Promise}
+ */
+ AuthService.ready = function() {
+ if (!connectorIFrame) {
+ throw new Error('AuthService.init() has to be called once when app run before any other methods of AuthService.');
+ }
+
+ return loading;
+ }
+
+ /**
+ * Retrieves new token v3 using hidden iframe
+ * check that user has administrator credentials and save it to the cookies
+ *
+ * @return {Promise} promise to get token v3
+ */
+ AuthService.retriveFreshToken = function() {
+ return proxyCall(GET_FRESH_TOKEN_REQUEST, GET_FRESH_TOKEN_SUCCESS, GET_FRESH_TOKEN_FAILURE)
+ .then(function(data) {
+ var user = jwtHelper.decodeToken(data.token);
+
+ if ($.inArray('administrator', user && user.roles) < 0) {
+ return $q.reject(AuthService.ERROR.NO_PERMISSIONS);
+ } else {
+ AuthService.setTokenV3(data.token);
+ }
+ });
+ }
+
+ /**
+ * Log out user
+ * Clear cookies and send request to the server for log out
+ *
+ * @return {Promise} promise which is resolved when user is logged out on the server
+ */
+ AuthService.logout = function() {
+ // send request to the server that we want to log out
+ // save logginOut promise to be accessed any time
+ AuthService.logginOut = proxyCall(LOGOUT_REQUEST, LOGOUT_SUCCESS, LOGOUT_FAILURE).then(function() {
+ AuthService.logginOut = null;
+ });
+ // remove only token V3, which we set from the script manually
+ // token V2 will be removed automatically during logout server request
+ $cookies.remove(JWT_V3_NAME);
+
+ return AuthService.logginOut;
+ }
+
+ AuthService.login = function() {
+ $window.location.href = AUTH_URL + '?retUrl=' + encodeURIComponent($window.location.href);
+ }
+
+ /**
+ * Init auth service
+ * This has to called once when app starts
+ */
+ AuthService.init = function() {
+ // add hidden iframe which is used to get API v3 token
+ configureConnector({
+ connectorUrl: ACCOUNTS_CONNECTOR_URL,
+ frameId: 'tc-accounts-iframe',
+ });
+ }
+
+ /**
+ * Checks if user is already login or not
+ * If usr is not login, then redirect to TopCoder login form
+ *
+ * @return {Promise} promise to authenticate
+ */
+ AuthService.authenticate = function() {
+ return AuthService.ready().then(function() {
+ if (AuthService.isLoggedIn()) {
+ return $q.resolve();
+ } else {
+ if (AuthService.getTokenV2()) {
+ return AuthService.retriveFreshToken().catch(function(err) {
+ // if error about permission denied we will pass this error through
+ // otherwise got to login page
+ if (err !== AuthService.ERROR.NO_PERMISSIONS) {
+ AuthService.login();
+ }
+ return $q.reject(err);
+ });
+ } else {
+ AuthService.login();
+ return $q.reject();
+ }
+ }
+ });
+ }
+
+ /**
+ * Returns token v3 or null
+ *
+ * @return {String} token v3
+ */
+ AuthService.getTokenV3 = function() {
+ return $cookies.get(JWT_V3_NAME);
+ }
+
+ /**
+ * Save token V3 to cookies
+ */
+ AuthService.setTokenV3 = function(token) {
+ return $cookies.put(JWT_V3_NAME, token, {
+ secure: COOKIES_SECURE,
+ });
+ }
+
+ /**
+ * Check if token V3 is expired or no
+ *
+ * @return {Boolean} true if token V3 is expired
+ */
+ AuthService.isTokenV3Expired = function() {
+ return !AuthService.getTokenV3() || jwtHelper.isTokenExpired(AuthService.getTokenV3(), 300);
+ }
+
+ /**
+ * Returns token v2 or null
+ *
+ * @return {String} token v2
+ */
+ AuthService.getTokenV2 = function() {
+ return $cookies.get(JWT_V2_NAME);
+ }
+
+ /**
+ * Check if user is fully logged in
+ *
+ * @return {Boolean} true if user is logged in
+ */
+ AuthService.isLoggedIn = function() {
+ // we have to ckeck only for token v3, as if have this one, it means we have and v2 also
+ return !!AuthService.getTokenV3();
+ }
+
+ /**
+ * Returns information of the current user, which is retrieved from token v3
+ *
+ * @return {Object} current user object
+ */
+ AuthService.getCurrentUser = function() {
+ var tctV3 = AuthService.getTokenV3();
+
+ if (!tctV3) {
+ return null;
+ }
+
+ var currentUser = jwtHelper.decodeToken(tctV3);
+ currentUser.id = currentUser.userId;
+ currentUser.token = tctV3;
+
+ return currentUser;
+ }
+
+ return AuthService;
+
+ }]);
diff --git a/src/app/billing_account_resources/billingaccountresources.service.js b/src/app/billing_account_resources/billingaccountresources.service.js
index 457848b..9186704 100644
--- a/src/app/billing_account_resources/billingaccountresources.service.js
+++ b/src/app/billing_account_resources/billingaccountresources.service.js
@@ -56,9 +56,11 @@ angular.module('supportAdminApp')
var deferred = $q.defer();
$http({
method: 'POST',
- data: {
- userId: entity.userId
- },
+ data: angular.toJson({
+ param: {
+ userId: entity.userId
+ }
+ }),
headers: {
'Content-Type': 'application/json'
},
diff --git a/src/app/billing_accounts/billingaccounts.service.js b/src/app/billing_accounts/billingaccounts.service.js
index 7cf084f..3e4654c 100644
--- a/src/app/billing_accounts/billingaccounts.service.js
+++ b/src/app/billing_accounts/billingaccounts.service.js
@@ -101,7 +101,9 @@ angular.module('supportAdminApp')
var deferred = $q.defer();
$http({
method: 'POST',
- data: request,
+ data: angular.toJson({
+ param: request
+ }),
headers: {
'Content-Type': 'application/json'
},
@@ -123,7 +125,9 @@ angular.module('supportAdminApp')
var deferred = $q.defer();
$http({
method: 'PATCH',
- data: entity,
+ data: angular.toJson({
+ param: entity
+ }),
headers: {
'Content-Type': 'application/json'
},
diff --git a/src/app/less/custom.less b/src/app/less/custom.less
index 89f8f14..ffddbda 100755
--- a/src/app/less/custom.less
+++ b/src/app/less/custom.less
@@ -3,4 +3,11 @@
.welcome-message {
display: none;
}
-}
\ No newline at end of file
+}
+
+/* Permission Management - Roles */
+
+.user-in-role {
+ display: inline-block;
+ margin-right: 12px;
+}
diff --git a/src/app/less/navigation.less b/src/app/less/navigation.less
index 3e4e56f..95ce0ee 100755
--- a/src/app/less/navigation.less
+++ b/src/app/less/navigation.less
@@ -476,6 +476,18 @@ body.canvas-menu.mini-navbar .navbar-default .nav li a span {
display: inline;
}
+#side-menu {
+ li {
+ span {
+ vertical-align: top;
+ }
+ }
+ .nav-label {
+ display: inline-block;
+ width: 120px;
+ }
+}
+
body.canvas-menu.mini-navbar .navbar-default .nav li .profile-element a span {
display: block;
}
diff --git a/src/app/login/login.controller.js b/src/app/login/login.controller.js
deleted file mode 100644
index f3a09bf..0000000
--- a/src/app/login/login.controller.js
+++ /dev/null
@@ -1,69 +0,0 @@
-'use strict';
-
-angular.module('supportAdminApp')
- .controller('LoginController', [
- '$log', '$scope', '$rootScope', '$location', '$state', 'AuthService', 'TokenService', 'UserService', 'Alert',
- function ($log, $scope, $rootScope, $location, $state, $authService, $tokenService, $userService, $alert) {
-
- $scope.loggingIn = false;
-
- $scope.formLogin = {
- username: null,
- password: null,
- loggingIn: false,
- valid: function() {
- return !!(this.username && this.username.length > 0 &&
- this.password && this.password.length > 0);
- }
- };
-
- $scope.login = function() {
-
- $alert.clear();
-
- var loginSuccess = function() {
- var token = $tokenService.decodeToken();
- $log.debug(token);
- if($.inArray('administrator', token && token.roles) < 0) {
- $alert.error('Permission denied.', $scope);
- $scope.formLogin.loggingIn = false;
- return;
- }
- $userService.findById(token.userId).then(
- function(currentUser) {
- $rootScope.currentUser = currentUser;
- $state.go('index.users');
- },
- function(err) {
- $log.error('Failed to get user data.');
- $log.error(err);
- $state.go('index.users');
- }
- );
- };
-
- var loginFailure = function(err) {
- $log.error('Login Failed')
- $log.error(err)
- var reason = err && err.data && err.data.error,
- msg = err && err.data && err.data.error_description || err.statusText;
- if(reason === "invalid_user_password") {
- msg = "Wrong username or password.";
- }
- $alert.error(msg, $scope);
- $scope.formLogin.loggingIn = false;
- };
-
- var options = {
- connection: "TC-User-Database",
- username: $scope.formLogin.username,
- password: $scope.formLogin.password,
- success: loginSuccess,
- error: loginFailure
- };
-
- $scope.formLogin.loggingIn = true;
- $authService.login(options);
- };
-
- }]);
diff --git a/src/app/login/login.html b/src/app/login/login.html
deleted file mode 100755
index 0af6d1c..0000000
--- a/src/app/login/login.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
diff --git a/src/app/main/main.controller.js b/src/app/main/main.controller.js
index 36d6843..59bbfda 100755
--- a/src/app/main/main.controller.js
+++ b/src/app/main/main.controller.js
@@ -6,11 +6,7 @@ angular.module('supportAdminApp')
$scope.logout = function() {
$authService.logout();
- $state.go('login');
- };
-
- $scope.login = function() {
- $state.go('login');
+ $state.go('auth')
};
// auth
diff --git a/src/app/permission_management/permission_management.controller.js b/src/app/permission_management/permission_management.controller.js
new file mode 100644
index 0000000..92dcb5b
--- /dev/null
+++ b/src/app/permission_management/permission_management.controller.js
@@ -0,0 +1,178 @@
+angular.module('supportAdminApp')
+.controller('PermissionManagementCtrl', [
+ '$scope', '$timeout', 'PermissionManagementService', 'UserService',
+ function ($scope, $timeout, PMService, UserService) {
+
+ var vm = this;
+
+ /* Table initialization. */
+
+ angular.element(document).ready(function() {
+ $('.footable').footable({
+ addRowToggle: true
+ });
+ });
+
+ $scope.$on('permissionManagement.DataUpdated', function(event) {
+ $timeout(function () {
+ $('.footable').trigger('footable_redraw');
+ }, 100);
+ });
+
+ /* Role search by name. */
+
+ vm.searchCreateRoleText = '';
+
+ vm.clearRoleSearch = function() {
+ vm.searchCreateRoleText = '';
+ vm.searchRole();
+ }
+
+ vm.searchRole = function() {
+ $('.footable').trigger('footable_filter', {
+ filter: vm.searchCreateRoleText,
+ });
+ }
+
+ /* Role creation. */
+
+ vm.creatingNewRole = false;
+ vm.createNewRoleError = '';
+
+ vm.createNewRole = function() {
+ vm.creatingNewRole = true;
+ vm.createNewRoleError = '';
+ PMService.createRole(vm.searchCreateRoleText)
+ .then(function(res) {
+ vm.roles.push(res);
+ loadUser(res.createdBy);
+ loadUser(res.modifiedBy);
+ vm.assignment[res.id] = {};
+ vm.roles = vm.roles.sort(function(a, b) {
+ return a.roleName.localeCompare(b.roleName);
+ });
+ }, function(error) {
+ vm.createNewRoleError =
+ 'Error: ' + (error.message || 'Failed to create role!');
+ }).then(function() {
+ vm.creatingNewRole = false;
+ $scope.$broadcast('permissionManagement.DataUpdated');
+ });
+ }
+
+ /* Role assignments. */
+
+ vm.assignment = {};
+
+ /**
+ * Assigns role to the user.
+ * @param {String} roleId
+ * @param {String} userHandle
+ */
+ vm.assignRole = function(roleId, userHandle) {
+ vm.assignment[roleId].inProgress = true;
+ vm.assignment[roleId].error = '';
+ vm.assignment[roleId].info = '';
+ var userId;
+ UserService.find({
+ filter: 'handle=' + userHandle,
+ }).then(function(res) {
+ if (!res.length) throw new Error('No user found!');
+ userId = res[0].id;
+ vm.users[userId] = userHandle;
+ return PMService.assignRole(roleId, userId);
+ }).then(function() {
+ var role = vm.roles.find(function (r) { return r.id === roleId; });
+ vm.assignment[roleId].info =
+ 'Success: Role ' + role.roleName
+ + ' assigned to the user ' + userHandle;
+ }, function(error) {
+ vm.assignment[roleId].error =
+ 'Error: ' + (error.message || 'Failed to assign role!');
+ }).then(function() {
+ vm.assignment[roleId].inProgress = false;
+ });
+ }
+
+ /**
+ * Unassign role from the user.
+ * @param {String} roleId
+ * @param {String} userId
+ */
+ vm.unassignRole = function(roleId, userHandle) {
+ vm.assignment[roleId].error = '';
+ var role = vm.roles.find(function(r) {
+ return r.id === roleId;
+ });
+ vm.assignment[roleId].error = '';
+ vm.assignment[roleId].info = '';
+ var userId;
+ UserService.find({
+ filter: 'handle=' + userHandle,
+ }).then(function (res) {
+ if (!res.length) throw new Error('No user found!');
+ userId = res[0].id;
+ vm.users[userId] = userHandle;
+ if (confirm('Unassign role ' + role.roleName + ' from user ' + vm.users[userId] + '?')) {
+ return PMService.unassignRole(roleId, userId).then(function() {
+ var role = vm.roles.find(function (r) { return r.id === roleId; });
+ vm.assignment[roleId].info =
+ 'Success: Role ' + role.roleName
+ + ' unassigned from the user ' + userHandle;
+ });
+ }
+ }).catch(function(error) {
+ vm.assignment[roleId].error =
+ 'Error: ' + (error.message || 'Failed to unassign role!');
+ });
+ };
+
+ /* Loading roles. */
+
+ vm.loadingRoles = true;
+ vm.loadingRolesError = null;
+ PMService.getRoles().then(function(roles) {
+ vm.roles = roles;
+ roles.forEach(function(role) {
+ vm.assignment[role.id] = {};
+ loadUser(role.createdBy);
+ loadUser(role.modifiedBy);
+ });
+ }, function(error) {
+ vm.loadingRolesError =
+ 'Error: ' + (error.message || 'Failed to load roles!');
+ }).then(function() {
+ vm.loadingRoles = false;
+ $scope.$broadcast('permissionManagement.DataUpdated');
+ });
+
+ /* Maps user ids, present in the page, into user handles. */
+ vm.users = {};
+
+ /**
+ * Loads handle of the user specified by id into $scope.users. Does nothing,
+ * if the handle is already in there. To avoid overflooding API with
+ * requests, this function handles the calls sequentially.
+ * @param {String} id User ID.
+ */
+ var loadingUser = false;
+ var userLoadQueue = [];
+ function loadUser(id) {
+ if (id && !vm.users[id]) {
+ if (loadingUser) userLoadQueue.push(id);
+ else {
+ loadingUser = true;
+ UserService.findById(id).then(function(res) {
+ vm.users[id] = res.handle;
+ loadingUser = false;
+ while (userLoadQueue.length) {
+ var next = userLoadQueue[0];
+ userLoadQueue = userLoadQueue.slice(1);
+ if (!vm.users[next]) return loadUser(next);
+ }
+ });
+ }
+ }
+ }
+ }
+]);
\ No newline at end of file
diff --git a/src/app/permission_management/permission_management.html b/src/app/permission_management/permission_management.html
new file mode 100644
index 0000000..9bb00bf
--- /dev/null
+++ b/src/app/permission_management/permission_management.html
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
{{ctrl.loadingRolesError}}
+
+
+
+
Press on a role row to assign/unassign users.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/permission_management/permission_management.service.js b/src/app/permission_management/permission_management.service.js
new file mode 100644
index 0000000..febbd24
--- /dev/null
+++ b/src/app/permission_management/permission_management.service.js
@@ -0,0 +1,73 @@
+angular.module('supportAdminApp')
+.factory('PermissionManagementService', [
+ '$http', 'API_URL',
+ function($http, API_URL) {
+ var Service = {};
+
+ /**
+ * Assigns role to the user.
+ * @param {String} roleId
+ * @param {String} userId
+ * @return {Promise} Resolves to the roleId, if success.
+ */
+ Service.assignRole = function(roleId, userId) {
+ return $http.post(API_URL + '/v3/roles/' + roleId
+ + '/assign?action=true&filter=subjectID%3D' + userId)
+ .then(function(res) {
+ return res.data.result.content;
+ });
+ };
+
+ /**
+ * Creates a new role.
+ * @param {String} roleName
+ * @return {Promise} Resolves to the created role object.
+ */
+ Service.createRole = function(roleName) {
+ return $http({
+ method: 'POST',
+ url: API_URL + '/v3/roles',
+ data: angular.toJson({
+ param: {
+ roleName: roleName
+ }
+ }),
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ }).then(function(res) {
+ return res.data.result.content;
+ });
+ };
+
+ /**
+ * Gets roles.
+ * @return {Promise} Resolves to the array of role objects, sorted
+ * by names.
+ */
+ Service.getRoles = function() {
+ return $http.get(API_URL + '/v3/roles')
+ .then(function(res) {
+ return res.data.result.content.sort(function(a, b) {
+ return a.roleName.localeCompare(b.roleName);
+ });
+ });
+ };
+
+ /**
+ * Unassigns the role from the user.
+ * @param {String} roleId
+ * @param {String} userId
+ * @return {Promise} Resolves to the roleId, if success.
+ */
+ Service.unassignRole = function(roleId, userId) {
+ return $http.delete(API_URL + '/v3/roles/' + roleId
+ + '/deassign?action=true&filter=subjectID%3D' + userId)
+ .then(function(res) {
+ return res.data.result.content;
+ });
+ };
+
+ return Service;
+ }
+]);
diff --git a/src/app/tags/tags.edit.controller.js b/src/app/tags/tags.edit.controller.js
index f079800..644d471 100755
--- a/src/app/tags/tags.edit.controller.js
+++ b/src/app/tags/tags.edit.controller.js
@@ -2,8 +2,8 @@
var module = angular.module('supportAdminApp');
-module.controller('EditTagCtrl', ['$rootScope','$scope', 'TagService', '$state','$stateParams', '$log', '$timeout',
- function($rootScope, $scope, $tagService, $state, $stateParams, $log, $timeout) {
+module.controller('EditTagCtrl', ['AuthService','$scope', 'TagService', '$state','$stateParams', '$log', '$timeout',
+ function($authService, $scope, $tagService, $state, $stateParams, $log, $timeout) {
$scope.loading = true;
$scope.processing = false;
$scope.editTag = {};
@@ -39,7 +39,7 @@ module.controller('EditTagCtrl', ['$rootScope','$scope', 'TagService', '$state',
$scope.submitTag = function() {
$scope.$broadcast('alert.ClearAll', {});
$scope.processing = true;
- $scope.editTag.updatedBy = $rootScope.currentUser.id;
+ $scope.editTag.updatedBy = $authService.getCurrentUser().id;
$scope.editTag.synonyms = $scope.editForm.synonyms? $scope.editForm.synonyms.split(','):[];
$scope.editTag.categories = [];
angular.forEach($scope.editCategories.options, function(c){
diff --git a/src/components/common/navigation.html b/src/components/common/navigation.html
index 949ac59..7d429d1 100755
--- a/src/components/common/navigation.html
+++ b/src/components/common/navigation.html
@@ -17,6 +17,16 @@
Import SSO Users
+
+
+
+ Permission Management
+
+
+
+
Billing Account