Skip to content

Commit

Permalink
feat: check on writing to a feedback chat if provided group id is valid
Browse files Browse the repository at this point in the history
  • Loading branch information
mobo4b committed Aug 24, 2020
1 parent d49cfcd commit 8291bb2
Show file tree
Hide file tree
Showing 15 changed files with 530 additions and 289 deletions.
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"dependencies": {
"dotenv": "^8.2.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.caritas.cob.messageservice.api;

import de.caritas.cob.messageservice.api.exception.BadRequestException;
import de.caritas.cob.messageservice.api.exception.CustomCryptoException;
import de.caritas.cob.messageservice.api.exception.InternalServerErrorException;
import de.caritas.cob.messageservice.api.exception.KeycloakException;
Expand Down Expand Up @@ -38,12 +39,12 @@ public class ApiResponseEntityExceptionHandler extends ResponseEntityExceptionHa
/**
* Constraint violations.
*
* @param ex the exception to be handled
* @param ex the exception to be handled
* @param request the web request where the exception was thrown
*/
@ExceptionHandler({ConstraintViolationException.class, RocketChatBadRequestException.class})
public ResponseEntity<Object> handleBadRequest(final RuntimeException ex,
final WebRequest request) {
public ResponseEntity<Object> handleBadRequest(
final RuntimeException ex, final WebRequest request) {
LogService.logWarning(ex);

return handleExceptionInternal(null, null, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
Expand All @@ -59,7 +60,9 @@ public ResponseEntity<Object> handleBadRequest(final RuntimeException ex,
*/
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(
final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status,
final HttpMessageNotReadableException ex,
final HttpHeaders headers,
final HttpStatus status,
final WebRequest request) {
LogService.logWarning(status, ex);

Expand All @@ -70,13 +73,15 @@ protected ResponseEntity<Object> handleHttpMessageNotReadable(
* @Valid on object fails validation.
*
* @param ex the exception to be handled
* @param headers http headers
* @param headers http headers
* @param status http status
* @param request web request
*/
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status,
final MethodArgumentNotValidException ex,
final HttpHeaders headers,
final HttpStatus status,
final WebRequest request) {
LogService.logWarning(status, ex);

Expand All @@ -86,12 +91,12 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(
/**
* 409 - Conflict.
*
* @param ex the exception to be handled
* @param ex the exception to be handled
* @param request web request
*/
@ExceptionHandler({InvalidDataAccessApiUsageException.class, DataAccessException.class})
protected ResponseEntity<Object> handleConflict(final RuntimeException ex,
final WebRequest request) {
protected ResponseEntity<Object> handleConflict(
final RuntimeException ex, final WebRequest request) {
LogService.logWarning(HttpStatus.CONFLICT, ex);

return handleExceptionInternal(null, null, new HttpHeaders(), HttpStatus.CONFLICT, request);
Expand All @@ -100,12 +105,12 @@ protected ResponseEntity<Object> handleConflict(final RuntimeException ex,
/**
* {@link RestTemplate} API client errors.
*
* @param ex the exception to be handled
* @param ex the exception to be handled
* @param request web request
*/
@ExceptionHandler({HttpClientErrorException.class})
protected ResponseEntity<Object> handleHttpClientException(final HttpClientErrorException ex,
final WebRequest request) {
protected ResponseEntity<Object> handleHttpClientException(
final HttpClientErrorException ex, final WebRequest request) {
LogService.logWarning(ex.getStatusCode(), ex);

return handleExceptionInternal(null, null, new HttpHeaders(), ex.getStatusCode(), request);
Expand All @@ -114,33 +119,46 @@ protected ResponseEntity<Object> handleHttpClientException(final HttpClientError
/**
* 500 - Internal Server Error.
*
* @param ex the exception to be handled
* @param ex the exception to be handled
* @param request web request
*/
@ExceptionHandler({NullPointerException.class, IllegalArgumentException.class,
IllegalStateException.class, ServiceException.class, KeycloakException.class,
UnknownHostException.class, CustomCryptoException.class, NoMasterKeyException.class})
public ResponseEntity<Object> handleInternal(final RuntimeException ex,
final WebRequest request) {
public ResponseEntity<Object> handleInternal(
final RuntimeException ex, final WebRequest request) {
LogService.logInternalServerError(ex);

return handleExceptionInternal(null, null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR,
request);
return handleExceptionInternal(
null, null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}

/**
* 500 - Custom Internal Server Error with logging method.
*
* @param ex the exception to be handled
* @param ex the exception to be handled
* @param request web request
*/
@ExceptionHandler({InternalServerErrorException.class})
public ResponseEntity<Object> handleInternal(final InternalServerErrorException ex,
final WebRequest request) {
public ResponseEntity<Object> handleInternal(
final InternalServerErrorException ex, final WebRequest request) {
ex.executeLogging();

return handleExceptionInternal(null, null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR,
request);
return handleExceptionInternal(
null, null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}

/**
* 400 - Custom Bad Request with logging method.
*
* @param ex the exception to be handled
* @param request web request
*/
@ExceptionHandler({BadRequestException.class})
public ResponseEntity<Object> handleInternal(
final BadRequestException ex, final WebRequest request) {
ex.executeLogging();

return handleExceptionInternal(null, null, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.caritas.cob.messageservice.api.exception;

import java.util.function.Consumer;

/** Represents the response status code 400 - Bad Request. */
public class BadRequestException extends CustomLoggableResponseException {

/**
* Creates a Bad Request with a custom message to be logged.
*
* @param message the message
* @param loggingMethod the method to log that exception
*/
public BadRequestException(String message, Consumer<String> loggingMethod) {
super(message, loggingMethod);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import static java.util.Objects.isNull;

import de.caritas.cob.messageservice.api.exception.BadRequestException;
import de.caritas.cob.messageservice.api.exception.CustomCryptoException;
import de.caritas.cob.messageservice.api.exception.InternalServerErrorException;
import de.caritas.cob.messageservice.api.exception.RocketChatPostMarkGroupAsReadException;
import de.caritas.cob.messageservice.api.exception.RocketChatPostMessageException;
import de.caritas.cob.messageservice.api.model.MessageDTO;
import de.caritas.cob.messageservice.api.model.rocket.chat.group.GetGroupInfoDto;
import de.caritas.cob.messageservice.api.model.rocket.chat.message.PostMessageResponseDTO;
import de.caritas.cob.messageservice.api.service.LogService;
import de.caritas.cob.messageservice.api.service.RocketChatService;
Expand All @@ -21,15 +23,16 @@ public class PostGroupMessageFacade {

private final RocketChatService rocketChatService;
private final EmailNotificationFacade emailNoticationFacade;
private static final String FEEDBACK_GROUP_SUFFIX = "feedback";

/**
* Constructor
*
* @param rocketChatService
* @param rocketChatService {@link RocketChatService}
*/
@Autowired
public PostGroupMessageFacade(RocketChatService rocketChatService,
EmailNotificationFacade emailNoticationFacade) {
public PostGroupMessageFacade(
RocketChatService rocketChatService, EmailNotificationFacade emailNoticationFacade) {
this.rocketChatService = rocketChatService;
this.emailNoticationFacade = emailNoticationFacade;
}
Expand All @@ -38,13 +41,13 @@ public PostGroupMessageFacade(RocketChatService rocketChatService,
* Posts a message to the given Rocket.Chat group id and sends out a notification e-mail via the
* UserService (because we need to get the user information).
*
* @param rcToken
* @param rcUserId
* @param rcGroupId
* @param message
* @param rcToken Rocket.Chat token
* @param rcUserId Rocket.Chat user ID
* @param rcGroupId Rocket.Chat group ID
* @param message the message
*/
public void postGroupMessage(String rcToken, String rcUserId, String rcGroupId,
MessageDTO message) {
public void postGroupMessage(
String rcToken, String rcUserId, String rcGroupId, MessageDTO message) {

postRocketChatGroupMessage(rcToken, rcUserId, rcGroupId, message.getMessage(), null);

Expand All @@ -57,43 +60,56 @@ public void postGroupMessage(String rcToken, String rcUserId, String rcGroupId,
* Posts a message to the given Rocket.Chat feedback group id and sends out a notification e-mail
* via the UserService (because we need to get the user information).
*
* @param rcToken
* @param rcUserId
* @param rcFeedbackGroupId
* @param message
* @param rcToken Rocket.Chat token
* @param rcUserId Rocket.Chat user ID
* @param rcFeedbackGroupId Rocket.Chat feedback group ID
* @param message the message
*/
public void postFeedbackGroupMessage(String rcToken, String rcUserId,
String rcFeedbackGroupId, String message, String alias) {
public void postFeedbackGroupMessage(
String rcToken, String rcUserId, String rcFeedbackGroupId, String message, String alias) {

validateFeedbackChatId(rcToken, rcUserId, rcFeedbackGroupId);
postRocketChatGroupMessage(rcToken, rcUserId, rcFeedbackGroupId, message, alias);
emailNoticationFacade.sendFeedbackEmailNotification(rcFeedbackGroupId);
}

/**
* Posts a message to the given Rocket.Chat group id
*
* @param rcToken
* @param rcUserId
* @param rcGroupId
* @param message
* @param alias
* @param rcToken Rocket.Chat token
* @param rcUserId Rocket.Chat user ID
* @param rcGroupId Rocket.Chat group ID
* @param message the message
* @param alias alias containing forward message information
*/
private void postRocketChatGroupMessage(String rcToken, String rcUserId, String rcGroupId,
String message, String alias) {
private void postRocketChatGroupMessage(
String rcToken, String rcUserId, String rcGroupId, String message, String alias) {

try {
// Send message to Rocket.Chat via RocketChatService
PostMessageResponseDTO response = rocketChatService.postGroupMessage(rcToken, rcUserId,
rcGroupId, message, alias);
PostMessageResponseDTO response =
rocketChatService.postGroupMessage(rcToken, rcUserId, rcGroupId, message, alias);
if (isNull(response) || !response.isSuccess()) {
throw new InternalServerErrorException();
}

// Set all messages as read for system message user
rocketChatService.markGroupAsReadForSystemUser(rcGroupId);

} catch (RocketChatPostMessageException | RocketChatPostMarkGroupAsReadException | CustomCryptoException ex) {
} catch (RocketChatPostMessageException
| RocketChatPostMarkGroupAsReadException
| CustomCryptoException ex) {
throw new InternalServerErrorException(ex, LogService::logInternalServerError);
}
}

private void validateFeedbackChatId(String rcToken, String rcUserId, String rcFeedbackGroupId) {
GetGroupInfoDto groupDto = rocketChatService.getGroupInfo(rcToken, rcUserId, rcFeedbackGroupId);

if (isNull(groupDto) || !groupDto.getGroup().getName().contains(FEEDBACK_GROUP_SUFFIX)) {
throw new BadRequestException(
String.format("Provided Rocket.Chat group ID %s is no feedback chat.", rcFeedbackGroupId),
LogService::logBadRequest);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.caritas.cob.messageservice.api.model.rocket.chat.group;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
* GetGroupInfoResponseDto: Rocket.Chat API response object for group infos.
*
* <p>https://docs.rocket.chat/api/rest-api/methods/groups/info
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class GetGroupInfoDto {

private GroupDto group;
private boolean success;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.caritas.cob.messageservice.api.model.rocket.chat.group;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
* GroupDto for {@link GetGroupInfoDto}
*
*/

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class GroupDto {

@JsonProperty("_id")
private String roomId;
private String name;
}
Loading

0 comments on commit 8291bb2

Please sign in to comment.