Skip to content

Commit

Permalink
SEBSERV-435 improved SEB Server SPS user account sync
Browse files Browse the repository at this point in the history
  • Loading branch information
anhefti committed Nov 29, 2023
1 parent 6a0d53c commit 9bda863
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ public void updateCollectingRoomActions(
proctoringGUIService,
room));

if (proctoringSettings.enabledFeatures.contains(ProctoringFeature.TOWN_HALL)) {
if (BooleanUtils.isTrue(proctoringSettings.enableProctoring) &&
proctoringSettings.enabledFeatures.contains(ProctoringFeature.TOWN_HALL)) {

updateTownhallButton(proctoringGUIService, pageContext);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,6 @@ private Result<UserRecord> recordByUsername(final String username) {
this.userRecordMapper
.selectByExample()
.where(UserRecordDynamicSqlSupport.username, isEqualTo(username))
.and(UserRecordDynamicSqlSupport.active,
isEqualTo(BooleanUtils.toInteger(true)))
.build()
.execute());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,7 @@ default void processSessionUpdateTask() {
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
void synchronizeSPSUser(final String userUUID);

@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
void deleteSPSUser(String userUUID);

}
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,9 @@ public Result<ClientConnection> disableConnection(final String connectionToken,
.getConnectionData(connectionToken)
.getOrThrow();

// A connection can only be disabled if we have a missing ping
if (!BooleanUtils.isTrue(connectionData.getMissingPing())) {
// A connection can only be disabled if we have a missing ping or for closed connections
if (connectionData.clientConnection.status != ConnectionStatus.CLOSED &&
!BooleanUtils.isTrue(connectionData.getMissingPing())) {
return connectionData.clientConnection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ void synchronizeUserAccount(final String userUUID) {
.toUriString();

final ResponseEntity<String> exchange = apiTemplate.exchange(
uri, HttpMethod.POST, null, apiTemplate.getHeaders());
uri, HttpMethod.GET, null, apiTemplate.getHeaders());

if (exchange.getStatusCode() == HttpStatus.OK) {
log.info("Synchronize SPS user account for SEB Server user account with id: {} ", userUUID);
Expand All @@ -386,6 +386,30 @@ void synchronizeUserAccounts(final Exam exam) {
log.error("Failed to synchronize user accounts with SPS for exam: {}", exam);
}
}
void deleteSPSUser(final String userUUID) {
try {

final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(null);

final String uri = UriComponentsBuilder
.fromUriString(apiTemplate.spsAPIAccessData.getSpsServiceURL())
.path(SPS_API.USER_ACCOUNT_ENDPOINT + userUUID)
.build()
.toUriString();

final ResponseEntity<String> exchange = apiTemplate.exchange(
uri, HttpMethod.DELETE, null, apiTemplate.getHeaders());

if (exchange.getStatusCode() == HttpStatus.OK) {
log.info("Successfully deleted User Account on SPS for user: {}", userUUID);
} else {
log.error("Failed to delete user account on SPS for user: {} response: {}", userUUID, exchange);
}

} catch (final Exception e) {
log.error("Failed to delete user account on SPS for user: {}", userUUID);
}
}

/** This is called when an exam has changed its parameter and needs data update on SPS side
*
Expand Down Expand Up @@ -583,7 +607,7 @@ private void synchronizeUserAccount(
.byModelId(userUUID)
.getOrThrow();
final SEBServerUser accountInfo = this.userDAO
.sebServerUserByUsername(userInfo.name)
.sebServerUserByUsername(userInfo.username)
.getOrThrow();

final UserMod userMod = getUserModifications(userInfo, accountInfo);
Expand All @@ -600,8 +624,24 @@ private void synchronizeUserAccount(
if (exchange.getStatusCode() != HttpStatus.OK) {
log.warn("Failed to synchronize user account on SPS: {}", exchange);
} else {
log.info("Successfully synchronize user account on SPS for user: ");
log.info("Successfully synchronize user account on SPS for user: {}", userUUID);
}

// sync activity
final String activityURI = UriComponentsBuilder
.fromUriString(apiTemplate.spsAPIAccessData.getSpsServiceURL())
.path(SPS_API.USER_ACCOUNT_ENDPOINT)
.pathSegment(userUUID)
.path(BooleanUtils.isTrue(userInfo.active) ? "/active" : "/inactive")
.build()
.toUriString();
final ResponseEntity<String> activityRequest = apiTemplate.exchange(
activityURI, HttpMethod.POST, jsonBody, apiTemplate.getHeaders());

if (activityRequest.getStatusCode() != HttpStatus.OK) {
log.warn("Failed to synchronize activity for user account on SPS: {}", activityRequest);
} else {
log.info("Successfully synchronize activity for user account on SPS for user: {}", userUUID);
}

} catch (final Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
import java.util.HashMap;
import java.util.Map;

import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import ch.ethz.seb.sebserver.gbl.api.APIMessage;
Expand Down Expand Up @@ -262,6 +264,7 @@ public void notifyExamSaved(final Exam exam) {
}

@Override
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
public void synchronizeSPSUser(final String userUUID) {

if (!webserviceInfo.getScreenProctoringServiceBundle().bundled) {
Expand All @@ -271,6 +274,17 @@ public void synchronizeSPSUser(final String userUUID) {
this.screenProctoringAPIBinding.synchronizeUserAccount(userUUID);
}

@Override
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
public void deleteSPSUser(final String userUUID) {

if (!webserviceInfo.getScreenProctoringServiceBundle().bundled) {
return;
}

this.screenProctoringAPIBinding.deleteSPSUser(userUUID);
}

@Override
public void notifyExamStarted(final ExamStartedEvent event) {
final Exam exam = event.exam;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import javax.validation.Valid;

import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
import ch.ethz.seb.sebserver.gbl.util.Pair;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ScreenProctoringService;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.beans.factory.annotation.Qualifier;
Expand Down Expand Up @@ -156,6 +158,13 @@ protected Result<UserInfo> notifySaved(final UserInfo entity) {
return userInfoResult;
}

@Override
protected Result<Pair<UserInfo, EntityProcessingReport>> notifyDeleted(final Pair<UserInfo, EntityProcessingReport> pair) {
final Result<Pair<UserInfo, EntityProcessingReport>> result = super.notifyDeleted(pair);
this.screenProctoringService.deleteSPSUser(pair.a.uuid);
return result;
}

@RequestMapping(
path = API.PASSWORD_PATH_SEGMENT,
method = RequestMethod.PUT,
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/config/application-dev-ws.properties
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ management.endpoints.web.exposure.include=logfile,loggers,jolokia
management.endpoints.web.path-mapping.jolokia=jmx

sebserver.feature.seb.screenProctoring.bundled=true
sebserver.feature.seb.screenProctoring.bundled.url=localhost:8090
sebserver.feature.seb.screenProctoring.bundled.url=http://localhost:8090
sebserver.feature.seb.screenProctoring.bundled.clientId=sebserverClient
sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username=SEBServerAPIAccount
Original file line number Diff line number Diff line change
Expand Up @@ -2437,7 +2437,7 @@ public void testUsecase17_RunningExam() throws IOException {
connections = connectionsCall.get();
assertFalse(connections.isEmpty());
conData = connections.iterator().next();
assertEquals("CLOSED", conData.clientConnection.status.name());
assertEquals("DISABLED", conData.clientConnection.status.name());

// get client logs
final Result<Page<ExtendedClientEvent>> clientLogPage = restService
Expand Down Expand Up @@ -2520,7 +2520,7 @@ public void testUsecase17_RunningExam() throws IOException {
assertFalse(ccDataPage.content.isEmpty());
final ClientConnectionData clientConnectionData = ccDataPage.content.get(0);
assertNotNull(clientConnectionData);
assertEquals("CLOSED", clientConnectionData.clientConnection.status.toString());
assertEquals("DISABLED", clientConnectionData.clientConnection.status.toString());

connectionDatacall = restService
.getBuilder(GetFinishedExamClientConnectionPage.class)
Expand Down Expand Up @@ -2552,9 +2552,9 @@ public void testUsecase17_RunningExam() throws IOException {
@Order(18)
// *************************************
// Use Case 18: Login as examAdmin2 and get dependencies of examAdmin2
// - Get all dependencies and check correctnes.
// - Get all dependencies including only Exam Configuration and check correctnes.
// - Get all dependencies including only ClientConnection and check correctnes.
// - Get all dependencies and check correctness.
// - Get all dependencies including only Exam Configuration and check correctness.
// - Get all dependencies including only ClientConnection and check correctness.
public void testUsecase18_UserDependencies() throws IOException {
final RestServiceImpl restService = createRestServiceForUser(
"examAdmin2",
Expand Down

0 comments on commit 9bda863

Please sign in to comment.