Skip to content

Commit

Permalink
Returning validation failures while creating organization (#1084)
Browse files Browse the repository at this point in the history
* Returning validation failures while creating organization

* Added unit tests

* Changing the name of test security config

Co-authored-by: nitesh261193 <[email protected]>
  • Loading branch information
pc9795 and nitesh261193 committed Oct 15, 2020
1 parent e85d5ed commit 67ef538
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class Organization extends BaseDomain {

private String domain;

@NotNull
@NotNull(message = "Name is mandatory")
private String name;

private String website;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public enum AppsmithError {
USER_NOT_FOUND(404, 4027, "Unable to find user with email {0}"),
ACL_NO_RESOURCE_FOUND(404, 4028, "Unable to find {0} with id {1}. Either the asset doesn't exist or you don't have required permissions"),
GENERIC_BAD_REQUEST(400, 4028, "Bad Request: {0}"),
VALIDATION_FAILURE(400, 4028, "Validation Failure(s): {0}"),
INVALID_CURL_COMMAND(400, 4029, "Invalid cURL command, couldn't import."),
INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request"),
REPOSITORY_SAVE_FAILED(500, 5001, "Failed to save the repository. Try again."),
Expand All @@ -58,9 +59,9 @@ public enum AppsmithError {
;


private Integer httpErrorCode;
private Integer appErrorCode;
private String message;
private final Integer httpErrorCode;
private final Integer appErrorCode;
private final String message;

AppsmithError(Integer httpErrorCode, Integer appErrorCode, String message, Object... args) {
this.httpErrorCode = httpErrorCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;


/**
* This class catches all the Exceptions and formats them into a proper ResponseDTO<ErrorDTO> object before
Expand Down Expand Up @@ -74,6 +79,26 @@ public Mono<ResponseDTO<ErrorDTO>> catchTimeoutException(java.util.concurrent.Ti
appsmithError.getMessage())));
}

@ExceptionHandler(WebExchangeBindException.class)
@ResponseBody
public Mono<ResponseDTO<ErrorDTO>> catchWebExchangeBindException(
WebExchangeBindException exc, ServerWebExchange exchange) {
AppsmithError appsmithError = AppsmithError.VALIDATION_FAILURE;
exchange.getResponse().setStatusCode(HttpStatus.resolve(appsmithError.getHttpErrorCode()));
Map<String, String> errors = new HashMap<>();
exc.getBindingResult()
.getAllErrors()
.forEach(
(error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return Mono.just(new ResponseDTO<>(appsmithError.getHttpErrorCode(), new ErrorDTO(appsmithError.getAppErrorCode(),
appsmithError.getMessage(errors.toString()))));
}


@ExceptionHandler
@ResponseBody
public Mono<ResponseDTO<ErrorDTO>> catchServerWebInputException(ServerWebInputException e, ServerWebExchange exchange) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.appsmith.server.configurations;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityTestConfig {

@Bean
public SecurityWebFilterChain testSecurityWebFilterChain(ServerHttpSecurity http){
return http.csrf().disable().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.appsmith.server.controllers;

import com.appsmith.server.configurations.CommonConfig;
import com.appsmith.server.configurations.SecurityTestConfig;
import com.appsmith.server.services.OrganizationService;
import com.appsmith.server.services.UserOrganizationService;
import com.appsmith.server.services.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.BodyInserters;

@RunWith(SpringRunner.class)
@WebFluxTest(OrganizationController.class)
@Import(SecurityTestConfig.class)
public class OrganizationControllerTest {
@Autowired
private WebTestClient webTestClient;

@MockBean
private OrganizationService organizationService;

@MockBean
private UserOrganizationService userOrganizationService;

@MockBean
private UserService userService;

@MockBean
private CommonConfig commonConfig;

@Test
@WithMockUser
public void getOrganizationNoName() {
webTestClient.post().uri("/api/v1/organizations").
contentType(MediaType.APPLICATION_JSON).
body(BodyInserters.fromValue("{}")).
exchange().
expectStatus().isEqualTo(400).
expectBody().json("{\n" +
" \"responseMeta\": {\n" +
" \"status\": 400,\n" +
" \"success\": false,\n" +
" \"error\": {\n" +
" \"code\": 4028,\n" +
" \"message\": \"Validation Failure(s): {name=Name is mandatory}\"\n" +
" }\n" +
" }\n" +
"}");
}
}

0 comments on commit 67ef538

Please sign in to comment.