SEBSERV-45 password field implementation
This commit is contained in:
parent
529e8c2f83
commit
0a648d8c84
7 changed files with 112 additions and 25 deletions
|
@ -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);
|
||||
|
|
|
@ -160,7 +160,8 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
|
|||
pageContext,
|
||||
this.restService,
|
||||
this.jsonMapper,
|
||||
this.valueChangeRules));
|
||||
this.valueChangeRules),
|
||||
this.widgetFactory.getI18nSupport());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Text> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<Long, InputField> 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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue