Skip to content

Commit

Permalink
feat: added guest video call url to moderator token
Browse files Browse the repository at this point in the history
  • Loading branch information
mobo4b committed Apr 12, 2021
1 parent f63b65b commit ae9b878
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 56 deletions.
7 changes: 2 additions & 5 deletions api/videoservice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,12 @@ components:
CreateVideoCallResponseDTO:
type: object
required:
- guestVideoCallUrl
- moderatorVideoCallUrl
properties:
guestVideoCallUrl:
type: string
example: http://video.call/332a573d-7c74-4080-8353-7954eca066f9?jwt={guestToken}
moderatorVideoCallUrl:
type: string
example: http://video.call/332a573d-7c74-4080-8353-7954eca066f9?jwt={moderatorToken}
example: https://video.call/332a573d-7c74-4080-8353-7954eca066f9?jwt={moderatorToken}
description: Moderator video call URL containing moderator role and guest join link
RejectVideoCallDTO:
type: object
required:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public CreateVideoCallResponseDTO startVideoCall(Long sessionId, String initiato
singletonList(consultantSessionDto.getAskerId()));

return new CreateVideoCallResponseDTO()
.guestVideoCallUrl(videoCallUrls.getGuestVideoUrl())
.moderatorVideoCallUrl(videoCallUrls.getModeratorVideoUrl());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ public class VideoCallUrlGeneratorService {
public VideoCallUrls generateVideoCallUrls(String askerName) {

String uuid = uuidRegistry.generateUniqueUuid();
VideoCallToken token = this.tokenGeneratorService.generateToken(uuid, askerName);
VideoCallToken token = this.tokenGeneratorService.generateNonModeratorToken(uuid, askerName);

return VideoCallUrls.builder()
.guestVideoUrl(buildUrl(uuid, token.getGuestToken()))
.userVideoUrl(buildUrl(uuid, token.getUserRelatedToken()))
.moderatorVideoUrl(buildUrl(uuid, token.getModeratorToken()))
.moderatorVideoUrl(buildUrl(uuid, this.tokenGeneratorService
.generateModeratorToken(uuid, buildUrl(uuid, token.getGuestToken()))))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import static java.time.ZoneOffset.UTC;
import static java.time.temporal.ChronoUnit.HOURS;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator.Builder;
import com.auth0.jwt.algorithms.Algorithm;
import de.caritas.cob.videoservice.api.exception.httpresponse.InternalServerErrorException;
import de.caritas.cob.videoservice.api.service.decoder.UsernameDecoder;
import de.caritas.cob.videoservice.api.service.video.jwt.model.VideoCallToken;
import java.sql.Date;
Expand All @@ -24,6 +26,7 @@ public class TokenGeneratorService {
private static final String CONTEXT_CLAIM = "context";
private static final String ROOM_CLAIM = "room";
private static final String MODERATOR_CLAIM = "moderator";
private static final String GUEST_URL_CLAIM = "guestVideoCallUrl";
private static final String CONTEXT_USER = "user";
private static final String USER_NAME = "name";

Expand All @@ -45,23 +48,44 @@ public class TokenGeneratorService {
private Algorithm algorithm;

/**
* Generates the {@link VideoCallToken} for anonymous user, asker (containing user name) and
* moderator.
* Generates the {@link VideoCallToken} for anonymous user and asker (containing user name).
*
* @param roomId the generated unique roomId
* @param askerName the username of the asker
* @return the generated {@link VideoCallToken}
*/
public VideoCallToken generateToken(String roomId, String askerName) {
algorithm = Algorithm.HMAC256(this.secret);
public VideoCallToken generateNonModeratorToken(String roomId, String askerName) {
this.setAlgorithm();

return VideoCallToken.builder()
.guestToken(buildGuestJwt(roomId))
.userRelatedToken(buildUserRelatedJwt(roomId, askerName))
.moderatorToken(buildModeratorJwt(roomId))
.build();
}

/**
* Generates the {@link VideoCallToken} for the moderator.
*
* @param roomId the generated unique roomId
* @param guestVideoCallUrl the guest video call URL
* @return the generated moderator token
*/
public String generateModeratorToken(String roomId, String guestVideoCallUrl) {
if (isEmpty(roomId) || isEmpty(guestVideoCallUrl)) {
throw new InternalServerErrorException(String
.format("Room ID (%s) and guest video call URL (%s) cannot be empty.", roomId,
guestVideoCallUrl));
}

this.setAlgorithm();

return buildModeratorJwt(roomId, guestVideoCallUrl);
}

private void setAlgorithm() {
this.algorithm = Algorithm.HMAC256(this.secret);
}

private String buildGuestJwt(String roomId) {
return buildBasicJwt(roomId)
.sign(algorithm);
Expand All @@ -73,9 +97,10 @@ private String buildUserRelatedJwt(String roomId, String askerName) {
.sign(algorithm);
}

private String buildModeratorJwt(String roomId) {
private String buildModeratorJwt(String roomId, String guestVideoCallUrl) {
return buildBasicJwt(roomId)
.withClaim(MODERATOR_CLAIM, true)
.withClaim(GUEST_URL_CLAIM, guestVideoCallUrl)
.sign(algorithm);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
import lombok.Getter;

/**
* Video call token for anonymous, asker (containing user name) and moderator.
* Video call token for anonymous user and asker (containing user name).
*/
@Getter
@Builder
public class VideoCallToken {

private final String guestToken;
private final String userRelatedToken;
private final String moderatorToken;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
@Builder
public class VideoCallUrls {

private final String guestVideoUrl;
private final String userVideoUrl;
private final String moderatorVideoUrl;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class StartVideoCallFacadeTest {
private AuthenticatedUser authenticatedUser;

@Test
public void startVideoCall_Should_ReturnCorrectVideoCallUrls_When_UrlWasGeneratedSuccessfully() {
public void startVideoCall_Should_ReturnCorrectVideoCallUrl_When_UrlWasGeneratedSuccessfully() {

ConsultantSessionDTO consultantSessionDto = mock(ConsultantSessionDTO.class);
when(consultantSessionDto.getStatus()).thenReturn(IN_PROGRESS.getValue());
Expand All @@ -59,7 +59,6 @@ public void startVideoCall_Should_ReturnCorrectVideoCallUrls_When_UrlWasGenerate

CreateVideoCallResponseDTO result = startVideoCallFacade.startVideoCall(SESSION_ID, "rcUserId");

assertThat(result.getGuestVideoCallUrl(), is(videoCallUrls.getGuestVideoUrl()));
assertThat(result.getModeratorVideoCallUrl(), is(videoCallUrls.getModeratorVideoUrl()));
}

Expand Down Expand Up @@ -103,4 +102,4 @@ public void startVideoCall_Should_throwBadRequestException_When_sessionIsNotInPr
startVideoCallFacade.startVideoCall(SESSION_ID, "");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public class VideoCallUrlGeneratorServiceTest {

private static final String FIELD_NAME_VIDEO_CALL_URL = "videoCallServerUrl";
private static final String VIDEO_CALL_URL = "http://video.call";
private static final String VIDEO_CALL_URL = "https://video.call";

@InjectMocks
private VideoCallUrlGeneratorService videoCallUrlGeneratorService;
Expand All @@ -38,24 +38,25 @@ public void generateVideoCallUrls_Should_generateExpectedVideoCallUrls_When_aske
setField(this.videoCallUrlGeneratorService, FIELD_NAME_VIDEO_CALL_URL, VIDEO_CALL_URL);
when(this.uuidRegistry.generateUniqueUuid()).thenReturn("uniqueId");
VideoCallToken videoCallToken = new EasyRandom().nextObject(VideoCallToken.class);
when(this.tokenGeneratorService.generateToken(any(), any()))
String moderatorToken = "moderatorToken";
when(this.tokenGeneratorService.generateNonModeratorToken(any(), any()))
.thenReturn(videoCallToken);
when(this.tokenGeneratorService.generateModeratorToken(any(), any()))
.thenReturn(moderatorToken);

VideoCallUrls videoCallUrls = this.videoCallUrlGeneratorService
.generateVideoCallUrls("asker123");

assertThat(videoCallUrls.getGuestVideoUrl(),
is(VIDEO_CALL_URL + "/uniqueId?jwt=" + videoCallToken.getGuestToken()));
assertThat(videoCallUrls.getUserVideoUrl(),
is(VIDEO_CALL_URL + "/uniqueId?jwt=" + videoCallToken.getUserRelatedToken()));
assertThat(videoCallUrls.getModeratorVideoUrl(),
is(VIDEO_CALL_URL + "/uniqueId?jwt=" + videoCallToken.getModeratorToken()));
is(VIDEO_CALL_URL + "/uniqueId?jwt=" + moderatorToken));
}

@Test(expected = InternalServerErrorException.class)
public void generateVideoCallUrls_Should_throwInternalServerErrorException_When_videoUrlIsInvalid() {
VideoCallToken videoCallToken = new EasyRandom().nextObject(VideoCallToken.class);
when(this.tokenGeneratorService.generateToken(any(), any()))
when(this.tokenGeneratorService.generateNonModeratorToken(any(), any()))
.thenReturn(videoCallToken);

this.videoCallUrlGeneratorService.generateVideoCallUrls("asker123");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.caritas.cob.videoservice.api.service.video.jwt;

import static de.caritas.cob.videoservice.api.testhelper.TestConstants.GUEST_VIDEO_CALL_URL;
import static java.util.Collections.singletonList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
Expand All @@ -10,6 +11,7 @@
import com.auth0.jwt.JWT;
import com.auth0.jwt.impl.NullClaim;
import com.auth0.jwt.interfaces.DecodedJWT;
import de.caritas.cob.videoservice.api.exception.httpresponse.InternalServerErrorException;
import de.caritas.cob.videoservice.api.service.video.jwt.model.VideoCallToken;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -31,24 +33,6 @@ public void setup() {
setField(tokenGeneratorService, "validityHours", 10);
}

@Test
public void generateToken_Should_returnExpectedTokens_When_roomIdAndAskerAreEmpty() {
VideoCallToken token = this.tokenGeneratorService.generateToken("", "");

String guestToken = token.getGuestToken();
String userToken = token.getUserRelatedToken();
String moderatorToken = token.getModeratorToken();

verifyBasicTokenFields(guestToken, "");
verifyBasicTokenFields(userToken, "");
verifyBasicTokenFields(moderatorToken, "");
assertThat(JWT.decode(guestToken).getClaim("context"), instanceOf(NullClaim.class));
assertThat(JWT.decode(userToken).getClaim("context").asMap().get("user").toString(),
is("{name=}"));
assertThat(JWT.decode(moderatorToken).getClaim("moderator").asBoolean(),
is(true));
}

private void verifyBasicTokenFields(String jwt, String expectedRoomId) {
DecodedJWT decodedBasicToken = JWT.decode(jwt);
assertThat(decodedBasicToken.getAudience(), is(singletonList(AUDIENCE_VALUE)));
Expand All @@ -60,28 +44,60 @@ private void verifyBasicTokenFields(String jwt, String expectedRoomId) {
}

@Test
public void generateToken_Should_returnExpectedTokens_When_roomIdIsGiven() {
VideoCallToken token = this.tokenGeneratorService.generateToken("validRoomId", "");
public void generateNonModeratorToken_Should_returnExpectedTokens_When_roomIdIsGiven() {
VideoCallToken token = this.tokenGeneratorService.generateNonModeratorToken("validRoomId", "");

String guestToken = token.getGuestToken();
String userToken = token.getUserRelatedToken();
String moderatorToken = token.getModeratorToken();

verifyBasicTokenFields(guestToken, "validRoomId");
verifyBasicTokenFields(userToken, "validRoomId");
verifyBasicTokenFields(moderatorToken, "validRoomId");
assertThat(JWT.decode(moderatorToken).getClaim("moderator").asBoolean(),
is(true));
}

@Test
public void generateToken_Should_returnExpectedContextInUserToken_When_askerUsernameIsGiven() {
VideoCallToken token = this.tokenGeneratorService.generateToken("", "asker123");
public void generateNonModeratorToken_Should_returnExpectedTokens_When_roomIdAndAskerAreEmpty() {
VideoCallToken token = this.tokenGeneratorService.generateNonModeratorToken("", "");

String guestToken = token.getGuestToken();
String userToken = token.getUserRelatedToken();

verifyBasicTokenFields(guestToken, "");
verifyBasicTokenFields(userToken, "");
assertThat(JWT.decode(guestToken).getClaim("context"), instanceOf(NullClaim.class));
assertThat(JWT.decode(userToken).getClaim("context").asMap().get("user").toString(),
is("{name=}"));
}

@Test
public void generateNonModeratorToken_Should_returnExpectedContextInUserToken_When_askerUsernameIsGiven() {
VideoCallToken token = this.tokenGeneratorService.generateNonModeratorToken("", "asker123");

String userToken = token.getUserRelatedToken();

assertThat(JWT.decode(userToken).getClaim("context").asMap().get("user").toString(),
is("{name=asker123}"));
}

@Test(expected = InternalServerErrorException.class)
public void generateModeratorToken_Should_ThrowInternalServerErrorException_When_roomIdIsEmpty() {
this.tokenGeneratorService
.generateModeratorToken("", GUEST_VIDEO_CALL_URL);
}

@Test(expected = InternalServerErrorException.class)
public void generateModeratorToken_Should_ThrowInternalServerErrorException_When_guestVideoCallUrlIsEmpty() {
this.tokenGeneratorService.generateModeratorToken("validRoomId", "");
}

@Test
public void generateModeratorToken_Should_returnExpectedToken_When_ParamsAreGiven() {
String moderatorToken = this.tokenGeneratorService
.generateModeratorToken("validRoomId", GUEST_VIDEO_CALL_URL);

verifyBasicTokenFields(moderatorToken, "validRoomId");
assertThat(JWT.decode(moderatorToken).getClaim("moderator").asBoolean(),
is(true));
assertThat(JWT.decode(moderatorToken).getClaim("guestVideoCallUrl").asString(),
is(GUEST_VIDEO_CALL_URL));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ public class TestConstants {
* Video call
*/
public static final String GUEST_VIDEO_CALL_URL =
"http://video.call/237849234-34534-345345?jwt={guestToken}";
"https://video.call/237849234-34534-345345?jwt={guestToken}";
public static final String MODERATOR_VIDEO_CALL_URL =
"http://video.call/237849234-34534-345345?jwt={moderatorToken}";
"https://video.call/237849234-34534-345345?jwt={moderatorToken}";
public static final CreateVideoCallResponseDTO CREATE_VIDEO_CALL_RESPONSE_DTO =
new CreateVideoCallResponseDTO()
.guestVideoCallUrl(GUEST_VIDEO_CALL_URL)
.moderatorVideoCallUrl(MODERATOR_VIDEO_CALL_URL);

/*
Expand Down

0 comments on commit ae9b878

Please sign in to comment.