Merge branch 'patch-1.0.2' into development

This commit is contained in:
anhefti 2020-07-16 16:17:30 +02:00
commit 265624ec4c
13 changed files with 60 additions and 14 deletions

View file

@ -200,7 +200,7 @@ public class APIMessage implements Serializable {
public static String toHTML(final String errorMessage, final List<APIMessage> messages) { public static String toHTML(final String errorMessage, final List<APIMessage> messages) {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
builder.append("<b>Failure: </b>").append("<br/><br/>").append(errorMessage).append("<br/><br/>"); builder.append("<b>Failure:</b>").append("<br/><br/>").append(errorMessage).append("<br/><br/>");
builder.append("<b>Detail Messages:</b><br/><br/>"); builder.append("<b>Detail Messages:</b><br/><br/>");
return buildHTML(messages, builder); return buildHTML(messages, builder);
} }

View file

@ -330,6 +330,12 @@ public final class Utils {
: null; : null;
} }
public static String formatHTMLLinesForceEscaped(final String message) {
return (message != null)
? message.replace("\n", "<br/>").replace("\\n", "<br/>")
: null;
}
public static String formatLineBreaks(final String text) { public static String formatLineBreaks(final String text) {
if (text == null) { if (text == null) {
return null; return null;

View file

@ -303,6 +303,11 @@ public class LmsSetupForm implements TemplateComposer {
.withEntityKey(entityKey) .withEntityKey(entityKey)
.publishIf(() -> modifyGrant && readonly && institutionActive) .publishIf(() -> modifyGrant && readonly && institutionActive)
.newAction(ActionDefinition.LMS_SETUP_TEST)
.withEntityKey(entityKey)
.withExec(action -> LmsSetupForm.testLmsSetup(action, formHandle, restService))
.publishIf(() -> readonly)
.newAction(ActionDefinition.LMS_SETUP_DEACTIVATE) .newAction(ActionDefinition.LMS_SETUP_DEACTIVATE)
.withEntityKey(entityKey) .withEntityKey(entityKey)
.withSimpleRestCall(restService, DeactivateLmsSetup.class) .withSimpleRestCall(restService, DeactivateLmsSetup.class)
@ -320,6 +325,12 @@ public class LmsSetupForm implements TemplateComposer {
.ignoreMoveAwayFromEdit() .ignoreMoveAwayFromEdit()
.publishIf(() -> !readonly) .publishIf(() -> !readonly)
.newAction(ActionDefinition.LMS_SETUP_TEST_EDIT)
.withEntityKey(entityKey)
.withExec(action -> this.testAdHoc(action, formHandle))
.ignoreMoveAwayFromEdit()
.publishIf(() -> !readonly && !isNew.getAsBoolean())
.newAction(ActionDefinition.LMS_SETUP_SAVE_AND_ACTIVATE) .newAction(ActionDefinition.LMS_SETUP_SAVE_AND_ACTIVATE)
.withEntityKey(entityKey) .withEntityKey(entityKey)
.withExec(action -> { .withExec(action -> {
@ -438,12 +449,12 @@ public class LmsSetupForm implements TemplateComposer {
case TOKEN_REQUEST: { case TOKEN_REQUEST: {
throw new PageMessageException(new LocTextKey( throw new PageMessageException(new LocTextKey(
"sebserver.lmssetup.action.test.tokenRequestError", "sebserver.lmssetup.action.test.tokenRequestError",
error.message)); Utils.formatHTMLLinesForceEscaped(Utils.escapeHTML_XML_EcmaScript(error.message))));
} }
case QUIZ_ACCESS_API_REQUEST: { case QUIZ_ACCESS_API_REQUEST: {
throw new PageMessageException(new LocTextKey( throw new PageMessageException(new LocTextKey(
"sebserver.lmssetup.action.test.quizRequestError", "sebserver.lmssetup.action.test.quizRequestError",
error.message)); Utils.formatHTMLLinesForceEscaped(Utils.escapeHTML_XML_EcmaScript(error.message))));
} }
case QUIZ_RESTRICTION_API_REQUEST: { case QUIZ_RESTRICTION_API_REQUEST: {
// NOTE: quiz restriction is not mandatory for functional LmsSetup // NOTE: quiz restriction is not mandatory for functional LmsSetup
@ -453,7 +464,7 @@ public class LmsSetupForm implements TemplateComposer {
default: { default: {
throw new PageMessageException(new LocTextKey( throw new PageMessageException(new LocTextKey(
"sebserver.lmssetup.action.test.unknownError", "sebserver.lmssetup.action.test.unknownError",
error.message)); Utils.formatHTMLLinesForceEscaped(Utils.escapeHTML_XML_EcmaScript(error.message))));
} }
} }
}); });

View file

@ -170,11 +170,16 @@ public enum ActionDefinition {
ImageIcon.EDIT, ImageIcon.EDIT,
PageStateDefinitionImpl.LMS_SETUP_EDIT, PageStateDefinitionImpl.LMS_SETUP_EDIT,
ActionCategory.FORM), ActionCategory.FORM),
LMS_SETUP_SAVE_AND_TEST( LMS_SETUP_TEST(
new LocTextKey("sebserver.lmssetup.action.savetest"), new LocTextKey("sebserver.lmssetup.action.test"),
ImageIcon.TEST, ImageIcon.TEST,
PageStateDefinitionImpl.LMS_SETUP_VIEW, PageStateDefinitionImpl.LMS_SETUP_VIEW,
ActionCategory.FORM), ActionCategory.FORM),
LMS_SETUP_TEST_EDIT(
new LocTextKey("sebserver.lmssetup.action.test"),
ImageIcon.TEST,
PageStateDefinitionImpl.LMS_SETUP_EDIT,
ActionCategory.FORM),
LMS_SETUP_TEST_AND_SAVE( LMS_SETUP_TEST_AND_SAVE(
new LocTextKey("sebserver.lmssetup.action.testsave"), new LocTextKey("sebserver.lmssetup.action.testsave"),
ImageIcon.TEST, ImageIcon.TEST,

View file

@ -198,6 +198,13 @@ public final class PageAction {
PageAction.this.getName(), PageAction.this.getName(),
e.getMessage(), e.getMessage(),
Utils.getErrorCauseMessage(e)); Utils.getErrorCauseMessage(e));
if (e.getCause() instanceof RestCallError) {
final RestCallError cause = (RestCallError) e.getCause();
PageAction.this.pageContext.notifyError(
PageContext.UNEXPECTED_ERROR_KEY,
cause);
return Result.ofError(cause);
}
return Result.ofError(e); return Result.ofError(e);
} catch (final Exception e) { } catch (final Exception e) {
log.error("Failed to execute action: {} | error: {} | cause: {}", log.error("Failed to execute action: {} | error: {} | cause: {}",

View file

@ -258,7 +258,6 @@ public class PageContextImpl implements PageContext {
this.i18nSupport.getText(message), this.i18nSupport.getText(message),
SWT.NONE, SWT.NONE,
this.i18nSupport); this.i18nSupport);
messageBox.setMarkupEnabled(true); messageBox.setMarkupEnabled(true);
messageBox.open(null); messageBox.open(null);
} }
@ -303,6 +302,7 @@ public class PageContextImpl implements PageContext {
Utils.formatHTMLLines(errorMessage + "<br/><br/> Cause: " + error.getMessage()), Utils.formatHTMLLines(errorMessage + "<br/><br/> Cause: " + error.getMessage()),
SWT.ERROR, SWT.ERROR,
this.i18nSupport); this.i18nSupport);
messageBox.setMarkupEnabled(true);
messageBox.open(null); messageBox.open(null);
} }

View file

@ -340,6 +340,8 @@ public class PageServiceImpl implements PageService {
} catch (final Exception e) { } catch (final Exception e) {
log.error("Failed to set current PageState: ", e); log.error("Failed to set current PageState: ", e);
} }
} else {
} }
callback.accept(result); callback.accept(result);
}); });

View file

@ -37,7 +37,6 @@ public final class Message extends MessageBox {
super(parent, type); super(parent, type);
super.setText(title); super.setText(title);
super.setMessage(message); super.setMessage(message);
super.setMarkupEnabled(true);
this.i18nSupport = i18nSupport; this.i18nSupport = i18nSupport;
} }

View file

@ -150,8 +150,12 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null, (lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
lmsSetup.lmsApiUrl, lmsSetup.lmsApiUrl,
lmsCredentials.clientIdAsString(), lmsCredentials.clientIdAsString(),
lmsCredentials.secretAsString(), (lmsCredentials.hasSecret())
lmsCredentials.accessTokenAsString(), ? lmsCredentials.secretAsString()
: savedRecord.getLmsClientsecret(),
(lmsCredentials.hasAccessToken())
? lmsCredentials.accessTokenAsString()
: savedRecord.getLmsRestApiToken(),
lmsSetup.getProxyHost(), lmsSetup.getProxyHost(),
lmsSetup.getProxyPort(), lmsSetup.getProxyPort(),
proxyCredentials.clientIdAsString(), proxyCredentials.clientIdAsString(),

View file

@ -86,6 +86,19 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
Utils.createJsonContentHeader(), Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST); HttpStatus.BAD_REQUEST);
} }
//
// @ExceptionHandler(RuntimeException.class)
// public ResponseEntity<Object> handleRuntimeException(
// final RuntimeException ex,
// final WebRequest request) {
//
// log.error("Unexpected generic error catched at the API endpoint: ", ex);
// final List<APIMessage> errors = Arrays.asList(APIMessage.ErrorMessage.GENERIC.of(ex.getMessage()));
// return new ResponseEntity<>(
// errors,
// Utils.createJsonContentHeader(),
// HttpStatus.INTERNAL_SERVER_ERROR);
// }
@ExceptionHandler(OnlyMessageLogExceptionWrapper.class) @ExceptionHandler(OnlyMessageLogExceptionWrapper.class)
public ResponseEntity<Object> onlyMessageLogExceptionWrapper( public ResponseEntity<Object> onlyMessageLogExceptionWrapper(

View file

@ -308,7 +308,6 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE) produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public T savePut(@Valid @RequestBody final T modifyData) { public T savePut(@Valid @RequestBody final T modifyData) {
return this.checkModifyAccess(modifyData) return this.checkModifyAccess(modifyData)
.flatMap(this::validForSave) .flatMap(this::validForSave)
.flatMap(this.entityDAO::save) .flatMap(this.entityDAO::save)

View file

@ -293,10 +293,10 @@ sebserver.lmssetup.action.new=Add LMS Setup
sebserver.lmssetup.action.list.view=View LMS Setup sebserver.lmssetup.action.list.view=View LMS Setup
sebserver.lmssetup.action.list.modify=Edit LMS Setup sebserver.lmssetup.action.list.modify=Edit LMS Setup
sebserver.lmssetup.action.modify=Edit sebserver.lmssetup.action.modify=Edit
sebserver.lmssetup.action.savetest=Test And Save sebserver.lmssetup.action.test=Test LMS Connection
sebserver.lmssetup.action.testsave=Test And Save sebserver.lmssetup.action.testsave=Test And Save
sebserver.lmssetup.action.test.ok=Successfully connected to the course API sebserver.lmssetup.action.test.ok=Successfully connected to the course API
sebserver.lmssetup.action.test.tokenRequestError=The API access was denied: {0}<br/>Please check the LMS connection details. sebserver.lmssetup.action.test.tokenRequestError=The API access was denied:<br/>{0}<br/><br/>Please check the LMS connection details.
sebserver.lmssetup.action.test.quizRequestError=Unable to request courses or exams from the course API of the LMS. {0} sebserver.lmssetup.action.test.quizRequestError=Unable to request courses or exams from the course API of the LMS. {0}
sebserver.lmssetup.action.test.quizRestrictionError=Unable to access course restriction API of the LMS. {0} sebserver.lmssetup.action.test.quizRestrictionError=Unable to access course restriction API of the LMS. {0}
sebserver.lmssetup.action.test.missingParameter=There is one or more missing connection parameter.<br/>Please check the connection parameter for this LMS Setup sebserver.lmssetup.action.test.missingParameter=There is one or more missing connection parameter.<br/>Please check the connection parameter for this LMS Setup

View file

@ -68,7 +68,7 @@ public class APIMessageTest {
final String html = APIMessage.toHTML("title message", messages); final String html = APIMessage.toHTML("title message", messages);
assertEquals( assertEquals(
"<b>Failure: </b><br/><br/>title message<br/><br/><b>Detail Messages:</b><br/><br/>&nbsp;&nbsp;code&nbsp;:&nbsp;0<br/>&nbsp;&nbsp;system message&nbsp;:&nbsp;Generic error message<br/>&nbsp;&nbsp;details&nbsp;:&nbsp;--<br/><br/>&nbsp;&nbsp;code&nbsp;:&nbsp;1010<br/>&nbsp;&nbsp;system message&nbsp;:&nbsp;Illegal API request argument<br/>&nbsp;&nbsp;details&nbsp;:&nbsp;--<br/><br/>", "<b>Failure:</b><br/><br/>title message<br/><br/><b>Detail Messages:</b><br/><br/>&nbsp;&nbsp;code&nbsp;:&nbsp;0<br/>&nbsp;&nbsp;system message&nbsp;:&nbsp;Generic error message<br/>&nbsp;&nbsp;details&nbsp;:&nbsp;--<br/><br/>&nbsp;&nbsp;code&nbsp;:&nbsp;1010<br/>&nbsp;&nbsp;system message&nbsp;:&nbsp;Illegal API request argument<br/>&nbsp;&nbsp;details&nbsp;:&nbsp;--<br/><br/>",
html); html);
final String html2 = APIMessage.toHTML(messages); final String html2 = APIMessage.toHTML(messages);