Skip to content

Commit

Permalink
feat: send live events only asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
webatspeed committed Oct 13, 2022
1 parent 4d0aa8c commit 2ea5ad6
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import de.caritas.cob.uploadservice.api.service.UploadTrackingService;
import de.caritas.cob.uploadservice.api.statistics.StatisticsService;
import de.caritas.cob.uploadservice.api.statistics.event.CreateMessageStatisticsEvent;
import de.caritas.cob.uploadservice.api.tenant.TenantContext;
import de.caritas.cob.uploadservice.statisticsservice.generated.web.model.UserRole;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -57,7 +58,8 @@ public void uploadFileToRoom(

sanitizeAndEncryptParametersAndUploadToRocketChatRoom(
rocketChatCredentials, rocketChatUploadParameter);
this.liveEventNotificationService.sendLiveEvent(rocketChatUploadParameter.getRoomId());
this.liveEventNotificationService.sendLiveEvent(rocketChatUploadParameter.getRoomId(),
authenticatedUser.getAccessToken(), TenantContext.getCurrentTenantOption());
this.uploadTrackingService.trackUploadedFileForUser(rocketChatUploadParameter.getRoomId());

if (sendNotification) {
Expand Down Expand Up @@ -93,7 +95,8 @@ public void uploadFileToFeedbackRoom(
this.uploadTrackingService.validateUploadLimit(rocketChatUploadParameter.getRoomId());
sanitizeAndEncryptParametersAndUploadToRocketChatRoom(
rocketChatCredentials, rocketChatUploadParameter);
this.liveEventNotificationService.sendLiveEvent(rocketChatUploadParameter.getRoomId());
this.liveEventNotificationService.sendLiveEvent(rocketChatUploadParameter.getRoomId(),
authenticatedUser.getAccessToken(), TenantContext.getCurrentTenantOption());
this.uploadTrackingService.trackUploadedFileForUser(rocketChatUploadParameter.getRoomId());

if (sendNotification) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ private void sendEmailNotificationCallingMethod(String rcGroupId, String accessT

private void addDefaultHeaders(
de.caritas.cob.uploadservice.userservice.generated.ApiClient apiClient, String accessToken, Optional<Long> currentTenant) {
HttpHeaders headers = this.serviceHelper.getKeycloakAndCsrfHttpHeaders(accessToken);
HttpHeaders headers = this.serviceHelper.getKeycloakAndCsrfHttpHeaders(accessToken, currentTenant);
addTenantHeaderIfPresent(currentTenant, headers);
headers.forEach((key, value) -> apiClient.addDefaultHeader(key, value.iterator().next()));
}

private void addTenantHeaderIfPresent(Optional<Long> currentTenant, HttpHeaders headers) {
if (currentTenant.isPresent()) {
TenantContext.setCurrentTenant(currentTenant.get());
tenantHeaderSupplier.addTenantHeader(headers);
tenantHeaderSupplier.addTenantHeader(headers, currentTenant);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import de.caritas.cob.uploadservice.api.service.helper.ServiceHelper;
import de.caritas.cob.uploadservice.userservice.generated.ApiClient;
import de.caritas.cob.uploadservice.userservice.generated.web.LiveproxyControllerApi;
import java.util.Optional;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
Expand All @@ -29,9 +29,9 @@ public class LiveEventNotificationService {
* @param rcGroupId the rocket chat group id
*/
@Async
public void sendLiveEvent(String rcGroupId) {
public void sendLiveEvent(String rcGroupId, String accessToken, Optional<Long> tenantId) {
if (isNotBlank(rcGroupId)) {
addDefaultHeaders(this.liveproxyControllerApi.getApiClient());
addDefaultHeaders(this.liveproxyControllerApi.getApiClient(), accessToken, tenantId);
try {
this.liveproxyControllerApi.sendLiveEvent(rcGroupId);
} catch (RestClientException e) {
Expand All @@ -41,9 +41,8 @@ public void sendLiveEvent(String rcGroupId) {
}
}

private void addDefaultHeaders(ApiClient apiClient) {
HttpHeaders headers = this.serviceHelper.getKeycloakAndCsrfHttpHeaders();
tenantHeaderSupplier.addTenantHeader(headers);
private void addDefaultHeaders(ApiClient apiClient, String accessToken, Optional<Long> tenantId) {
var headers = serviceHelper.getKeycloakAndCsrfHttpHeaders(accessToken, tenantId);
headers.forEach((key, value) -> apiClient.addDefaultHeader(key, value.iterator().next()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ public class TenantHeaderSupplier {
@Value("${multitenancy.enabled}")
private boolean multitenancy;

public void addTenantHeader(HttpHeaders headers) {
public void addTenantHeader(HttpHeaders headers, Optional<Long> tenantId) {
if (multitenancy) {
headers.add("tenantId", TenantContext.getCurrentTenant().toString());
var tenantIdNumber = tenantId.orElseGet(TenantContext::getCurrentTenant);
headers.add("tenantId", tenantIdNumber.toString());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package de.caritas.cob.uploadservice.api.service.helper;

import static java.util.Objects.isNull;

import de.caritas.cob.uploadservice.api.helper.AuthenticatedUser;
import de.caritas.cob.uploadservice.api.service.TenantHeaderSupplier;
import java.util.Optional;
import java.util.UUID;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
Expand All @@ -20,34 +24,28 @@ public class ServiceHelper {
private String csrfCookieProperty;

private final @NonNull AuthenticatedUser authenticatedUser;
private final @NonNull TenantHeaderSupplier tenantHeaderSupplier;

/**
* Returns {@link HttpHeaders} with CSRF cookie and CSRF header and the provided Keycloak Bearer
* token.
*
* @param accessToken Keycloak Bearer token
* @param tenantId optional tenant ID
* @return {@link HttpHeaders}
*/
public HttpHeaders getKeycloakAndCsrfHttpHeaders(String accessToken) {
return createKeycloakAuthHeader(accessToken);
}
public HttpHeaders getKeycloakAndCsrfHttpHeaders(String accessToken, Optional<Long> tenantId) {
var headers = new HttpHeaders();
addCsrfValues(headers);
tenantHeaderSupplier.addTenantHeader(headers, tenantId);
addAuthorizationHeader(headers, accessToken);

/**
* Returns {@link HttpHeaders} with CSRF cookie and CSRF header and the Keycloak Bearer token of
* the currently authenticated user.
*
* @return {@link HttpHeaders}
*/
public HttpHeaders getKeycloakAndCsrfHttpHeaders() {
return createKeycloakAuthHeader(authenticatedUser.getAccessToken());
return headers;
}

private HttpHeaders createKeycloakAuthHeader(String accessToken) {
HttpHeaders header = new HttpHeaders();
header = this.addCsrfValues(header);
header.add("Authorization", "Bearer " + accessToken);

return header;
private void addAuthorizationHeader(HttpHeaders headers, String accessToken) {
var token = isNull(accessToken) ? authenticatedUser.getAccessToken() : accessToken;
headers.add("Authorization", "Bearer " + token);
}

private HttpHeaders addCsrfValues(HttpHeaders httpHeaders) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.caritas.cob.uploadservice.api.tenant;

import java.util.Optional;

public class TenantContext {

private TenantContext() {
Expand All @@ -12,11 +14,15 @@ public static Long getCurrentTenant() {
return currentTenant.get();
}

public static Optional<Long> getCurrentTenantOption() {
return Optional.ofNullable(getCurrentTenant());
}

public static void setCurrentTenant(Long tenant) {
currentTenant.set(tenant);
}

public static void clear() {
currentTenant.remove();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
Expand Down Expand Up @@ -187,7 +188,7 @@ public void uploadFileToRoom_Should_sendLiveNotification_When_UploadSucceeds() {
uploadFacade.uploadFileToRoom(rocketChatCredentials, rocketChatUploadParameter, false);

verify(this.liveEventNotificationService, times(1))
.sendLiveEvent(rocketChatUploadParameter.getRoomId());
.sendLiveEvent(eq(rocketChatUploadParameter.getRoomId()), any(), any());
}

@Test(expected = InternalServerErrorException.class)
Expand Down Expand Up @@ -286,6 +287,6 @@ public void uploadFileToFeedbackRoom_Should_sendLiveNotification_When_UploadSucc
uploadFacade.uploadFileToFeedbackRoom(rocketChatCredentials, rocketChatUploadParameter, false);

verify(this.liveEventNotificationService, times(1))
.sendLiveEvent(rocketChatUploadParameter.getRoomId());
.sendLiveEvent(eq(rocketChatUploadParameter.getRoomId()), any(), any());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.caritas.cob.uploadservice.api.helper;

import static de.caritas.cob.uploadservice.helper.TestConstants.KEYCLOAK_ACCESS_TOKEN;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
Expand Down Expand Up @@ -56,7 +57,7 @@ public void sendEmailNotificationViaUserService_Should_LogException_OnError()
// given
RestClientException exception = new RestClientException(ERROR);
when(userControllerApi.getApiClient()).thenReturn(apiClient);
when(serviceHelper.getKeycloakAndCsrfHttpHeaders(Mockito.anyString())).thenReturn(new HttpHeaders());
when(serviceHelper.getKeycloakAndCsrfHttpHeaders(Mockito.anyString(), any())).thenReturn(new HttpHeaders());
doThrow(exception).when(userControllerApi).sendNewMessageNotification(Mockito.any(NewMessageNotificationDTO.class));

// when
Expand All @@ -72,7 +73,7 @@ public void sendEmailNotificationViaUserService_Should_LogException_OnError()
public void sendEmailNotificationViaUserService_Should_CallUserServiceWithGiveUrl() {
// given
when(userControllerApi.getApiClient()).thenReturn(apiClient);
when(serviceHelper.getKeycloakAndCsrfHttpHeaders(Mockito.anyString())).thenReturn(new HttpHeaders());
when(serviceHelper.getKeycloakAndCsrfHttpHeaders(Mockito.anyString(), any())).thenReturn(new HttpHeaders());

// when
emailNotificationHelper.sendEmailNotificationViaUserService(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package de.caritas.cob.uploadservice.api.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import de.caritas.cob.uploadservice.api.service.helper.ServiceHelper;
import de.caritas.cob.uploadservice.api.helper.AuthenticatedUser;
import de.caritas.cob.uploadservice.userservice.generated.ApiClient;
import de.caritas.cob.uploadservice.userservice.generated.web.LiveproxyControllerApi;
import java.lang.management.ManagementFactory;
import java.util.Optional;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpHeaders;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;

Expand All @@ -30,15 +33,49 @@ class LiveEventNotificationServiceIT {
private LiveproxyControllerApi liveproxyControllerApi;

@MockBean
private ServiceHelper serviceHelper;
private AuthenticatedUser authenticatedUser;

@MockBean
private ApiClient apiClient;

@Test
void sendLiveEventShouldRunInAnotherThread() {
when(serviceHelper.getKeycloakAndCsrfHttpHeaders()).thenReturn(new HttpHeaders());
when(liveproxyControllerApi.getApiClient()).thenReturn(apiClient);
var threadCount = ManagementFactory.getThreadMXBean().getThreadCount();

underTest.sendLiveEvent(RandomStringUtils.randomAlphanumeric(16));
underTest.sendLiveEvent(
RandomStringUtils.randomAlphanumeric(16),
RandomStringUtils.randomAlphanumeric(16),
Optional.of(Long.valueOf(RandomStringUtils.randomNumeric(1)))
);

assertEquals(threadCount + 1, ManagementFactory.getThreadMXBean().getThreadCount());
}

@Test
void sendLiveEventShouldNeverCallAuthenticatedUserMethodsWhenAccessTokenGiven() {
when(liveproxyControllerApi.getApiClient()).thenReturn(apiClient);

underTest.sendLiveEvent(
RandomStringUtils.randomAlphanumeric(16),
RandomStringUtils.randomAlphanumeric(16),
Optional.of(Long.valueOf(RandomStringUtils.randomNumeric(1)))
);

verify(authenticatedUser, timeout(1000).times(0))
.getAccessToken();
}

@Test
void sendLiveEventShouldCallAuthenticatedUserMethodsWhenAccessTokenMissing() {
when(liveproxyControllerApi.getApiClient()).thenReturn(apiClient);

underTest.sendLiveEvent(
RandomStringUtils.randomAlphanumeric(16),
null,
Optional.of(Long.valueOf(RandomStringUtils.randomNumeric(1)))
);

verify(authenticatedUser, timeout(1000)).getAccessToken();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.caritas.cob.uploadservice.api.service;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
Expand All @@ -12,6 +13,7 @@
import de.caritas.cob.uploadservice.api.service.helper.ServiceHelper;
import de.caritas.cob.uploadservice.userservice.generated.ApiClient;
import de.caritas.cob.uploadservice.userservice.generated.web.LiveproxyControllerApi;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -47,15 +49,15 @@ public void setup() {

@Test
public void sendLiveEvent_Should_notTriggerLiveEvent_When_rcGroupIdIsNull() {
this.liveEventNotificationService.sendLiveEvent(null);
this.liveEventNotificationService.sendLiveEvent(null, null, Optional.empty());

verifyNoMoreInteractions(this.liveproxyControllerApi);
verifyNoMoreInteractions(this.serviceHelper);
}

@Test
public void sendLiveEvent_Should_notTriggerLiveEvent_When_rcGroupIdIsEmpty() {
this.liveEventNotificationService.sendLiveEvent("");
this.liveEventNotificationService.sendLiveEvent(null, null, Optional.empty());

verifyNoMoreInteractions(this.liveproxyControllerApi);
verifyNoMoreInteractions(this.serviceHelper);
Expand All @@ -68,12 +70,12 @@ public void sendLiveEvent_Should_triggerLiveEventWithHeaders_When_rcGroupIdIsVal
HttpHeaders headers = new HttpHeaders();
headers.add("header 1", "value 1");
headers.add("header 2", "value 2");
when(this.serviceHelper.getKeycloakAndCsrfHttpHeaders()).thenReturn(headers);
when(this.serviceHelper.getKeycloakAndCsrfHttpHeaders(anyString(), any())).thenReturn(headers);

this.liveEventNotificationService.sendLiveEvent("valid");
this.liveEventNotificationService.sendLiveEvent("valid", "", Optional.empty());

verify(this.liveproxyControllerApi, times(1)).sendLiveEvent("valid");
verify(this.serviceHelper, times(1)).getKeycloakAndCsrfHttpHeaders();
verify(this.serviceHelper, times(1)).getKeycloakAndCsrfHttpHeaders(anyString(), any());
verify(apiClient, times(2)).addDefaultHeader(anyString(), anyString());
}

Expand All @@ -82,9 +84,10 @@ public void sendLiveEvent_Should_logError_When_apiClientThrowsRestClientExceptio
doThrow(new RestClientException("")).when(this.liveproxyControllerApi)
.sendLiveEvent(anyString());
when(this.liveproxyControllerApi.getApiClient()).thenReturn(mock(ApiClient.class));
when(this.serviceHelper.getKeycloakAndCsrfHttpHeaders()).thenReturn(new HttpHeaders());
when(this.serviceHelper.getKeycloakAndCsrfHttpHeaders(anyString(), any()))
.thenReturn(new HttpHeaders());

this.liveEventNotificationService.sendLiveEvent("valid");
this.liveEventNotificationService.sendLiveEvent("valid", "", Optional.empty());

verify(this.logger, times(1)).error(anyString(), anyString(), anyString());
}
Expand Down
Loading

0 comments on commit 2ea5ad6

Please sign in to comment.