SEBSERV-139 added moderator flag to the jitsi meet room token
This commit is contained in:
		
							parent
							
								
									b6e9e55106
								
							
						
					
					
						commit
						a6a9988cbe
					
				
					 3 changed files with 100 additions and 23 deletions
				
			
		|  | @ -16,10 +16,23 @@ import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
| 
 | 
 | ||||||
| public interface ExamProctoringService { | public interface ExamProctoringService { | ||||||
| 
 | 
 | ||||||
|  |     /** Get the proctoring server type of the specific implementation | ||||||
|  |      * | ||||||
|  |      * @return the proctoring service type of the specific implementation */ | ||||||
|     ProctoringServerType getType(); |     ProctoringServerType getType(); | ||||||
| 
 | 
 | ||||||
|  |     /** Use this to test the proctoring service settings against the remote proctoring server. | ||||||
|  |      * | ||||||
|  |      * @param examProctoring the settings to test | ||||||
|  |      * @return Result refer to true if the settings are correct and the proctoring server can be accessed. */ | ||||||
|     Result<Boolean> testExamProctoring(final ProctoringSettings examProctoring); |     Result<Boolean> testExamProctoring(final ProctoringSettings examProctoring); | ||||||
| 
 | 
 | ||||||
|  |     /** Used to get the proctor's room connection data. | ||||||
|  |      * | ||||||
|  |      * @param proctoringSettings the proctoring settings | ||||||
|  |      * @param roomName the name of the room | ||||||
|  |      * @param subject name of the room | ||||||
|  |      * @return SEBProctoringConnectionData that contains all connection data */ | ||||||
|     Result<SEBProctoringConnectionData> createProctorPublicRoomConnection( |     Result<SEBProctoringConnectionData> createProctorPublicRoomConnection( | ||||||
|             final ProctoringSettings proctoringSettings, |             final ProctoringSettings proctoringSettings, | ||||||
|             final String roomName, |             final String roomName, | ||||||
|  | @ -59,7 +72,8 @@ public interface ExamProctoringService { | ||||||
|             final String clientKey, |             final String clientKey, | ||||||
|             final String roomName, |             final String roomName, | ||||||
|             final String subject, |             final String subject, | ||||||
|             final Long expTime); |             final Long expTime, | ||||||
|  |             final boolean moderator); | ||||||
| 
 | 
 | ||||||
|     Result<String> createClientAccessToken( |     Result<String> createClientAccessToken( | ||||||
|             final ProctoringSettings proctoringSettings, |             final ProctoringSettings proctoringSettings, | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|             "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; |             "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; | ||||||
| 
 | 
 | ||||||
|     private static final String JITSI_ACCESS_TOKEN_PAYLOAD = |     private static final String JITSI_ACCESS_TOKEN_PAYLOAD = | ||||||
|             "{\"context\":{\"user\":{\"name\":\"%s\"}},\"iss\":\"%s\",\"aud\":\"%s\",\"sub\":\"%s\",\"room\":\"%s\"%s}"; |             "{\"context\":{\"user\":{\"name\":\"%s\"}},\"iss\":\"%s\",\"aud\":\"%s\",\"sub\":\"%s\",\"room\":\"%s\"%s%s}"; | ||||||
| 
 | 
 | ||||||
|     private final RemoteProctoringRoomDAO remoteProctoringRoomDAO; |     private final RemoteProctoringRoomDAO remoteProctoringRoomDAO; | ||||||
|     private final AuthorizationService authorizationService; |     private final AuthorizationService authorizationService; | ||||||
|  | @ -93,7 +93,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|                     "seb-server", |                     "seb-server", | ||||||
|                     roomName, |                     roomName, | ||||||
|                     subject, |                     subject, | ||||||
|                     forExam(proctoringSettings)) |                     forExam(proctoringSettings), | ||||||
|  |                     true) | ||||||
|                             .getOrThrow(); |                             .getOrThrow(); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | @ -131,7 +132,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|                     "seb-client", |                     "seb-client", | ||||||
|                     roomName, |                     roomName, | ||||||
|                     connection.userSessionId, |                     connection.userSessionId, | ||||||
|                     forExam(proctoringSettings)) |                     forExam(proctoringSettings), | ||||||
|  |                     false) | ||||||
|                             .getOrThrow(); |                             .getOrThrow(); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | @ -158,7 +160,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|                     "seb-client", |                     "seb-client", | ||||||
|                     roomName, |                     roomName, | ||||||
|                     subject, |                     subject, | ||||||
|                     forExam(proctoringSettings)) |                     forExam(proctoringSettings), | ||||||
|  |                     false) | ||||||
|                             .getOrThrow(); |                             .getOrThrow(); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | @ -209,7 +212,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|                     "seb-client", |                     "seb-client", | ||||||
|                     roomName, |                     roomName, | ||||||
|                     subject, |                     subject, | ||||||
|                     expTime) |                     expTime, | ||||||
|  |                     false) | ||||||
|                             .getOrThrow(); |                             .getOrThrow(); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | @ -226,7 +230,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|             final String clientKey, |             final String clientKey, | ||||||
|             final String roomName, |             final String roomName, | ||||||
|             final String subject, |             final String subject, | ||||||
|             final Long expTime) { |             final Long expTime, | ||||||
|  |             final boolean moderator) { | ||||||
| 
 | 
 | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> { | ||||||
| 
 | 
 | ||||||
|  | @ -242,7 +247,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|                     clientKey, |                     clientKey, | ||||||
|                     roomName, |                     roomName, | ||||||
|                     expTime, |                     expTime, | ||||||
|                     host); |                     host, | ||||||
|  |                     moderator); | ||||||
| 
 | 
 | ||||||
|             return new SEBProctoringConnectionData( |             return new SEBProctoringConnectionData( | ||||||
|                     proctoringServerType, |                     proctoringServerType, | ||||||
|  | @ -279,34 +285,27 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|                     "seb-client", |                     "seb-client", | ||||||
|                     roomName, |                     roomName, | ||||||
|                     forExam(proctoringSettings), |                     forExam(proctoringSettings), | ||||||
|                     host); |                     host, | ||||||
|  |                     false); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String internalCreateAccessToken( |     protected String internalCreateAccessToken( | ||||||
|             final String appKey, |             final String appKey, | ||||||
|             final CharSequence appSecret, |             final CharSequence appSecret, | ||||||
|             final String clientName, |             final String clientName, | ||||||
|             final String clientKey, |             final String clientKey, | ||||||
|             final String roomName, |             final String roomName, | ||||||
|             final Long expTime, |             final Long expTime, | ||||||
|             final String host) throws NoSuchAlgorithmException, InvalidKeyException { |             final String host, | ||||||
|  |             final boolean moderator) throws NoSuchAlgorithmException, InvalidKeyException { | ||||||
| 
 | 
 | ||||||
|         final StringBuilder builder = new StringBuilder(); |         final StringBuilder builder = new StringBuilder(); | ||||||
|         final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding(); |         final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding(); | ||||||
| 
 | 
 | ||||||
|         final String jwtHeaderPart = urlEncoder |         final String jwtHeaderPart = urlEncoder | ||||||
|                 .encodeToString(JITSI_ACCESS_TOKEN_HEADER.getBytes(StandardCharsets.UTF_8)); |                 .encodeToString(JITSI_ACCESS_TOKEN_HEADER.getBytes(StandardCharsets.UTF_8)); | ||||||
|         final String jwtPayload = String.format( |         final String jwtPayload = createPayload(appKey, clientName, clientKey, roomName, expTime, host, moderator); | ||||||
|                 JITSI_ACCESS_TOKEN_PAYLOAD.replaceAll(" ", "").replaceAll("\n", ""), |  | ||||||
|                 clientName, |  | ||||||
|                 appKey, |  | ||||||
|                 clientKey, |  | ||||||
|                 host, |  | ||||||
|                 roomName, |  | ||||||
|                 (expTime != null) |  | ||||||
|                         ? String.format(",\"exp\":%s", String.valueOf(expTime)) |  | ||||||
|                         : ""); |  | ||||||
|         final String jwtPayloadPart = urlEncoder |         final String jwtPayloadPart = urlEncoder | ||||||
|                 .encodeToString(jwtPayload.getBytes(StandardCharsets.UTF_8)); |                 .encodeToString(jwtPayload.getBytes(StandardCharsets.UTF_8)); | ||||||
|         final String message = jwtHeaderPart + "." + jwtPayloadPart; |         final String message = jwtHeaderPart + "." + jwtPayloadPart; | ||||||
|  | @ -324,6 +323,31 @@ public class ExamJITSIProctoringService implements ExamProctoringService { | ||||||
|         return builder.toString(); |         return builder.toString(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     protected String createPayload( | ||||||
|  |             final String appKey, | ||||||
|  |             final String clientName, | ||||||
|  |             final String clientKey, | ||||||
|  |             final String roomName, | ||||||
|  |             final Long expTime, | ||||||
|  |             final String host, | ||||||
|  |             final boolean moderator) { | ||||||
|  | 
 | ||||||
|  |         final String jwtPayload = String.format( | ||||||
|  |                 JITSI_ACCESS_TOKEN_PAYLOAD.replaceAll(" ", "").replaceAll("\n", ""), | ||||||
|  |                 clientName, | ||||||
|  |                 appKey, | ||||||
|  |                 clientKey, | ||||||
|  |                 host, | ||||||
|  |                 roomName, | ||||||
|  |                 (moderator) | ||||||
|  |                         ? ",\"moderator\":true" | ||||||
|  |                         : ",\"moderator\":false", | ||||||
|  |                 (expTime != null) | ||||||
|  |                         ? String.format(",\"exp\":%s", String.valueOf(expTime)) | ||||||
|  |                         : ""); | ||||||
|  |         return jwtPayload; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private long forExam(final ProctoringSettings examProctoring) { |     private long forExam(final ProctoringSettings examProctoring) { | ||||||
|         if (examProctoring.examId == null) { |         if (examProctoring.examId == null) { | ||||||
|             throw new IllegalStateException("Missing exam identifier from ExamProctoring data"); |             throw new IllegalStateException("Missing exam identifier from ExamProctoring data"); | ||||||
|  |  | ||||||
|  | @ -11,6 +11,9 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl; | ||||||
| import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||||
| import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||||
| 
 | 
 | ||||||
|  | import java.security.InvalidKeyException; | ||||||
|  | import java.security.NoSuchAlgorithmException; | ||||||
|  | 
 | ||||||
| import org.junit.Test; | import org.junit.Test; | ||||||
| import org.mockito.Mockito; | import org.mockito.Mockito; | ||||||
| 
 | 
 | ||||||
|  | @ -20,6 +23,40 @@ import ch.ethz.seb.sebserver.gbl.util.Cryptor; | ||||||
| 
 | 
 | ||||||
| public class ExamJITSIProctoringServiceTest { | public class ExamJITSIProctoringServiceTest { | ||||||
| 
 | 
 | ||||||
|  |     @Test | ||||||
|  |     public void testTokenPayload() throws InvalidKeyException, NoSuchAlgorithmException { | ||||||
|  |         final Cryptor cryptorMock = Mockito.mock(Cryptor.class); | ||||||
|  |         Mockito.when(cryptorMock.decrypt(Mockito.any())).thenReturn("fbvgeghergrgrthrehreg123"); | ||||||
|  |         final ExamJITSIProctoringService examJITSIProctoringService = | ||||||
|  |                 new ExamJITSIProctoringService(null, null, null, cryptorMock); | ||||||
|  | 
 | ||||||
|  |         String accessToken = examJITSIProctoringService.createPayload( | ||||||
|  |                 "test-app", | ||||||
|  |                 "Test Name", | ||||||
|  |                 "test-client", | ||||||
|  |                 "SomeRoom", | ||||||
|  |                 1609459200L, | ||||||
|  |                 "https://test.ch", | ||||||
|  |                 false); | ||||||
|  | 
 | ||||||
|  |         assertEquals( | ||||||
|  |                 "{\"context\":{\"user\":{\"name\":\"Test Name\"}},\"iss\":\"test-app\",\"aud\":\"test-client\",\"sub\":\"https://test.ch\",\"room\":\"SomeRoom\",\"moderator\":false,\"exp\":1609459200}", | ||||||
|  |                 accessToken); | ||||||
|  | 
 | ||||||
|  |         accessToken = examJITSIProctoringService.createPayload( | ||||||
|  |                 "test-app", | ||||||
|  |                 "Test Name", | ||||||
|  |                 "test-client", | ||||||
|  |                 "SomeRoom", | ||||||
|  |                 1609459200L, | ||||||
|  |                 "https://test.ch", | ||||||
|  |                 true); | ||||||
|  | 
 | ||||||
|  |         assertEquals( | ||||||
|  |                 "{\"context\":{\"user\":{\"name\":\"Test Name\"}},\"iss\":\"test-app\",\"aud\":\"test-client\",\"sub\":\"https://test.ch\",\"room\":\"SomeRoom\",\"moderator\":true,\"exp\":1609459200}", | ||||||
|  |                 accessToken); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void testCreateProctoringURL() { |     public void testCreateProctoringURL() { | ||||||
|         final Cryptor cryptorMock = Mockito.mock(Cryptor.class); |         final Cryptor cryptorMock = Mockito.mock(Cryptor.class); | ||||||
|  | @ -36,15 +73,17 @@ public class ExamJITSIProctoringServiceTest { | ||||||
|                 "test-client", |                 "test-client", | ||||||
|                 "SomeRoom", |                 "SomeRoom", | ||||||
|                 "Subject", |                 "Subject", | ||||||
|                 1609459200L) |                 1609459200L, | ||||||
|  |                 true) | ||||||
|                 .getOrThrow(); |                 .getOrThrow(); | ||||||
| 
 | 
 | ||||||
|         assertNotNull(data); |         assertNotNull(data); | ||||||
|         assertEquals( |         assertEquals( | ||||||
|                 "https://seb-jitsi.example.ch", |                 "https://seb-jitsi.example.ch", | ||||||
|                 data.serverURL); |                 data.serverURL); | ||||||
|  | 
 | ||||||
|         assertEquals( |         assertEquals( | ||||||
|                 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7InVzZXIiOnsibmFtZSI6IlRlc3QgTmFtZSJ9fSwiaXNzIjoidGVzdC1hcHAiLCJhdWQiOiJ0ZXN0LWNsaWVudCIsInN1YiI6InNlYi1qaXRzaS5leGFtcGxlLmNoIiwicm9vbSI6IlNvbWVSb29tIiwiZXhwIjoxNjA5NDU5MjAwfQ.4ovqUkG6jrLvkDEZNdhbtFI_DFLDFsM2eBJHhcYq7a4", |                 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7InVzZXIiOnsibmFtZSI6IlRlc3QgTmFtZSJ9fSwiaXNzIjoidGVzdC1hcHAiLCJhdWQiOiJ0ZXN0LWNsaWVudCIsInN1YiI6InNlYi1qaXRzaS5leGFtcGxlLmNoIiwicm9vbSI6IlNvbWVSb29tIiwibW9kZXJhdG9yIjogdHJ1ZSwiZXhwIjoxNjA5NDU5MjAwfQ.RjqLawNlBQgECKGZFi6jfcVXEw2dbZ1p9C1xEz-0e9w", | ||||||
|                 data.accessToken); |                 data.accessToken); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti