disallow proctoring service change if there are existing proctoring
rooms
This commit is contained in:
		
							parent
							
								
									8381b5d621
								
							
						
					
					
						commit
						d2036a8598
					
				
					 7 changed files with 57 additions and 32 deletions
				
			
		|  | @ -36,6 +36,7 @@ public class ProctoringServiceSettings implements Entity { | |||
|     public static final String ATTR_APP_SECRET = "appSecret"; | ||||
|     public static final String ATTR_COLLECTING_ROOM_SIZE = "collectingRoomSize"; | ||||
|     public static final String ATTR_COLLECT_ALL_ROOM_NAME = "collectAllRoomName"; | ||||
|     public static final String ATTR_SERVICE_IN_USE = "serviceInUse"; | ||||
| 
 | ||||
|     @JsonProperty(Domain.EXAM.ATTR_ID) | ||||
|     public final Long examId; | ||||
|  | @ -59,6 +60,9 @@ public class ProctoringServiceSettings implements Entity { | |||
|     @JsonProperty(ATTR_COLLECTING_ROOM_SIZE) | ||||
|     public final Integer collectingRoomSize; | ||||
| 
 | ||||
|     @JsonProperty(ATTR_SERVICE_IN_USE) | ||||
|     public final Boolean serviceInUse; | ||||
| 
 | ||||
|     @JsonCreator | ||||
|     public ProctoringServiceSettings( | ||||
|             @JsonProperty(Domain.EXAM.ATTR_ID) final Long examId, | ||||
|  | @ -66,6 +70,7 @@ public class ProctoringServiceSettings implements Entity { | |||
|             @JsonProperty(ATTR_SERVER_TYPE) final ProctoringServerType serverType, | ||||
|             @JsonProperty(ATTR_SERVER_URL) final String serverURL, | ||||
|             @JsonProperty(ATTR_COLLECTING_ROOM_SIZE) final Integer collectingRoomSize, | ||||
|             @JsonProperty(ATTR_SERVICE_IN_USE) final Boolean serviceInUse, | ||||
|             @JsonProperty(ATTR_APP_KEY) final String appKey, | ||||
|             @JsonProperty(ATTR_APP_SECRET) final CharSequence appSecret) { | ||||
| 
 | ||||
|  | @ -74,6 +79,7 @@ public class ProctoringServiceSettings implements Entity { | |||
|         this.serverType = (serverType != null) ? serverType : ProctoringServerType.JITSI_MEET; | ||||
|         this.serverURL = serverURL; | ||||
|         this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20; | ||||
|         this.serviceInUse = serviceInUse; | ||||
|         this.appKey = appKey; | ||||
|         this.appSecret = appSecret; | ||||
|     } | ||||
|  | @ -121,6 +127,10 @@ public class ProctoringServiceSettings implements Entity { | |||
|         return this.appSecret; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean getServiceInUse() { | ||||
|         return this.serviceInUse; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         final int prime = 31; | ||||
|  |  | |||
|  | @ -128,8 +128,8 @@ public class ExamProctoringSettings { | |||
| 
 | ||||
|             final boolean enabled = BooleanUtils.toBoolean( | ||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_ENABLE_PROCTORING)); | ||||
|             final ProctoringServerType serverType = ProctoringServerType.valueOf( | ||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE)); | ||||
|             final ProctoringServerType serverType = ProctoringServerType | ||||
|                     .valueOf(form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE)); | ||||
| 
 | ||||
|             examProctoring = new ProctoringServiceSettings( | ||||
|                     Long.parseLong(entityKey.modelId), | ||||
|  | @ -137,6 +137,7 @@ public class ExamProctoringSettings { | |||
|                     serverType, | ||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_URL), | ||||
|                     Integer.parseInt(form.getFieldValue(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)), | ||||
|                     false, | ||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_APP_KEY), | ||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_APP_SECRET)); | ||||
| 
 | ||||
|  | @ -263,6 +264,11 @@ public class ExamProctoringSettings { | |||
| 
 | ||||
|                     .build(); | ||||
| 
 | ||||
|             if (proctoringSettings.serviceInUse) { | ||||
|                 formHandle.getForm().getFieldInput(ProctoringServiceSettings.ATTR_SERVER_TYPE).setEnabled(false); | ||||
|                 formHandle.getForm().getFieldInput(ProctoringServiceSettings.ATTR_SERVER_URL).setEnabled(false); | ||||
|             } | ||||
| 
 | ||||
|             return () -> formHandle; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -19,6 +19,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.proctoring.New | |||
| /** Data access for RemoteProctoringRoom domain objects. */ | ||||
| public interface RemoteProctoringRoomDAO { | ||||
| 
 | ||||
|     /** Indicates if there is already any proctoring service in use for the specified exam | ||||
|      * | ||||
|      * @param examId the exam identifier | ||||
|      * @return Result refer to the indication or to an error when happened. */ | ||||
|     Result<Boolean> isServiceInUse(Long examId); | ||||
| 
 | ||||
|     /** Get all collecting room records that exists for a given exam. | ||||
|      * | ||||
|      * @param examId the exam identifier | ||||
|  |  | |||
|  | @ -56,6 +56,15 @@ public class RemoteProctoringRoomDAOImpl implements RemoteProctoringRoomDAO { | |||
|         this.remoteProctoringRoomRecordMapper = remoteProctoringRoomRecordMapper; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Result<Boolean> isServiceInUse(final Long examId) { | ||||
|         return Result.tryCatch(() -> this.remoteProctoringRoomRecordMapper | ||||
|                 .countByExample() | ||||
|                 .where(RemoteProctoringRoomRecordDynamicSqlSupport.examId, isEqualTo(examId)) | ||||
|                 .build() | ||||
|                 .execute() > 0); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     @Transactional(readOnly = true) | ||||
|     public Result<Collection<RemoteProctoringRoom>> getCollectingRooms(final Long examId) { | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.AdditionalAttribut | |||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.RemoteProctoringRoomDAO; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | ||||
|  | @ -62,6 +63,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | |||
|     private final JSONMapper jsonMapper; | ||||
|     private final Cryptor cryptor; | ||||
|     private final ExamProctoringServiceFactory examProctoringServiceFactory; | ||||
|     private final RemoteProctoringRoomDAO remoteProctoringRoomDAO; | ||||
| 
 | ||||
|     private final String defaultIndicatorName; | ||||
|     private final String defaultIndicatorType; | ||||
|  | @ -76,6 +78,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | |||
|             final JSONMapper jsonMapper, | ||||
|             final Cryptor cryptor, | ||||
|             final ExamProctoringServiceFactory examProctoringServiceFactory, | ||||
|             final RemoteProctoringRoomDAO remoteProctoringRoomDAO, | ||||
|             @Value("${sebserver.webservice.api.exam.indicator.name:Ping}") final String defaultIndicatorName, | ||||
|             @Value("${sebserver.webservice.api.exam.indicator.type:LAST_PING}") final String defaultIndicatorType, | ||||
|             @Value("${sebserver.webservice.api.exam.indicator.color:b4b4b4}") final String defaultIndicatorColor, | ||||
|  | @ -88,6 +91,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | |||
|         this.jsonMapper = jsonMapper; | ||||
|         this.cryptor = cryptor; | ||||
|         this.examProctoringServiceFactory = examProctoringServiceFactory; | ||||
|         this.remoteProctoringRoomDAO = remoteProctoringRoomDAO; | ||||
| 
 | ||||
|         this.defaultIndicatorName = defaultIndicatorName; | ||||
|         this.defaultIndicatorType = defaultIndicatorType; | ||||
|  | @ -199,6 +203,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | |||
|                             getServerType(mapping), | ||||
|                             getString(mapping, ProctoringServiceSettings.ATTR_SERVER_URL), | ||||
|                             getCollectingRoomSize(mapping), | ||||
|                             this.remoteProctoringRoomDAO.isServiceInUse(examId).getOr(true), | ||||
|                             getString(mapping, ProctoringServiceSettings.ATTR_APP_KEY), | ||||
|                             getString(mapping, ProctoringServiceSettings.ATTR_APP_SECRET)); | ||||
|                 }); | ||||
|  |  | |||
|  | @ -170,30 +170,6 @@ public class ZoomProctoringService implements ExamProctoringService { | |||
|                     throw new APIMessageException( | ||||
|                             APIMessage.ErrorMessage.BINDING_ERROR, | ||||
|                             String.valueOf(result.getStatusCode())); | ||||
|                 } else { | ||||
|                     // TODO this is just for cleaning up along development process. | ||||
|                     // Remove this before finish up the Zoom integration | ||||
| 
 | ||||
|                     try { | ||||
|                         final ProctoringServiceSettings encryptedSettings = new ProctoringServiceSettings( | ||||
|                                 proctoringSettings.examId, | ||||
|                                 proctoringSettings.enableProctoring, | ||||
|                                 proctoringSettings.serverType, | ||||
|                                 proctoringSettings.serverURL, | ||||
|                                 proctoringSettings.collectingRoomSize, | ||||
|                                 proctoringSettings.appKey, | ||||
|                                 this.cryptor | ||||
|                                         .encrypt(proctoringSettings.appSecret) | ||||
|                                         .getOrThrow()); | ||||
| 
 | ||||
|                         disposeServiceRoomsForExam( | ||||
|                                 proctoringSettings.examId, | ||||
|                                 encryptedSettings) | ||||
|                                         .getOrThrow(); | ||||
| 
 | ||||
|                     } catch (final Exception e) { | ||||
|                         log.error("Failed to dev-cleanup rooms: ", e); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|             } catch (final Exception e) { | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ import org.springframework.test.context.jdbc.Sql; | |||
| import ch.ethz.seb.sebserver.gbl.model.exam.Exam; | ||||
| import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings; | ||||
| import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType; | ||||
| import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; | ||||
| import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; | ||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; | ||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; | ||||
|  | @ -60,16 +62,27 @@ public class ExamProctoringRoomServiceTest extends AdministrationAPIIntegrationT | |||
|         this.examAdminService.saveProctoringServiceSettings( | ||||
|                 2L, | ||||
|                 new ProctoringServiceSettings( | ||||
|                         2L, true, ProctoringServerType.JITSI_MEET, "http://jitsi.ch", 1, | ||||
|                         2L, true, ProctoringServerType.JITSI_MEET, "http://jitsi.ch", 1, false, | ||||
|                         "app-key", "app.secret")); | ||||
| 
 | ||||
|         assertTrue(this.examAdminService.isProctoringEnabled(2L).get()); | ||||
|     } | ||||
| 
 | ||||
| //    @Test | ||||
| //    @Order(3) | ||||
| //    public void test03_addClientConnection() { | ||||
| //        clientConnectionDAO.createNew(new ClientConnection(null, 1L, 2L, ConnectionStatus.CONNECTION_REQUESTED, CONNECTION_TOKEN_1)) | ||||
| //    } | ||||
|     @Test | ||||
|     @Order(3) | ||||
|     public void test03_addClientConnection() { | ||||
|         final Result<ClientConnection> createNew = this.clientConnectionDAO.createNew(new ClientConnection( | ||||
|                 null, | ||||
|                 1L, | ||||
|                 2L, | ||||
|                 ConnectionStatus.CONNECTION_REQUESTED, | ||||
|                 CONNECTION_TOKEN_1, | ||||
|                 "", | ||||
|                 "", | ||||
|                 false, | ||||
|                 "", | ||||
|                 null)); | ||||
|         assertFalse(createNew.hasError()); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti