Skip to content

Commit 7771789

Browse files
committed
SEBSERV-652 fixed by apply proper form URL encoding to Moodle POST body
1 parent a55ad67 commit 7771789

File tree

5 files changed

+24
-69
lines changed

5 files changed

+24
-69
lines changed

src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java

+1
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ public static String toColorFractionString(final int fraction) {
630630

631631
public static String toAppFormUrlEncodedBody(final MultiValueMap<String, String> attributes) {
632632
return toAppFormUrlEncodedBodyForSPService(attributes);
633+
// TODO do it all the same with toAppFormUrlEncodedBody
633634
// if (attributes == null) {
634635
// return StringUtils.EMPTY;
635636
// }

src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,13 @@ static Predicate<QuizData> quizFilterPredicate(final FilterMap filterMap) {
9494
if (filterMap == null) {
9595
return q -> true;
9696
}
97-
9897
final String name = filterMap.getQuizName();
9998
final DateTime from = filterMap.getQuizFromTime();
10099
final DateTime now = DateTime.now(DateTimeZone.UTC);
101-
102100
return q -> {
103101
final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name));
104-
final boolean startTimeFilter = from == null || (q.startTime != null && (q.startTime.isEqual(from) || q.startTime.isAfter(from)));
102+
final boolean startTimeFilter =
103+
from == null || (q.startTime != null && (q.startTime.isEqual(from) || q.startTime.isAfter(from)));
105104
final DateTime endTime = now.isAfter(from) ? now : from;
106105
final boolean fromTimeFilter = (endTime == null || q.endTime == null || endTime.isBefore(q.endTime));
107106
return nameFilter && (startTimeFilter || fromTimeFilter);

src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/QuizLookupServiceImpl.java

+6-9
Original file line numberDiff line numberDiff line change
@@ -152,18 +152,15 @@ private AsyncLookup getAsyncLookup(
152152
final FilterMap filterMap,
153153
final Function<String, Result<LmsAPITemplate>> lmsAPITemplateSupplier) {
154154

155-
// check if there is already a lookup for the user in the cache, if not create one
156155
if (!this.lookups.containsKey(userId)) {
157156
this.createNewAsyncLookup(userId, filterMap, lmsAPITemplateSupplier);
158157
}
159-
160-
// get the users lookup from the cache
158+
161159
final AsyncLookup asyncLookup = this.lookups.get(userId);
162160
if (asyncLookup == null) {
163161
return null;
164162
}
165163

166-
// if the lookup still valid use it otherwise, create new empty one and use this
167164
if (!asyncLookup.isValid(filterMap)) {
168165
final AsyncLookup removed = this.lookups.remove(userId);
169166
if (removed != null) {
@@ -336,9 +333,7 @@ boolean isValid(final FilterMap filterMap) {
336333
return false;
337334
}
338335

339-
boolean valid = this.lookupFilterCriteria.equals(filterMap);
340-
System.out.println("******************** valid: " + valid + " filterMap: " + filterMap);
341-
return valid;
336+
return this.lookupFilterCriteria.equals(filterMap);
342337
}
343338

344339
boolean isRunning() {
@@ -347,15 +342,17 @@ boolean isRunning() {
347342
}
348343
final boolean running = this.asyncBuffers
349344
.stream()
350-
.anyMatch(b -> !b.finished);
345+
.filter(b -> !b.finished)
346+
.findFirst()
347+
.isPresent();
351348
if (!running) {
352349
this.timeCompleted = Utils.getMillisecondsNow();
353350
}
354351
return running;
355352
}
356353

357354
void cancel() {
358-
this.asyncBuffers.forEach(AsyncQuizFetchBuffer::cancel);
355+
this.asyncBuffers.stream().forEach(AsyncQuizFetchBuffer::cancel);
359356
}
360357
}
361358

src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactoryImpl.java

-8
Original file line numberDiff line numberDiff line change
@@ -478,21 +478,13 @@ private String doRequest(
478478
final UriComponentsBuilder queryParam,
479479
final boolean usePOST,
480480
final HttpEntity<?> functionReqEntity) {
481-
482-
if (log.isDebugEnabled()) {
483-
log.debug("*** Call Moodle: {} BODY: {}", queryParam.toUriString(), functionReqEntity.getBody());
484-
}
485481

486482
final ResponseEntity<String> response = super.exchange(
487483
queryParam.toUriString(),
488484
usePOST ? HttpMethod.POST : HttpMethod.GET,
489485
functionReqEntity,
490486
String.class);
491487

492-
if (log.isDebugEnabled()) {
493-
log.debug("*** Moodle Response: {}", response);
494-
}
495-
496488
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
497489
if (response.getStatusCode() != HttpStatus.OK) {
498490
throw new RuntimeException(

src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/plugin/MoodlePluginCourseAccess.java

+15-49
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.ArrayList;
1313
import java.util.Collection;
1414
import java.util.Collections;
15+
import java.util.HashMap;
1516
import java.util.HashSet;
1617
import java.util.Iterator;
1718
import java.util.List;
@@ -57,6 +58,7 @@
5758
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory;
5859
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils;
5960
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils.CourseData;
61+
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils.Courses;
6062
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils.CoursesPlugin;
6163
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleUtils.MoodleUserDetails;
6264
import io.micrometer.core.instrument.util.StringUtils;
@@ -425,26 +427,29 @@ private Collection<CourseData> fetchCoursesPage(
425427
try {
426428
// get course ids per page
427429
final long filterDate = Utils.toUnixTimeInSeconds(quizFromTime);
428-
final long defaultCutOff = Utils.toUnixTimeInSeconds(DateTime.now(DateTimeZone.UTC).minusYears(this.cutoffTimeOffset));
430+
final long defaultCutOff = Utils.toUnixTimeInSeconds(
431+
DateTime.now(DateTimeZone.UTC).minusYears(this.cutoffTimeOffset));
429432
final long cutoffDate = Math.min(filterDate, defaultCutOff);
430-
431-
final String sqlCondition = getSQLCondition(nameCondition, cutoffDate, filterDate);
433+
String sqlCondition = String.format(
434+
SQL_CONDITION_TEMPLATE, cutoffDate, filterDate);
432435
final String fromElement = String.valueOf(page * size);
433436
final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>();
434-
437+
438+
if (this.applyNameCriteria && StringUtils.isNotBlank(nameCondition)) {
439+
final String n = Utils.toSQLWildcard(nameCondition);
440+
sqlCondition = sqlCondition + " AND (" + SQL_QUIZ_NAME + " LIKE '" + n + "' OR " + SQL_COURSE_NAME + " LIKE '" + n + "')";
441+
}
442+
435443
// Note: courseid[]=0 means all courses. Moodle don't like empty parameter
436444
attributes.add(PARAM_COURSE_ID_ARRAY, "0");
437445
attributes.add(PARAM_SQL_CONDITIONS, sqlCondition);
438446
attributes.add(PARAM_PAGE_START, fromElement);
439447
attributes.add(PARAM_PAGE_SIZE, String.valueOf(size));
440448

441449
final String courseKeyPageJSON = this.protectedMoodlePageCall
442-
.protectedRun(() -> getCoursePageFromMoodle(
443-
restTemplate,
444-
attributes,
445-
cutoffDate,
446-
filterDate
447-
))
450+
.protectedRun(() -> restTemplate.callMoodleAPIFunction(
451+
COURSES_API_FUNCTION_NAME,
452+
attributes))
448453
.getOrThrow();
449454

450455
MoodleUtils.checkJSONFormat(courseKeyPageJSON);
@@ -498,45 +503,6 @@ private Collection<CourseData> fetchCoursesPage(
498503
return Collections.emptyList();
499504
}
500505
}
501-
502-
private String getCoursePageFromMoodle(
503-
final MoodleAPIRestTemplate restTemplate,
504-
final LinkedMultiValueMap<String, String> attributes,
505-
final long cutoffDate,
506-
final long filterDate) {
507-
508-
String responseBody = null;
509-
510-
// SEBSERV-652 mitigation (can be removed when Moodle bug is fixed
511-
try {
512-
responseBody = restTemplate.callMoodleAPIFunction(COURSES_API_FUNCTION_NAME, attributes);
513-
} catch (final Exception e) {
514-
responseBody = null;
515-
}
516-
517-
if (responseBody == null) {
518-
519-
log.warn("*** Moodle respond with empty body on request with attributes: {}", attributes);
520-
log.info("*** Apply SEBSERV-652 mitigation...");
521-
522-
attributes.remove(PARAM_SQL_CONDITIONS);
523-
attributes.add(PARAM_SQL_CONDITIONS, getSQLCondition(null, cutoffDate, filterDate));
524-
responseBody = restTemplate.callMoodleAPIFunction(COURSES_API_FUNCTION_NAME, attributes);
525-
}
526-
527-
return responseBody;
528-
}
529-
530-
private String getSQLCondition(final String nameCondition, final long cutoffDate, final long filterDate) {
531-
String sqlCondition = String.format(SQL_CONDITION_TEMPLATE, cutoffDate, filterDate);
532-
533-
if (this.applyNameCriteria && StringUtils.isNotBlank(nameCondition)) {
534-
final String nc = Utils.toSQLWildcard(nameCondition);
535-
sqlCondition = sqlCondition + " AND (" + SQL_QUIZ_NAME + " LIKE '" + nc + "' OR " + SQL_COURSE_NAME + " LIKE '" + nc + "')";
536-
}
537-
538-
return sqlCondition;
539-
}
540506

541507
private List<QuizData> getQuizzesForIds(
542508
final MoodleAPIRestTemplate restTemplate,

0 commit comments

Comments
 (0)