SEBSERV-301 adapted to Moodle plugin

This commit is contained in:
anhefti 2023-01-25 09:04:35 +01:00
parent 574c397a54
commit 4888b4596c
13 changed files with 118 additions and 45 deletions

View file

@ -61,7 +61,7 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
@Override @Override
public Result<CharSequence> getPlainClientSecret(final ClientCredentials credentials) { public Result<CharSequence> getPlainClientSecret(final ClientCredentials credentials) {
if (credentials == null || !credentials.hasSecret()) { if (credentials == null || !credentials.hasSecret()) {
return null; return Result.ofRuntimeError("ClientCredentials has no secret");
} }
return this.cryptor.decrypt(credentials.secret); return this.cryptor.decrypt(credentials.secret);

View file

@ -658,7 +658,7 @@ public final class Utils {
(sb, entry) -> { (sb, entry) -> {
final String name = entry.getKey(); final String name = entry.getKey();
final List<String> values = entry.getValue(); final List<String> values = entry.getValue();
if (values == null || values.isEmpty()) { if (values == null) {
return sb; return sb;
} }
if (sb.length() > 0) { if (sb.length() > 0) {

View file

@ -76,6 +76,8 @@ public class LmsSetupForm implements TemplateComposer {
new LocTextKey("sebserver.lmssetup.form.secret.lms"); new LocTextKey("sebserver.lmssetup.form.secret.lms");
private static final LocTextKey FORM_CLIENTNAME_LMS_TEXT_KEY = private static final LocTextKey FORM_CLIENTNAME_LMS_TEXT_KEY =
new LocTextKey("sebserver.lmssetup.form.clientname.lms"); new LocTextKey("sebserver.lmssetup.form.clientname.lms");
private static final LocTextKey FORM_TOKEN_LMS_TEXT_KEY =
new LocTextKey("sebserver.lmssetup.form.accesstoken.lms");
private static final LocTextKey FORM_URL_TEXT_KEY = private static final LocTextKey FORM_URL_TEXT_KEY =
new LocTextKey("sebserver.lmssetup.form.url"); new LocTextKey("sebserver.lmssetup.form.url");
private static final LocTextKey FORM_TYPE_TEXT_KEY = private static final LocTextKey FORM_TYPE_TEXT_KEY =
@ -227,6 +229,13 @@ public class LmsSetupForm implements TemplateComposer {
.asPasswordField() .asPasswordField()
.mandatory(!readonly)) .mandatory(!readonly))
.addFieldIf(
isEdit,
() -> FormBuilder.text(
Domain.LMS_SETUP.ATTR_LMS_REST_API_TOKEN,
FORM_TOKEN_LMS_TEXT_KEY)
.mandatory(!readonly))
.addFieldIf( .addFieldIf(
isEdit, isEdit,
() -> FormBuilder.checkbox( () -> FormBuilder.checkbox(

View file

@ -178,7 +178,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
final ClientCredentials proxyCredentials = createProxyClientCredentials(lmsSetup); final ClientCredentials proxyCredentials = createProxyClientCredentials(lmsSetup);
final LmsSetupRecord newRecord = new LmsSetupRecord( final LmsSetupRecord newRecord = new LmsSetupRecord(
lmsSetup.id, lmsSetup.id,
null, lmsSetup.institutionId,
lmsSetup.name, lmsSetup.name,
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null, (lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
lmsSetup.lmsApiUrl, lmsSetup.lmsApiUrl,
@ -196,7 +196,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
System.currentTimeMillis(), System.currentTimeMillis(),
savedRecord.getActive()); savedRecord.getActive());
this.lmsSetupRecordMapper.updateByPrimaryKeySelective(newRecord); this.lmsSetupRecordMapper.updateByPrimaryKey(newRecord);
return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id); return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id);
}) })
.flatMap(this::toDomainModel) .flatMap(this::toDomainModel)

View file

@ -14,16 +14,34 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier;
/** Defines a MoodleAPIRestTemplate factory for moodle */
public interface MoodleRestTemplateFactory { public interface MoodleRestTemplateFactory {
/** Use this to test the LMSSetup input for MoodleAPIRestTemplate
*
* @return LmsSetupTestResult containing the result of the test */
LmsSetupTestResult test(); LmsSetupTestResult test();
/** Get the LMSSetup data supplier for this factory.
*
* @return APITemplateDataSupplier */
APITemplateDataSupplier getApiTemplateDataSupplier(); APITemplateDataSupplier getApiTemplateDataSupplier();
/** Get all known, defined API access token request paths.
*
* @return Set of known and configured API access token paths */
Set<String> getKnownTokenAccessPaths(); Set<String> getKnownTokenAccessPaths();
/** Creates a MoodleAPIRestTemplate for the bundled LMSSetup of this factory.
*
* @return Result refer to the MoodleAPIRestTemplate or to an error when happened */
Result<MoodleAPIRestTemplate> createRestTemplate(); Result<MoodleAPIRestTemplate> createRestTemplate();
/** Creates a MoodleAPIRestTemplate for the bundled LMSSetup of this factory.
* Uses specified access token request path to request an access token.
*
* @param accessTokenPath access token request path to request an access token
* @return Result refer to the MoodleAPIRestTemplate or to an error when happened */
Result<MoodleAPIRestTemplate> createRestTemplate(final String accessTokenPath); Result<MoodleAPIRestTemplate> createRestTemplate(final String accessTokenPath);
} }

View file

@ -114,6 +114,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
} }
if (StringUtils.isBlank(lmsSetup.lmsRestApiToken)) { if (StringUtils.isBlank(lmsSetup.lmsRestApiToken)) {
if (!credentials.hasAccessToken()) {
if (!credentials.hasClientId()) { if (!credentials.hasClientId()) {
missingAttrs.add(APIMessage.fieldValidationError( missingAttrs.add(APIMessage.fieldValidationError(
LMS_SETUP.ATTR_LMS_CLIENTNAME, LMS_SETUP.ATTR_LMS_CLIENTNAME,
@ -125,6 +126,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
"lmsSetup:lmsClientsecret:notNull")); "lmsSetup:lmsClientsecret:notNull"));
} }
} }
}
if (!missingAttrs.isEmpty()) { if (!missingAttrs.isEmpty()) {
return LmsSetupTestResult.ofMissingAttributes(LmsType.MOODLE, missingAttrs); return LmsSetupTestResult.ofMissingAttributes(LmsType.MOODLE, missingAttrs);
@ -170,14 +172,17 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
final CharSequence plainClientId = credentials.clientId; final CharSequence plainClientId = credentials.clientId;
final CharSequence plainClientSecret = this.clientCredentialService final CharSequence plainClientSecret = this.clientCredentialService
.getPlainClientSecret(credentials) .getPlainClientSecret(credentials)
.getOrThrow(); .getOr(StringUtils.EMPTY);
final CharSequence plainAPIToken = this.clientCredentialService
.getPlainAccessToken(credentials)
.getOr(StringUtils.EMPTY);
final MoodleAPIRestTemplateImpl restTemplate = new MoodleAPIRestTemplateImpl( final MoodleAPIRestTemplateImpl restTemplate = new MoodleAPIRestTemplateImpl(
this.jsonMapper, this.jsonMapper,
this.apiTemplateDataSupplier, this.apiTemplateDataSupplier,
lmsSetup.lmsApiUrl, lmsSetup.lmsApiUrl,
accessTokenPath, accessTokenPath,
lmsSetup.lmsRestApiToken, plainAPIToken,
plainClientId, plainClientId,
plainClientSecret); plainClientSecret);
@ -200,6 +205,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
public static class MoodleAPIRestTemplateImpl extends RestTemplate implements MoodleAPIRestTemplate { public static class MoodleAPIRestTemplateImpl extends RestTemplate implements MoodleAPIRestTemplate {
private static final String MOODLE_MOBILE_APP_SERVICE = "moodle_mobile_app";
private static final String REST_API_TEST_FUNCTION = "core_webservice_get_site_info"; private static final String REST_API_TEST_FUNCTION = "core_webservice_get_site_info";
final JSONMapper jsonMapper; final JSONMapper jsonMapper;
@ -208,6 +214,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
private final String serverURL; private final String serverURL;
private final String tokenPath; private final String tokenPath;
private final CharSequence apiToken;
private CharSequence accessToken; private CharSequence accessToken;
private final Map<String, String> tokenReqURIVars; private final Map<String, String> tokenReqURIVars;
@ -218,7 +225,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
final APITemplateDataSupplier apiTemplateDataSupplier, final APITemplateDataSupplier apiTemplateDataSupplier,
final String serverURL, final String serverURL,
final String tokenPath, final String tokenPath,
final CharSequence accessToken, final CharSequence apiToken,
final CharSequence username, final CharSequence username,
final CharSequence password) { final CharSequence password) {
@ -227,12 +234,13 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
this.serverURL = serverURL; this.serverURL = serverURL;
this.tokenPath = tokenPath; this.tokenPath = tokenPath;
this.accessToken = StringUtils.isNotBlank(accessToken) ? accessToken : null; this.apiToken = apiToken;
this.accessToken = StringUtils.isNotBlank(apiToken) ? apiToken : null;
this.tokenReqURIVars = new HashMap<>(); this.tokenReqURIVars = new HashMap<>();
this.tokenReqURIVars.put(URI_VAR_USER_NAME, String.valueOf(username)); this.tokenReqURIVars.put(URI_VAR_USER_NAME, String.valueOf(username));
this.tokenReqURIVars.put(URI_VAR_PASSWORD, String.valueOf(password)); this.tokenReqURIVars.put(URI_VAR_PASSWORD, String.valueOf(password));
this.tokenReqURIVars.put(URI_VAR_SERVICE, "moodle_mobile_app"); this.tokenReqURIVars.put(URI_VAR_SERVICE, MOODLE_MOBILE_APP_SERVICE);
} }
@ -336,6 +344,8 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
functionReqEntity, functionReqEntity,
String.class); String.class);
System.out.println("*************** response: " + response);
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup(); final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
if (response.getStatusCode() != HttpStatus.OK) { if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException( throw new RuntimeException(
@ -362,6 +372,11 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
private void requestAccessToken() { private void requestAccessToken() {
if (StringUtils.isNotBlank(this.apiToken)) {
this.accessToken = this.apiToken;
return;
}
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup(); final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
try { try {

View file

@ -75,13 +75,14 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
public static final String ATTR_ID = "id"; public static final String ATTR_ID = "id";
public static final String ATTR_SHORTNAME = "shortname"; public static final String ATTR_SHORTNAME = "shortname";
public static final String PARAM_COURSE_ID = "courseid"; public static final String PARAM_COURSE_ID_ARRAY = "courseid[]";
public static final String PARAM_SQL_CONDITIONS = "conditions"; public static final String PARAM_SQL_CONDITIONS = "conditions";
public static final String PARAM_PAGE_START = "startneedle"; public static final String PARAM_PAGE_START = "startneedle";
public static final String PARAM_PAGE_SIZE = "perpage"; public static final String PARAM_PAGE_SIZE = "perpage";
public static final String SQL_CONDITION_TEMPLATE = public static final String SQL_CONDITION_TEMPLATE =
"(startdate >= %s or timecreated >=%s) and (enddate is null or enddate is 0 or enddate is >= %s)"; //"(startdate >= %s or timecreated >=%s) and (enddate is null or enddate = 0 or enddate >= %s)";
"(startdate is null OR startdate = 0 OR startdate >= %s) AND (enddate is null or enddate = 0 OR enddate >= %s)";
private final JSONMapper jsonMapper; private final JSONMapper jsonMapper;
private final MoodleRestTemplateFactory restTemplateFactory; private final MoodleRestTemplateFactory restTemplateFactory;
@ -423,10 +424,12 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
final String sqlCondition = String.format( final String sqlCondition = String.format(
SQL_CONDITION_TEMPLATE, SQL_CONDITION_TEMPLATE,
String.valueOf(cutoffDate), String.valueOf(cutoffDate),
String.valueOf(cutoffDate),
String.valueOf(filterDate)); String.valueOf(filterDate));
final String fromElement = String.valueOf(page * size); final String fromElement = String.valueOf(page * size);
final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>(); final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>();
// Note: courseid[]=0 means all courses. Moodle don't like empty parameter
attributes.add(PARAM_COURSE_ID_ARRAY, "0");
attributes.add(PARAM_SQL_CONDITIONS, sqlCondition); attributes.add(PARAM_SQL_CONDITIONS, sqlCondition);
attributes.add(PARAM_PAGE_START, fromElement); attributes.add(PARAM_PAGE_START, fromElement);
attributes.add(PARAM_PAGE_SIZE, String.valueOf(size)); attributes.add(PARAM_PAGE_SIZE, String.valueOf(size));
@ -526,7 +529,7 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
} }
final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>(); final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>();
attributes.put(PARAM_COURSE_ID, new ArrayList<>(courseIds)); attributes.put(PARAM_COURSE_ID_ARRAY, new ArrayList<>(courseIds));
final String coursePageJSON = restTemplate.callMoodleAPIFunction( final String coursePageJSON = restTemplate.callMoodleAPIFunction(
COURSES_API_FUNCTION_NAME, COURSES_API_FUNCTION_NAME,
attributes); attributes);
@ -560,7 +563,9 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
if (templateRequest.hasError()) { if (templateRequest.hasError()) {
return templateRequest; return templateRequest;
} else { } else {
this.restTemplate = templateRequest.get(); final MoodleAPIRestTemplate moodleAPIRestTemplate = templateRequest.get();
moodleAPIRestTemplate.setService(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME);
this.restTemplate = moodleAPIRestTemplate;
} }
} }

View file

@ -43,11 +43,14 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
public static final String RESTRICTION_GET_FUNCTION_NAME = "quizaccess_sebserver_get_restriction"; public static final String RESTRICTION_GET_FUNCTION_NAME = "quizaccess_sebserver_get_restriction";
public static final String RESTRICTION_SET_FUNCTION_NAME = "quizaccess_sebserver_set_restriction"; public static final String RESTRICTION_SET_FUNCTION_NAME = "quizaccess_sebserver_set_restriction";
public static final String ATTRIBUTE_QUIZ_ID = "quiz_id"; public static final String ATTRIBUTE_QUIZ_ID = "quizid";
public static final String ATTRIBUTE_CONFIG_KEYS = "config_keys"; public static final String ATTRIBUTE_CONFIG_KEYS = "configkeys[]";
public static final String ATTRIBUTE_BROWSER_EXAM_KEYS = "browser_exam_keys"; public static final String ATTRIBUTE_BROWSER_EXAM_KEYS = "browserkeys[]";
public static final String ATTRIBUTE_QUIT_URL = "quit_link"; public static final String ATTRIBUTE_QUIT_URL = "quitlink";
public static final String ATTRIBUTE_QUIT_SECRET = "quit_secret"; public static final String ATTRIBUTE_QUIT_SECRET = "quitsecret";
private static final String NO_RESTRICTION_SET_WARNING = "error/SEB Server is not enabled";
private static final String DELETED_RESTRICTION_WARNING = "You have deleted restriction";
private final JSONMapper jsonMapper; private final JSONMapper jsonMapper;
private final MoodleRestTemplateFactory restTemplateFactory; private final MoodleRestTemplateFactory restTemplateFactory;
@ -168,18 +171,20 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
final LinkedMultiValueMap<String, String> addQuery = new LinkedMultiValueMap<>(); final LinkedMultiValueMap<String, String> addQuery = new LinkedMultiValueMap<>();
addQuery.add(ATTRIBUTE_QUIZ_ID, quizId); addQuery.add(ATTRIBUTE_QUIZ_ID, quizId);
final String quitLink = this.examConfigurationValueService.getQuitLink(exam.id);
final String quitSecret = this.examConfigurationValueService.getQuitSecret(exam.id);
final LinkedMultiValueMap<String, String> queryAttributes = new LinkedMultiValueMap<>(); final LinkedMultiValueMap<String, String> queryAttributes = new LinkedMultiValueMap<>();
queryAttributes.add(ATTRIBUTE_QUIT_URL, quitLink);
queryAttributes.add(ATTRIBUTE_QUIT_SECRET, quitSecret);
restTemplate.callMoodleAPIFunction( queryAttributes.add(ATTRIBUTE_CONFIG_KEYS, StringUtils.EMPTY);
queryAttributes.add(ATTRIBUTE_BROWSER_EXAM_KEYS, StringUtils.EMPTY);
final String srJSON = restTemplate.callMoodleAPIFunction(
RESTRICTION_SET_FUNCTION_NAME, RESTRICTION_SET_FUNCTION_NAME,
addQuery, addQuery,
queryAttributes); queryAttributes);
if (!srJSON.contains(DELETED_RESTRICTION_WARNING)) {
log.warn("Release SEB restriction seems to failed. Moodle response: {}", srJSON);
}
return exam; return exam;
}); });
} }
@ -187,6 +192,7 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
private SEBRestriction restrictionFromJson(final Exam exam, final String srJSON) { private SEBRestriction restrictionFromJson(final Exam exam, final String srJSON) {
try { try {
// check blank result
if (StringUtils.isBlank(srJSON)) { if (StringUtils.isBlank(srJSON)) {
return new SEBRestriction( return new SEBRestriction(
exam.id, exam.id,
@ -195,6 +201,20 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
Collections.emptyMap()); Collections.emptyMap());
} }
// check no restriction set
if (srJSON.contains(NO_RESTRICTION_SET_WARNING)) {
if (log.isDebugEnabled()) {
log.debug("No restriction set for exam: {}", exam);
}
return new SEBRestriction(
exam.id,
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyMap());
}
// fist try to get from multiple data // fist try to get from multiple data
final MoodleQuizRestrictions moodleRestrictions = this.jsonMapper.readValue( final MoodleQuizRestrictions moodleRestrictions = this.jsonMapper.readValue(
srJSON, srJSON,
@ -262,7 +282,9 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
if (templateRequest.hasError()) { if (templateRequest.hasError()) {
return templateRequest; return templateRequest;
} else { } else {
this.restTemplate = templateRequest.get(); final MoodleAPIRestTemplate moodleAPIRestTemplate = templateRequest.get();
moodleAPIRestTemplate.setService(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME);
this.restTemplate = moodleAPIRestTemplate;
} }
} }

View file

@ -36,6 +36,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestT
@WebServiceProfile @WebServiceProfile
public class MooldePluginLmsAPITemplateFactory implements LmsAPITemplateFactory { public class MooldePluginLmsAPITemplateFactory implements LmsAPITemplateFactory {
public static final String SEB_SERVER_SERVICE_NAME = "seb-server-service";
private final JSONMapper jsonMapper; private final JSONMapper jsonMapper;
private final CacheManager cacheManager; private final CacheManager cacheManager;
private final AsyncService asyncService; private final AsyncService asyncService;

View file

@ -390,6 +390,8 @@ sebserver.lmssetup.form.clientname.lms=LMS Server Username
sebserver.lmssetup.form.clientname.lms.tooltip=The client name of the API client access to the LMS<br/><br/>This is usually provided by an LMS administrator that has created a API access account for SEB Server binding within the LMS server. sebserver.lmssetup.form.clientname.lms.tooltip=The client name of the API client access to the LMS<br/><br/>This is usually provided by an LMS administrator that has created a API access account for SEB Server binding within the LMS server.
sebserver.lmssetup.form.secret.lms=LMS Server Password sebserver.lmssetup.form.secret.lms=LMS Server Password
sebserver.lmssetup.form.secret.lms.tooltip=The secret or password of the API client access to the LMS<br/><br/>This is usually provided by an LMS administrator that has created a API access account for SEB Server binding within the LMS server. sebserver.lmssetup.form.secret.lms.tooltip=The secret or password of the API client access to the LMS<br/><br/>This is usually provided by an LMS administrator that has created a API access account for SEB Server binding within the LMS server.
sebserver.lmssetup.form.accesstoken.lms=Access Token
sebserver.lmssetup.form.accesstoken.lms.tooltip=The Access Token for the LMS API if LMS supports access token
sebserver.lmssetup.form.proxy=Proxy sebserver.lmssetup.form.proxy=Proxy
sebserver.lmssetup.form.proxy.check=With Proxy sebserver.lmssetup.form.proxy.check=With Proxy
sebserver.lmssetup.form.proxy.check.tooltip=Check and give detailed information if the SEB Server runs behind a proxy<br/>and need proxy settings to connect to the internet sebserver.lmssetup.form.proxy.check.tooltip=Check and give detailed information if the SEB Server runs behind a proxy<br/>and need proxy settings to connect to the internet

View file

@ -35,7 +35,6 @@ public class AsyncBlockingTest {
final Collection<Future<String>> features = new ArrayList<>(); final Collection<Future<String>> features = new ArrayList<>();
for (int i = 0; i < TASKS; i++) { for (int i = 0; i < TASKS; i++) {
final Future<String> runAsync = this.asyncRunner.runAsync(this::doAsync); final Future<String> runAsync = this.asyncRunner.runAsync(this::doAsync);
//System.out.println("*********** run async: " + i);
features.add(runAsync); features.add(runAsync);
} }
assertEquals(TASKS, features.size()); assertEquals(TASKS, features.size());

View file

@ -248,11 +248,12 @@ public class MoodleMockupRestTemplateFactory implements MoodleRestTemplateFactor
private String respondCourses(final MultiValueMap<String, String> queryAttributes) { private String respondCourses(final MultiValueMap<String, String> queryAttributes) {
try { try {
final List<String> ids = queryAttributes.get(MoodlePluginCourseAccess.PARAM_COURSE_ID); final List<String> ids = queryAttributes.get(MoodlePluginCourseAccess.PARAM_COURSE_ID_ARRAY);
final String from = queryAttributes.getFirst(MoodlePluginCourseAccess.PARAM_PAGE_START); final String from = queryAttributes.getFirst(MoodlePluginCourseAccess.PARAM_PAGE_START);
final String size = queryAttributes.getFirst(MoodlePluginCourseAccess.PARAM_PAGE_SIZE); final String size = queryAttributes.getFirst(MoodlePluginCourseAccess.PARAM_PAGE_SIZE);
final List<MockCD> courses; final List<MockCD> courses;
if (ids != null && !ids.isEmpty()) {
if (ids != null && !ids.isEmpty() && !ids.get(0).equals("0")) {
courses = this.courses.stream().filter(c -> ids.contains(c.id)).collect(Collectors.toList()); courses = this.courses.stream().filter(c -> ids.contains(c.id)).collect(Collectors.toList());
} else if (from != null && Integer.valueOf(from) < this.courses.size()) { } else if (from != null && Integer.valueOf(from) < this.courses.size()) {

View file

@ -84,8 +84,8 @@ public class MoodlePluginCourseAccessTest {
+ "callMoodleAPIFunction: quizaccess_sebserver_get_exams, " + "callMoodleAPIFunction: quizaccess_sebserver_get_exams, "
+ "callMoodleAPIFunction: quizaccess_sebserver_get_exams], " + "callMoodleAPIFunction: quizaccess_sebserver_get_exams], "
+ "callLog=[" + "callLog=["
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=0&perpage=500,[Content-Type:\"application/x-www-form-urlencoded\"]>, " + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=0&perpage=500,[Content-Type:\"application/x-www-form-urlencoded\"]>, "
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=500&perpage=500,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]", + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=500&perpage=500,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]",
candidate.toTestString()); candidate.toTestString());
final List<String> ids = final List<String> ids =
@ -152,11 +152,11 @@ public class MoodlePluginCourseAccessTest {
+ "callMoodleAPIFunction: quizaccess_sebserver_get_exams, " + "callMoodleAPIFunction: quizaccess_sebserver_get_exams, "
+ "callMoodleAPIFunction: quizaccess_sebserver_get_exams], " + "callMoodleAPIFunction: quizaccess_sebserver_get_exams], "
+ "callLog=[" + "callLog=["
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=0&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, " + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=0&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, "
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=5&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, " + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=5&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, "
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=10&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, " + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=10&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, "
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=15&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, " + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=15&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>, "
+ "<conditions=(startdate >= -94694400 or timecreated >=-94694400) and (enddate is null or enddate is 0 or enddate is >= -94694400)&startneedle=20&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]", + "<courseid[]=0&conditions=(startdate is null OR startdate = 0 OR startdate >= -94694400) AND (enddate is null or enddate = 0 OR enddate >= -94694400)&startneedle=20&perpage=5,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]",
candidate.toTestString()); candidate.toTestString());
final List<String> ids = final List<String> ids =