diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/LoginForward.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/LoginForward.java new file mode 100644 index 00000000..ba753145 --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/LoginForward.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 ETH Zürich, IT Services + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.gbl.model.user; + +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class LoginForward { + @JsonProperty("entityKey") + public final EntityKey entityKey; + @JsonProperty("actionName") + public final String actionName; + + public LoginForward( + @JsonProperty("entityKey") final EntityKey entityKey, + @JsonProperty("actionName") final String actionName) { + this.entityKey = entityKey; + this.actionName = actionName; + } +} diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/TokenLoginInfo.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/TokenLoginInfo.java index 0701470a..71201f1f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/TokenLoginInfo.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/TokenLoginInfo.java @@ -8,7 +8,6 @@ package ch.ethz.seb.sebserver.gbl.model.user; -import ch.ethz.seb.sebserver.gbl.model.EntityKey; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -19,7 +18,7 @@ public class TokenLoginInfo { @JsonProperty("userUUID") public final String userUUID; @JsonProperty("redirect") - public final EntityKey redirect; + public final LoginForward login_forward; @JsonProperty("login") public final OAuth2AccessToken login; @@ -27,12 +26,13 @@ public class TokenLoginInfo { public TokenLoginInfo( @JsonProperty("username") final String username, @JsonProperty("userUUID") final String userUUID, - @JsonProperty("redirect") final EntityKey redirect, + @JsonProperty("redirect") final LoginForward login_forward, @JsonProperty("login") final OAuth2AccessToken login) { this.username = username; this.userUUID = userUUID; - this.redirect = redirect; + this.login_forward = login_forward; this.login = login; } + } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java b/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java index 69f2feab..323e21e0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java @@ -21,6 +21,8 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder; import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext; import org.apache.commons.codec.binary.Base64InputStream; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/MainPage.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/MainPage.java index 6ad053a0..561de337 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/MainPage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/MainPage.java @@ -8,8 +8,16 @@ package ch.ethz.seb.sebserver.gui.content; +import javax.servlet.http.HttpServletRequest; import java.util.function.Consumer; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.user.LoginForward; +import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; +import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; +import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; @@ -54,13 +62,19 @@ public class MainPage implements TemplateComposer { private final WidgetFactory widgetFactory; private final PolyglotPageService polyglotPageService; + private final AuthorizationContextHolder authorizationContextHolder; + private final PageService pageService; public MainPage( final WidgetFactory widgetFactory, - final PolyglotPageService polyglotPageService) { + final PolyglotPageService polyglotPageService, + final AuthorizationContextHolder authorizationContextHolder, + final PageService pageService) { this.widgetFactory = widgetFactory; this.polyglotPageService = polyglotPageService; + this.authorizationContextHolder = authorizationContextHolder; + this.pageService = pageService; } @Override @@ -158,6 +172,19 @@ public class MainPage implements TemplateComposer { pageContext.copyOf(nav)); mainSash.setWeights(DEFAULT_SASH_WEIGHTS); + + final LoginForward loginForward = authorizationContextHolder + .getAuthorizationContext() + .getLoginForward(); + + if (loginForward != null) { + final PageAction pageAction = pageService.pageActionBuilder(pageContext) + .newAction( ActionDefinition.valueOf(loginForward.actionName)) + .withEntityKey(loginForward.entityKey) + .create(); + + pageService.executePageAction(pageAction); + } } private static final class ContentActionEventListener implements ActionEventListener { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java index 7d4e7b1d..2bfb0745 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.gui.content.action; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gui.content.activity.PageStateDefinitionImpl; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.page.PageStateDefinition; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/LmsSetupForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/LmsSetupForm.java index 4535fe98..b34bfb8d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/LmsSetupForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/LmsSetupForm.java @@ -456,8 +456,9 @@ public class LmsSetupForm implements TemplateComposer { } else if (formHandle != null && formHandle.handleError(result.getError())) { action.pageContext().notifyActivationError(EntityType.LMS_SETUP, error); } else { - result.getOrThrow(); + action.pageContext().notifyUnexpectedError(result.getError()); } + return action; } return handleTestResult( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java index aa560b8b..6e41ec61 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java @@ -15,6 +15,8 @@ import java.nio.charset.StandardCharsets; import javax.servlet.http.HttpSession; import ch.ethz.seb.sebserver.gbl.api.API; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.user.LoginForward; import ch.ethz.seb.sebserver.gbl.model.user.TokenLoginInfo; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; @@ -152,6 +154,7 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol private final String jwtTokenVerificationURI; private Result loggedInUser = null; + private LoginForward loginForward = null; OAuth2AuthorizationContext( final String guiClientId, @@ -215,6 +218,11 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol return null; } + @Override + public LoginForward getLoginForward() { + return loginForward; + } + @Override public boolean login(final String username, final CharSequence password) { if (!this.valid || this.isLoggedIn()) { @@ -282,6 +290,7 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol final TokenLoginInfo loginInfo = response.getBody(); this.restTemplate.getOAuth2ClientContext().setAccessToken(loginInfo.login); + loginForward = loginInfo.login_forward; return this.isLoggedIn(); } catch (final Exception e) { log.warn("Autologin failed due to unexpected error: {}", e.getMessage()); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java index fd398e1d..fa611b22 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java @@ -8,6 +8,8 @@ package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.user.LoginForward; import org.springframework.web.client.RestTemplate; import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; @@ -67,4 +69,5 @@ public interface SEBServerAuthorizationContext { CharSequence getUserPassword(); + LoginForward getLoginForward(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/impl/TeacherAccountServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/impl/TeacherAccountServiceImpl.java index a58832e9..a6a95184 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/impl/TeacherAccountServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/impl/TeacherAccountServiceImpl.java @@ -15,10 +15,7 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; -import ch.ethz.seb.sebserver.gbl.model.user.TokenLoginInfo; -import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; -import ch.ethz.seb.sebserver.gbl.model.user.UserMod; -import ch.ethz.seb.sebserver.gbl.model.user.UserRole; +import ch.ethz.seb.sebserver.gbl.model.user.*; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Cryptor; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -187,11 +184,14 @@ public class TeacherAccountServiceImpl implements TeacherAccountService { final OAuth2AccessToken token = accessToken.getBody(); final String examId = claims.get(EXAM_ID_CLAIM, String.class); - final EntityKey redirectTo = (StringUtils.isNotBlank(examId)) + final EntityKey key = (StringUtils.isNotBlank(examId)) ? new EntityKey(examId, EntityType.EXAM) : null; + final LoginForward loginForward = new LoginForward( + key, + "MONITOR_EXAM_FROM_LIST"); - return new TokenLoginInfo(user.username, user.uuid, redirectTo, token); + return new TokenLoginInfo(user.username, user.uuid, loginForward, token); }); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/FullLmsIntegrationService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/FullLmsIntegrationService.java index da2d7d30..4a16abed 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/FullLmsIntegrationService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/FullLmsIntegrationService.java @@ -144,8 +144,6 @@ public interface FullLmsIntegrationService { public final String name; @JsonProperty("url") public final String url; - @JsonProperty("autologin_url") - public final String autoLoginURL; @JsonProperty("access_token") public final String access_token; @JsonProperty("exam_templates") @@ -156,14 +154,12 @@ public interface FullLmsIntegrationService { @JsonProperty("id") final String id, @JsonProperty("name") final String name, @JsonProperty("url") final String url, - @JsonProperty("autologin_url") final String autoLoginURL, @JsonProperty("access_token") final String access_token, @JsonProperty("exam_templates") final Collection exam_templates) { this.id = id; this.name = name; this.url = url; - this.autoLoginURL = autoLoginURL; this.access_token = access_token; this.exam_templates = Utils.immutableCollectionOf(exam_templates); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplateCacheService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplateCacheService.java index 5a1fe459..77bc7e78 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplateCacheService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplateCacheService.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms; +import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import org.springframework.context.annotation.Lazy; @@ -30,7 +31,7 @@ public interface LmsAPITemplateCacheService { * @return LmsAPITemplate for specified LmsSetup configuration */ Result getLmsAPITemplate(String lmsSetupId); - Result getLmsAPITemplateForTesting(String lmsSetupId); + Result createInMemoryLmsAPITemplate(LmsSetup lmsSetup); void clearCache(String lmsSetupId); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/FullLmsIntegrationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/FullLmsIntegrationServiceImpl.java index 222a7391..81d7c140 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/FullLmsIntegrationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/FullLmsIntegrationServiceImpl.java @@ -49,7 +49,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateCacheServ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigurationChangeEvent; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigurationService; -import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ScreenProctoringService; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -241,7 +240,6 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService connectionId, lmsSetup.name, getAPIRootURL(), - getAutoLoginURL(), accessToken, this.getIntegrationTemplates(lmsSetup.institutionId) ); @@ -317,8 +315,6 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService .flatMap(this::findExam) .map(this::checkDeletion) .map(this::logExamDeleted) - .flatMap(teacherAccountServiceImpl::deactivateTeacherAccountsForExam) - .map(exam -> applyExamData(exam, true)) .flatMap(deleteExamAction::deleteExamInternal); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateAdapter.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateAdapter.java index 96f3b69b..4ca3577a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateAdapter.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateAdapter.java @@ -251,6 +251,16 @@ public class LmsAPITemplateAdapter implements LmsAPITemplate { }).getOrThrow(); } + @Override + public String getCourseIdFromExam(final Exam exam) { + return this.courseAccessAPI.getCourseIdFromExam(exam); + } + + @Override + public String getQuizIdFromExam(final Exam exam) { + return this.courseAccessAPI.getQuizIdFromExam(exam); + } + @Override public LmsSetupTestResult testCourseAccessAPI() { if (this.courseAccessAPI != null) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateCacheServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateCacheServiceImpl.java index 7b8d3818..27a5439a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateCacheServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsAPITemplateCacheServiceImpl.java @@ -8,6 +8,8 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl; +import static ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport.lmsSetupId; + import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; @@ -94,12 +96,13 @@ public class LmsAPITemplateCacheServiceImpl implements LmsAPITemplateCacheServic } @Override - public Result getLmsAPITemplateForTesting(final String lmsSetupId) { - return lmsSetupDAO.byModelId(lmsSetupId) - .map(lmsSetup -> new AdHocAPITemplateDataSupplier( - lmsSetup, - this.clientCredentialService)) - .flatMap(this::createLmsSetupTemplate); + public Result createInMemoryLmsAPITemplate(final LmsSetup lmsSetup) { + return Result.tryCatch(() -> { + final AdHocAPITemplateDataSupplier adHocAPITemplateDataSupplier = new AdHocAPITemplateDataSupplier( + lmsSetup, + this.clientCredentialService); + return this.createLmsSetupTemplate(adHocAPITemplateDataSupplier).getOrThrow(); + }); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsTestServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsTestServiceImpl.java index 43f3404c..5fe1497d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsTestServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/LmsTestServiceImpl.java @@ -87,7 +87,7 @@ public class LmsTestServiceImpl implements LmsTestService { public LmsSetupTestResult testAdHoc(final LmsSetup lmsSetup) { final Result createLmsSetupTemplate = lmsAPITemplateCacheService - .getLmsAPITemplateForTesting(lmsSetup.getModelId()); + .createInMemoryLmsAPITemplate(lmsSetup); if (createLmsSetupTemplate.hasError()) { return new LmsSetupTestResult( lmsSetup.lmsType, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactoryImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactoryImpl.java index 1a26770b..5608d489 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactoryImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactoryImpl.java @@ -379,9 +379,9 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory queryParam.queryParams(queryParams); } - final boolean usePOST = queryAttributes != null && !queryAttributes.isEmpty(); + //final boolean usePOST = queryAttributes != null && !queryAttributes.isEmpty(); final HttpEntity functionReqEntity; - if (usePOST) { + if ( queryAttributes != null && !queryAttributes.isEmpty()) { final HttpHeaders headers = new HttpHeaders(); headers.set( HttpHeaders.CONTENT_TYPE, @@ -394,7 +394,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory functionReqEntity = new HttpEntity<>(new LinkedMultiValueMap<>()); } - return doRequest(functionName, queryParam, usePOST, functionReqEntity); + return doRequest(functionName, queryParam, true, functionReqEntity); } @Override @@ -465,7 +465,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory final ResponseEntity response = super.exchange( this.serverURL + this.tokenPath, - HttpMethod.GET, + HttpMethod.POST, this.tokenReqEntity, String.class, this.tokenReqURIVars); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/plugin/MoodlePluginFullIntegration.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/plugin/MoodlePluginFullIntegration.java index 2daca0f5..602b2ed5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/plugin/MoodlePluginFullIntegration.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/plugin/MoodlePluginFullIntegration.java @@ -9,6 +9,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.plugin; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import ch.ethz.seb.sebserver.gbl.api.APIMessage; @@ -156,7 +157,7 @@ public class MoodlePluginFullIntegration implements FullLmsIntegrationAPI { final MoodleAPIRestTemplate rest = getRestTemplate().getOrThrow(); final Map> attributes = new HashMap<>(); - final Map data_mapping = new HashMap<>(); + final Map data_mapping = new LinkedHashMap<>(); attributes.put(ATTRIBUTE_EXAM_DATA, data_mapping); // data[quizid]= int @@ -168,7 +169,7 @@ public class MoodlePluginFullIntegration implements FullLmsIntegrationAPI { if (BooleanUtils.isTrue(examData.exam_created)) { data_mapping.put("addordelete", "1"); data_mapping.put("templateid", examData.template_id); - data_mapping.put("showquitlink", BooleanUtils.isTrue(examData.show_quit_link) ? "1" : "2"); + data_mapping.put("showquitlink", BooleanUtils.isTrue(examData.show_quit_link) ? "1" : "0"); data_mapping.put("quitsecret", examData.quit_password); } else { data_mapping.put("addordelete", "0");