diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java index c5c2812c..2f95ac50 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java @@ -157,8 +157,16 @@ public final class API { + LMS_SETUP_TEST_PATH_SEGMENT + LMS_SETUP_TEST_AD_HOC_PATH_SEGMENT; - public static final String LMS_FULL_INTEGRATION_REFRESH_TOKEN_ENDPOINT = "/refresh-access-token"; - public static final String LMS_FULL_INTEGRATION_LMS_UUID = "lms_uuid"; + public static final String LMS_FULL_INTEGRATION_EXAM_ENDPOINT = "/exam"; + public static final String LMS_FULL_INTEGRATION_CONNECTION_CONFIG_ENDPOINT = "/seb_config"; + public static final String LMS_FULL_INTEGRATION_LOGIN_TOKEN_ENDPOINT = "/login_token"; + public static final String LMS_FULL_INTEGRATION_LMS_UUID = "id"; + public static final String LMS_FULL_INTEGRATION_COURSE_ID = "course_id"; + public static final String LMS_FULL_INTEGRATION_QUIZ_ID = "quiz_id"; + public static final String LMS_FULL_INTEGRATION_EXAM_TEMPLATE_ID = "exam_template_id"; + public static final String LMS_FULL_INTEGRATION_QUIT_PASSWORD = "quit_password"; + public static final String LMS_FULL_INTEGRATION_QUIT_LINK = "quit_link"; + public static final String USER_ACCOUNT_ENDPOINT = "/useraccount"; 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 4892b7de..d9976133 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 @@ -8,8 +8,10 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms; +import java.io.OutputStream; import java.util.Map; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -19,13 +21,28 @@ public interface FullLmsIntegrationService { Result refreshAccessToken(String lmsUUID); - Result applyFullLmsIntegration(Long lmsSetupId, boolean refreshToken); + Result applyFullLmsIntegration(Long lmsSetupId); Result deleteFullLmsIntegration(Long lmsSetupId); Result> getExamTemplateSelection(); - Result importExam(String lmsUUID, String courseId, String quizId, String examTemplateId); + Result importExam( + String lmsUUID, + String courseId, + String quizId, + String examTemplateId, + String quitPassword, + String quitLink); + Result deleteExam( + String lmsUUID, + String courseId, + String quizId); + Result streamConnectionConfiguration( + String lmsUUID, + String courseId, + String quizId, + OutputStream out); } 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 e49b0001..cf978874 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 @@ -8,9 +8,12 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl; +import java.io.OutputStream; import java.util.Map; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +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 ch.ethz.seb.sebserver.webservice.servicelayer.lms.FullLmsIntegrationService; @@ -33,7 +36,7 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService } @Override - public Result applyFullLmsIntegration(final Long lmsSetupId, final boolean refreshToken) { + public Result applyFullLmsIntegration(final Long lmsSetupId) { return Result.ofRuntimeError("TODO"); } @@ -52,7 +55,31 @@ public class FullLmsIntegrationServiceImpl implements FullLmsIntegrationService final String lmsUUID, final String courseId, final String quizId, - final String examTemplateId) { + final String examTemplateId, + final String quitPassword, + final String quitLink) { return Result.ofRuntimeError("TODO"); } + + @Override + public Result deleteExam( + final String lmsUUID, + final String courseId, + final String quizId) { + return Result.ofRuntimeError("TODO"); + } + + @Override + public Result streamConnectionConfiguration( + final String lmsUUID, + final String courseId, + final String quizId, + final OutputStream out) { + return Result.ofRuntimeError("TODO"); + } + + private Long findLMSSetup(final String lmsUUID) { + // TODO + return null; + } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsIntegrationController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsIntegrationController.java index dbe12ddc..17f5e4e8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsIntegrationController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsIntegrationController.java @@ -11,8 +11,12 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.model.Entity; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; +import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.FullLmsIntegrationService; @@ -39,20 +43,62 @@ public class LmsIntegrationController { } @RequestMapping( - path = API.LMS_FULL_INTEGRATION_REFRESH_TOKEN_ENDPOINT, + path = API.LMS_FULL_INTEGRATION_EXAM_ENDPOINT, method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public void refreshAccessToken( - @RequestParam(name = API.LMS_FULL_INTEGRATION_LMS_UUID, required = true) final String lmsUUID, + public void createExam( + @RequestParam(name = API.LMS_FULL_INTEGRATION_LMS_UUID, required = true) final String lmsUUId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_COURSE_ID, required = true) final String courseId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_QUIZ_ID, required = true) final String quizId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_EXAM_TEMPLATE_ID, required = true) final String templateId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_QUIT_PASSWORD, required = false) final String quitPassword, + @RequestParam(name = API.LMS_FULL_INTEGRATION_QUIT_LINK, required = false) final String quitLink, final HttpServletResponse response) { - final Result result = fullLmsIntegrationService.refreshAccessToken(lmsUUID) - .onError(e -> log.error("Failed to refresh access token for LMS Setup: {}", lmsUUID, e)); + final Exam exam = fullLmsIntegrationService.importExam(lmsUUId, courseId, quizId, templateId, quitPassword, quitLink) + .onError(e -> log.error( + "Failed to create/import exam: lmsId:{}, courseId: {}, quizId: {}, templateId: {}", + lmsUUId, courseId, quizId, templateId, e)) + .getOrThrow(); + + log.info("Auto import of exam successful: {}", exam); + } + + @RequestMapping( + path = API.LMS_FULL_INTEGRATION_EXAM_ENDPOINT, + method = RequestMethod.DELETE, + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public void deleteExam( + @RequestParam(name = API.LMS_FULL_INTEGRATION_LMS_UUID, required = true) final String lmsUUId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_COURSE_ID, required = true) final String courseId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_QUIZ_ID, required = true) final String quizId, + final HttpServletResponse response) { + + final EntityKey examID = fullLmsIntegrationService.deleteExam(lmsUUId, courseId, quizId) + .onError(e -> log.error( + "Failed to delete exam: lmsId:{}, courseId: {}, quizId: {}", + lmsUUId, courseId, quizId, e)) + .getOrThrow(); + + log.info("Auto delete of exam successful: {}", examID); + } + + @RequestMapping( + path = API.LMS_FULL_INTEGRATION_EXAM_ENDPOINT, + method = RequestMethod.DELETE, + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public void getConnectionConfiguration( + @RequestParam(name = API.LMS_FULL_INTEGRATION_LMS_UUID, required = true) final String lmsUUId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_COURSE_ID, required = true) final String courseId, + @RequestParam(name = API.LMS_FULL_INTEGRATION_QUIZ_ID, required = true) final String quizId, + final HttpServletResponse response) throws IOException { + + fullLmsIntegrationService.streamConnectionConfiguration(lmsUUId, courseId, quizId, response.getOutputStream()) + .onError(e -> log.error( + "Failed to stream connection configuration for exam: lmsId:{}, courseId: {}, quizId: {}", + lmsUUId, courseId, quizId, e)) + .getOrThrow(); - if (result.hasError()) { - response.setStatus(HttpStatus.NOT_FOUND.value()); - } else { - response.setStatus(HttpStatus.OK.value()); - } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java index 303cd2e4..9e31e014 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java @@ -91,7 +91,6 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf .antMatchers(configurerAdapter.apiEndpoint + API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT + "/**").permitAll() .antMatchers(configurerAdapter.apiEndpoint + API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT + "/**").permitAll() .antMatchers(configurerAdapter.apiEndpoint + API.REGISTER_ENDPOINT).permitAll() - .antMatchers(this.lmsAPIEndpoint + API.LMS_FULL_INTEGRATION_REFRESH_TOKEN_ENDPOINT).permitAll() .and() .antMatcher(configurerAdapter.apiEndpoint + "/**")