Skip to content

Commit 9a32c44

Browse files
committed
Handle exceptions for signin/signup
1 parent ada6962 commit 9a32c44

File tree

10 files changed

+2002
-746
lines changed

10 files changed

+2002
-746
lines changed

logs/flight-advisor.log

Lines changed: 1955 additions & 735 deletions
Large diffs are not rendered by default.

pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@
7979
<version>0.11.1</version>
8080
<scope>runtime</scope>
8181
</dependency>
82+
<dependency>
83+
<groupId>org.springframework.boot</groupId>
84+
<artifactId>spring-boot-starter-validation</artifactId>
85+
</dependency>
8286
<dependency>
8387
<groupId>javax.validation</groupId>
8488
<artifactId>validation-api</artifactId>

src/main/java/com/miro/flightadvisor/FlightAdvisorServiceApplication.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import org.springframework.context.annotation.Bean;
99
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
10+
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
11+
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
1012
import springfox.documentation.builders.PathSelectors;
1113
import springfox.documentation.builders.RequestHandlerSelectors;
1214
import springfox.documentation.service.ApiInfo;
@@ -15,6 +17,7 @@
1517
import springfox.documentation.spring.web.plugins.Docket;
1618
import springfox.documentation.swagger2.annotations.EnableSwagger2;
1719

20+
import java.nio.file.AccessDeniedException;
1821
import java.util.ArrayList;
1922
import java.util.concurrent.Executor;
2023

src/main/java/com/miro/flightadvisor/SecurityConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
import org.springframework.security.config.http.SessionCreationPolicy;
1515
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
1616
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
17+
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
18+
19+
import java.nio.file.AccessDeniedException;
1720

1821
@Configuration
1922
@EnableWebSecurity
@@ -42,6 +45,7 @@ public AuthenticationManager authenticationManager() throws Exception {
4245
"/v2/api-docs",
4346
"/webjars/**"
4447
};
48+
4549
@Override
4650
public void configure(WebSecurity web) throws Exception {
4751
web.ignoring().antMatchers(AUTH_WHITELIST);

src/main/java/com/miro/flightadvisor/controllers/CityController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
import org.springframework.beans.factory.annotation.Autowired;
1919
import org.springframework.http.HttpStatus;
2020
import org.springframework.http.ResponseEntity;
21+
import org.springframework.security.access.AccessDeniedException;
2122
import org.springframework.security.access.prepost.PreAuthorize;
2223
import org.springframework.web.bind.annotation.*;
2324

25+
import javax.persistence.Access;
2426
import javax.validation.Valid;
2527
import java.time.LocalDate;
2628
import java.util.List;
@@ -74,7 +76,7 @@ public Optional<?> getCity(
7476
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Bad request"), @ApiResponse(code = 500, message = "Server error")})
7577
@PreAuthorize("hasRole('ROLE_USER')")
7678
public Optional<List<Comment>> comments() {
77-
return cityService.allCommentsForCity();
79+
return cityService.allCommentsForCity();
7880
}
7981

8082
@PostMapping("{cityId}/comments")

src/main/java/com/miro/flightadvisor/controllers/ExceptionsControllerAdvice.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
import org.springframework.web.bind.MissingServletRequestParameterException;
1111
import org.springframework.web.bind.annotation.ExceptionHandler;
1212
import org.springframework.web.bind.annotation.RestControllerAdvice;
13+
import org.springframework.web.client.HttpServerErrorException;
1314
import org.springframework.web.context.request.WebRequest;
1415
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
1516
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
1617

1718
import javax.validation.ConstraintViolation;
1819
import javax.validation.ConstraintViolationException;
20+
import java.nio.file.AccessDeniedException;
1921
import java.util.ArrayList;
2022
import java.util.List;
2123

@@ -31,7 +33,7 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotV
3133
errors.add(error.getObjectName() + ": " + error.getDefaultMessage());
3234
}
3335

34-
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
36+
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST.value(), ex.getLocalizedMessage(), errors);
3537
return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request);
3638
}
3739

@@ -52,7 +54,7 @@ public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationExcep
5254
errors.add(violation.getMessage());
5355
}
5456

55-
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
57+
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST.value(), ex.getLocalizedMessage(), errors);
5658
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
5759

5860
}
@@ -69,10 +71,22 @@ public ResponseEntity<Object> handleMethodArgumentTypeMismatch(
6971
apiError, new HttpHeaders(), apiError.getStatus());
7072
}
7173

72-
// @ExceptionHandler({Exception.class})
73-
// public ResponseEntity<Object> handleAll(Exception ex, WebRequest request) {
74-
// ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "error occurred");
75-
// return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
76-
// }
74+
@ExceptionHandler({HttpServerErrorException.class})
75+
public ResponseEntity<Object> handleAll(HttpServerErrorException ex, WebRequest request) {
76+
ApiError apiError = new ApiError(HttpStatus.FORBIDDEN, HttpStatus.FORBIDDEN.value(), ex.getMessage(), "error occured");
77+
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
78+
}
79+
80+
@ExceptionHandler({Exception.class})
81+
public ResponseEntity<Object> handleAll(Exception ex, WebRequest request) {
82+
ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getLocalizedMessage(), "error occurred");
83+
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
84+
}
85+
86+
@ExceptionHandler({AccessDeniedException.class})
87+
public ResponseEntity<Object> handleAccessDenied(AccessDeniedException ex, WebRequest request) {
88+
ApiError apiError = new ApiError(HttpStatus.FORBIDDEN, HttpStatus.FORBIDDEN.value(), ex.getLocalizedMessage(), "error occurred");
89+
return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
90+
}
7791

7892
}

src/main/java/com/miro/flightadvisor/exception/ApiError.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ public class ApiError {
1616
private String message;
1717
private List<String> errors;
1818

19-
public ApiError(HttpStatus status, String message, List<String> errors) {
19+
public ApiError(HttpStatus status, int errorCode, String message, List<String> errors) {
2020
super();
2121
this.status = status;
22+
this.errorCode = errorCode;
2223
this.message = message;
2324
this.errors = errors;
2425
}

src/main/java/com/miro/flightadvisor/security/beans/SignupBean.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.miro.flightadvisor.security.beans;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnore;
34
import lombok.Getter;
45
import lombok.Setter;
56
import org.springframework.stereotype.Component;
@@ -14,8 +15,11 @@ public class SignupBean {
1415
private String username;
1516
@NotBlank(message = "Password is required")
1617
private String password;
18+
@NotBlank(message = "First name is required")
1719
private String firstName;
20+
@NotBlank(message = "Last name is required")
1821
private String lastName;
1922
private String role;
23+
@JsonIgnore
2024
private String salt;
2125
}

src/main/java/com/miro/flightadvisor/security/controllers/UserController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ public class UserController {
2626
@PostMapping("/signin")
2727
public String login(@RequestBody @Valid LoginBean loginBean) {
2828
return userService.signin(loginBean.getUsername(), loginBean.getPassword()).orElseThrow(() ->
29-
new HttpServerErrorException(HttpStatus.FORBIDDEN, "LoginBean Failed"));
29+
new HttpServerErrorException(HttpStatus.FORBIDDEN, "login failed, please try again"));
3030
}
3131

3232
@PostMapping("/signup")
3333
@ResponseStatus(HttpStatus.CREATED)
34-
public User signup(@RequestBody @Valid SignupBean signupBean) {
34+
public User signup(@Valid @RequestBody SignupBean signupBean) {
3535
return userService.signup(signupBean.getUsername(), signupBean.getPassword(), signupBean.getFirstName(),
3636
signupBean.getLastName()).orElseThrow(() -> new HttpServerErrorException(HttpStatus.BAD_REQUEST, "User already exists"));
3737
}

src/main/java/com/miro/flightadvisor/security/entities/User.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import lombok.Setter;
77

88
import javax.persistence.*;
9+
import javax.validation.constraints.NotBlank;
10+
import javax.validation.constraints.NotEmpty;
911

1012

1113
import java.security.SecureRandom;
@@ -27,6 +29,7 @@ public class User {
2729
@Column(name = "id")
2830
private Long id;
2931
@Column(name = "username")
32+
@NotBlank
3033
private String username;
3134
@Column(name = "password")
3235
@JsonIgnore
@@ -36,6 +39,7 @@ public class User {
3639
@Column(name = "last_name")
3740
private String lastName;
3841
@Column(name = "salt")
42+
@JsonIgnore
3943
private byte[] salt;
4044
@ManyToMany(fetch = FetchType.EAGER)
4145
@JoinTable(name = "user_role", joinColumns

0 commit comments

Comments
 (0)