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 {
|
||||
|
||||
/** Get the proctoring server type of the specific implementation
|
||||
*
|
||||
* @return the proctoring service type of the specific implementation */
|
||||
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);
|
||||
|
||||
/** 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(
|
||||
final ProctoringSettings proctoringSettings,
|
||||
final String roomName,
|
||||
|
@ -59,7 +72,8 @@ public interface ExamProctoringService {
|
|||
final String clientKey,
|
||||
final String roomName,
|
||||
final String subject,
|
||||
final Long expTime);
|
||||
final Long expTime,
|
||||
final boolean moderator);
|
||||
|
||||
Result<String> createClientAccessToken(
|
||||
final ProctoringSettings proctoringSettings,
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
"{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
|
||||
|
||||
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 AuthorizationService authorizationService;
|
||||
|
@ -93,7 +93,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
"seb-server",
|
||||
roomName,
|
||||
subject,
|
||||
forExam(proctoringSettings))
|
||||
forExam(proctoringSettings),
|
||||
true)
|
||||
.getOrThrow();
|
||||
});
|
||||
}
|
||||
|
@ -131,7 +132,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
"seb-client",
|
||||
roomName,
|
||||
connection.userSessionId,
|
||||
forExam(proctoringSettings))
|
||||
forExam(proctoringSettings),
|
||||
false)
|
||||
.getOrThrow();
|
||||
});
|
||||
}
|
||||
|
@ -158,7 +160,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
"seb-client",
|
||||
roomName,
|
||||
subject,
|
||||
forExam(proctoringSettings))
|
||||
forExam(proctoringSettings),
|
||||
false)
|
||||
.getOrThrow();
|
||||
});
|
||||
}
|
||||
|
@ -209,7 +212,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
"seb-client",
|
||||
roomName,
|
||||
subject,
|
||||
expTime)
|
||||
expTime,
|
||||
false)
|
||||
.getOrThrow();
|
||||
});
|
||||
|
||||
|
@ -226,7 +230,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
final String clientKey,
|
||||
final String roomName,
|
||||
final String subject,
|
||||
final Long expTime) {
|
||||
final Long expTime,
|
||||
final boolean moderator) {
|
||||
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
|
@ -242,7 +247,8 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
clientKey,
|
||||
roomName,
|
||||
expTime,
|
||||
host);
|
||||
host,
|
||||
moderator);
|
||||
|
||||
return new SEBProctoringConnectionData(
|
||||
proctoringServerType,
|
||||
|
@ -279,34 +285,27 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
"seb-client",
|
||||
roomName,
|
||||
forExam(proctoringSettings),
|
||||
host);
|
||||
host,
|
||||
false);
|
||||
});
|
||||
}
|
||||
|
||||
private String internalCreateAccessToken(
|
||||
protected String internalCreateAccessToken(
|
||||
final String appKey,
|
||||
final CharSequence appSecret,
|
||||
final String clientName,
|
||||
final String clientKey,
|
||||
final String roomName,
|
||||
final Long expTime,
|
||||
final String host) throws NoSuchAlgorithmException, InvalidKeyException {
|
||||
final String host,
|
||||
final boolean moderator) throws NoSuchAlgorithmException, InvalidKeyException {
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final Encoder urlEncoder = Base64.getUrlEncoder().withoutPadding();
|
||||
|
||||
final String jwtHeaderPart = urlEncoder
|
||||
.encodeToString(JITSI_ACCESS_TOKEN_HEADER.getBytes(StandardCharsets.UTF_8));
|
||||
final String jwtPayload = String.format(
|
||||
JITSI_ACCESS_TOKEN_PAYLOAD.replaceAll(" ", "").replaceAll("\n", ""),
|
||||
clientName,
|
||||
appKey,
|
||||
clientKey,
|
||||
host,
|
||||
roomName,
|
||||
(expTime != null)
|
||||
? String.format(",\"exp\":%s", String.valueOf(expTime))
|
||||
: "");
|
||||
final String jwtPayload = createPayload(appKey, clientName, clientKey, roomName, expTime, host, moderator);
|
||||
final String jwtPayloadPart = urlEncoder
|
||||
.encodeToString(jwtPayload.getBytes(StandardCharsets.UTF_8));
|
||||
final String message = jwtHeaderPart + "." + jwtPayloadPart;
|
||||
|
@ -324,6 +323,31 @@ public class ExamJITSIProctoringService implements ExamProctoringService {
|
|||
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) {
|
||||
if (examProctoring.examId == null) {
|
||||
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.assertNotNull;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
@ -20,6 +23,40 @@ import ch.ethz.seb.sebserver.gbl.util.Cryptor;
|
|||
|
||||
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
|
||||
public void testCreateProctoringURL() {
|
||||
final Cryptor cryptorMock = Mockito.mock(Cryptor.class);
|
||||
|
@ -36,15 +73,17 @@ public class ExamJITSIProctoringServiceTest {
|
|||
"test-client",
|
||||
"SomeRoom",
|
||||
"Subject",
|
||||
1609459200L)
|
||||
1609459200L,
|
||||
true)
|
||||
.getOrThrow();
|
||||
|
||||
assertNotNull(data);
|
||||
assertEquals(
|
||||
"https://seb-jitsi.example.ch",
|
||||
data.serverURL);
|
||||
|
||||
assertEquals(
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7InVzZXIiOnsibmFtZSI6IlRlc3QgTmFtZSJ9fSwiaXNzIjoidGVzdC1hcHAiLCJhdWQiOiJ0ZXN0LWNsaWVudCIsInN1YiI6InNlYi1qaXRzaS5leGFtcGxlLmNoIiwicm9vbSI6IlNvbWVSb29tIiwiZXhwIjoxNjA5NDU5MjAwfQ.4ovqUkG6jrLvkDEZNdhbtFI_DFLDFsM2eBJHhcYq7a4",
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb250ZXh0Ijp7InVzZXIiOnsibmFtZSI6IlRlc3QgTmFtZSJ9fSwiaXNzIjoidGVzdC1hcHAiLCJhdWQiOiJ0ZXN0LWNsaWVudCIsInN1YiI6InNlYi1qaXRzaS5leGFtcGxlLmNoIiwicm9vbSI6IlNvbWVSb29tIiwibW9kZXJhdG9yIjogdHJ1ZSwiZXhwIjoxNjA5NDU5MjAwfQ.RjqLawNlBQgECKGZFi6jfcVXEw2dbZ1p9C1xEz-0e9w",
|
||||
data.accessToken);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue