From 99f34176f2e176314741ec11dd720894af8efb52 Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 15 Jul 2020 12:32:26 +0200 Subject: [PATCH] SEBSERV-75 implemented user account display name resolving --- .../model/user/ExamineeAccountDetails.java | 25 +++- .../servicelayer/lms/LmsAPITemplate.java | 19 ++- .../servicelayer/lms/impl/CourseAccess.java | 32 +++++ .../lms/impl/MockupLmsAPITemplate.java | 11 ++ .../lms/impl/edx/OpenEdxLmsAPITemplate.java | 11 ++ .../lms/impl/moodle/MoodleCourseAccess.java | 113 +++++++++++++++++- .../lms/impl/moodle/MoodleLmsAPITemplate.java | 11 ++ .../session/ExamSessionService.java | 6 + .../session/impl/ExamSessionServiceImpl.java | 5 + .../impl/SEBClientConnectionServiceImpl.java | 26 +++- .../resources/config/application.properties | 2 +- 11 files changed, 252 insertions(+), 9 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/ExamineeAccountDetails.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/ExamineeAccountDetails.java index 31b06222..ea1d333d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/ExamineeAccountDetails.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/ExamineeAccountDetails.java @@ -8,15 +8,20 @@ package ch.ethz.seb.sebserver.gbl.model.user; +import java.util.Map; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import ch.ethz.seb.sebserver.gbl.util.Utils; + public class ExamineeAccountDetails { public static final String ATTR_ID = "id"; public static final String ATTR_NAME = "name"; public static final String ATTR_USER_NAME = "username"; public static final String ATTR_EMAIL = "email"; + public static final String ATTR_ADDITIONAL_ATTRIBUTES = "additionalAttributes"; @JsonProperty(ATTR_ID) public final String id; @@ -30,17 +35,22 @@ public class ExamineeAccountDetails { @JsonProperty(ATTR_EMAIL) public final String email; + @JsonProperty(ATTR_ADDITIONAL_ATTRIBUTES) + public final Map additionalAttributes; + @JsonCreator public ExamineeAccountDetails( @JsonProperty(ATTR_ID) final String id, @JsonProperty(ATTR_NAME) final String name, @JsonProperty(ATTR_USER_NAME) final String username, - @JsonProperty(ATTR_EMAIL) final String email) { + @JsonProperty(ATTR_EMAIL) final String email, + @JsonProperty(ATTR_ADDITIONAL_ATTRIBUTES) final Map additionalAttributes) { this.id = id; this.name = name; this.username = username; this.email = email; + this.additionalAttributes = Utils.immutableMapOf(additionalAttributes); } public String getId() { @@ -59,6 +69,17 @@ public class ExamineeAccountDetails { return this.email; } + public Map getAdditionalAttributes() { + return this.additionalAttributes; + } + + public String getDisplayName() { + if (this.name == null) { + return this.id; + } + return (this.name.equals(this.id)) ? this.id : this.name + " (" + this.id + ")"; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -70,6 +91,8 @@ public class ExamineeAccountDetails { builder.append(this.username); builder.append(", email="); builder.append(this.email); + builder.append(", additionalAttributes="); + builder.append(this.additionalAttributes); builder.append("]"); return builder.toString(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java index a7117e1c..713a57ed 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java @@ -25,6 +25,7 @@ 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; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; @@ -105,8 +106,22 @@ public interface LmsAPITemplate { Result getQuizFromCache(String id); - // TODO - //Result getExamineeAccountDetails(String examineeUserId); + /** Convert a an anonymous or temporary user session identifier from SEB Client into a user + * account details. + * + * @param examineeSessionId the user session identifier from SEB Client + * @return a Result refer to the ExamineeAccountDetails instance or to an error when happened or not supported */ + Result getExamineeAccountDetails(String examineeSessionId); + + /** Used to convert an anonymous or temporary user session identifier from SEB Client into a user + * account name for displaying on monitoring page. + * + * If the underling concrete template implementation does not support this user name conversion, + * the given examineeSessionId shall be returned. + * + * @param examineeSessionId the user session identifier from SEB Client + * @return a user account display name if supported or the given examineeSessionId if not. */ + String getExamineeName(String examineeSessionId); /** Used to get a list of chapters (display name and chapter-identifier) that can be used to * apply chapter-based SEB restriction for a specified course. diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java index 9af7d5ec..9640f0c8 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java @@ -9,6 +9,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -23,6 +24,7 @@ import ch.ethz.seb.sebserver.gbl.async.CircuitBreaker; import ch.ethz.seb.sebserver.gbl.async.MemoizingCircuitBreaker; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; @@ -31,6 +33,7 @@ public abstract class CourseAccess { protected final MemoizingCircuitBreaker> allQuizzesRequest; protected final CircuitBreaker chaptersRequest; + protected final CircuitBreaker accountDetailRequest; protected CourseAccess(final AsyncService asyncService) { this.allQuizzesRequest = asyncService.createMemoizingCircuitBreaker( @@ -45,6 +48,11 @@ public abstract class CourseAccess { 3, Constants.MINUTE_IN_MILLIS, Constants.MINUTE_IN_MILLIS); + + this.accountDetailRequest = asyncService.createCircuitBreaker( + 1, + Constants.SECOND_IN_MILLIS * 10, + Constants.SECOND_IN_MILLIS * 10); } public Result getQuizFromCache(final String id) { @@ -88,10 +96,34 @@ public abstract class CourseAccess { .map(LmsAPIService.quizzesFilterFunction(filterMap)); } + public Result getExamineeAccountDetails(final String examineeSessionId) { + return this.accountDetailRequest.protectedRun(accountDetailsSupplier(examineeSessionId)); + } + + public String getExamineeName(final String examineeSessionId) { + return getExamineeAccountDetails(examineeSessionId) + .map(ExamineeAccountDetails::getDisplayName) + .getOr(examineeSessionId); + } + protected Result getCourseChapters(final String courseId) { return this.chaptersRequest.protectedRun(getCourseChaptersSupplier(courseId)); } + /** NOTE: this returns a ExamineeAccountDetails with given examineeSessionId for default. + * Override this if requesting account details is supported for specified LMS access. + * + * @param examineeSessionId + * @return this returns a ExamineeAccountDetails with given examineeSessionId for default */ + protected Supplier accountDetailsSupplier(final String examineeSessionId) { + return () -> new ExamineeAccountDetails( + examineeSessionId, + examineeSessionId, + examineeSessionId, + examineeSessionId, + Collections.emptyMap()); + } + protected abstract Supplier> allQuizzesSupplier(); protected abstract Supplier getCourseChaptersSupplier(final String courseId); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java index ae3cfaeb..35d5c9ec 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java @@ -31,6 +31,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.SEBRestriction; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.WebserviceInfo; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; @@ -183,6 +184,16 @@ final class MockupLmsAPITemplate implements LmsAPITemplate { return Result.ofError(new UnsupportedOperationException()); } + @Override + public Result getExamineeAccountDetails(final String examineeSessionId) { + return Result.ofError(new UnsupportedOperationException()); + } + + @Override + public String getExamineeName(final String examineeSessionId) { + return "--" + " (" + examineeSessionId + ")"; + } + @Override public Result getSEBClientRestriction(final Exam exam) { log.info("Apply SEB Client restriction for Exam: {}", exam); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxLmsAPITemplate.java index 2ee937c8..51814386 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxLmsAPITemplate.java @@ -24,6 +24,7 @@ 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; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; @@ -86,6 +87,16 @@ final class OpenEdxLmsAPITemplate implements LmsAPITemplate { .get()); } + @Override + public Result getExamineeAccountDetails(final String examineeSessionId) { + return this.openEdxCourseAccess.getExamineeAccountDetails(examineeSessionId); + } + + @Override + public String getExamineeName(final String examineeSessionId) { + return this.openEdxCourseAccess.getExamineeName(examineeSessionId); + } + @Override public Result getSEBClientRestriction(final Exam exam) { if (log.isDebugEnabled()) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java index f6f806f0..9d7ceca1 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java @@ -20,6 +20,7 @@ import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -32,6 +33,7 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.CourseAccess; @@ -46,6 +48,7 @@ public class MoodleCourseAccess extends CourseAccess { private static final String MOODLE_QUIZ_START_URL_PATH = "mod/quiz/view.php?id="; private static final String MOODLE_COURSE_API_FUNCTION_NAME = "core_course_get_courses"; + private static final String MOODLE_USER_PROFILE_API_FUNCTION_NAME = "core_user_get_users_by_field"; private static final String MOODLE_QUIZ_API_FUNCTION_NAME = "mod_quiz_get_quizzes_by_courses"; private static final String MOODLE_COURSE_API_COURSE_IDS = "courseids"; @@ -55,6 +58,53 @@ public class MoodleCourseAccess extends CourseAccess { private MoodleAPIRestTemplate restTemplate; + @Override + public Result getExamineeAccountDetails(final String examineeSessionId) { + return Result.tryCatch(() -> { + final MoodleAPIRestTemplate template = getRestTemplate() + .getOrThrow(); + + final MultiValueMap queryAttributes = new LinkedMultiValueMap<>(); + queryAttributes.add("field", "id"); + queryAttributes.add("values[0]", examineeSessionId); + + final String userDetailsJSON = template.callMoodleAPIFunction( + MOODLE_USER_PROFILE_API_FUNCTION_NAME, + queryAttributes); + + final MoodleUserDetails[] userDetails = this.jsonMapper. readValue( + userDetailsJSON, + new TypeReference() { + }); + + if (userDetails == null || userDetails.length <= 0) { + throw new RuntimeException("No user details on Moodle API request"); + } + + final Map additionalAttributes = new HashMap<>(); + additionalAttributes.put("firstname", userDetails[0].firstname); + additionalAttributes.put("lastname", userDetails[0].lastname); + additionalAttributes.put("department", userDetails[0].department); + additionalAttributes.put("firstaccess", String.valueOf(userDetails[0].firstaccess)); + additionalAttributes.put("lastaccess", String.valueOf(userDetails[0].lastaccess)); + additionalAttributes.put("auth", userDetails[0].auth); + additionalAttributes.put("suspended", String.valueOf(userDetails[0].suspended)); + additionalAttributes.put("confirmed", String.valueOf(userDetails[0].confirmed)); + additionalAttributes.put("lang", userDetails[0].lang); + additionalAttributes.put("theme", userDetails[0].theme); + additionalAttributes.put("timezone", userDetails[0].timezone); + additionalAttributes.put("description", userDetails[0].description); + additionalAttributes.put("mailformat", String.valueOf(userDetails[0].mailformat)); + additionalAttributes.put("descriptionformat", String.valueOf(userDetails[0].descriptionformat)); + return new ExamineeAccountDetails( + userDetails[0].id, + userDetails[0].fullname, + userDetails[0].username, + userDetails[0].email, + additionalAttributes); + }); + } + protected MoodleCourseAccess( final JSONMapper jsonMapper, final LmsSetup lmsSetup, @@ -261,7 +311,6 @@ public class MoodleCourseAccess extends CourseAccess { @JsonCreator protected CourseQuizData( @JsonProperty(value = "quizzes") final Collection quizzes) { - this.quizzes = quizzes; } } @@ -291,7 +340,69 @@ public class MoodleCourseAccess extends CourseAccess { this.intro = intro; this.time_limit = time_limit; } + } + @JsonIgnoreProperties(ignoreUnknown = true) + static final class MoodleUserDetails { + final String id; + final String username; + final String firstname; + final String lastname; + final String fullname; + final String email; + final String department; + final Long firstaccess; + final Long lastaccess; + final String auth; + final Boolean suspended; + final Boolean confirmed; + final String lang; + final String theme; + final String timezone; + final String description; + final Integer mailformat; + final Integer descriptionformat; + + @JsonCreator + protected MoodleUserDetails( + @JsonProperty(value = "id") final String id, + @JsonProperty(value = "username") final String username, + @JsonProperty(value = "firstname") final String firstname, + @JsonProperty(value = "lastname") final String lastname, + @JsonProperty(value = "fullname") final String fullname, + @JsonProperty(value = "email") final String email, + @JsonProperty(value = "department") final String department, + @JsonProperty(value = "firstaccess") final Long firstaccess, + @JsonProperty(value = "lastaccess") final Long lastaccess, + @JsonProperty(value = "auth") final String auth, + @JsonProperty(value = "suspended") final Boolean suspended, + @JsonProperty(value = "confirmed") final Boolean confirmed, + @JsonProperty(value = "lang") final String lang, + @JsonProperty(value = "theme") final String theme, + @JsonProperty(value = "timezone") final String timezone, + @JsonProperty(value = "description") final String description, + @JsonProperty(value = "mailformat") final Integer mailformat, + @JsonProperty(value = "descriptionformat") final Integer descriptionformat) { + + this.id = id; + this.username = username; + this.firstname = firstname; + this.lastname = lastname; + this.fullname = fullname; + this.email = email; + this.department = department; + this.firstaccess = firstaccess; + this.lastaccess = lastaccess; + this.auth = auth; + this.suspended = suspended; + this.confirmed = confirmed; + this.lang = lang; + this.theme = theme; + this.timezone = timezone; + this.description = description; + this.mailformat = mailformat; + this.descriptionformat = descriptionformat; + } } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleLmsAPITemplate.java index 7aae8ec6..ed12153b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleLmsAPITemplate.java @@ -18,6 +18,7 @@ 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; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; @@ -74,6 +75,16 @@ public class MoodleLmsAPITemplate implements LmsAPITemplate { .get()); } + @Override + public Result getExamineeAccountDetails(final String examineeSessionId) { + return this.moodleCourseAccess.getExamineeAccountDetails(examineeSessionId); + } + + @Override + public String getExamineeName(final String examineeSessionId) { + return this.moodleCourseAccess.getExamineeName(examineeSessionId); + } + @Override public Result getSEBClientRestriction(final Exam exam) { return Result.ofError(new UnsupportedOperationException("SEB Restriction API not available yet")); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamSessionService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamSessionService.java index cce27c0c..7b70ccb0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamSessionService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/ExamSessionService.java @@ -24,6 +24,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; +import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.ExamSessionCacheService; /** A Service to handle running exam sessions */ @@ -49,6 +50,11 @@ public interface ExamSessionService { * @return the underling CacheManager */ CacheManager getCacheManager(); + /** Get the underling LmsAPIService + * + * @return the underling LmsAPIService */ + LmsAPIService getLmsAPIService(); + /** Use this to check the consistency of a running Exam. * Current consistency checks are: * - Check if there is at least one Exam supporter attached to the Exam diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java index 66babe9c..470a7554 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java @@ -100,6 +100,11 @@ public class ExamSessionServiceImpl implements ExamSessionService { return this.cacheManager; } + @Override + public LmsAPIService getLmsAPIService() { + return this.lmsAPIService; + } + @Override public Result> checkRunningExamConsistency(final Long examId) { return Result.tryCatch(() -> { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java index 47a13ef4..71583eeb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java @@ -265,7 +265,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic ClientConnection clientConnection = getClientConnection(connectionToken); checkInstitutionalIntegrity(institutionId, clientConnection); checkExamIntegrity(examId, clientConnection); - clientConnection = updateUserSessionId(userSessionId, clientConnection); + clientConnection = updateUserSessionId(userSessionId, clientConnection, examId); // connection integrity check if (clientConnection.status == ConnectionStatus.CONNECTION_REQUESTED) { @@ -292,7 +292,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic (examId != null) ? examId : clientConnection.examId, ConnectionStatus.ACTIVE, null, - userSessionId, + clientConnection.userSessionId, null, virtualClientAddress, null); @@ -564,7 +564,11 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic checkExamRunning(examId); } - private ClientConnection updateUserSessionId(final String userSessionId, ClientConnection clientConnection) { + private ClientConnection updateUserSessionId( + final String userSessionId, + ClientConnection clientConnection, + final Long examId) { + if (StringUtils.isNoneBlank(userSessionId)) { if (StringUtils.isNoneBlank(clientConnection.userSessionId)) { log.error( @@ -574,6 +578,20 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic "ClientConnection integrity violation: clientConnection has already a userSessionId"); } + // try to get user account display name + String accountId = userSessionId; + try { + accountId = this.examSessionService + .getRunningExam((clientConnection.examId != null) + ? clientConnection.examId + : examId) + .flatMap(exam -> this.examSessionService.getLmsAPIService().getLmsAPITemplate(exam.lmsSetupId)) + .map(template -> template.getExamineeName(userSessionId)) + .getOr(userSessionId); + } catch (final Exception e) { + log.warn("Unexpected error while trying to get user account display name: {}", e.getMessage()); + } + // create new ClientConnection for update final ClientConnection authenticatedClientConnection = new ClientConnection( clientConnection.id, @@ -581,7 +599,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic null, ConnectionStatus.AUTHENTICATED, null, - userSessionId, + accountId, null, null, null); diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties index dc986cfb..be6a3135 100644 --- a/src/main/resources/config/application.properties +++ b/src/main/resources/config/application.properties @@ -1,6 +1,6 @@ spring.application.name=SEB Server spring.profiles.active=ws,gui,dev -sebserver.version=1.0.1 +sebserver.version=@sebserver-version@ ########################################################## ### Global Server Settings