Skip to content

Commit

Permalink
Merge branch 'master' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
Johaney-s committed Nov 14, 2022
2 parents bd175db + 93e884c commit 2e00a77
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,33 @@ public interface PerunTranslation extends Messages {
@DefaultMessage("Password must <ul><li>contain only printing (non-accented) characters<li>be at least 10 characters long<li>consist of at least 3 of 4 character groups<ul><li>lower-case letters<li>upper-case letters<li>digits<li>special characters</ul></ul>")
public String einfraPasswordHelp();

@DefaultMessage("Password must <ul><li>contain only printing (non-accented) characters<li>be at least 14 characters long<li>consist of at least 3 of 4 character groups<ul><li>lower-case letters<li>upper-case letters<li>digits<li>special characters</ul></ul>")
public String muAdmPasswordHelp();

@DefaultMessage("Password must be <b>at least 10 characters</b> long!")
public String einfraPasswordLength();

@DefaultMessage("Password must be <b>at least 14 characters</b> long!")
public String muAdmPasswordLength();

@DefaultMessage("Password <b>can`t contain accented characters (diacritics)</b> or non-printing and control characters!")
public String einfraPasswordFormat();

@DefaultMessage("Password <b>can`t contain accented characters (diacritics)</b> or non-printing and control characters!")
public String muAdmPasswordFormat();

@DefaultMessage("Password must consist of <b>at least 3 of 4</b> character groups<ul><li>lower-case letters</li><li>upper-case letters</li><li>digits</li><li>special characters</li></ul>")
public String einfraPasswordStrength();

@DefaultMessage("Password must consist of <b>at least 3 of 4</b> character groups<ul><li>lower-case letters</li><li>upper-case letters</li><li>digits</li><li>special characters</li></ul>")
public String muAdmPasswordStrength();

@DefaultMessage("Password <b>can`t contain login, name or surname</b>, not even backwards!")
public String einfraPasswordStrengthForNameLogin();

@DefaultMessage("Password <b>can`t contain login</b>, not even backwards!")
public String muAdmPasswordStrengthForNameLogin();

@DefaultMessage("New password can`t be empty!")
public String passwordCantBeEmpty();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ einfraPasswordLength=Heslo musí mít <b>alespoň 10 znaků!</b>
einfraPasswordFormat=Heslo <b>nesmí obsahovat diakritiku</b> nebo řídící a formátovací znaky!</b>
einfraPasswordStrength=Heslo musí obsahovat <b>alespoň 3 ze 4</b> kategorií znaků<ul><li>malá písmena</li><li>velká písmena</li><li>číslice</li><li>speciální znaky</li></ul>
einfraPasswordStrengthForNameLogin=Heslo <b>nesmí obsahovat login, jméno nebo příjmení</b> a to ani pozpátku!
muAdmPasswordLength=Heslo musí mít <b>alespoň 14 znaků!</b>
muAdmPasswordFormat=Heslo <b>nesmí obsahovat diakritiku</b> nebo řídící a formátovací znaky!</b>
muAdmPasswordStrengthForNameLogin=Heslo <b>nesmí obsahovat login</b> a to ani pozpátku!
muAdmPasswordStrength=Heslo musí obsahovat <b>alespoň 3 ze 4</b> kategorií znaků<ul><li>malá písmena</li><li>velká písmena</li><li>číslice</li><li>speciální znaky</li></ul>
muAdmPasswordHelp=Heslo musí<ul><li>obsahovat pouze tisknutelné znaky (bez diakritiky)<li>mít délku 14 a více znaků<li>obsahovat alespoň 3 ze 4 kategorií znaků<ul><li>malá písmena<li>velká písmena<li>číslice<li>speciální znaky</ul></ul>
passwordCantBeEmpty=Nové heslo nesmí být prázdné!
passwordMismatch=Hesla se neshodují!
secondPasswordIsEmpty=Zopakujte nové heslo pro kontrolu
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import cz.metacentrum.perun.wui.model.beans.ApplicationFormItemData;
import cz.metacentrum.perun.wui.registrar.widgets.PerunForm;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.EinfraPasswordValidator;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.MuAdmPasswordValidator;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.PasswordValidator;
import cz.metacentrum.perun.wui.registrar.widgets.items.validators.PerunFormItemValidator;
import cz.metacentrum.perun.wui.widgets.boxes.ExtendedPasswordTextBox;
Expand Down Expand Up @@ -35,6 +36,8 @@ public Password(PerunForm form, ApplicationFormItemData item, String lang) {
// FIXME - specific per-namespace validation
if (item.getFormItem() != null && Objects.equals("urn:perun:user:attribute-def:def:login-namespace:einfra", item.getFormItem().getPerunDestinationAttribute())) {
this.validator = new EinfraPasswordValidator();
} else if (item.getFormItem() != null && Objects.equals("urn:perun:user:attribute-def:def:login-namespace:mu-adm", item.getFormItem().getPerunDestinationAttribute())) {
this.validator = new MuAdmPasswordValidator();
} else {
this.validator = new PasswordValidator();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ protected Widget initFormItem() {
}
}

// replace MU-ADM help texts to support HTML formatting
if (this.getItemData().getFormItem() != null &&
"urn:perun:user:attribute-def:def:login-namespace:mu-adm".equals(this.getItemData().getFormItem().getPerunDestinationAttribute())) {
if (this instanceof Password) {
help.setHTML(translation.muAdmPasswordHelp());
}
}

widgetWithTexts.add(help);

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package cz.metacentrum.perun.wui.registrar.widgets.items.validators;

import com.google.gwt.regexp.shared.RegExp;
import cz.metacentrum.perun.wui.registrar.widgets.items.Password;
import cz.metacentrum.perun.wui.registrar.widgets.items.PerunFormItem;
import cz.metacentrum.perun.wui.registrar.widgets.items.Username;
import org.gwtbootstrap3.client.ui.constants.ValidationState;

import java.util.List;
import java.util.Objects;

/**
* Specific password validator for MU-ADM namespace
*
* TODO: We must revalidate this form item when person`s name changes after entering password value !!
*
* @author Pavel Zlámal <zlamal@cesnet.cz>
*/
public class MuAdmPasswordValidator extends PasswordValidator {

@Override
public boolean validateLocal(Password password) {

if (password.isRequired() && isNullOrEmpty(password.getValue())) {
setResult(Result.EMPTY_PASSWORD);
password.setRawStatus(getTransl().passEmpty(), ValidationState.ERROR);
return false;
}

// limit only to ASCII printable chars
RegExp regExp2 = RegExp.compile("^[\\x20-\\x7E]{1,}$");
if(regExp2.exec(password.getValue()) == null){
setResult(Result.INVALID_FORMAT);
password.setRawStatus(getTransl().muAdmPasswordFormat(), ValidationState.ERROR);
return false;
}

// Check that password contains at least 3 of 4 character groups

RegExp regExpDigit = RegExp.compile("^.*[0-9].*$");
RegExp regExpLower = RegExp.compile("^.*[a-z].*$");
RegExp regExpUpper = RegExp.compile("^.*[A-Z].*$");
RegExp regExpSpec = RegExp.compile("^.*[\\x20-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E].*$"); // FIXME - are those correct printable specific chars?

int matchCounter = 0;
if (regExpDigit.exec(password.getValue()) != null) matchCounter++;
if (regExpLower.exec(password.getValue()) != null) matchCounter++;
if (regExpUpper.exec(password.getValue()) != null) matchCounter++;
if (regExpSpec.exec(password.getValue()) != null) matchCounter++;

if(matchCounter < 3){
setResult(Result.INVALID_FORMAT);
password.setRawStatus(getTransl().muAdmPasswordStrength(), ValidationState.ERROR);
return false;
}

if (!checkOnNamesAndLogins(getLoginValue(password), password)) return false;

// check length
if (password.getValue().length() < 14) {
setResult(Result.INVALID_FORMAT);
password.setRawStatus(getTransl().muAdmPasswordLength(), ValidationState.ERROR);
return false;
}

// check typos
if (!password.getPassword().getValue().equals(password.getPasswordSecond().getValue())) {
if (isNullOrEmpty(password.getPasswordSecond().getValue())) {
setResult(Result.SECOND_PASSWORD_EMPTY);
password.setStatus(getTransl().secondPassEmpty(), ValidationState.WARNING);
return false;
}
setResult(Result.PASSWORD_MISSMATCH);
password.setStatus(getTransl().passMismatch(), ValidationState.ERROR);
return false;
}

password.setStatus(ValidationState.SUCCESS);
return true;

}

private String getLoginValue(Password password) {

List<PerunFormItem> items = password.getForm().getPerunFormItems();
for (PerunFormItem item : items) {
if (item instanceof Username) {
if (item.getItemData().getFormItem() != null && Objects.equals("urn:perun:user:attribute-def:def:login-namespace:mu-adm", item.getItemData().getFormItem().getPerunDestinationAttribute())) {
return item.getValue();
}
}
}
return null;

}

public static String reverse(String string) {
if (string == null || string.isEmpty() || string.length() == 1) return string;
return string.charAt(string.length()-1)+reverse(string.substring(1, string.length()-1))+string.charAt(0);
}

/**
* Return FALSE if password contains "login"
*
* @param string
* @param password
* @return
*/
public boolean checkOnNamesAndLogins(String string, Password password) {

// do not check too small string parts !!
if (string == null || string.length() < 3) return true;

if (string.split("\\s").length > 1) {

// consist of more pieces - check them individually - each piece must be relevant
String[] splitedString = string.split("\\s");
for (String s : splitedString) {

// too small part, skip
if (s == null || s.length() < 3) continue;

// check part
if (password.getValue().toLowerCase().contains(s.toLowerCase()) ||
password.getValue().toLowerCase().contains(reverse(s.toLowerCase())) ||
normalizeString(password.getValue()).contains(normalizeString(s)) ||
normalizeString(password.getValue()).contains(normalizeString(reverse(s)))) {
setResult(Result.INVALID_FORMAT);
password.setRawStatus(getTransl().muAdmPasswordStrengthForNameLogin(), ValidationState.ERROR);
return false;
}

}

}

// check also whole string
if (password.getValue().toLowerCase().contains(string.toLowerCase()) ||
password.getValue().toLowerCase().contains(reverse(string.toLowerCase())) ||
normalizeString(password.getValue()).contains(normalizeString(string)) ||
normalizeString(password.getValue()).contains(normalizeString(reverse(string)))) {
setResult(Result.INVALID_FORMAT);
password.setRawStatus(getTransl().muAdmPasswordStrengthForNameLogin(), ValidationState.ERROR);
return false;
}

return true;

}

private String normalizeString(String string) {
String result = normalizeStringToNFD(string);
result = result.replaceAll("\\s","");
return result;
}

private final native String normalizeStringToNFD(String input) /*-{
if (typeof input.normalize !== "undefined") {
// convert to normal decomposed form and replace all combining-diacritics marks
return input.normalize('NFD').replace(/[\u0300-\u036f]/g, "").toLowerCase();
}
// just lowercase
return input.toLowerCase();
}-*/;

}

0 comments on commit 2e00a77

Please sign in to comment.