mirror of https://github.com/portainer/portainer
non-admins must supply existing passwd when changing passwd (#10249)
parent
515b02813b
commit
e5f7641e46
|
@ -20,6 +20,7 @@ var (
|
||||||
errAdminCannotRemoveSelf = errors.New("Cannot remove your own user account. Contact another administrator")
|
errAdminCannotRemoveSelf = errors.New("Cannot remove your own user account. Contact another administrator")
|
||||||
errCannotRemoveLastLocalAdmin = errors.New("Cannot remove the last local administrator account")
|
errCannotRemoveLastLocalAdmin = errors.New("Cannot remove the last local administrator account")
|
||||||
errCryptoHashFailure = errors.New("Unable to hash data")
|
errCryptoHashFailure = errors.New("Unable to hash data")
|
||||||
|
errWrongPassword = errors.New("Wrong password")
|
||||||
)
|
)
|
||||||
|
|
||||||
func hideFields(user *portainer.User) {
|
func hideFields(user *portainer.User) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ type themePayload struct {
|
||||||
type userUpdatePayload struct {
|
type userUpdatePayload struct {
|
||||||
Username string `validate:"required" example:"bob"`
|
Username string `validate:"required" example:"bob"`
|
||||||
Password string `validate:"required" example:"cg9Wgky3"`
|
Password string `validate:"required" example:"cg9Wgky3"`
|
||||||
|
NewPassword string `validate:"required" example:"asfj2emv"`
|
||||||
Theme *themePayload
|
Theme *themePayload
|
||||||
|
|
||||||
// User role (1 for administrator account and 2 for regular account)
|
// User role (1 for administrator account and 2 for regular account)
|
||||||
|
@ -37,6 +38,7 @@ func (payload *userUpdatePayload) Validate(r *http.Request) error {
|
||||||
if payload.Role != 0 && payload.Role != 1 && payload.Role != 2 {
|
if payload.Role != 0 && payload.Role != 1 && payload.Role != 2 {
|
||||||
return errors.New("invalid role value. Value must be one of: 1 (administrator) or 2 (regular user)")
|
return errors.New("invalid role value. Value must be one of: 1 (administrator) or 2 (regular user)")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +108,20 @@ func (handler *Handler) userUpdate(w http.ResponseWriter, r *http.Request) *http
|
||||||
user.Username = payload.Username
|
user.Username = payload.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.Password != "" {
|
if payload.NewPassword != "" {
|
||||||
user.Password, err = handler.CryptoService.Hash(payload.Password)
|
// Non-admins need to supply the previous password
|
||||||
|
if tokenData.Role != portainer.AdministratorRole {
|
||||||
|
err := handler.CryptoService.CompareHashAndData(user.Password, payload.Password)
|
||||||
|
if err != nil {
|
||||||
|
return httperror.Forbidden("Current password doesn't match. Password left unchanged", errors.New("Current password does not match the password provided. Please try again"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !handler.passwordStrengthChecker.Check(payload.NewPassword) {
|
||||||
|
return httperror.BadRequest("Password does not meet the minimum strength requirements", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Password, err = handler.CryptoService.Hash(payload.NewPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return httperror.InternalServerError("Unable to hash user password", errCryptoHashFailure)
|
return httperror.InternalServerError("Unable to hash user password", errCryptoHashFailure)
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (handler *Handler) userUpdatePassword(w http.ResponseWriter, r *http.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
if !handler.passwordStrengthChecker.Check(payload.NewPassword) {
|
if !handler.passwordStrengthChecker.Check(payload.NewPassword) {
|
||||||
return httperror.BadRequest("Password does not meet the requirements", nil)
|
return httperror.BadRequest("Password does not meet the minimum strength requirements", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Password, err = handler.CryptoService.Hash(payload.NewPassword)
|
user.Password, err = handler.CryptoService.Hash(payload.NewPassword)
|
||||||
|
|
|
@ -54,8 +54,8 @@ export function UserService($q, Users, TeamService, TeamMembershipService) {
|
||||||
return Users.remove({ id: id }).$promise;
|
return Users.remove({ id: id }).$promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
service.updateUser = function (id, { password, role, username }) {
|
service.updateUser = function (id, { newPassword, role, username }) {
|
||||||
return Users.update({ id }, { password, role, username }).$promise;
|
return Users.update({ id }, { newPassword, role, username }).$promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
service.updateUserPassword = function (id, currentPassword, newPassword) {
|
service.updateUserPassword = function (id, currentPassword, newPassword) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ angular.module('portainer.app').controller('UserController', [
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UserService.updateUser($scope.user.Id, { password: $scope.formValues.newPassword })
|
UserService.updateUser($scope.user.Id, { newPassword: $scope.formValues.newPassword })
|
||||||
.then(function success() {
|
.then(function success() {
|
||||||
Notifications.success('Success', 'Password successfully updated');
|
Notifications.success('Success', 'Password successfully updated');
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue