request current password when changing profile data for security reasons

This commit is contained in:
Athou
2022-07-23 10:57:10 +02:00
parent b6a9b17410
commit c36dd47afd
34 changed files with 103 additions and 50 deletions

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Change password",
"confirm_password" : "Confirm password",
"minimum_6_chars" : "Minimum 6 characters",
"minimum_8_chars" : "Minimum 8 characters",
"passwords_do_not_match" : "Passwords do not match",
"api_key" : "API key",
"api_key_not_generated" : "Not generated yet",

View File

@@ -111,7 +111,7 @@
"email" : "Adreça electrònica",
"change_password" : "Canvia la contrasenya ",
"confirm_password" : "Confirma la contrasenya",
"minimum_6_chars" : "Mínim de 6 caracters",
"minimum_8_chars" : "Mínim de 8 caracters",
"passwords_do_not_match" : "Les contrasenyes no coincideixen",
"api_key" : "Clau API ",
"api_key_not_generated" : "Encara no s'ha generat",

View File

@@ -111,7 +111,7 @@
"email " : " E-mail",
"change_password " : " Změnit heslo",
"confirm_password " : " Potvrdit heslo",
"minimum_6_chars " : " Minimum je 6 znaků",
"minimum_8_chars " : " Minimum je 8 znaků",
"passwords_do_not_match " : " Hesla se neshodují",
"api_key " : " API klíč",
"api_key_not_generated " : " Není vygenerován",

View File

@@ -111,7 +111,7 @@
"email" : "E-bost",
"change_password" : "Newid cyfrinair",
"confirm_password" : "Cadarnhau cyfrinair",
"minimum_6_chars" : "Isafswm 6 nod",
"minimum_8_chars" : "Isafswm 8 nod",
"passwords_do_not_match" : "Mae'r cyfrineiriau yn wahanol",
"api_key" : "Allwedd API",
"api_key_not_generated" : "Heb ei gynhyrchu eto",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Skift adgangskode",
"confirm_password" : "Bekræft adgangskode",
"minimum_6_chars" : "Minimum 6 karakter",
"minimum_8_chars" : "Minimum 8 karakter",
"passwords_do_not_match" : "Adgangskoderne er ikke ens",
"api_key" : "API nøgle",
"api_key_not_generated" : "Ikke genereret endnu",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Passwort ändern",
"confirm_password" : "Passwort bestätigen",
"minimum_6_chars" : "Mindestens 6 Zeichen",
"minimum_8_chars" : "Mindestens 8 Zeichen",
"passwords_do_not_match" : "Passwörter stimmen nicht überein",
"api_key" : "API Schlüssel",
"api_key_not_generated" : "Noch nicht generiert",

View File

@@ -111,9 +111,10 @@
"profile" : {
"user_name" : "User name",
"email" : "E-mail",
"current_password" : "Current Password",
"change_password" : "Change password",
"confirm_password" : "Confirm password",
"minimum_6_chars" : "Minimum 6 characters",
"minimum_8_chars" : "Minimum 8 characters",
"passwords_do_not_match" : "Passwords do not match",
"api_key" : "API key",
"api_key_not_generated" : "Not generated yet",

View File

@@ -113,7 +113,7 @@
"email" : "Correo electrónico",
"change_password" : "Cambiar contraseña",
"confirm_password" : "Confirmar contraseña",
"minimum_6_chars" : "Mínimo 6 caracteres",
"minimum_8_chars" : "Mínimo 8 caracteres",
"passwords_do_not_match" : "Las contraseñas no coinciden",
"api_key" : "Clave API",
"api_key_not_generated" : "No generado todavía",

View File

@@ -111,7 +111,7 @@
"email" : "رایانامه",
"change_password" : "تغییر گذرواژه",
"confirm_password" : "تأیید گذرواژه",
"minimum_6_chars" : "حداقل ۶ نویسه",
"minimum_8_chars" : "حداقل ۸ نویسه",
"passwords_do_not_match" : "گذرواژه‌ها انطباق ندارند",
"api_key" : "کلید API",
"api_key_not_generated" : "هنوز ایجاد نشده‌است",

View File

@@ -111,7 +111,7 @@
"email" : "Sähköposti",
"change_password" : "Vaihda salasana",
"confirm_password" : "Vahvista uusi salasana",
"minimum_6_chars" : "Vähintään 6 merkkiä",
"minimum_8_chars" : "Vähintään 8 merkkiä",
"passwords_do_not_match" : "Salasanat eivät täsmää",
"api_key" : "API-avain",
"api_key_not_generated" : "API-avainta ei ole vielä luotu",

View File

@@ -109,9 +109,10 @@
"profile" : {
"user_name" : "Nom",
"email" : "E-mail",
"current_password" : "Mot de passe actuel",
"change_password" : "Changer de mot de passe",
"confirm_password" : "Confirmer le mot de passe",
"minimum_6_chars" : "Minimum 6 caractères",
"minimum_8_chars" : "Minimum 8 caractères",
"passwords_do_not_match" : "Les mots de passe ne correspondent pas",
"api_key" : "Clé API",
"api_key_not_generated" : "Pas encore générée",

View File

@@ -111,7 +111,7 @@
"email" : "Correo",
"change_password" : "Cambiar contrasinal",
"confirm_password" : "Confirmar contrasinal",
"minimum_6_chars" : "Mínimo 6 caracteres",
"minimum_8_chars" : "Mínimo 8 caracteres",
"passwords_do_not_match" : "Os contrasinais non coinciden no coinciden",
"api_key" : "Chave API",
"api_key_not_generated" : "Non xerado todavía",

View File

@@ -111,7 +111,7 @@
"email" : "ایمئل",
"change_password" : "رمزه عوضأگودن",
"confirm_password" : "رمزه تأیید گودن",
"minimum_6_chars" : "ناقلن 6 کارکتر",
"minimum_8_chars" : "ناقلن 8 کارکتر",
"passwords_do_not_match" : "رمزان کس‌به‌کسه نخانید",
"api_key" : "کلید API",
"api_key_not_generated" : "هلئه چاگوده نبؤ",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Jelszó megváltoztatás",
"confirm_password" : "Jelszó megerősítése",
"minimum_6_chars" : "Legalább 8 karakter",
"minimum_8_chars" : "Legalább 8 karakter",
"passwords_do_not_match" : "A jelszavak nem egyeznek",
"api_key" : "API kulcs",
"api_key_not_generated" : "Még nincsen generálva",

View File

@@ -113,7 +113,7 @@
"email" : "Surel",
"change_password" : "Ganti kata sandi",
"confirm_password" : "Konfirmasi kata sandi",
"minimum_6_chars" : "Minimal 6 karakter",
"minimum_8_chars" : "Minimal 8 karakter",
"passwords_do_not_match" : "Kata sandi tidak sesuai",
"api_key" : "kunci API",
"api_key_not_generated" : "Belum menghasilkan",

View File

@@ -113,7 +113,7 @@
"email" : "E-mail",
"change_password" : "Cambia password",
"confirm_password" : "Conferma password",
"minimum_6_chars" : "Minimo 6 caratteri",
"minimum_8_chars" : "Minimo 8 caratteri",
"passwords_do_not_match" : "Le password non corrispondono",
"api_key" : "chiave API",
"api_key_not_generated" : "Non ancora generata",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "パスワードの変更",
"confirm_password" : "変更パスワードの確認",
"minimum_6_chars" : "6文字以上",
"minimum_8_chars" : "8文字以上",
"passwords_do_not_match" : "パスワードが一致しません",
"api_key" : "APIキー",
"api_key_not_generated" : "APIキーが生成されていません",

View File

@@ -111,7 +111,7 @@
"email" : "이메일",
"change_password" : "비밀번호 변경",
"confirm_password" : "비밀번호 확인",
"minimum_6_chars" : "최소 6개의 문자가 필요합니다.",
"minimum_8_chars" : "최소 8개의 문자가 필요합니다.",
"passwords_do_not_match" : "비밀번호가 일치하지 않습니다.",
"api_key" : "API key",
"api_key_not_generated" : "아직 API Key가 생성되지 않았습니다.",

View File

@@ -111,7 +111,7 @@
"email" : "E-mel",
"change_password" : "Tukar kata laluan",
"confirm_password" : "Sahkan kata laluan",
"minimum_6_chars" : "Minimum 6 huruf",
"minimum_8_chars" : "Minimum 8 huruf",
"passwords_do_not_match" : "Kata laluan tidak sama",
"api_key" : "API key",
"api_key_not_generated" : "Belum dijana",

View File

@@ -111,7 +111,7 @@
"email" : "E-post",
"change_password" : "Endre passord",
"confirm_password" : "Bekreft passord",
"minimum_6_chars" : "Minimum 6 tegn",
"minimum_8_chars" : "Minimum 8 tegn",
"passwords_do_not_match" : "Passordene er ikke like",
"api_key" : "API-nøkkel",
"api_key_not_generated" : "Har ikke blitt generert",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Verander wachtwoord",
"confirm_password" : "Bevestig wachtwoord",
"minimum_6_chars" : "Minimaal 6 tekens",
"minimum_8_chars" : "Minimaal 8 tekens",
"passwords_do_not_match" : "Wachtwoorden komen niet overeen",
"api_key" : "API sleutel",
"api_key_not_generated" : "Nog niet gegenereerd",

View File

@@ -111,7 +111,7 @@
"email" : "E-post",
"change_password" : "Endre passord",
"confirm_password" : "Stadfest passord",
"minimum_6_chars" : "Minimum 6 teikn",
"minimum_8_chars" : "Minimum 8 teikn",
"passwords_do_not_match" : "Passorda er usamde",
"api_key" : "API-nykel",
"api_key_not_generated" : "Har ikkje vorte generert",

View File

@@ -113,7 +113,7 @@
"email" : "E-mail",
"change_password" : "Zmień hasło",
"confirm_password" : "Potwierdź hasło",
"minimum_6_chars" : "Minimum 6 znaków",
"minimum_8_chars" : "Minimum 8 znaków",
"passwords_do_not_match" : "Hasła nie pasują do siebie",
"api_key" : "Klucz API",
"api_key_not_generated" : "Jeszcze niewygenerowany",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Trocar senha",
"confirm_password" : "Confirmar senha",
"minimum_6_chars" : "Mínimo de 6 caracteres",
"minimum_8_chars" : "Mínimo de 8 caracteres",
"passwords_do_not_match" : "Senhas não conferem",
"api_key" : "Chave de API",
"api_key_not_generated" : "Ainda não gerada",

View File

@@ -111,7 +111,7 @@
"email" : "Эл. почта",
"change_password" : "Изменить пароль",
"confirm_password" : "Подтвердите пароль",
"minimum_6_chars" : "Не меньше 6 символов",
"minimum_8_chars" : "Не меньше 8 символов",
"passwords_do_not_match" : "Пароли не совпадают",
"api_key" : "API-ключ",
"api_key_not_generated" : "Не сгенерирован",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Zmeniť heslo",
"confirm_password" : "Potvrdiť heslo",
"minimum_6_chars" : "Minimum je 6 znakov",
"minimum_8_chars" : "Minimum je 8 znakov",
"passwords_do_not_match" : "Heslá sa nezhodujú",
"api_key" : "API kľúč",
"api_key_not_generated" : "Nie je vygenerovaný",

View File

@@ -111,7 +111,7 @@
"email" : "E-mail",
"change_password" : "Ändra lösenord",
"confirm_password" : "Bekräfta lösenord",
"minimum_6_chars" : "Minst 6 bokstäver",
"minimum_8_chars" : "Minst 8 bokstäver",
"passwords_do_not_match" : "Lösenorden matchar inte",
"api_key" : "API-nyckel",
"api_key_not_generated" : "Inte skapad än",

View File

@@ -111,7 +111,7 @@
"email" : "E-posta",
"change_password" : "Şifre değiştir",
"confirm_password" : "Şifreyi doğrula",
"minimum_6_chars" : "En az 6 karakter",
"minimum_8_chars" : "En az 8 karakter",
"passwords_do_not_match" : "Şifreler uyuşmuyor",
"api_key" : "API anahtarı",
"api_key_not_generated" : "Henüz oluşturulmadı",

View File

@@ -111,7 +111,7 @@
"email" : "邮箱",
"change_password" : "修改密码",
"confirm_password" : "确认密码",
"minimum_6_chars" : "最少为 6 个字母",
"minimum_8_chars" : "最少为 8 个字母",
"passwords_do_not_match" : "密码不匹配",
"api_key" : "API 密钥",
"api_key_not_generated" : "API 密钥尚未生成",

View File

@@ -1546,23 +1546,39 @@ module.controller("ProfileCtrl", [
AnalyticsService.track()
$scope.user = ProfileService.get()
$scope.error = ""
$scope.cancel = function () {
$location.path("/")
}
$scope.save = function () {
$scope.error = ""
if (!$scope.profileForm.$valid) {
return
}
var o = {
email: $scope.user.email,
password: $scope.user.password,
currentPassword: $scope.currentPassword,
newPassword: $scope.newPassword,
newApiKey: $scope.newApiKey,
}
ProfileService.save(o, function () {
$location.path("/")
})
ProfileService.save(
o,
function () {
$location.path("/")
},
function (error) {
var data = error.data
if (data.errors) {
// password validation error
$scope.error = data.errors.join(", ")
} else {
// bad request error
$scope.error = data.message
}
}
)
}
$scope.deleteAccount = function () {
ProfileService.deleteAccount({})

View File

@@ -3,12 +3,27 @@
<h1>{{ 'toolbar.profile' | translate }}</h1>
</div>
<form name="profileForm" ng-submit="save()" class="form-horizontal">
<div ng-if="error" class="col-sm-offset-2 col-sm-10 alert alert-danger">{{error}}</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="email">{{ 'profile.user_name' | translate }}</label>
<div class="col-sm-10 checkbox">
<span>{{user.name}}</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="currentPassword">{{ 'profile.current_password' | translate }}</label>
<div class="col-sm-10">
<input
type="password"
name="currentPassword"
id="currentPassword"
ng-model="currentPassword"
class="form-control"
autocomplete="off"
required
/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="email">{{ 'profile.email' | translate }}</label>
<div class="col-sm-10">
@@ -16,18 +31,20 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">{{ 'profile.change_password' | translate }}</label>
<label class="col-sm-2 control-label" for="newPassword">{{ 'profile.change_password' | translate }}</label>
<div class="col-sm-10">
<input
type="password"
name="password"
id="password"
ng-model="user.password"
name="newPassword"
id="newPassword"
ng-model="newPassword"
class="form-control"
ng-minlength="6"
ng-minlength="8"
autocomplete="off"
/>
<span class="help-inline" ng-show="profileForm.password.$error.minlength">{{ 'profile.minimum_6_chars' | translate }}</span>
<span class="help-inline" ng-show="profileForm.newPassword.$error.minlength"
>{{ 'profile.minimum_8_chars' | translate }}</span
>
</div>
</div>
<div class="form-group">
@@ -39,8 +56,8 @@
name="password_c"
id="password_c"
ng-model="password_c"
ui-validate="'$value==user.password'"
ui-validate-watch="'user.password'"
ui-validate="'$value==newPassword'"
ui-validate-watch="'newPassword'"
autocomplete="off"
/>
<span class="help-inline" ng-show="profileForm.password_c.$error.validator"

View File

@@ -5,6 +5,7 @@ import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.lang3.StringUtils;
import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.LengthRule;
@@ -22,6 +23,10 @@ public class PasswordConstraintValidator implements ConstraintValidator<ValidPas
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (StringUtils.isBlank(value)) {
return true;
}
PasswordValidator validator = buildPasswordValidator();
RuleResult result = validator.validate(new PasswordData(value));

View File

@@ -12,13 +12,15 @@ import lombok.Data;
@ApiModel(description = "Profile modification request")
@Data
public class ProfileModificationRequest implements Serializable {
@ApiModelProperty(value = "current user password, required to change profile data", required = true)
private String currentPassword;
@ApiModelProperty(value = "changes email of the user, if specified")
private String email;
@ApiModelProperty(value = "changes password of the user, if specified")
@ValidPassword
private String password;
private String newPassword;
@ApiModelProperty(value = "generate a new api key")
private boolean newApiKey;

View File

@@ -8,6 +8,7 @@ import java.util.UUID;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.validation.Valid;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -193,24 +194,34 @@ public class UserREST {
@Timed
public Response saveUserProfile(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(required = true) ProfileModificationRequest request) {
if (StringUtils.isNotBlank(request.getEmail())) {
User u = userDAO.findByEmail(request.getEmail());
Preconditions.checkArgument(u == null || user.getId().equals(u.getId()));
}
if (CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
return Response.status(Status.FORBIDDEN).build();
}
user.setEmail(StringUtils.trimToNull(request.getEmail()));
if (StringUtils.isNotBlank(request.getPassword())) {
byte[] password = encryptionService.getEncryptedPassword(request.getPassword(), user.getSalt());
Optional<User> login = userService.login(user.getEmail(), request.getCurrentPassword());
if (!login.isPresent()) {
throw new BadRequestException("invalid password");
}
String email = StringUtils.trimToNull(request.getEmail());
if (StringUtils.isNotBlank(email)) {
User u = userDAO.findByEmail(email);
if (u != null && !user.getId().equals(u.getId())) {
throw new BadRequestException("email already taken");
}
}
user.setEmail(email);
if (StringUtils.isNotBlank(request.getNewPassword())) {
byte[] password = encryptionService.getEncryptedPassword(request.getNewPassword(), user.getSalt());
user.setPassword(password);
user.setApiKey(userService.generateApiKey(user));
}
if (request.isNewApiKey()) {
user.setApiKey(userService.generateApiKey(user));
}
userDAO.update(user);
return Response.ok().build();
}