diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java index d8c7a3ff..1c01dce3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/InputFieldBuilder.java @@ -37,8 +37,16 @@ public interface InputFieldBuilder { final Composite parent, final Orientation orientation) { + return createInnerGrid(parent, orientation, 1); + } + + static Composite createInnerGrid( + final Composite parent, + final Orientation orientation, + final int numColumns) { + final Composite comp = new Composite(parent, SWT.NONE); - final GridLayout gridLayout = new GridLayout(); + final GridLayout gridLayout = new GridLayout(numColumns, true); gridLayout.verticalSpacing = 0; gridLayout.marginHeight = 1; comp.setLayout(gridLayout); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java index 00dea417..102b793a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java @@ -160,7 +160,8 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService { pageContext, this.restService, this.jsonMapper, - this.valueChangeRules)); + this.valueChangeRules), + this.widgetFactory.getI18nSupport()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java index 7381e89f..14eeea30 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/PassworFieldBuilder.java @@ -8,6 +8,11 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -15,15 +20,29 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; +import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder; +import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +@Lazy +@Component +@GuiProfile public class PassworFieldBuilder implements InputFieldBuilder { + private static final Logger log = LoggerFactory.getLogger(PassworFieldBuilder.class); + + private static final LocTextKey VAL_CONFIRM_PWD_TEXT_KEY = + new LocTextKey("sebserver.examconfig.props.validation.password.confirm"); + @Override public boolean builderFor( final ConfigurationAttribute attribute, @@ -50,7 +69,9 @@ public class PassworFieldBuilder implements InputFieldBuilder { final Text passwordInput = new Text(innerGrid, SWT.LEFT | SWT.BORDER | SWT.PASSWORD); passwordInput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); final Text confirmInput = new Text(innerGrid, SWT.LEFT | SWT.BORDER | SWT.PASSWORD); - confirmInput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); + gridData.verticalIndent = 5; + confirmInput.setLayoutData(gridData); final PasswordInputField passwordInputField = new PasswordInputField( attribute, @@ -69,18 +90,29 @@ public class PassworFieldBuilder implements InputFieldBuilder { } if (!pwd.equals(confirm)) { - passwordInputField.showError("TODO confirm password message"); + passwordInputField.showError(viewContext + .getI18nSupport() + .getText(VAL_CONFIRM_PWD_TEXT_KEY)); return; } - // TODO hash password + String hashedPWD; + try { + hashedPWD = hashPassword(pwd); + } catch (final NoSuchAlgorithmException e) { + log.error("Failed to hash password: ", e); + passwordInputField.showError("Failed to hash password"); + hashedPWD = null; + } - passwordInputField.clearError(); - viewContext.getValueChangeListener().valueChanged( - viewContext, - attribute, - pwd, - passwordInputField.listIndex); + if (hashedPWD != null) { + passwordInputField.clearError(); + viewContext.getValueChangeListener().valueChanged( + viewContext, + attribute, + hashedPWD, + passwordInputField.listIndex); + } }; passwordInput.addListener(SWT.FocusOut, valueChangeEventListener); @@ -90,6 +122,14 @@ public class PassworFieldBuilder implements InputFieldBuilder { return passwordInputField; } + private String hashPassword(final String pwd) throws NoSuchAlgorithmException { + final MessageDigest digest = MessageDigest.getInstance("SHA-256"); + final byte[] encodedhash = digest.digest( + pwd.getBytes(StandardCharsets.UTF_8)); + + return Hex.encodeHexString(encodedhash); + } + static final class PasswordInputField extends AbstractInputField { private final Text confirm; @@ -108,8 +148,10 @@ public class PassworFieldBuilder implements InputFieldBuilder { @Override protected void setDefaultValue() { // TODO clarify setting some "fake" input when a password is set (like in config tool) - this.control.setText(this.initValue); - this.confirm.setText(this.initValue); + if (this.initValue != null) { + this.control.setText(this.initValue); + this.confirm.setText(this.initValue); + } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java index 57a0e281..c39f876f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewContext.java @@ -18,6 +18,7 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.View; import ch.ethz.seb.sebserver.gui.service.examconfig.InputField; import ch.ethz.seb.sebserver.gui.service.examconfig.ValueChangeListener; +import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport; public final class ViewContext { @@ -28,6 +29,7 @@ public final class ViewContext { public final AttributeMapping attributeMapping; private final Map inputFieldMapping; private final ValueChangeListener valueChangeListener; + private final I18nSupport i18nSupport; ViewContext( final Configuration configuration, @@ -35,7 +37,8 @@ public final class ViewContext { final int columns, final int rows, final AttributeMapping attributeContext, - final ValueChangeListener valueChangeListener) { + final ValueChangeListener valueChangeListener, + final I18nSupport i18nSupport) { Objects.requireNonNull(configuration); Objects.requireNonNull(view); @@ -50,6 +53,11 @@ public final class ViewContext { this.attributeMapping = attributeContext; this.inputFieldMapping = new HashMap<>(); this.valueChangeListener = valueChangeListener; + this.i18nSupport = i18nSupport; + } + + public I18nSupport getI18nSupport() { + return this.i18nSupport; } public Long getId() { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java index 045fda14..f57cc4d6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ViewGridBuilder.java @@ -20,6 +20,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation; import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService; @@ -92,10 +93,16 @@ public class ViewGridBuilder { case RIGHT: { this.grid[ypos][xpos] = fieldBuilderAdapter; this.grid[ypos][xpos + 1] = labelBuilder(attribute, orientation); + if (attribute.type == AttributeType.PASSWORD_FIELD) { + this.grid[ypos + 1][xpos + 1] = passwordConfirmLabel(attribute, orientation); + } break; } case LEFT: { this.grid[ypos][xpos] = labelBuilder(attribute, orientation); + if (attribute.type == AttributeType.PASSWORD_FIELD) { + this.grid[ypos + 1][xpos] = passwordConfirmLabel(attribute, orientation); + } this.grid[ypos][xpos + 1] = fieldBuilderAdapter; break; } @@ -157,6 +164,27 @@ public class ViewGridBuilder { }; } + private CellFieldBuilderAdapter passwordConfirmLabel( + final ConfigurationAttribute attribute, + final Orientation orientation) { + + return new CellFieldBuilderAdapter() { + @Override + public void createCell(final ViewGridBuilder builder) { + final WidgetFactory widgetFactory = builder.examConfigurationService.getWidgetFactory(); + final Label label = widgetFactory.labelLocalized( + ViewGridBuilder.this.parent, + new LocTextKey( + ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.name + ".confirm"), + "Confirm Password"); + final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); + label.setAlignment(SWT.LEFT); + gridData.verticalIndent = 10; + label.setLayoutData(gridData); + } + }; + } + private CellFieldBuilderAdapter labelBuilder( final ConfigurationAttribute attribute, final Orientation orientation) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java index 43b9a896..ea3cfc37 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java @@ -21,7 +21,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.mybatis.dynamic.sql.SqlBuilder; @@ -368,16 +367,16 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { attrRec.getId(), attrRec.getDefaultValue()); - if (StringUtils.isNoneBlank(value)) { - this.configurationValueRecordMapper.insert(new ConfigurationValueRecord( - null, - configNode.institutionId, - config.getId(), - attrRec.getId(), - 0, - bigValue ? null : value, - bigValue ? value : null)); - } + //if (StringUtils.isNoneBlank(value)) { + this.configurationValueRecordMapper.insert(new ConfigurationValueRecord( + null, + configNode.institutionId, + config.getId(), + attrRec.getId(), + 0, + bigValue ? null : value, + bigValue ? value : null)); + //} }); return configNode; diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index c3e04aa0..9f529d77 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -377,6 +377,7 @@ sebserver.examconfig.props.action.list.modify=Edit Properties sebserver.examconfig.props.label.testNumber1=Test Number 1 sebserver.examconfig.props.label.testNumber2=Test Number 2 +sebserver.examconfig.props.validation.password.confirm=Please enter correct confirm password sebserver.examconfig.props.validation.unexpected=Unexpected error happened. Value was not set correctly sebserver.examconfig.props.validation.INTEGER=Invalid number sebserver.examconfig.props.validation.DECIMAL=Invalid decimal number