improved missing password message, message popup improvement

This commit is contained in:
anhefti 2019-11-19 10:39:55 +01:00
parent 11471eea00
commit 188c59c6e5
8 changed files with 46 additions and 30 deletions

View file

@ -41,10 +41,11 @@ public class APIMessage implements Serializable {
FORBIDDEN("1001", HttpStatus.FORBIDDEN, "FORBIDDEN"), FORBIDDEN("1001", HttpStatus.FORBIDDEN, "FORBIDDEN"),
RESOURCE_NOT_FOUND("1002", HttpStatus.NOT_FOUND, "resource not found"), RESOURCE_NOT_FOUND("1002", HttpStatus.NOT_FOUND, "resource not found"),
ILLEGAL_API_ARGUMENT("1010", HttpStatus.BAD_REQUEST, "Illegal API request argument"), ILLEGAL_API_ARGUMENT("1010", HttpStatus.BAD_REQUEST, "Illegal API request argument"),
UNEXPECTED("1100", HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected intenral server-side error"), UNEXPECTED("1100", HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected internal server-side error"),
FIELD_VALIDATION("1200", HttpStatus.BAD_REQUEST, "Field validation error"), FIELD_VALIDATION("1200", HttpStatus.BAD_REQUEST, "Field validation error"),
INTEGRITY_VALIDATION("1201", HttpStatus.BAD_REQUEST, "Action would lied to an integrity violation"), INTEGRITY_VALIDATION("1201", HttpStatus.BAD_REQUEST, "Action would lied to an integrity violation"),
PASSWORD_MISMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match confirmed password"), PASSWORD_MISMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match confirmed password"),
MISSING_PASSWORD("1301", HttpStatus.BAD_REQUEST, "Missing Password"),
EXAM_CONSISTANCY_VALIDATION_SUPPORTER("1400", HttpStatus.OK, "No Exam Supporter defined for the Exam"), EXAM_CONSISTANCY_VALIDATION_SUPPORTER("1400", HttpStatus.OK, "No Exam Supporter defined for the Exam"),
EXAM_CONSISTANCY_VALIDATION_CONFIG("1401", HttpStatus.OK, "No SEB Exam Configuration defined for the Exam"), EXAM_CONSISTANCY_VALIDATION_CONFIG("1401", HttpStatus.OK, "No SEB Exam Configuration defined for the Exam"),

View file

@ -19,6 +19,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Control;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
@ -33,17 +34,22 @@ import ch.ethz.seb.sebserver.gui.service.ResourceService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer; import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
import ch.ethz.seb.sebserver.gui.service.page.PageContext; import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
import ch.ethz.seb.sebserver.gui.service.page.PageService; import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent; import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog; import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfigOnExistingConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfigOnExistingConfig;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig;
import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection; import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection;
public final class SebExamConfigImport { public final class SebExamConfigImport {
private final static PageMessageException MISSING_PASSWORD = new PageMessageException(
new LocTextKey("sebserver.examconfig.action.import.missing-password"));
static Function<PageAction, PageAction> importFunction( static Function<PageAction, PageAction> importFunction(
final PageService pageService, final PageService pageService,
final boolean newConfig) { final boolean newConfig) {
@ -157,6 +163,19 @@ public final class SebExamConfigImport {
} }
return true; return true;
} else { } else {
final Throwable error = configuration.getError();
if (error instanceof RestCallError) {
((RestCallError) error)
.getErrorMessages()
.stream()
.filter(APIMessage.ErrorMessage.MISSING_PASSWORD::isOf)
.findFirst()
.ifPresent(message -> formHandle
.getContext()
.publishPageMessage(MISSING_PASSWORD));
return true;
}
formHandle.getContext().notifyError(configuration.getError()); formHandle.getContext().notifyError(configuration.getError());
return true; return true;
} }

View file

@ -35,13 +35,18 @@ public final class Message extends MessageBox {
super.prepareOpen(); super.prepareOpen();
final GridLayout layout = (GridLayout) super.shell.getLayout(); final GridLayout layout = (GridLayout) super.shell.getLayout();
layout.marginTop = 10; layout.marginTop = 10;
layout.marginBottom = 10; layout.marginLeft = 10;
layout.marginRight = 10;
layout.verticalSpacing = 10;
layout.horizontalSpacing = 10;
super.shell.setData(RWT.CUSTOM_VARIANT, "message"); super.shell.setData(RWT.CUSTOM_VARIANT, "message");
final Rectangle bounds = super.shell.getBounds(); final Rectangle bounds = super.shell.getBounds();
if (bounds.width < NORMAL_WIDTH) { if (bounds.width < NORMAL_WIDTH) {
bounds.x = bounds.x - (NORMAL_WIDTH - bounds.width) / 2; bounds.x = bounds.x - (NORMAL_WIDTH - bounds.width) / 2;
bounds.width = NORMAL_WIDTH; bounds.width = NORMAL_WIDTH;
super.shell.setBounds(bounds); super.shell.setBounds(bounds);
} else {
super.shell.pack(true);
} }
} }

View file

@ -32,6 +32,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor;
@ -138,7 +139,8 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption
if ((strategy == Strategy.PASSWORD_PSWD || strategy == Strategy.PASSWORD_PWCC) if ((strategy == Strategy.PASSWORD_PSWD || strategy == Strategy.PASSWORD_PWCC)
&& StringUtils.isBlank(context.getPassword())) { && StringUtils.isBlank(context.getPassword())) {
return new AsyncResult<>(new IllegalArgumentException("Missing Password")); return new AsyncResult<>(new APIMessage.APIMessageException(
APIMessage.ErrorMessage.MISSING_PASSWORD.of("Missing Password")));
} }
// then decrypt stream // then decrypt stream

View file

@ -22,13 +22,11 @@ import javax.validation.Valid;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.mybatis.dynamic.sql.SqlTable; import org.mybatis.dynamic.sql.SqlTable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@ -39,7 +37,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper; import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
@ -57,7 +54,6 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.TemplateAttribute;
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType; import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport; import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService; import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
@ -233,7 +229,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
method = RequestMethod.POST, method = RequestMethod.POST,
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE) produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Object importExamConfig( public Configuration importExamConfig(
@RequestHeader(name = Domain.CONFIGURATION_NODE.ATTR_NAME, required = false) final String name, @RequestHeader(name = Domain.CONFIGURATION_NODE.ATTR_NAME, required = false) final String name,
@RequestHeader(name = Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION, @RequestHeader(name = Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
required = false) final String description, required = false) final String description,
@ -271,15 +267,10 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
this.configurationNodeDAO.delete(new HashSet<>(Arrays.asList(new EntityKey( this.configurationNodeDAO.delete(new HashSet<>(Arrays.asList(new EntityKey(
followup.configurationNodeId, followup.configurationNodeId,
EntityType.CONFIGURATION_NODE)))); EntityType.CONFIGURATION_NODE))));
final Throwable rootCause = ExceptionUtils.getRootCause(doImport.getError());
return new ResponseEntity<>(
Arrays.asList(APIMessage.ErrorMessage.UNEXPECTED.of(rootCause.getMessage())),
Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST);
} else {
return doImport;
} }
return doImport
.getOrThrow();
} }
@RequestMapping( @RequestMapping(
@ -287,7 +278,7 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
method = RequestMethod.POST, method = RequestMethod.POST,
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE) produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Object importExamConfigOnExistingConfig( public Configuration importExamConfigOnExistingConfig(
@PathVariable final Long modelId, @PathVariable final Long modelId,
@RequestHeader(name = API.IMPORT_PASSWORD_ATTR_NAME, required = false) final String password, @RequestHeader(name = API.IMPORT_PASSWORD_ATTR_NAME, required = false) final String password,
@RequestParam( @RequestParam(
@ -309,14 +300,11 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
// rollback of the existing values // rollback of the existing values
this.configurationDAO.undo(newConfig.configurationNodeId); this.configurationDAO.undo(newConfig.configurationNodeId);
final Throwable rootCause = ExceptionUtils.getRootCause(doImport.getError());
return new ResponseEntity<>(
Arrays.asList(APIMessage.ErrorMessage.UNEXPECTED.of(rootCause.getMessage())),
Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST);
} else {
return doImport;
} }
return doImport
.getOrThrow();
} }
@RequestMapping( @RequestMapping(

View file

@ -463,7 +463,8 @@ sebserver.examconfig.action.import-config=Import Exam Configuration
sebserver.examconfig.action.import-file-select=Import From File sebserver.examconfig.action.import-file-select=Import From File
sebserver.examconfig.action.import-file-password=Password sebserver.examconfig.action.import-file-password=Password
sebserver.examconfig.action.import-config.confirm=Configuration successfully imported sebserver.examconfig.action.import-config.confirm=Configuration successfully imported
sebserver.examconfig.action.state-change.confirm=This configuration is already attached to an exam.<br/>Please note that changing an attached configuration will take effect on the exam when the configuration changes are saved<br/><br/>Are you sure to change this configuration to an editable state? sebserver.examconfig.action.import.missing-password=Missing Password: The chosen SEB Configuration is password-protected.<br/><br/>Please choose it again and provide the correct password within the password field.
sebserver.examconfig.action.state-change.confirm=This configuration is already attached to an exam.<br/><br/>Please note that changing an attached configuration will take effect on the exam when the configuration changes are saved<br/><br/>Are you sure to change this configuration to an editable state?
sebserver.examconfig.form.title.new=Add Exam Configuration sebserver.examconfig.form.title.new=Add Exam Configuration
sebserver.examconfig.form.title=Exam Configuration sebserver.examconfig.form.title=Exam Configuration

View file

@ -164,7 +164,7 @@ sebserver.lmssetup.list.column.name=Name
sebserver.lmssetup.list.column.type=LMS Type sebserver.lmssetup.list.column.type=LMS Type
sebserver.lmssetup.list.column.active=Active sebserver.lmssetup.list.column.active=Active
sebserver.lmssetup.action.list=LMS Setup sebserver.lmssetup.action.list=LMS Connection Settings
sebserver.lmssetup.action.form=LMS Setup sebserver.lmssetup.action.form=LMS Setup
sebserver.lmssetup.action.new=Add LMS Setup sebserver.lmssetup.action.new=Add LMS Setup
sebserver.lmssetup.action.list.view=View LMS Setup sebserver.lmssetup.action.list.view=View LMS Setup
@ -210,7 +210,7 @@ sebserver.quizdiscovery.list.column.starttime=Start Time {0}
sebserver.quizdiscovery.list.column.endtime=End Time {0} sebserver.quizdiscovery.list.column.endtime=End Time {0}
sebserver.quizdiscovery.info.pleaseSelect=Please Select a Quiz first sebserver.quizdiscovery.info.pleaseSelect=Please Select a Quiz first
sebserver.quizdiscovery.action.list=Quiz Discovery sebserver.quizdiscovery.action.list=LMS Exam Discovery
sebserver.quizdiscovery.action.import=Import as Exam sebserver.quizdiscovery.action.import=Import as Exam
sebserver.quizdiscovery.action.details=Show Details sebserver.quizdiscovery.action.details=Show Details
@ -236,7 +236,7 @@ sebserver.exam.list.column.type=Type
sebserver.exam.list.empty=No Exam has been found. Please adapt the filter or import one from Quiz sebserver.exam.list.empty=No Exam has been found. Please adapt the filter or import one from Quiz
sebserver.exam.action.list=Exam sebserver.exam.action.list=SEB Exam Settings
sebserver.exam.action.list.view=View Exam sebserver.exam.action.list.view=View Exam
sebserver.exam.action.list.modify=Edit Exam sebserver.exam.action.list.modify=Edit Exam
sebserver.exam.action.modify=Edit Exam sebserver.exam.action.modify=Edit Exam

View file

@ -378,14 +378,14 @@ DateTime-DropDownButton {
/* Message titlebar */ /* Message titlebar */
Shell.message { Shell.message {
font: 12px Arial, Helvetica, sans-serif;
animation: none; animation: none;
border: 1px solid #bdbdbd; border: 1px solid #bdbdbd;
background-color: #ffffff; background-color: #ffffff;
background-image: none; background-image: none;
padding: 0px;
opacity: 1; opacity: 1;
box-shadow: none; box-shadow: none;
width: 400px; padding: 5px 10px 5px 10px;
} }
Shell-Titlebar.message { Shell-Titlebar.message {