From 6e48ade688c6f975addab3921fca19823d509128 Mon Sep 17 00:00:00 2001 From: HejdaJakub Date: Tue, 12 Apr 2022 19:39:15 +0200 Subject: [PATCH 1/2] feat(registrar): add list and map application form items * Added support for new applicatoin form items. * Both items have default input and add button. With this button, user can add new values to the list or map. Each new value in the list or map has also a remove button, so user can also remove the previously added value. * ListBox and MapBox have new own validators, ListBox has one more validator for ssh keys. --- .../wui/model/beans/ApplicationFormItem.java | 4 +- .../resources/PerunRegistrarResources.java | 2 + .../resources/PerunRegistrarTranslation.java | 39 ++- .../widgets/PerunFormItemsGeneratorImpl.java | 7 +- .../wui/registrar/widgets/items/ListBox.java | 168 +++++++++++++ .../wui/registrar/widgets/items/MapBox.java | 238 ++++++++++++++++++ .../widgets/items/PerunFormItemEditable.java | 1 + .../registrar/widgets/items/WidgetBox.java | 127 ++++++++++ .../items/validators/ListBoxValidator.java | 43 ++++ .../items/validators/MapBoxValidator.java | 52 ++++ .../validators/PerunFormItemValidator.java | 3 +- .../validators/SshKeysListBoxValidator.java | 59 +++++ .../validators/SshKeysTextAreaValidator.java | 17 +- .../validators/SshKeysTextFieldValidator.java | 4 +- .../PerunRegistrarTranslation_cs.properties | 17 +- .../client/resources/css/PerunRegistrar.gss | 4 + 16 files changed, 750 insertions(+), 35 deletions(-) create mode 100644 perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/ListBox.java create mode 100644 perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/MapBox.java create mode 100644 perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/WidgetBox.java create mode 100644 perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/ListBoxValidator.java create mode 100644 perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/MapBoxValidator.java create mode 100644 perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysListBoxValidator.java diff --git a/perun-wui-core/src/main/java/cz/metacentrum/perun/wui/model/beans/ApplicationFormItem.java b/perun-wui-core/src/main/java/cz/metacentrum/perun/wui/model/beans/ApplicationFormItem.java index 02d69f25..bc4fa98c 100644 --- a/perun-wui-core/src/main/java/cz/metacentrum/perun/wui/model/beans/ApplicationFormItem.java +++ b/perun-wui-core/src/main/java/cz/metacentrum/perun/wui/model/beans/ApplicationFormItem.java @@ -36,7 +36,9 @@ public enum ApplicationFormItemType { USERNAME, HEADING, TIMEZONE, - EMBEDDED_GROUP_APPLICATION + EMBEDDED_GROUP_APPLICATION, + LIST_INPUT_BOX, + MAP_INPUT_BOX } public enum Hidden { diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarResources.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarResources.java index a0b893c8..216368b9 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarResources.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarResources.java @@ -38,6 +38,8 @@ interface PerunRegistrarCss extends CssResource { String help(); + String overflow(); + } @Source("css/PerunRegistrar.gss") diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation.java index 56e9d3ad..819f3573 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation.java @@ -118,6 +118,15 @@ public interface PerunRegistrarTranslation extends PerunTranslation { @DefaultMessage("Incorrect input format!") public String incorrectFormat(); + @DefaultMessage("The following items have incorrect format:") + public String incorrectFormatItemList(); + + @DefaultMessage("Items with the following keys have incorrect format:") + public String incorrectFormatItemMap(); + + @DefaultMessage("Each key must be unique!") + public String duplicateKeys(); + @DefaultMessage("Item can`t be empty!") public String cantBeEmpty(); @@ -211,17 +220,11 @@ public interface PerunRegistrarTranslation extends PerunTranslation { @DefaultMessage("Key \"{0}\" does not have the correct format.") String sshKeyFormat(String key); - @DefaultMessage("Do not mix commas and new-lines as SSH keys separators.") - String mixingNewlinesWithCommas(); - - @DefaultMessage("Multiple consecutive commas are not allowed, use a single comma or newline as a separator between SSH keys.") - String tooMuchCommas(); + @DefaultMessage("Newlines are not allowed, use a single comma as a separator between SSH keys.") + String newlinesNotAllowed(); @DefaultMessage("Multiple consecutive commas are not allowed, use a single comma as a separator between SSH keys.") - String tooMuchCommasTextField(); - - @DefaultMessage("Multiple consecutive newlines are not allowed, use one newline or comma as a separator between SSH keys.") - String tooMuchNewlines(); + String tooMuchCommas(); @DefaultMessage("Missing separator between the SSH keys (comma or newline).") String sshKeyMissingDelimiter(); @@ -229,11 +232,23 @@ public interface PerunRegistrarTranslation extends PerunTranslation { @DefaultMessage("Missing comma as a separator between the SSH keys.") String sshKeyMissingCommaDelimiterTextField(); - @DefaultMessage("No spaces are allowed around the SSH key separator (comma or newline).") + @DefaultMessage("No spaces are allowed around the SSH key separator (comma).") String sshKeyNoSpaceAroundKeySeparator(); - @DefaultMessage("No spaces are allowed around the SSH key separator (comma).") - String sshKeyNoSpaceAroundCommasTextField(); + @DefaultMessage("No separators (commas) are allowed. Add new value for the new SSH key.") + String sshKeySeparatorNotAllowed(); + + @DefaultMessage("Add new value") + public String addNewValue(); + + @DefaultMessage("Remove value") + String removeValue(); + + @DefaultMessage("Enter new key") + public String enterKey(); + + @DefaultMessage("Enter value") + String enterValue(); // -------------- SUBMITTED APPS PAGE ------------------------ // diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/PerunFormItemsGeneratorImpl.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/PerunFormItemsGeneratorImpl.java index 760c7464..e29cd4da 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/PerunFormItemsGeneratorImpl.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/PerunFormItemsGeneratorImpl.java @@ -25,10 +25,11 @@ import cz.metacentrum.perun.wui.registrar.widgets.items.Undefined; import cz.metacentrum.perun.wui.registrar.widgets.items.Username; import cz.metacentrum.perun.wui.registrar.widgets.items.ValidatedEmail; +import cz.metacentrum.perun.wui.registrar.widgets.items.ListBox; +import cz.metacentrum.perun.wui.registrar.widgets.items.MapBox; import org.gwtbootstrap3.client.ui.constants.ValidationState; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -235,6 +236,10 @@ private PerunFormItem generatePerunFormItem(ApplicationFormItemData data) { return new SubmitButton(form, data, lang, true); case EMBEDDED_GROUP_APPLICATION: return new GroupCheckBox(form, data, lang); + case LIST_INPUT_BOX: + return new ListBox(form, data, lang); + case MAP_INPUT_BOX: + return new MapBox(form, data, lang); default: return new Undefined(form, data, lang); } diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/ListBox.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/ListBox.java new file mode 100644 index 00000000..81470486 --- /dev/null +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/ListBox.java @@ -0,0 +1,168 @@ +package cz.metacentrum.perun.wui.registrar.widgets.items; + +import com.google.gwt.event.dom.client.BlurEvent; +import com.google.gwt.event.dom.client.BlurHandler; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.HasVerticalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.user.client.ui.VerticalPanel; +import cz.metacentrum.perun.wui.json.Events; +import cz.metacentrum.perun.wui.registrar.client.resources.PerunRegistrarResources; +import cz.metacentrum.perun.wui.registrar.widgets.items.validators.ListBoxValidator; +import cz.metacentrum.perun.wui.registrar.widgets.items.validators.SshKeysListBoxValidator; +import cz.metacentrum.perun.wui.widgets.boxes.ExtendedTextBox; +import cz.metacentrum.perun.wui.widgets.PerunButton; +import cz.metacentrum.perun.wui.model.beans.ApplicationFormItemData; +import cz.metacentrum.perun.wui.registrar.widgets.PerunForm; +import org.gwtbootstrap3.client.ui.html.Paragraph; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents ListBox form item. + * + * @author Jakub Hejda + */ +public class ListBox extends WidgetBox { + + private final ListBoxValidator validator; + List inputList; + + public ListBox(PerunForm form, ApplicationFormItemData item, String lang) { + super(form, item, lang); + if ("urn:perun:user:attribute-def:def:sshPublicKey".equals(item.getFormItem().getPerunDestinationAttribute())) { + this.validator = new SshKeysListBoxValidator(); + } else { + this.validator = new ListBoxValidator(); + } + } + + @Override + public String getValue() { + StringBuilder value = new StringBuilder(); + if (isOnlyPreview()) { + for(int i = 0; i < getPreview().getWidgetCount(); i++) { + Paragraph p = (Paragraph) getPreview().getWidget(i); + value.append((p.getText() == null || p.getText().isEmpty()) + ? "" + : p.getText().replace(",", "\\,") + ","); + } + } else { + for (ExtendedTextBox input : inputList) { + value.append((input.getValue() == null || input.getValue().isEmpty()) + ? "" + : input.getValue().replace(",", "\\,") + ","); + } + } + + return value.toString(); + } + + public List getListValue() { + return inputList; + } + + @Override + public void validate(Events events) { + validator.validate(this, events); + } + + @Override + public boolean validateLocal() { + return validator.validateLocal(this); + } + + @Override + protected Widget initWidget() { + inputList = new ArrayList<>(); + return super.initWidget(); + } + + @Override + protected Widget initWidgetOnlyPreview() { + widget = new Paragraph(); + Paragraph p = new Paragraph(); + p.addStyleName("form-control"); + getPreview().add(p); + return widget; + } + + @Override + protected void setValidationTriggers() { + if (isOnlyPreview()) { + return; + } + for (ExtendedTextBox input : inputList) { + input.addBlurHandler(new BlurHandler() { + @Override + public void onBlur(BlurEvent event) { + validateLocal(); + } + }); + } + } + + @Override + protected void setValueImpl(String value) { + int counter = 0; + if (isOnlyPreview()) { + // delete default empty widget if there is some value + getPreview().getWidget(0).removeFromParent(); + } + for (String val : value.split("(? + */ +public class MapBox extends WidgetBox { + + private final MapBoxValidator validator; + List keys; + List values; + + public MapBox(PerunForm form, ApplicationFormItemData item, String lang) { + super(form, item, lang); + this.validator = new MapBoxValidator(); + } + + @Override + public String getValue() { + StringBuilder value = new StringBuilder(); + if(isOnlyPreview()) { + for(int i = 0; i < getPreview().getWidgetCount(); i++) { + HorizontalPanel hp = (HorizontalPanel) getPreview().getWidget(i); + Paragraph p = (Paragraph) hp.getWidget(0); + if (p.getText() != null && !p.getText().isEmpty()) { + value.append(p.getText().replace(",", "\\,").replace(":", "\\:")) + .append(":"); + p = (Paragraph) hp.getWidget(2); + value.append(p.getText().replace(",", "\\,").replace(":", "\\:")) + .append(","); + } + } + } else { + for (ExtendedTextBox key : keys) { + ExtendedTextBox val = values.get(keys.indexOf(key)); + if (key.getValue() != null && !key.getValue().isEmpty()) { + value.append(key.getValue().replace(",", "\\,").replace(":", "\\:")) + .append(":") + .append(val.getValue().replace(",", "\\,").replace(":", "\\:")) + .append(","); + } + } + } + + return value.toString(); + } + + public List getKeys() { + return keys; + } + + public List getValues() { + return values; + } + + public Map getKeysAndValues() { + Map map = new HashMap<>(); + for (ExtendedTextBox key : keys) { + map.put(key, values.get(keys.indexOf(key))); + } + return map; + } + + @Override + public void validate(Events events) { + validator.validate(this, events); +} + + @Override + public boolean validateLocal() { + return validator.validateLocal(this); + } + + @Override + protected Widget initWidget() { + keys = new ArrayList<>(); + values = new ArrayList<>(); + return super.initWidget(); + } + + @Override + protected Widget initWidgetOnlyPreview() { + widget = new Paragraph(); + + HorizontalPanel hp = new HorizontalPanel(); + hp.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); + hp.setWidth("100%"); + Paragraph key = new Paragraph(); + key.addStyleName("form-control"); + Paragraph equals = new Paragraph("="); + Paragraph val = new Paragraph(); + val.addStyleName("form-control"); + addItemToPreview(hp, key, equals, val); + + return widget; + } + + @Override + protected void setValidationTriggers() { + if (isOnlyPreview()) { + return; + } + for (ExtendedTextBox input : keys) { + input.addBlurHandler(new BlurHandler() { + @Override + public void onBlur(BlurEvent event) { + validateLocal(); + } + }); + } + + for (ExtendedTextBox input : values) { + input.addBlurHandler(new BlurHandler() { + @Override + public void onBlur(BlurEvent event) { + validateLocal(); + } + }); + } + } + + @Override + protected void setValueImpl(String value) { + int counter = 0; + if (isOnlyPreview()) { + // delete default empty widget if there is some value + getPreview().getWidget(0).removeFromParent(); + } + for (String keyAndValue : value.split("(? + */ +public class WidgetBox extends PerunFormItemEditable { + + protected Widget widget; + + public WidgetBox(PerunForm form, ApplicationFormItemData item, String lang) { + super(form, item, lang); + } + + @Override + public String getValue() { + return null; + } + + @Override + public void validate(Events events) {} + + @Override + public boolean validateLocal() { return false; } + + @Override + public PerunFormItemValidator.Result getLastValidationResult() { + return null; + } + + @Override + public boolean focus() { + return false; + } + + @Override + protected Widget initWidget() { + VerticalPanel vp = new VerticalPanel(); + vp.setWidth("100%"); + vp.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); + PerunButton addButton = generateAddButton(vp); + addButton.setIcon(IconType.PLUS); + addButton.setType(ButtonType.SUCCESS); + addButton.setMarginRight(40); + addButton.setTooltipText(getTranslation().addNewValue()); + + vp.add(addButton); + generateItemWithRemoveButton(vp); + + widget = vp; + return vp; + } + + @Override + protected Widget initWidgetOnlyPreview() { + widget = new Paragraph(); + return widget; + } + + @Override + protected Widget getWidget() { + return this.widget; + } + + @Override + protected void setValidationTriggers() {} + + @Override + protected void setValueImpl(String value) {} + + public Paragraph getPreview() { + if (widget instanceof Paragraph) { + return (Paragraph) widget; + } + return null; + } + + /** + * Generates new customized button with no default behavior + * @param vp VerticalPanel to which will be added new widgets by this button + * @return PerunButton customized addButton + */ + protected PerunButton generateAddButton(VerticalPanel vp) { + return new PerunButton(getTranslation().addNewValue(), new ClickHandler() { + public void onClick(ClickEvent event) { + // behavior need to be implemented in the child class + } + }); + } + + /** + * Generates new input with remove button + * @param vp VerticalPanel to which will be added new item with remove button + */ + protected void generateItemWithRemoveButton(VerticalPanel vp) { + // behavior need to be implemented in the child class + } + + protected void setupRemoveButton (PerunButton removeButton) { + removeButton.setIcon(IconType.MINUS); + removeButton.setType(ButtonType.DANGER); + removeButton.setTooltipText(getTranslation().removeValue()); + } + + protected void setupHPandAddToVP (HorizontalPanel hp, VerticalPanel vp, PerunButton removeButton) { + hp.setCellWidth(removeButton, "40px"); + hp.setCellHorizontalAlignment(removeButton, HasHorizontalAlignment.ALIGN_RIGHT); + hp.setHeight("40px"); + vp.insert(hp, vp.getWidgetCount() - 1); + } +} diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/ListBoxValidator.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/ListBoxValidator.java new file mode 100644 index 00000000..29cc839c --- /dev/null +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/ListBoxValidator.java @@ -0,0 +1,43 @@ +package cz.metacentrum.perun.wui.registrar.widgets.items.validators; + +import cz.metacentrum.perun.wui.registrar.widgets.items.ListBox; +import cz.metacentrum.perun.wui.widgets.boxes.ExtendedTextBox; +import org.gwtbootstrap3.client.ui.constants.ValidationState; + +/** + * Validator for ListBox + * + * @author Jakub Hejda + */ +public class ListBoxValidator extends PerunFormItemValidatorImpl{ + @Override + public boolean validateLocal(ListBox listBox) { + if (listBox.isRequired() && isNullOrEmpty(listBox.getValue())) { + setResult(Result.EMPTY); + listBox.setRawStatus(getTransl().cantBeEmpty(), ValidationState.ERROR); + return false; + } + + String wrongValues = ""; + int index = 1; + for (ExtendedTextBox lBox : listBox.getListValue()) { + if (!lBox.isValid()) { + String value = lBox.getValue().isEmpty() ? "\"\"" : lBox.getValue(); + if (lBox.getValue().length() > 25) { + wrongValues += "
" + index + ". " + value.substring(0, 23) + "..."; + } else { + wrongValues += "
" + index + ". " + value; + } + } + index++; + } + if (!wrongValues.isEmpty()) { + setResult(Result.INVALID_FORMAT); + listBox.setRawStatus(getTransl().incorrectFormatItemList() + " " + wrongValues + "" , ValidationState.ERROR); + return false; + } + + listBox.setStatus(ValidationState.SUCCESS); + return true; + } +} diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/MapBoxValidator.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/MapBoxValidator.java new file mode 100644 index 00000000..f236d27d --- /dev/null +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/MapBoxValidator.java @@ -0,0 +1,52 @@ +package cz.metacentrum.perun.wui.registrar.widgets.items.validators; + +import cz.metacentrum.perun.wui.registrar.widgets.items.MapBox; +import cz.metacentrum.perun.wui.widgets.boxes.ExtendedTextBox; +import org.gwtbootstrap3.client.ui.constants.ValidationState; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Validator for MapBox + * + * @author Jakub Hejda + */ +public class MapBoxValidator extends PerunFormItemValidatorImpl{ + @Override + public boolean validateLocal(MapBox mapBox) { + if (mapBox.isRequired() && isNullOrEmpty(mapBox.getValue())) { + setResult(Result.EMPTY); + mapBox.setRawStatus(getTransl().cantBeEmpty(), ValidationState.ERROR); + return false; + } + + Set checkSet = new HashSet<>(); + for (ExtendedTextBox box : mapBox.getKeys()) { + if (!checkSet.add(box.getValue())) { + setResult(Result.DUPLICATE_KEYS); + mapBox.setStatus(getTransl().duplicateKeys(), ValidationState.ERROR); + return false; + } + } + + Map keysAndValues = mapBox.getKeysAndValues(); + String wrongValues = ""; + int index = 1; + for (ExtendedTextBox key : keysAndValues.keySet()) { + if (!key.isValid() || !keysAndValues.get(key).isValid()) { + wrongValues += "
" + index + ". " + (key.getValue().isEmpty() ? "\"\"" : key.getValue()); + } + index++; + } + if (!wrongValues.isEmpty()) { + setResult(Result.INVALID_FORMAT); + mapBox.setRawStatus(getTransl().incorrectFormatItemMap() + " " + wrongValues + "" , ValidationState.ERROR); + return false; + } + + mapBox.setStatus(ValidationState.SUCCESS); + return true; + } +} diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/PerunFormItemValidator.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/PerunFormItemValidator.java index 2525c21e..1abf69f2 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/PerunFormItemValidator.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/PerunFormItemValidator.java @@ -24,7 +24,8 @@ enum Result { EMPTY_PASSWORD, PASSWORD_MISSMATCH, MUST_VALIDATE_EMAIL, - SECOND_PASSWORD_EMPTY + SECOND_PASSWORD_EMPTY, + DUPLICATE_KEYS } /** diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysListBoxValidator.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysListBoxValidator.java new file mode 100644 index 00000000..d4f4c096 --- /dev/null +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysListBoxValidator.java @@ -0,0 +1,59 @@ +package cz.metacentrum.perun.wui.registrar.widgets.items.validators; + +import com.google.gwt.regexp.shared.MatchResult; +import com.google.gwt.regexp.shared.RegExp; +import cz.metacentrum.perun.wui.registrar.widgets.items.ListBox; +import cz.metacentrum.perun.wui.widgets.boxes.ExtendedTextBox; +import org.gwtbootstrap3.client.ui.constants.ValidationState; + +/** + * Validator for ListBox + * + * @author Jakub Hejda + */ +public class SshKeysListBoxValidator extends ListBoxValidator { + + RegExp regExp = RegExp.compile("^(" + + "(ssh-(rsa|dss|ed25519)(-cert-v01@openssh.com)?)|" + + "(sk-(ssh-ed25519|ecdsa-sha2-nistp256)(-cert-v01)?@openssh.com)|" + + "(ecdsa-sha2-nistp(256|384|521)(-cert-v01@openssh.com)?))" + + " (([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?)( [^,\n]+)?$"); + + @Override + public boolean validateLocal(ListBox listBox) { + if (listBox.isRequired() && isNullOrEmpty(listBox.getValue())) { + setResult(Result.EMPTY); + listBox.setRawStatus(getTransl().cantBeEmpty(), ValidationState.ERROR); + return false; + } + + if (listBox.getValue() != null && !listBox.getValue().isEmpty()) { + + String wrongValues = ""; + int index = 1; + for (ExtendedTextBox extendedTextBox : listBox.getListValue()) { + String sshKey = extendedTextBox.getValue(); + + if (sshKey.contains(",")) { + setResult(Result.INVALID_FORMAT); + listBox.setStatus(getTransl().sshKeySeparatorNotAllowed(), ValidationState.ERROR); + return false; + } + + MatchResult matcher = regExp.exec(sshKey); + if (matcher == null) { + wrongValues += "
" + index + ". " + (sshKey.length() > 25 ? sshKey.substring(0, 23) + "..." : sshKey); + } + index++; + } + if (!wrongValues.isEmpty()) { + setResult(Result.INVALID_FORMAT); + listBox.setRawStatus(getTransl().incorrectFormatItemList() + " " + wrongValues + "", ValidationState.ERROR); + return false; + } + } + + listBox.setStatus(ValidationState.SUCCESS); + return true; + } +} diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextAreaValidator.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextAreaValidator.java index 17e013de..5f16d7b1 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextAreaValidator.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextAreaValidator.java @@ -45,25 +45,19 @@ public boolean validateLocal(TextArea textArea) { String sshKeys = textArea.getValue(); - if (sshKeys.contains(",,")) { - setResult(Result.INVALID_FORMAT); - textArea.setStatus(getTransl().tooMuchCommas(), ValidationState.ERROR); - return false; - } - - if (sshKeys.contains("\n\n")) { + if (sshKeys.contains("\n")) { setResult(Result.INVALID_FORMAT); - textArea.setStatus(getTransl().tooMuchNewlines(), ValidationState.ERROR); + textArea.setStatus(getTransl().newlinesNotAllowed(), ValidationState.ERROR); return false; } - if (sshKeys.contains(",") && sshKeys.contains("\n")) { + if (sshKeys.contains(",,")) { setResult(Result.INVALID_FORMAT); - textArea.setStatus(getTransl().mixingNewlinesWithCommas(), ValidationState.ERROR); + textArea.setStatus(getTransl().tooMuchCommas(), ValidationState.ERROR); return false; } - if (sshKeys.contains(", ") || sshKeys.contains(" ,") || sshKeys.contains("\n ") || sshKeys.contains(" \n")) { + if (sshKeys.contains(", ") || sshKeys.contains(" ,")) { setResult(Result.INVALID_FORMAT); textArea.setStatus(getTransl().sshKeyNoSpaceAroundKeySeparator(), ValidationState.ERROR); return false; @@ -82,7 +76,6 @@ public boolean validateLocal(TextArea textArea) { */ // normalize value just in case - sshKeys = sshKeys.replaceAll("(\n)+", ","); sshKeys = sshKeys.replaceAll("(,)+", ","); List keys = Arrays.stream(sshKeys.split(",")).collect(Collectors.toList()); diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextFieldValidator.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextFieldValidator.java index 16a0d999..fd42724f 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextFieldValidator.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/validators/SshKeysTextFieldValidator.java @@ -47,13 +47,13 @@ public boolean validateLocal(TextField textField) { if (sshKeys.contains(",,")) { setResult(Result.INVALID_FORMAT); - textField.setStatus(getTransl().tooMuchCommasTextField(), ValidationState.ERROR); + textField.setStatus(getTransl().tooMuchCommas(), ValidationState.ERROR); return false; } if (sshKeys.contains(", ") || sshKeys.contains(" ,")) { setResult(Result.INVALID_FORMAT); - textField.setStatus(getTransl().sshKeyNoSpaceAroundCommasTextField(), ValidationState.ERROR); + textField.setStatus(getTransl().sshKeyNoSpaceAroundKeySeparator(), ValidationState.ERROR); return false; } diff --git a/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation_cs.properties b/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation_cs.properties index ac6ec41d..78c45259 100644 --- a/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation_cs.properties +++ b/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/PerunRegistrarTranslation_cs.properties @@ -48,6 +48,9 @@ redirectingBackToService=Prosím počkejte, probíhá přesměrování zpět na tooLong=Text je příliš dlouhý! incorrectFormat=Špatný formát vstupu! +incorrectFormatItemList=Následující položky mají špatný formát: +incorrectFormatItemMap=Položky s následujícími klíči mají špatný formát: +duplicateKeys=Každý klíč musí být unikátní! cantBeEmpty=Položka nesmí být prázdná! cantBeEmptySelect=Musíte vybrat alespoň jednu možnost! incorrectEmail=Neplatný formát e-mailové adresy! @@ -79,14 +82,16 @@ undefinedFormItem=NEDEFINOVANÝ clearRadiobox=žádný z předchozích typeToSearch=Hledej psaním... sshKeyFormat=Klíč "{0}" nemá správný formát. -mixingNewlinesWithCommas=Nemíchejte čárky a nové řádky jako oddělovače SSH klíčů. -tooMuchCommas=Více čárek za sebou není dovoleno, jako oddělovač mezi SSH klíči používejte jednu čárku nebo nový řádek. -tooMuchCommasTextField=Více čárek za sebou není dovoleno, jako oddělovač mezi SSH klíči používejte jednu čárku. -tooMuchNewlines=Více nových řádků za sebou není dovoleno, jako oddělovač mezi SSH klíči používejte jeden nový řádek nebo čárku. +newlinesNotAllowed=Nové řádky nejsou dovoleny, jako oddělovač mezi SSH klíči používejte jednu čárku. +tooMuchCommas=Více čárek za sebou není dovoleno, jako oddělovač mezi SSH klíči používejte jednu čárku. sshKeyMissingDelimiter=Mezi SSH klíči chybí oddělovač (čárka nebo nový řádek). sshKeyMissingCommaDelimiterTextField=Mezi SSH klíči chybí oddělovač (čárka). -sshKeyNoSpaceAroundKeySeparator=Kolem oddělovače SSH klíčů (čárky nebo nového řádku) nejsou dovoleny mezery. -sshKeyNoSpaceAroundCommasTextField=Kolem oddělovače SSH klíčů (čárky) nejsou dovoleny mezery. +sshKeyNoSpaceAroundKeySeparator=Kolem oddělovače SSH klíčů (čárky) nejsou dovoleny mezery. +sshKeySeparatorNotAllowed=Oddělovače (čárky) nejsou povoleny. Přidejte novou hodnotu pro nový SSH klíč. +addNewValue=Přidat hodnotu +removeValue=Odstranit hodnotu +enterKey=Zadejte nový klíč +enterValue=Zadejte hodnotu # // -------------- SUBMITTED APPS PAGE ------------------------ // diff --git a/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/css/PerunRegistrar.gss b/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/css/PerunRegistrar.gss index c6a30a80..b55c72de 100644 --- a/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/css/PerunRegistrar.gss +++ b/perun-wui-registrar/src/main/resources/cz/metacentrum/perun/wui/registrar/client/resources/css/PerunRegistrar.gss @@ -77,6 +77,10 @@ body { cursor: text; } +.overflow { + overflow-x: auto; +} + .help { color: #737373 !important; } From cdc8ff00159d9dd5ec9ec2995377c10ee57d61b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Zl=C3=A1mal?= Date: Mon, 23 May 2022 13:45:08 +0200 Subject: [PATCH 2/2] fix(registrar): return empty value if no option selected in selectbox - Previously generic "--- Not selected ---" option in the select box returned "null" string value. - Now we return empty string which is correctly recognized as an empty/null value for the attribute on Perun side. - This prevents bug when such value should be stored in attribute with checked syntax. --- .../perun/wui/registrar/widgets/items/Selectionbox.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/Selectionbox.java b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/Selectionbox.java index 38c7a49f..418c197f 100644 --- a/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/Selectionbox.java +++ b/perun-wui-registrar/src/main/java/cz/metacentrum/perun/wui/registrar/widgets/items/Selectionbox.java @@ -43,7 +43,7 @@ protected Widget initWidget() { getSelect().clear(); if (!isRequired()) { - getSelect().addItem(translation.notSelected(), (String) null); + getSelect().addItem(translation.notSelected(), ""); } Map opts = parseItemOptions();