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_APP_SECRET = "appSecret"; | ||||||
|     public static final String ATTR_COLLECTING_ROOM_SIZE = "collectingRoomSize"; |     public static final String ATTR_COLLECTING_ROOM_SIZE = "collectingRoomSize"; | ||||||
|     public static final String ATTR_COLLECT_ALL_ROOM_NAME = "collectAllRoomName"; |     public static final String ATTR_COLLECT_ALL_ROOM_NAME = "collectAllRoomName"; | ||||||
|  |     public static final String ATTR_SERVICE_IN_USE = "serviceInUse"; | ||||||
| 
 | 
 | ||||||
|     @JsonProperty(Domain.EXAM.ATTR_ID) |     @JsonProperty(Domain.EXAM.ATTR_ID) | ||||||
|     public final Long examId; |     public final Long examId; | ||||||
|  | @ -59,6 +60,9 @@ public class ProctoringServiceSettings implements Entity { | ||||||
|     @JsonProperty(ATTR_COLLECTING_ROOM_SIZE) |     @JsonProperty(ATTR_COLLECTING_ROOM_SIZE) | ||||||
|     public final Integer collectingRoomSize; |     public final Integer collectingRoomSize; | ||||||
| 
 | 
 | ||||||
|  |     @JsonProperty(ATTR_SERVICE_IN_USE) | ||||||
|  |     public final Boolean serviceInUse; | ||||||
|  | 
 | ||||||
|     @JsonCreator |     @JsonCreator | ||||||
|     public ProctoringServiceSettings( |     public ProctoringServiceSettings( | ||||||
|             @JsonProperty(Domain.EXAM.ATTR_ID) final Long examId, |             @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_TYPE) final ProctoringServerType serverType, | ||||||
|             @JsonProperty(ATTR_SERVER_URL) final String serverURL, |             @JsonProperty(ATTR_SERVER_URL) final String serverURL, | ||||||
|             @JsonProperty(ATTR_COLLECTING_ROOM_SIZE) final Integer collectingRoomSize, |             @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_KEY) final String appKey, | ||||||
|             @JsonProperty(ATTR_APP_SECRET) final CharSequence appSecret) { |             @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.serverType = (serverType != null) ? serverType : ProctoringServerType.JITSI_MEET; | ||||||
|         this.serverURL = serverURL; |         this.serverURL = serverURL; | ||||||
|         this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20; |         this.collectingRoomSize = (collectingRoomSize != null) ? collectingRoomSize : 20; | ||||||
|  |         this.serviceInUse = serviceInUse; | ||||||
|         this.appKey = appKey; |         this.appKey = appKey; | ||||||
|         this.appSecret = appSecret; |         this.appSecret = appSecret; | ||||||
|     } |     } | ||||||
|  | @ -121,6 +127,10 @@ public class ProctoringServiceSettings implements Entity { | ||||||
|         return this.appSecret; |         return this.appSecret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public Boolean getServiceInUse() { | ||||||
|  |         return this.serviceInUse; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public int hashCode() { |     public int hashCode() { | ||||||
|         final int prime = 31; |         final int prime = 31; | ||||||
|  |  | ||||||
|  | @ -128,8 +128,8 @@ public class ExamProctoringSettings { | ||||||
| 
 | 
 | ||||||
|             final boolean enabled = BooleanUtils.toBoolean( |             final boolean enabled = BooleanUtils.toBoolean( | ||||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_ENABLE_PROCTORING)); |                     form.getFieldValue(ProctoringServiceSettings.ATTR_ENABLE_PROCTORING)); | ||||||
|             final ProctoringServerType serverType = ProctoringServerType.valueOf( |             final ProctoringServerType serverType = ProctoringServerType | ||||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE)); |                     .valueOf(form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_TYPE)); | ||||||
| 
 | 
 | ||||||
|             examProctoring = new ProctoringServiceSettings( |             examProctoring = new ProctoringServiceSettings( | ||||||
|                     Long.parseLong(entityKey.modelId), |                     Long.parseLong(entityKey.modelId), | ||||||
|  | @ -137,6 +137,7 @@ public class ExamProctoringSettings { | ||||||
|                     serverType, |                     serverType, | ||||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_URL), |                     form.getFieldValue(ProctoringServiceSettings.ATTR_SERVER_URL), | ||||||
|                     Integer.parseInt(form.getFieldValue(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)), |                     Integer.parseInt(form.getFieldValue(ProctoringServiceSettings.ATTR_COLLECTING_ROOM_SIZE)), | ||||||
|  |                     false, | ||||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_APP_KEY), |                     form.getFieldValue(ProctoringServiceSettings.ATTR_APP_KEY), | ||||||
|                     form.getFieldValue(ProctoringServiceSettings.ATTR_APP_SECRET)); |                     form.getFieldValue(ProctoringServiceSettings.ATTR_APP_SECRET)); | ||||||
| 
 | 
 | ||||||
|  | @ -263,6 +264,11 @@ public class ExamProctoringSettings { | ||||||
| 
 | 
 | ||||||
|                     .build(); |                     .build(); | ||||||
| 
 | 
 | ||||||
|  |             if (proctoringSettings.serviceInUse) { | ||||||
|  |                 formHandle.getForm().getFieldInput(ProctoringServiceSettings.ATTR_SERVER_TYPE).setEnabled(false); | ||||||
|  |                 formHandle.getForm().getFieldInput(ProctoringServiceSettings.ATTR_SERVER_URL).setEnabled(false); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             return () -> formHandle; |             return () -> formHandle; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -19,6 +19,12 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.proctoring.New | ||||||
| /** Data access for RemoteProctoringRoom domain objects. */ | /** Data access for RemoteProctoringRoom domain objects. */ | ||||||
| public interface RemoteProctoringRoomDAO { | 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. |     /** Get all collecting room records that exists for a given exam. | ||||||
|      * |      * | ||||||
|      * @param examId the exam identifier |      * @param examId the exam identifier | ||||||
|  |  | ||||||
|  | @ -56,6 +56,15 @@ public class RemoteProctoringRoomDAOImpl implements RemoteProctoringRoomDAO { | ||||||
|         this.remoteProctoringRoomRecordMapper = remoteProctoringRoomRecordMapper; |         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 |     @Override | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     public Result<Collection<RemoteProctoringRoom>> getCollectingRooms(final Long examId) { |     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.AdditionalAttributesDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; | 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.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.exam.ExamAdminService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; | ||||||
|  | @ -62,6 +63,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|     private final JSONMapper jsonMapper; |     private final JSONMapper jsonMapper; | ||||||
|     private final Cryptor cryptor; |     private final Cryptor cryptor; | ||||||
|     private final ExamProctoringServiceFactory examProctoringServiceFactory; |     private final ExamProctoringServiceFactory examProctoringServiceFactory; | ||||||
|  |     private final RemoteProctoringRoomDAO remoteProctoringRoomDAO; | ||||||
| 
 | 
 | ||||||
|     private final String defaultIndicatorName; |     private final String defaultIndicatorName; | ||||||
|     private final String defaultIndicatorType; |     private final String defaultIndicatorType; | ||||||
|  | @ -76,6 +78,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|             final JSONMapper jsonMapper, |             final JSONMapper jsonMapper, | ||||||
|             final Cryptor cryptor, |             final Cryptor cryptor, | ||||||
|             final ExamProctoringServiceFactory examProctoringServiceFactory, |             final ExamProctoringServiceFactory examProctoringServiceFactory, | ||||||
|  |             final RemoteProctoringRoomDAO remoteProctoringRoomDAO, | ||||||
|             @Value("${sebserver.webservice.api.exam.indicator.name:Ping}") final String defaultIndicatorName, |             @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.type:LAST_PING}") final String defaultIndicatorType, | ||||||
|             @Value("${sebserver.webservice.api.exam.indicator.color:b4b4b4}") final String defaultIndicatorColor, |             @Value("${sebserver.webservice.api.exam.indicator.color:b4b4b4}") final String defaultIndicatorColor, | ||||||
|  | @ -88,6 +91,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|         this.jsonMapper = jsonMapper; |         this.jsonMapper = jsonMapper; | ||||||
|         this.cryptor = cryptor; |         this.cryptor = cryptor; | ||||||
|         this.examProctoringServiceFactory = examProctoringServiceFactory; |         this.examProctoringServiceFactory = examProctoringServiceFactory; | ||||||
|  |         this.remoteProctoringRoomDAO = remoteProctoringRoomDAO; | ||||||
| 
 | 
 | ||||||
|         this.defaultIndicatorName = defaultIndicatorName; |         this.defaultIndicatorName = defaultIndicatorName; | ||||||
|         this.defaultIndicatorType = defaultIndicatorType; |         this.defaultIndicatorType = defaultIndicatorType; | ||||||
|  | @ -199,6 +203,7 @@ public class ExamAdminServiceImpl implements ExamAdminService { | ||||||
|                             getServerType(mapping), |                             getServerType(mapping), | ||||||
|                             getString(mapping, ProctoringServiceSettings.ATTR_SERVER_URL), |                             getString(mapping, ProctoringServiceSettings.ATTR_SERVER_URL), | ||||||
|                             getCollectingRoomSize(mapping), |                             getCollectingRoomSize(mapping), | ||||||
|  |                             this.remoteProctoringRoomDAO.isServiceInUse(examId).getOr(true), | ||||||
|                             getString(mapping, ProctoringServiceSettings.ATTR_APP_KEY), |                             getString(mapping, ProctoringServiceSettings.ATTR_APP_KEY), | ||||||
|                             getString(mapping, ProctoringServiceSettings.ATTR_APP_SECRET)); |                             getString(mapping, ProctoringServiceSettings.ATTR_APP_SECRET)); | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|  | @ -170,30 +170,6 @@ public class ZoomProctoringService implements ExamProctoringService { | ||||||
|                     throw new APIMessageException( |                     throw new APIMessageException( | ||||||
|                             APIMessage.ErrorMessage.BINDING_ERROR, |                             APIMessage.ErrorMessage.BINDING_ERROR, | ||||||
|                             String.valueOf(result.getStatusCode())); |                             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) { |             } 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.Exam; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings; | 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.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.gbl.util.Result; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; | import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; | ||||||
|  | @ -60,16 +62,27 @@ public class ExamProctoringRoomServiceTest extends AdministrationAPIIntegrationT | ||||||
|         this.examAdminService.saveProctoringServiceSettings( |         this.examAdminService.saveProctoringServiceSettings( | ||||||
|                 2L, |                 2L, | ||||||
|                 new ProctoringServiceSettings( |                 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")); |                         "app-key", "app.secret")); | ||||||
| 
 | 
 | ||||||
|         assertTrue(this.examAdminService.isProctoringEnabled(2L).get()); |         assertTrue(this.examAdminService.isProctoringEnabled(2L).get()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| //    @Test |     @Test | ||||||
| //    @Order(3) |     @Order(3) | ||||||
| //    public void test03_addClientConnection() { |     public void test03_addClientConnection() { | ||||||
| //        clientConnectionDAO.createNew(new ClientConnection(null, 1L, 2L, ConnectionStatus.CONNECTION_REQUESTED, CONNECTION_TOKEN_1)) |         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