SEBSERV-75 added Moodle course restriction on SEB Server side
This commit is contained in:
parent
cfaaf964fe
commit
532ca816bc
7 changed files with 317 additions and 31 deletions
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* 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.exam;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MoodleSEBRestriction {
|
||||
|
||||
public static final String ATTR_BROWSER_KEYS = "BROWSER_KEYS";
|
||||
public static final String ATTR_CONFIG_KEYS = "CONFIG_KEYS";
|
||||
|
||||
@JsonProperty(ATTR_CONFIG_KEYS)
|
||||
public final Collection<String> configKeys;
|
||||
|
||||
@JsonProperty(ATTR_BROWSER_KEYS)
|
||||
public final Collection<String> browserExamKeys;
|
||||
|
||||
@JsonCreator
|
||||
protected MoodleSEBRestriction(
|
||||
@JsonProperty(ATTR_CONFIG_KEYS) final Collection<String> configKeys,
|
||||
@JsonProperty(ATTR_BROWSER_KEYS) final Collection<String> browserExamKeys) {
|
||||
|
||||
this.configKeys = Utils.immutableCollectionOf(configKeys);
|
||||
this.browserExamKeys = Utils.immutableCollectionOf(browserExamKeys);
|
||||
}
|
||||
|
||||
public Collection<String> getConfigKeys() {
|
||||
return this.configKeys;
|
||||
}
|
||||
|
||||
public Collection<String> getBrowserExamKeys() {
|
||||
return this.browserExamKeys;
|
||||
}
|
||||
|
||||
public static MoodleSEBRestriction from(final SEBRestriction sebRestrictionData) {
|
||||
return new MoodleSEBRestriction(
|
||||
sebRestrictionData.configKeys,
|
||||
sebRestrictionData.browserExamKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("MoodleSEBRestriction [configKeys=");
|
||||
builder.append(this.configKeys);
|
||||
builder.append(", browserExamKeys=");
|
||||
builder.append(this.browserExamKeys);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -173,4 +173,12 @@ public final class SEBRestriction implements Entity {
|
|||
attrs);
|
||||
}
|
||||
|
||||
public static SEBRestriction from(final Long examId, final MoodleSEBRestriction restriction) {
|
||||
return new SEBRestriction(
|
||||
examId,
|
||||
restriction.configKeys,
|
||||
restriction.browserExamKeys,
|
||||
null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -133,7 +133,6 @@ final class OpenEdxLmsAPITemplate implements LmsAPITemplate {
|
|||
|
||||
return this.openEdxCourseRestriction.deleteSEBRestriction(exam.externalId)
|
||||
.map(result -> exam);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* 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.webservice.servicelayer.lms.impl.moodle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.MoodleSEBRestriction;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory.MoodleAPIRestTemplate;
|
||||
|
||||
/** GET:
|
||||
* http://yourmoodle.org/webservice/rest/server.php?wstoken={token}&moodlewsrestformat=json&wsfunction=seb_restriction&courseId=123
|
||||
*
|
||||
* Response (JSON):
|
||||
* {"courseId"="123", "configKeys"=["key1","key2","key3",...], "browserKeys"=["bkey1", "bkey2", "bkey3",...]}
|
||||
*
|
||||
* Set keys:
|
||||
* POST:
|
||||
* http://yourmoodle.org/webservice/rest/server.php?wstoken={token}&moodlewsrestformat=json&wsfunction=seb_restriction&courseId=123&configKey[0]=key1&configKey[1]=key2&browserKey[0]=bkey1&browserKey[1]=bkey2
|
||||
*
|
||||
* Delete all key (and remove restrictions):
|
||||
* POST:
|
||||
* http://yourmoodle.org/webservice/rest/server.php?wstoken={token}&moodlewsrestformat=json&wsfunction=seb_restriction_delete&courseId=123 */
|
||||
public class MoodleCourseRestriction {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MoodleCourseRestriction.class);
|
||||
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION = "seb_restriction";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION_DELETE = "seb_restriction_delete";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_COURSE_ID = "courseId";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_CONFIG_KEY = "configKey";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_BROWSER_KEY = "browserKey";
|
||||
|
||||
private final JSONMapper jsonMapper;
|
||||
private final LmsSetup lmsSetup;
|
||||
private final MoodleRestTemplateFactory moodleRestTemplateFactory;
|
||||
|
||||
private MoodleAPIRestTemplate restTemplate;
|
||||
|
||||
protected MoodleCourseRestriction(
|
||||
final JSONMapper jsonMapper,
|
||||
final LmsSetup lmsSetup,
|
||||
final MoodleRestTemplateFactory moodleRestTemplateFactory) {
|
||||
|
||||
this.jsonMapper = jsonMapper;
|
||||
this.lmsSetup = lmsSetup;
|
||||
this.moodleRestTemplateFactory = moodleRestTemplateFactory;
|
||||
}
|
||||
|
||||
LmsSetupTestResult initAPIAccess() {
|
||||
// TODO test availability
|
||||
return LmsSetupTestResult.ofQuizAccessAPIError("not available yet");
|
||||
}
|
||||
|
||||
Result<MoodleSEBRestriction> getSEBRestriction(final String courseId) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("GET SEB Client restriction on course: {}", courseId);
|
||||
}
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final MoodleAPIRestTemplate template = getRestTemplate()
|
||||
.getOrThrow();
|
||||
|
||||
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add(MOODLE_DEFAULT_COURSE_RESTRICTION_COURSE_ID, courseId);
|
||||
|
||||
final String resultJSON = template.callMoodleAPIFunction(
|
||||
MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION,
|
||||
queryParams,
|
||||
null);
|
||||
|
||||
final MoodleSEBRestriction restrictiondata = this.jsonMapper.readValue(
|
||||
resultJSON,
|
||||
new TypeReference<MoodleSEBRestriction>() {
|
||||
});
|
||||
|
||||
return restrictiondata;
|
||||
});
|
||||
}
|
||||
|
||||
Result<Boolean> putSEBRestriction(
|
||||
final String courseId,
|
||||
final MoodleSEBRestriction restriction) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("PUT SEB Client restriction on course: {} : {}", courseId, restriction);
|
||||
}
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final MoodleAPIRestTemplate template = getRestTemplate()
|
||||
.getOrThrow();
|
||||
|
||||
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add(MOODLE_DEFAULT_COURSE_RESTRICTION_COURSE_ID, courseId);
|
||||
|
||||
final MultiValueMap<String, String> queryAttributes = new LinkedMultiValueMap<>();
|
||||
queryAttributes.addAll(
|
||||
MOODLE_DEFAULT_COURSE_RESTRICTION_CONFIG_KEY,
|
||||
new ArrayList<>(restriction.configKeys));
|
||||
queryAttributes.addAll(
|
||||
MOODLE_DEFAULT_COURSE_RESTRICTION_BROWSER_KEY,
|
||||
new ArrayList<>(restriction.browserExamKeys));
|
||||
|
||||
template.callMoodleAPIFunction(
|
||||
MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION,
|
||||
queryParams,
|
||||
queryAttributes);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Result<Boolean> deleteSEBRestriction(final String courseId) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("DELETE SEB Client restriction on course: {}", courseId);
|
||||
}
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
final MoodleAPIRestTemplate template = getRestTemplate()
|
||||
.getOrThrow();
|
||||
|
||||
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add(MOODLE_DEFAULT_COURSE_RESTRICTION_COURSE_ID, courseId);
|
||||
|
||||
template.callMoodleAPIFunction(
|
||||
MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION_DELETE,
|
||||
queryParams,
|
||||
null);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private Result<MoodleAPIRestTemplate> getRestTemplate() {
|
||||
if (this.restTemplate == null) {
|
||||
final Result<MoodleAPIRestTemplate> templateRequest = this.moodleRestTemplateFactory
|
||||
.createRestTemplate();
|
||||
if (templateRequest.hasError()) {
|
||||
return templateRequest;
|
||||
} else {
|
||||
this.restTemplate = templateRequest.get();
|
||||
}
|
||||
}
|
||||
|
||||
return Result.of(this.restTemplate);
|
||||
}
|
||||
|
||||
}
|
|
@ -12,8 +12,12 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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.MoodleSEBRestriction;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
||||
|
@ -25,15 +29,20 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
|
|||
|
||||
public class MoodleLmsAPITemplate implements LmsAPITemplate {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MoodleLmsAPITemplate.class);
|
||||
|
||||
private final LmsSetup lmsSetup;
|
||||
private final MoodleCourseAccess moodleCourseAccess;
|
||||
private final MoodleCourseRestriction moodleCourseRestriction;
|
||||
|
||||
protected MoodleLmsAPITemplate(
|
||||
final LmsSetup lmsSetup,
|
||||
final MoodleCourseAccess moodleCourseAccess) {
|
||||
final MoodleCourseAccess moodleCourseAccess,
|
||||
final MoodleCourseRestriction moodleCourseRestriction) {
|
||||
|
||||
this.lmsSetup = lmsSetup;
|
||||
this.moodleCourseAccess = moodleCourseAccess;
|
||||
this.moodleCourseRestriction = moodleCourseRestriction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,7 +96,13 @@ public class MoodleLmsAPITemplate implements LmsAPITemplate {
|
|||
|
||||
@Override
|
||||
public Result<SEBRestriction> getSEBClientRestriction(final Exam exam) {
|
||||
return Result.ofError(new UnsupportedOperationException("SEB Restriction API not available yet"));
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Get SEB Client restriction for Exam: {}", exam);
|
||||
}
|
||||
|
||||
return this.moodleCourseRestriction
|
||||
.getSEBRestriction(exam.externalId)
|
||||
.map(restriction -> SEBRestriction.from(exam.id, restriction));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,12 +110,25 @@ public class MoodleLmsAPITemplate implements LmsAPITemplate {
|
|||
final String externalExamId,
|
||||
final SEBRestriction sebRestrictionData) {
|
||||
|
||||
return Result.ofError(new UnsupportedOperationException("SEB Restriction API not available yet"));
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Apply SEB Client restriction: {}", sebRestrictionData);
|
||||
}
|
||||
|
||||
return this.moodleCourseRestriction
|
||||
.putSEBRestriction(
|
||||
externalExamId,
|
||||
MoodleSEBRestriction.from(sebRestrictionData))
|
||||
.map(result -> sebRestrictionData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Exam> releaseSEBClientRestriction(final Exam exam) {
|
||||
return Result.ofError(new UnsupportedOperationException("SEB Restriction API not available yet"));
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Release SEB Client restriction for Exam: {}", exam);
|
||||
}
|
||||
|
||||
return this.moodleCourseRestriction.deleteSEBRestriction(exam.externalId)
|
||||
.map(result -> exam);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,9 +73,15 @@ public class MoodleLmsAPITemplateFactory {
|
|||
moodleRestTemplateFactory,
|
||||
this.asyncService);
|
||||
|
||||
final MoodleCourseRestriction moodleCourseRestriction = new MoodleCourseRestriction(
|
||||
this.jsonMapper,
|
||||
lmsSetup,
|
||||
moodleRestTemplateFactory);
|
||||
|
||||
return new MoodleLmsAPITemplate(
|
||||
lmsSetup,
|
||||
moodleCourseAccess);
|
||||
moodleCourseAccess,
|
||||
moodleCourseRestriction);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -8,21 +8,17 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle;
|
||||
|
||||
import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
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.institution.LmsSetup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
@ -36,16 +32,21 @@ import org.springframework.util.MultiValueMap;
|
|||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
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.institution.LmsSetup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
final class MoodleRestTemplateFactory {
|
||||
|
||||
|
@ -243,12 +244,19 @@ final class MoodleRestTemplateFactory {
|
|||
}
|
||||
|
||||
public String callMoodleAPIFunction(final String functionName) {
|
||||
return callMoodleAPIFunction(functionName, null);
|
||||
return callMoodleAPIFunction(functionName, null, null);
|
||||
}
|
||||
|
||||
public String callMoodleAPIFunction(
|
||||
final String functionName,
|
||||
final MultiValueMap<String, String> queryAttributes) {
|
||||
return callMoodleAPIFunction(functionName, null, queryAttributes);
|
||||
}
|
||||
|
||||
public String callMoodleAPIFunction(
|
||||
final String functionName,
|
||||
final MultiValueMap<String, String> queryParams,
|
||||
final MultiValueMap<String, String> queryAttributes) {
|
||||
|
||||
getAccessToken();
|
||||
|
||||
|
@ -258,6 +266,10 @@ final class MoodleRestTemplateFactory {
|
|||
.queryParam(REST_REQUEST_FUNCTION_NAME, functionName)
|
||||
.queryParam(REST_REQUEST_FORMAT_NAME, "json");
|
||||
|
||||
if (queryParams != null && !queryParams.isEmpty()) {
|
||||
queryParam.queryParams(queryParams);
|
||||
}
|
||||
|
||||
final boolean usePOST = queryAttributes != null && !queryAttributes.isEmpty();
|
||||
HttpEntity<?> functionReqEntity;
|
||||
if (usePOST) {
|
||||
|
|
Loading…
Add table
Reference in a new issue