From 812f3e3e8532f1c23df251d8eaa0c6c1a1089ec6 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Tue, 28 Aug 2018 10:13:01 +0200 Subject: [PATCH] feat(auth): remove sanitization calls and ask for password update if needed (#2222) * wip * feat(auth): remove sanitization calls and ask for password update if needed --- app/portainer/__module.js | 90 +++++++++++-------- .../views/account/accountController.js | 8 +- app/portainer/views/auth/authController.js | 54 ++++++----- .../views/init/admin/initAdminController.js | 8 +- .../views/update-password/updatePassword.html | 64 +++++++++++++ .../updatePasswordController.js | 40 +++++++++ app/portainer/views/users/usersController.js | 8 +- index.html | 4 +- 8 files changed, 203 insertions(+), 73 deletions(-) create mode 100644 app/portainer/views/update-password/updatePassword.html create mode 100644 app/portainer/views/update-password/updatePasswordController.js diff --git a/app/portainer/__module.js b/app/portainer/__module.js index a2ad9053d..6ddfb5f2a 100644 --- a/app/portainer/__module.js +++ b/app/portainer/__module.js @@ -65,40 +65,6 @@ angular.module('portainer.app', []) } }; - var init = { - name: 'portainer.init', - abstract: true, - url: '/init', - data: { - requiresLogin: false - }, - views: { - 'sidebar@': {} - } - }; - - var initEndpoint = { - name: 'portainer.init.endpoint', - url: '/endpoint', - views: { - 'content@': { - templateUrl: 'app/portainer/views/init/endpoint/initEndpoint.html', - controller: 'InitEndpointController' - } - } - }; - - var initAdmin = { - name: 'portainer.init.admin', - url: '/admin', - views: { - 'content@': { - templateUrl: 'app/portainer/views/init/admin/initAdmin.html', - controller: 'InitAdminController' - } - } - }; - var endpoints = { name: 'portainer.endpoints', url: '/endpoints', @@ -198,6 +164,40 @@ angular.module('portainer.app', []) } }; + var init = { + name: 'portainer.init', + abstract: true, + url: '/init', + data: { + requiresLogin: false + }, + views: { + 'sidebar@': {} + } + }; + + var initEndpoint = { + name: 'portainer.init.endpoint', + url: '/endpoint', + views: { + 'content@': { + templateUrl: 'app/portainer/views/init/endpoint/initEndpoint.html', + controller: 'InitEndpointController' + } + } + }; + + var initAdmin = { + name: 'portainer.init.admin', + url: '/admin', + views: { + 'content@': { + templateUrl: 'app/portainer/views/init/admin/initAdmin.html', + controller: 'InitAdminController' + } + } + }; + var registries = { name: 'portainer.registries', url: '/registries', @@ -318,6 +318,21 @@ angular.module('portainer.app', []) } }; + var updatePassword = { + name: 'portainer.updatePassword', + url: '/update-password', + views: { + 'content@': { + templateUrl: 'app/portainer/views/update-password/updatePassword.html', + controller: 'UpdatePasswordController' + }, + 'sidebar@': {} + }, + params: { + password: '' + } + }; + var users = { name: 'portainer.users', url: '/users', @@ -404,9 +419,6 @@ angular.module('portainer.app', []) $stateRegistryProvider.register(about); $stateRegistryProvider.register(account); $stateRegistryProvider.register(authentication); - $stateRegistryProvider.register(init); - $stateRegistryProvider.register(initEndpoint); - $stateRegistryProvider.register(initAdmin); $stateRegistryProvider.register(endpoints); $stateRegistryProvider.register(endpoint); $stateRegistryProvider.register(endpointAccess); @@ -416,6 +428,9 @@ angular.module('portainer.app', []) $stateRegistryProvider.register(groupAccess); $stateRegistryProvider.register(groupCreation); $stateRegistryProvider.register(home); + $stateRegistryProvider.register(init); + $stateRegistryProvider.register(initEndpoint); + $stateRegistryProvider.register(initAdmin); $stateRegistryProvider.register(registries); $stateRegistryProvider.register(registry); $stateRegistryProvider.register(registryAccess); @@ -427,6 +442,7 @@ angular.module('portainer.app', []) $stateRegistryProvider.register(stackCreation); $stateRegistryProvider.register(support); $stateRegistryProvider.register(tags); + $stateRegistryProvider.register(updatePassword); $stateRegistryProvider.register(users); $stateRegistryProvider.register(user); $stateRegistryProvider.register(teams); diff --git a/app/portainer/views/account/accountController.js b/app/portainer/views/account/accountController.js index b842b7317..304fd2586 100644 --- a/app/portainer/views/account/accountController.js +++ b/app/portainer/views/account/accountController.js @@ -1,6 +1,6 @@ angular.module('portainer.app') -.controller('AccountController', ['$scope', '$state', '$sanitize', 'Authentication', 'UserService', 'Notifications', 'SettingsService', -function ($scope, $state, $sanitize, Authentication, UserService, Notifications, SettingsService) { +.controller('AccountController', ['$scope', '$state', 'Authentication', 'UserService', 'Notifications', 'SettingsService', +function ($scope, $state, Authentication, UserService, Notifications, SettingsService) { $scope.formValues = { currentPassword: '', newPassword: '', @@ -9,10 +9,8 @@ function ($scope, $state, $sanitize, Authentication, UserService, Notifications, $scope.updatePassword = function() { $scope.invalidPassword = false; - var currentPassword = $sanitize($scope.formValues.currentPassword); - var newPassword = $sanitize($scope.formValues.newPassword); - UserService.updateUserPassword($scope.userID, currentPassword, newPassword) + UserService.updateUserPassword($scope.userID, $scope.formValues.currentPassword, $scope.formValues.newPassword) .then(function success() { Notifications.success('Success', 'Password successfully updated'); $state.reload(); diff --git a/app/portainer/views/auth/authController.js b/app/portainer/views/auth/authController.js index 90d5e85a2..3b18d600c 100644 --- a/app/portainer/views/auth/authController.js +++ b/app/portainer/views/auth/authController.js @@ -1,6 +1,6 @@ angular.module('portainer.app') -.controller('AuthenticationController', ['$scope', '$state', '$transition$', '$sanitize', 'Authentication', 'UserService', 'EndpointService', 'StateManager', 'Notifications', 'SettingsService', -function ($scope, $state, $transition$, $sanitize, Authentication, UserService, EndpointService, StateManager, Notifications, SettingsService) { +.controller('AuthenticationController', ['$q', '$scope', '$state', '$transition$', '$sanitize', 'Authentication', 'UserService', 'EndpointService', 'StateManager', 'Notifications', 'SettingsService', +function ($q, $scope, $state, $transition$, $sanitize, Authentication, UserService, EndpointService, StateManager, Notifications, SettingsService) { $scope.logo = StateManager.getState().application.logo; @@ -13,6 +13,31 @@ function ($scope, $state, $transition$, $sanitize, Authentication, UserService, AuthenticationError: '' }; + $scope.authenticateUser = function() { + var username = $scope.formValues.Username; + var password = $scope.formValues.Password; + + Authentication.login(username, password) + .then(function success() { + checkForEndpoints(); + }) + .catch(function error() { + SettingsService.publicSettings() + .then(function success(settings) { + if (settings.AuthenticationMethod === 1) { + return Authentication.login($sanitize(username), $sanitize(password)); + } + return $q.reject(); + }) + .then(function success() { + $state.go('portainer.updatePassword', { password: $sanitize(password) }); + }) + .catch(function error() { + $scope.state.AuthenticationError = 'Invalid credentials'; + }); + }); + }; + function unauthenticatedFlow() { EndpointService.endpoints() .then(function success(endpoints) { @@ -39,35 +64,22 @@ function ($scope, $state, $transition$, $sanitize, Authentication, UserService, }); } - $scope.authenticateUser = function() { - var username = $scope.formValues.Username; - var password = $scope.formValues.Password; - - SettingsService.publicSettings() - .then(function success(data) { - var settings = data; - if (settings.AuthenticationMethod === 1) { - username = $sanitize(username); - password = $sanitize(password); - } - return Authentication.login(username, password); - }) - .then(function success() { - return EndpointService.endpoints(); - }) + function checkForEndpoints() { + EndpointService.endpoints() .then(function success(data) { var endpoints = data; var userDetails = Authentication.getUserDetails(); + if (endpoints.length === 0 && userDetails.role === 1) { $state.go('portainer.init.endpoint'); } else { $state.go('portainer.home'); } }) - .catch(function error() { - $scope.state.AuthenticationError = 'Invalid credentials'; + .catch(function error(err) { + Notifications.error('Failure', err, 'Unable to retrieve endpoints'); }); - }; + } function initView() { if ($transition$.params().logout || $transition$.params().error) { diff --git a/app/portainer/views/init/admin/initAdminController.js b/app/portainer/views/init/admin/initAdminController.js index e43f8a0ec..569bb1491 100644 --- a/app/portainer/views/init/admin/initAdminController.js +++ b/app/portainer/views/init/admin/initAdminController.js @@ -1,6 +1,6 @@ angular.module('portainer.app') -.controller('InitAdminController', ['$scope', '$state', '$sanitize', 'Notifications', 'Authentication', 'StateManager', 'UserService', 'EndpointService', -function ($scope, $state, $sanitize, Notifications, Authentication, StateManager, UserService, EndpointService) { +.controller('InitAdminController', ['$scope', '$state', 'Notifications', 'Authentication', 'StateManager', 'UserService', 'EndpointService', +function ($scope, $state, Notifications, Authentication, StateManager, UserService, EndpointService) { $scope.logo = StateManager.getState().application.logo; @@ -15,8 +15,8 @@ function ($scope, $state, $sanitize, Notifications, Authentication, StateManager }; $scope.createAdminUser = function() { - var username = $sanitize($scope.formValues.Username); - var password = $sanitize($scope.formValues.Password); + var username = $scope.formValues.Username; + var password = $scope.formValues.Password; $scope.state.actionInProgress = true; UserService.initAdministrator(username, password) diff --git a/app/portainer/views/update-password/updatePassword.html b/app/portainer/views/update-password/updatePassword.html new file mode 100644 index 000000000..62c726a61 --- /dev/null +++ b/app/portainer/views/update-password/updatePassword.html @@ -0,0 +1,64 @@ +
+ +
+
+ +
+
+
+ +
+
+ + Your password must be updated. + +
+
+ + +
+ +
+ +
+
+ + +
+ +
+
+ + +
+
+
+ + +
+
+ + + The password must be at least 8 characters long + +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+
+ +
diff --git a/app/portainer/views/update-password/updatePasswordController.js b/app/portainer/views/update-password/updatePasswordController.js new file mode 100644 index 000000000..6809d1a34 --- /dev/null +++ b/app/portainer/views/update-password/updatePasswordController.js @@ -0,0 +1,40 @@ +angular.module('portainer.app') +.controller('UpdatePasswordController', ['$scope', '$state', '$transition$', 'UserService', 'Authentication', 'Notifications', +function UpdatePasswordController($scope, $state, $transition$, UserService, Authentication, Notifications) { + + $scope.formValues = { + Password: '', + ConfirmPassword: '' + }; + + $scope.state = { + actionInProgress: false, + currentPassword: '' + }; + + $scope.updatePassword = function() { + var userId = Authentication.getUserDetails().ID; + + $scope.state.actionInProgress = true; + UserService.updateUserPassword(userId, $scope.state.currentPassword, $scope.formValues.Password) + .then(function success() { + $state.go('portainer.home'); + }) + .catch(function error(err) { + Notifications.error('Failure', err, 'Unable to update password'); + }) + .finally(function final() { + $scope.state.actionInProgress = false; + }); + }; + + function initView() { + if (!Authentication.isAuthenticated()) { + $state.go('portainer.auth'); + } + + $scope.state.currentPassword = $transition$.params().password; + } + + initView(); +}]); diff --git a/app/portainer/views/users/usersController.js b/app/portainer/views/users/usersController.js index 3fb6de991..ea9bb425d 100644 --- a/app/portainer/views/users/usersController.js +++ b/app/portainer/views/users/usersController.js @@ -1,6 +1,6 @@ angular.module('portainer.app') -.controller('UsersController', ['$q', '$scope', '$state', '$sanitize', 'UserService', 'TeamService', 'TeamMembershipService', 'ModalService', 'Notifications', 'Authentication', 'SettingsService', -function ($q, $scope, $state, $sanitize, UserService, TeamService, TeamMembershipService, ModalService, Notifications, Authentication, SettingsService) { +.controller('UsersController', ['$q', '$scope', '$state', 'UserService', 'TeamService', 'TeamMembershipService', 'ModalService', 'Notifications', 'Authentication', 'SettingsService', +function ($q, $scope, $state, UserService, TeamService, TeamMembershipService, ModalService, Notifications, Authentication, SettingsService) { $scope.state = { userCreationError: '', validUsername: false, @@ -30,8 +30,8 @@ function ($q, $scope, $state, $sanitize, UserService, TeamService, TeamMembershi $scope.addUser = function() { $scope.state.actionInProgress = true; $scope.state.userCreationError = ''; - var username = $sanitize($scope.formValues.Username); - var password = $sanitize($scope.formValues.Password); + var username = $scope.formValues.Username; + var password = $scope.formValues.Password; var role = $scope.formValues.Administrator ? 1 : 2; var teamIds = []; angular.forEach($scope.formValues.Teams, function(team) { diff --git a/index.html b/index.html index cb5540b9a..0ec14b658 100644 --- a/index.html +++ b/index.html @@ -36,8 +36,8 @@