preparing

This commit is contained in:
anhefti 2021-05-19 14:59:10 +02:00
parent a7d3b51005
commit 054a4f9e31
3 changed files with 53 additions and 15 deletions

View file

@ -8,6 +8,7 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.olat; package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.olat;
import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -20,10 +21,16 @@ import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.core.env.Environment; 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.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.async.AsyncService; 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.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.Domain.LMS_SETUP;
import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
@ -45,6 +52,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.AbstractCachedCour
public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements LmsAPITemplate { public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements LmsAPITemplate {
// TODO add needed dependencies here // TODO add needed dependencies here
private final ClientHttpRequestFactoryService clientHttpRequestFactoryService;
private final ClientCredentialService clientCredentialService;
private final APITemplateDataSupplier apiTemplateDataSupplier; private final APITemplateDataSupplier apiTemplateDataSupplier;
private final Long lmsSetupId; private final Long lmsSetupId;
@ -52,6 +61,8 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
// TODO if you need more dependencies inject them here and set the reference // TODO if you need more dependencies inject them here and set the reference
final ClientHttpRequestFactoryService clientHttpRequestFactoryService,
final ClientCredentialService clientCredentialService,
final APITemplateDataSupplier apiTemplateDataSupplier, final APITemplateDataSupplier apiTemplateDataSupplier,
final AsyncService asyncService, final AsyncService asyncService,
final Environment environment, final Environment environment,
@ -59,6 +70,8 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
super(asyncService, environment, cacheManager); super(asyncService, environment, cacheManager);
this.clientHttpRequestFactoryService = clientHttpRequestFactoryService;
this.clientCredentialService = clientCredentialService;
this.apiTemplateDataSupplier = apiTemplateDataSupplier; this.apiTemplateDataSupplier = apiTemplateDataSupplier;
this.lmsSetupId = apiTemplateDataSupplier.getLmsSetup().id; this.lmsSetupId = apiTemplateDataSupplier.getLmsSetup().id;
} }
@ -288,4 +301,34 @@ public class OlatLmsAPITemplate extends AbstractCachedCourseAccess implements Lm
return Result.ofRuntimeError("TODO"); return Result.ofRuntimeError("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) throws URISyntaxException {
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;
}
} }

View file

@ -13,7 +13,9 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; 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.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.model.institution.LmsSetup.LmsType;
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;
@ -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 OlatLmsAPITemplate. */ * as usual. Just add the additionally needed dependencies used to build a OlatLmsAPITemplate. */
public class OlatLmsAPITemplateFactory implements LmsAPITemplateFactory { public class OlatLmsAPITemplateFactory implements LmsAPITemplateFactory {
private final ClientHttpRequestFactoryService clientHttpRequestFactoryService;
private final ClientCredentialService clientCredentialService;
private final AsyncService asyncService; private final AsyncService asyncService;
private final Environment environment; private final Environment environment;
private final CacheManager cacheManager; private final CacheManager cacheManager;
public OlatLmsAPITemplateFactory( public OlatLmsAPITemplateFactory(
final ClientHttpRequestFactoryService clientHttpRequestFactoryService,
final ClientCredentialService clientCredentialService,
final AsyncService asyncService, final AsyncService asyncService,
final Environment environment, final Environment environment,
final CacheManager cacheManager) { final CacheManager cacheManager) {
this.clientHttpRequestFactoryService = clientHttpRequestFactoryService;
this.clientCredentialService = clientCredentialService;
this.asyncService = asyncService; this.asyncService = asyncService;
this.environment = environment; this.environment = environment;
this.cacheManager = cacheManager; this.cacheManager = cacheManager;
@ -56,6 +64,8 @@ public class OlatLmsAPITemplateFactory implements LmsAPITemplateFactory {
public Result<LmsAPITemplate> create(final APITemplateDataSupplier apiTemplateDataSupplier) { public Result<LmsAPITemplate> create(final APITemplateDataSupplier apiTemplateDataSupplier) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
return new OlatLmsAPITemplate( return new OlatLmsAPITemplate(
this.clientHttpRequestFactoryService,
this.clientCredentialService,
apiTemplateDataSupplier, apiTemplateDataSupplier,
this.asyncService, this.asyncService,
this.environment, this.environment,

View file

@ -51,21 +51,6 @@ sebserver.webservice.lms.openedx.api.token.request.paths=/oauth2/access_token
sebserver.webservice.lms.moodle.api.token.request.paths= sebserver.webservice.lms.moodle.api.token.request.paths=
sebserver.webservice.lms.address.alias=lms.mockup.com=lms.address.alias sebserver.webservice.lms.address.alias=lms.mockup.com=lms.address.alias
# NOTE: This is a temporary work-around for SEB Restriction API within Open edX SEB integration plugin to
# apply on load-balanced infrastructure or infrastructure that has several layers of cache.
# The reason for this is that the API (Open edX system) internally don't apply a resource-change that is
# done within HTTP API call immediately from an outside perspective.
# After a resource-change on the API is done, the system toggles between the old and the new resource
# while constantly calling GET. This usually happens for about a minute or two then it stabilizes on the new resource
#
# This may source on load-balancing or internally caching on Open edX side.
# To mitigate this effect the SEB Server can be configured to apply a resource-change on the
# API several times in a row to flush as match caches and reach as match as possible server instances.
#
# Since this is a brute-force method to mitigate the problem, this should only be a temporary
# work-around until a better solution on Open edX SEB integration side has been found and applied.
#sebserver.webservice.lms.openedx.seb.restriction.push-count=10
# actuator configuration # actuator configuration
management.server.port=${server.port} management.server.port=${server.port}
management.endpoints.web.base-path=/management management.endpoints.web.base-path=/management