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
pull/2228/head
Anthony Lapenna 2018-08-28 10:13:01 +02:00 committed by GitHub
parent bfccf55729
commit 812f3e3e85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 203 additions and 73 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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) {

View File

@ -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)

View File

@ -0,0 +1,64 @@
<div class="page-wrapper">
<!-- box -->
<div class="container simple-box">
<div class="col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1">
<!-- panel -->
<div class="panel panel-default">
<div class="panel-body">
<form class="simple-box-form form-horizontal" name="updatePasswordForm">
<!-- note -->
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">
Your password must be updated.
</span>
</div>
</div>
<!-- !note -->
<!-- new-password-input -->
<div class="form-group">
<label for="password" class="col-sm-4 control-label text-left">Password</label>
<div class="col-sm-8">
<input type="password" class="form-control" ng-model="formValues.Password" id="password" auto-focus required>
</div>
</div>
<!-- !new-password-input -->
<!-- confirm-password-input -->
<div class="form-group">
<label for="confirm_password" class="col-sm-4 control-label text-left">Confirm password</label>
<div class="col-sm-8">
<div class="input-group">
<input type="password" class="form-control" ng-model="formValues.ConfirmPassword" id="confirm_password" required>
<span class="input-group-addon"><i ng-class="{true: 'fa fa-check green-icon', false: 'fa fa-times red-icon'}[formValues.Password !== '' && formValues.Password === formValues.ConfirmPassword]" aria-hidden="true"></i></span>
</div>
</div>
</div>
<!-- !confirm-password-input -->
<!-- note -->
<div class="form-group">
<div class="col-sm-12">
<span class="small text-muted">
<i ng-class="{true: 'fa fa-check green-icon', false: 'fa fa-times red-icon'}[formValues.Password.length >= 8]" aria-hidden="true"></i>
The password must be at least 8 characters long
</span>
</div>
</div>
<!-- !note -->
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !updatePasswordForm.$valid || formValues.Password.length < 8 || formValues.Password !== formValues.ConfirmPassword" ng-click="updatePassword()" button-spinner="state.actionInProgress">
<span ng-hide="state.actionInProgress">Update password</span>
<span ng-show="state.actionInProgress">Updating password...</span>
</button>
</div>
</div>
<!-- !actions -->
</form>
</div>
</div>
<!-- ! panel -->
</div>
</div>
<!-- ! box -->
</div>

View File

@ -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();
}]);

View File

@ -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) {

View File

@ -36,8 +36,8 @@
<body ng-controller="MainController">
<div id="page-wrapper" ng-class="{
open: toggle && ['portainer.auth', 'portainer.init.admin', 'portainer.init.endpoint'].indexOf($state.current.name) === -1,
nopadding: ['portainer.auth', 'portainer.init.admin', 'portainer.init.endpoint'].indexOf($state.current.name) > -1 || applicationState.loading
open: toggle && ['portainer.auth', 'portainer.updatePassword', 'portainer.init.admin', 'portainer.init.endpoint'].indexOf($state.current.name) === -1,
nopadding: ['portainer.auth', 'portainer.updatePassword', 'portainer.init.admin', 'portainer.init.endpoint'].indexOf($state.current.name) > -1 || applicationState.loading
}"
ng-cloak>
<div id="sideview" ui-view="sidebar" ng-if="!applicationState.loading"></div>