Skip to content

Commit

Permalink
SEBSERV-586 and SEBSERV-590
Browse files Browse the repository at this point in the history
  • Loading branch information
anhefti committed Sep 24, 2024
1 parent d34b3e4 commit e3b73e1
Show file tree
Hide file tree
Showing 18 changed files with 180 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import ch.ethz.seb.sebserver.gbl.model.user.TokenLoginInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.FullLmsIntegrationService;

/** Service used to maintain Teacher Ad-Hoc Accounts */
public interface TeacherAccountService {
Expand Down Expand Up @@ -67,9 +66,14 @@ Result<String> getOneTimeTokenForTeacherAccount(

/** Used to verify a given One Time Access JWT Token. This must have the expected claims and must not be expired
*
*
* @param token The One Time Access JWT Token to verify access for
* @return Result refer to the login information for auto-login or to an error when happened or access is denied
*/
Result<TokenLoginInfo> verifyOneTimeTokenForTeacherAccount(String token);

/** Deletes all ad hoc teacher user from a particular LMS.
* @param lmsId The LMS identifier
*/
void deleteAllFromLMS(Long lmsId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AdHocAccountData;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.TeacherAccountService;
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.dao.UserDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ScreenProctoringService;
import ch.ethz.seb.sebserver.webservice.weblayer.oauth.AdminAPIClientDetails;
Expand Down Expand Up @@ -183,6 +184,13 @@ public Result<TokenLoginInfo> verifyOneTimeTokenForTeacherAccount(final String l
});
}

@Override
public void deleteAllFromLMS(final Long lmsId) {
userDAO
.deleteAdHocAccountsForLMS(AD_HOC_TEACHER_ID_PREFIX, lmsId)
.onError(error -> log.error("Failed to delete all teacher accounts for LMS with id: {}", lmsId, error));
}

private UserInfo handleAccountDoesNotExistYet(
final boolean createIfNotExists,
final Exam exam,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,20 @@ Result<Collection<Exam>> getExamsForStatus(
* @return Result refer to all exams for LMS update or to an error when happened */
Result<Collection<Exam>> allForLMSUpdate();

/** Gets all Exams of all active LMS Setups form a given LMS Setup Id list.
*
* @param lmsId List of LMS Setup ids
* @return Result refer to all Exams of all active LMS Setups form a given LMS Setup Id list or to an error when happened
*/
Result<Collection<Exam>> allActiveForLMSSetup(Collection<Long> lmsId);

/** Get all Exams form LMS Setup with a given id.
*
* @param lmsSetupId The LMS Setup id
* @return Result refer to all Exam if the LMS Setup or to an error when happened
*/
Result<Collection<Exam>> allForLMSSetup(Long lmsSetupId);

/** This is used to get all Exams that potentially needs a state change.
* Checks if the stored running time frame of the exam is not in sync with the current state and return
* all exams for this is the case.
Expand Down Expand Up @@ -250,5 +262,4 @@ default Result<Exam> releaseLock(final Exam exam, final String updateId) {

void updateQuitPassword(Exam exam, String quitPassword);


}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ public interface UserDAO extends ActivatableEntityDAO<UserInfo, UserMod>, BulkAc
* @return a Collection containing EntityKey's of all entities that belongs to a given User */
Collection<EntityKey> getAllUserRelatedData(String uuid);

Result<Collection<EntityKey>> deleteAdHocAccountsForLMS(String adHocTeacherIdPrefix, Long lmsSetupId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,21 @@ public Result<Collection<Exam>> allActiveForLMSSetup(final Collection<Long> lmsI
}).flatMap(this::toDomainModel);
}

@Override
@Transactional(readOnly = true)
public Result<Collection<Exam>> allForLMSSetup(final Long lmsSetupId) {
return Result.tryCatch(() -> this.examRecordMapper.selectByExample()
.where(
ExamRecordDynamicSqlSupport.lmsSetupId,
isNotNull())
.and(
ExamRecordDynamicSqlSupport.status,
isNotEqualTo(ExamStatus.ARCHIVED.name()))
.build()
.execute())
.flatMap(this::toDomainModel);
}

@Override
public Result<Collection<Exam>> allThatNeedsStatusUpdate(final long leadTime, final long followupTime) {
return this.examRecordDAO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,22 @@ public Collection<EntityKey> getAllUserRelatedData(final String uuid) {
return Collections.emptyList();
}

@Override
public Result<Collection<EntityKey>> deleteAdHocAccountsForLMS(
final String adHocTeacherIdPrefix,
final Long lmsSetupId) {

return Result.tryCatch(() ->this.userRecordMapper.selectByExample()
.where(uuid, isLike(adHocTeacherIdPrefix + Constants.PERCENTAGE))
.build()
.execute()
.stream()
.map(record -> new EntityKey(record.getUuid(), EntityType.USER))
.collect(Collectors.toSet())
)
.flatMap(this::delete);
}

@Override
@Transactional(readOnly = true)
public Set<EntityDependency> getDependencies(final BulkAction bulkAction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@

import ch.ethz.seb.sebserver.gbl.model.exam.*;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.*;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamArchivedEvent;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -50,6 +52,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
private final LmsAPIService lmsAPIService;
private final ExamConfigurationValueService examConfigurationValueService;
private final SEBRestrictionService sebRestrictionService;
private final ApplicationEventPublisher applicationEventPublisher;

protected ExamAdminServiceImpl(
final ExamDAO examDAO,
Expand All @@ -59,7 +62,8 @@ protected ExamAdminServiceImpl(
final ExamConfigurationMapDAO examConfigurationMapDAO,
final LmsAPIService lmsAPIService,
final ExamConfigurationValueService examConfigurationValueService,
final SEBRestrictionService sebRestrictionService) {
final SEBRestrictionService sebRestrictionService,
final ApplicationEventPublisher applicationEventPublisher) {

this.examDAO = examDAO;
this.proctoringAdminService = proctoringAdminService;
Expand All @@ -69,6 +73,7 @@ protected ExamAdminServiceImpl(
this.lmsAPIService = lmsAPIService;
this.examConfigurationValueService = examConfigurationValueService;
this.sebRestrictionService = sebRestrictionService;
this.applicationEventPublisher = applicationEventPublisher;
}

@Override
Expand Down Expand Up @@ -287,7 +292,6 @@ public Result<Exam> archiveExam(final Exam exam) {
this.examConfigurationMapDAO
.getConfigurationNodeIds(result.id)
.getOrThrow()
.stream()
.forEach(configNodeId -> {
if (this.examConfigurationMapDAO.checkNoActiveExamReferences(configNodeId).getOr(false)) {
log.debug("Also set exam configuration to archived: {}", configNodeId);
Expand All @@ -300,6 +304,12 @@ public Result<Exam> archiveExam(final Exam exam) {
}
});

try {
applicationEventPublisher.publishEvent(new ExamArchivedEvent(result));
} catch (final Exception e) {
log.error("Unexpected error while ExamArchivedEvent processing: ", e);
}

return result;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamTemplateChangeEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.LmsSetupChangeEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConnectionConfigurationChangeEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamArchivedEvent;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateEvent;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
Expand All @@ -39,6 +40,8 @@ public interface FullLmsIntegrationService {
void notifyExamDeletion(ExamDeletionEvent event);
@EventListener(ExamConfigUpdateEvent.class)
void notifyExamConfigChange(ExamConfigUpdateEvent event);
@EventListener(ExamArchivedEvent.class)
void notifyExamArchived(ExamArchivedEvent event);

/** Applies the exam data to LMS to inform the LMS that the exam exists on SEB Server site.
* @param exam The Exam
Expand All @@ -64,9 +67,7 @@ Result<EntityKey> deleteExam(
String lmsUUID,
String courseId,
String quizId);




Result<Void> streamConnectionConfiguration(
String lmsUUID,
String courseId,
Expand All @@ -79,9 +80,6 @@ Result<String> getOneTimeLoginToken(
String quizId,
AdHocAccountData adHocAccountData);




@JsonIgnoreProperties(ignoreUnknown = true)
final class ExamData {
@JsonProperty("id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ default Result<Exam> applySEBRestrictionIfExamRunning(final Exam exam) {
* to the LMS */
boolean checkSebRestrictionSet(Exam exam);

@EventListener
@EventListener(LmsSetupChangeEvent.class)
void notifyLmsSetupChange(final LmsSetupChangeEvent event);

Result<LmsSetup> releaseAllRestrictionsOf(LmsSetup lmsSetup);
Expand Down
Loading

0 comments on commit e3b73e1

Please sign in to comment.