From 58064de2e84d4ed28943fe2cb83beb88d45cb929 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 20 May 2021 12:52:18 +0200 Subject: [PATCH 1/3] Ans integration preparation --- .../lms/impl/ans/AnsLmsAPITemplate.java | 113 +++++++++++++----- .../impl/ans/AnsLmsAPITemplateFactory.java | 10 ++ 2 files changed, 96 insertions(+), 27 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java index 0d6d50a2..d167f16f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java @@ -20,10 +20,16 @@ import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.springframework.cache.CacheManager; import org.springframework.core.env.Environment; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.async.AsyncService; +import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService; import ch.ethz.seb.sebserver.gbl.client.ClientCredentials; +import ch.ethz.seb.sebserver.gbl.client.ProxyData; import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; @@ -45,11 +51,18 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.AbstractCachedCour public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements LmsAPITemplate { // TODO add needed dependencies here + + private final ClientHttpRequestFactoryService clientHttpRequestFactoryService; + private final ClientCredentialService clientCredentialService; private final APITemplateDataSupplier apiTemplateDataSupplier; private final Long lmsSetupId; protected AnsLmsAPITemplate( + // TODO if you need more dependencies inject them here and set the reference + + final ClientHttpRequestFactoryService clientHttpRequestFactoryService, + final ClientCredentialService clientCredentialService, final APITemplateDataSupplier apiTemplateDataSupplier, final AsyncService asyncService, final Environment environment, @@ -57,6 +70,8 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms super(asyncService, environment, cacheManager); + this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; + this.clientCredentialService = clientCredentialService; this.apiTemplateDataSupplier = apiTemplateDataSupplier; this.lmsSetupId = apiTemplateDataSupplier.getLmsSetup().id; } @@ -194,35 +209,36 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms final String quizName = filterMap.getString(QuizData.FILTER_ATTR_QUIZ_NAME); final DateTime quizFromTime = (filterMap != null) ? filterMap.getQuizFromTime() : null; - // TODO get all course / quiz data from remote LMS that matches the filter criteria. - // put loaded QuizData to the cache: super.putToCache(quizDataCollection); - // before returning it. - return () -> { + + // TODO get all course / quiz data from remote LMS that matches the filter criteria. + // put loaded QuizData to the cache: super.putToCache(quizDataCollection); + // before returning it. + throw new RuntimeException("TODO"); }; } @Override protected Supplier> quizzesSupplier(final Set ids) { - - // TODO get all quiz / course data for specified identifiers from remote LMS - // and put it to the cache: super.putToCache(quizDataCollection); - // before returning it. - return () -> { + + // TODO get all quiz / course data for specified identifiers from remote LMS + // and put it to the cache: super.putToCache(quizDataCollection); + // before returning it. + throw new RuntimeException("TODO"); }; } @Override protected Supplier quizSupplier(final String id) { - - // TODO get the specified quiz / course data for specified identifier from remote LMS - // and put it to the cache: super.putToCache(quizDataCollection); - // before returning it. - return () -> { + + // TODO get the specified quiz / course data for specified identifier from remote LMS + // and put it to the cache: super.putToCache(quizDataCollection); + // before returning it. + throw new RuntimeException("TODO"); }; } @@ -230,10 +246,11 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms @Override protected Supplier accountDetailsSupplier(final String examineeSessionId) { - // TODO get the examinee's account details by the given examineeSessionId from remote LMS. - // Currently only the name is needed to display on monitoring view. - return () -> { + + // TODO get the examinee's account details by the given examineeSessionId from remote LMS. + // Currently only the name is needed to display on monitoring view. + throw new RuntimeException("TODO"); }; } @@ -250,10 +267,14 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms final String quizId = exam.externalId; - // TODO get the SEB client restrictions that are currently set on the remote LMS for - // the given quiz / course derived from the given exam + return Result.tryCatch(() -> { - return Result.ofRuntimeError("TODO"); + // TODO get the SEB client restrictions that are currently set on the remote LMS for + // the given quiz / course derived from the given exam + + throw new RuntimeException("TODO"); + + }); } @Override @@ -261,11 +282,15 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms final String externalExamId, final SEBRestriction sebRestrictionData) { - // TODO apply the given sebRestrictionData settings as current SEB client restriction setting - // to the remote LMS for the given quiz / course. - // Mainly SEBRestriction.configKeys and SEBRestriction.browserExamKeys + return Result.tryCatch(() -> { - return Result.ofRuntimeError("TODO"); + // TODO apply the given sebRestrictionData settings as current SEB client restriction setting + // to the remote LMS for the given quiz / course. + // Mainly SEBRestriction.configKeys and SEBRestriction.browserExamKeys + + throw new RuntimeException("TODO"); + + }); } @Override @@ -273,10 +298,44 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms final String quizId = exam.externalId; - // TODO Release respectively delete all SEB client restrictions for the given - // course / quize on the remote LMS. + return Result.tryCatch(() -> { - return Result.ofRuntimeError("TODO"); + // TODO Release respectively delete all SEB client restrictions for the given + // course / quize on the remote LMS. + + throw new RuntimeException("TODO"); + + }); + } + + // TODO: This is an example of how to create a RestTemplate for the service to access the LMS API + // The example deals with a Http based API that is secured by an OAuth2 client-credential flow. + // You might need some different template, then you have to adapt this code + // To your needs. + private OAuth2RestTemplate createRestTemplate(final String accessTokenRequestPath) { + + final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup(); + final ClientCredentials credentials = this.apiTemplateDataSupplier.getLmsClientCredentials(); + final ProxyData proxyData = this.apiTemplateDataSupplier.getProxyData(); + + final CharSequence plainClientId = credentials.clientId; + final CharSequence plainClientSecret = this.clientCredentialService + .getPlainClientSecret(credentials) + .getOrThrow(); + + final ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); + details.setAccessTokenUri(lmsSetup.lmsApiUrl + accessTokenRequestPath); + details.setClientId(plainClientId.toString()); + details.setClientSecret(plainClientSecret.toString()); + + final ClientHttpRequestFactory clientHttpRequestFactory = this.clientHttpRequestFactoryService + .getClientHttpRequestFactory(proxyData) + .getOrThrow(); + + final OAuth2RestTemplate template = new OAuth2RestTemplate(details); + template.setRequestFactory(clientHttpRequestFactory); + + return template; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplateFactory.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplateFactory.java index 67c9a98d..549bf5a5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplateFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplateFactory.java @@ -13,7 +13,9 @@ import org.springframework.context.annotation.Lazy; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService; import ch.ethz.seb.sebserver.gbl.async.AsyncService; +import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -33,15 +35,21 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory; * as usual. Just add the additionally needed dependencies used to build a AnsLmsAPITemplateFactory */ public class AnsLmsAPITemplateFactory implements LmsAPITemplateFactory { + private final ClientHttpRequestFactoryService clientHttpRequestFactoryService; + private final ClientCredentialService clientCredentialService; private final AsyncService asyncService; private final Environment environment; private final CacheManager cacheManager; public AnsLmsAPITemplateFactory( + final ClientHttpRequestFactoryService clientHttpRequestFactoryService, + final ClientCredentialService clientCredentialService, final AsyncService asyncService, final Environment environment, final CacheManager cacheManager) { + this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; + this.clientCredentialService = clientCredentialService; this.asyncService = asyncService; this.environment = environment; this.cacheManager = cacheManager; @@ -56,6 +64,8 @@ public class AnsLmsAPITemplateFactory implements LmsAPITemplateFactory { public Result create(final APITemplateDataSupplier apiTemplateDataSupplier) { return Result.tryCatch(() -> { return new AnsLmsAPITemplate( + this.clientHttpRequestFactoryService, + this.clientCredentialService, apiTemplateDataSupplier, this.asyncService, this.environment, From 4dcb29e1071cf0cda2bd60ccb263c249119a9cd4 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 20 May 2021 13:10:12 +0200 Subject: [PATCH 2/3] binding preparation --- .../ch/ethz/seb/sebserver/gbl/model/institution/LmsSetup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/LmsSetup.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/LmsSetup.java index 595ca273..87be7b36 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/LmsSetup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/institution/LmsSetup.java @@ -61,7 +61,7 @@ public final class LmsSetup implements GrantEntity, Activatable { /** The Moodle binding features only the course access API so far */ MOODLE(Features.COURSE_API /* , Features.SEB_RESTRICTION */), /** The Ans Delft binding is on the way */ - ANS_DELFT(/* Features.COURSE_API , Features.SEB_RESTRICTION */), + ANS_DELFT(Features.COURSE_API, Features.SEB_RESTRICTION), /** The OpenOLAT binding is on the way */ OPEN_OLAT(/* Features.COURSE_API , Features.SEB_RESTRICTION */); From 65d9957fae75aaf8ac3b4ff94d7032cc3b997e7b Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 30 Jun 2021 14:21:45 +0200 Subject: [PATCH 3/3] suppress warnings --- .../servicelayer/lms/impl/ans/AnsLmsAPITemplate.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java index d167f16f..c8e9fa16 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/ans/AnsLmsAPITemplate.java @@ -206,7 +206,9 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms @Override protected Supplier> allQuizzesSupplier(final FilterMap filterMap) { + @SuppressWarnings("unused") final String quizName = filterMap.getString(QuizData.FILTER_ATTR_QUIZ_NAME); + @SuppressWarnings("unused") final DateTime quizFromTime = (filterMap != null) ? filterMap.getQuizFromTime() : null; return () -> { @@ -264,7 +266,7 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms @Override public Result getSEBClientRestriction(final Exam exam) { - + @SuppressWarnings("unused") final String quizId = exam.externalId; return Result.tryCatch(() -> { @@ -295,7 +297,7 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms @Override public Result releaseSEBClientRestriction(final Exam exam) { - + @SuppressWarnings("unused") final String quizId = exam.externalId; return Result.tryCatch(() -> { @@ -312,6 +314,7 @@ public class AnsLmsAPITemplate extends AbstractCachedCourseAccess implements Lms // The example deals with a Http based API that is secured by an OAuth2 client-credential flow. // You might need some different template, then you have to adapt this code // To your needs. + @SuppressWarnings("unused") private OAuth2RestTemplate createRestTemplate(final String accessTokenRequestPath) { final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();