Skip to content

Commit

Permalink
Merge pull request #1 from jpcchaves/SECURITY-IMPL
Browse files Browse the repository at this point in the history
Security impl
  • Loading branch information
jpcchaves authored Mar 19, 2023
2 parents e31aed9 + 3830bd3 commit 05bb111
Show file tree
Hide file tree
Showing 43 changed files with 1,314 additions and 322 deletions.
43 changes: 36 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
Expand Down Expand Up @@ -46,14 +46,18 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<scope>compile</scope>
</dependency>

<!-- <dependency>-->
<!-- <groupId>org.modelmapper</groupId>-->
<!-- <artifactId>modelmapper</artifactId>-->
<!-- <version>3.1.1</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>

<dependency>
<groupId>com.github.dozermapper</groupId>
Expand All @@ -72,6 +76,31 @@
<version>${springdoc.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>


</dependencies>

Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/ws/taskmanager/common/DateUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ws.taskmanager.common;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DateUtils {
public static String convertDateToString(Date date) {
SimpleDateFormat formatter = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
return formatter.format(date);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.ws.taskmanager.configs;
package com.ws.taskmanager.config;

import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;

import java.util.TimeZone;
import java.util.spi.TimeZoneNameProvider;

@Configuration
public class AppConfig {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ws.taskmanager.configs.date;
package com.ws.taskmanager.config.date;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.ws.taskmanager.config.security;

import com.ws.taskmanager.security.CustomAccessDeniedHandler;
import com.ws.taskmanager.security.JwtAuthenticationEntrypoint;
import com.ws.taskmanager.security.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

private final UserDetailsService userDetailsService;
private final JwtAuthenticationEntrypoint authenticationEntryPoint;
private final CustomAccessDeniedHandler customAccessDeniedHandler;
private JwtAuthenticationFilter authenticationFilter;

public SecurityConfig(JwtAuthenticationEntrypoint authenticationEntryPoint,
UserDetailsService userDetailsService,
JwtAuthenticationFilter authenticationFilter,
CustomAccessDeniedHandler customAccessDeniedHandler) {
this.authenticationEntryPoint = authenticationEntryPoint;
this.userDetailsService = userDetailsService;
this.authenticationFilter = authenticationFilter;
this.customAccessDeniedHandler = customAccessDeniedHandler;
}

@Bean
public static PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

http.csrf().disable()
.authorizeHttpRequests(authorize ->
authorize
.requestMatchers("/api/v1/auth/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html")
.permitAll()
.anyRequest()
.authenticated()
)
.exceptionHandling(exception ->
exception
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(customAccessDeniedHandler)
)
.sessionManagement(session ->
session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);

http.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.ws.taskmanager.configs.swagger;
package com.ws.taskmanager.config.swagger;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/ws/taskmanager/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.ws.taskmanager.controller;

import com.ws.taskmanager.data.DTO.JWTAuthResponseDto;
import com.ws.taskmanager.data.DTO.LoginDto;
import com.ws.taskmanager.data.DTO.RegisterDto;
import com.ws.taskmanager.data.DTO.RegisterResponseDto;
import com.ws.taskmanager.services.AuthService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {
private final AuthService authService;

public AuthController(AuthService authService) {
this.authService = authService;
}

@PostMapping(value = {"/login", "/signin"})
public ResponseEntity<JWTAuthResponseDto> login(@RequestBody LoginDto loginDto) {
return ResponseEntity.ok(authService.login(loginDto));
}

@PostMapping(value = {"/register", "/signup"})
public ResponseEntity<RegisterResponseDto> register(@RequestBody RegisterDto registerDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(authService.register(registerDto));
}
}
33 changes: 17 additions & 16 deletions src/main/java/com/ws/taskmanager/controller/TaskController.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.ws.taskmanager.controller;


import com.ws.taskmanager.data.DTO.TaskCreateDTO;
import com.ws.taskmanager.data.DTO.TaskDTO;
import com.ws.taskmanager.data.DTO.TaskPatchDTO;
import com.ws.taskmanager.data.DTO.TaskResponseDTO;
import com.ws.taskmanager.data.DTO.TaskCreateDto;
import com.ws.taskmanager.data.DTO.TaskDto;
import com.ws.taskmanager.data.DTO.TaskPatchDto;
import com.ws.taskmanager.data.DTO.TaskResponseDto;
import com.ws.taskmanager.services.TaskService;
import com.ws.taskmanager.services.impl.TaskServiceImpl;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -28,9 +29,9 @@
@RequestMapping("api/v1/tasks")
public class TaskController {

final TaskService taskService;
private final TaskService taskService;

public TaskController(TaskService taskService) {
public TaskController(TaskServiceImpl taskService) {
this.taskService = taskService;
}

Expand All @@ -39,15 +40,15 @@ public TaskController(TaskService taskService) {
tags = {"Tasks"},
responses = {
@ApiResponse(description = "Success", responseCode = "200",
content = @Content(schema = @Schema(implementation = TaskResponseDTO.class))
content = @Content(schema = @Schema(implementation = TaskResponseDto.class))
),
@ApiResponse(description = "Bad Request", responseCode = "400", content = @Content),
@ApiResponse(description = "Unauthorized", responseCode = "401", content = @Content),
@ApiResponse(description = "Internal Error", responseCode = "500", content = @Content),
}
)
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<TaskResponseDTO> createTask(@RequestBody @Valid TaskCreateDTO taskDTO)
public ResponseEntity<TaskResponseDto> createTask(@RequestBody @Valid TaskCreateDto taskDTO)
throws Exception {
return ResponseEntity.status(HttpStatus.CREATED).body(taskService.createTask(taskDTO));
}
Expand All @@ -61,7 +62,7 @@ public ResponseEntity<TaskResponseDTO> createTask(@RequestBody @Valid TaskCreate
content = {
@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = TaskResponseDTO.class))
array = @ArraySchema(schema = @Schema(implementation = TaskResponseDto.class))
)
}),
@ApiResponse(description = "Bad Request", responseCode = "400", content = @Content),
Expand All @@ -70,7 +71,7 @@ public ResponseEntity<TaskResponseDTO> createTask(@RequestBody @Valid TaskCreate
@ApiResponse(description = "Internal Error", responseCode = "500", content = @Content),
}
)
public ResponseEntity<Page<TaskResponseDTO>> listAllTasks(@RequestParam(value = "page", defaultValue = "0") Integer page,
public ResponseEntity<Page<TaskResponseDto>> listAllTasks(@RequestParam(value = "page", defaultValue = "0") Integer page,
@RequestParam(value = "size", defaultValue = "10") Integer size,
@RequestParam(value = "direction", defaultValue = "asc") String direction) {

Expand All @@ -86,7 +87,7 @@ public ResponseEntity<Page<TaskResponseDTO>> listAllTasks(@RequestParam(value =
tags = {"Tasks"},
responses = {
@ApiResponse(description = "Success", responseCode = "200",
content = @Content(schema = @Schema(implementation = TaskResponseDTO.class))
content = @Content(schema = @Schema(implementation = TaskResponseDto.class))
),
@ApiResponse(description = "No Content", responseCode = "204", content = @Content),
@ApiResponse(description = "Bad Request", responseCode = "400", content = @Content),
Expand All @@ -95,7 +96,7 @@ public ResponseEntity<Page<TaskResponseDTO>> listAllTasks(@RequestParam(value =
@ApiResponse(description = "Internal Error", responseCode = "500", content = @Content),
}
)
public ResponseEntity<TaskResponseDTO> listTaskById(@PathVariable(value = "id") UUID id) throws Exception {
public ResponseEntity<TaskResponseDto> listTaskById(@PathVariable(value = "id") UUID id) throws Exception {
return ResponseEntity.status(HttpStatus.OK).body(taskService.listTaskById(id));
}

Expand All @@ -105,15 +106,15 @@ public ResponseEntity<TaskResponseDTO> listTaskById(@PathVariable(value = "id")
tags = {"Tasks"},
responses = {
@ApiResponse(description = "Updated", responseCode = "200",
content = @Content(schema = @Schema(implementation = TaskResponseDTO.class))
content = @Content(schema = @Schema(implementation = TaskResponseDto.class))
),
@ApiResponse(description = "Bad Request", responseCode = "400", content = @Content),
@ApiResponse(description = "Unauthorized", responseCode = "401", content = @Content),
@ApiResponse(description = "Not Found", responseCode = "404", content = @Content),
@ApiResponse(description = "Internal Error", responseCode = "500", content = @Content),
}
)
public ResponseEntity<TaskResponseDTO> updateTask(@PathVariable(value = "id") UUID id, @Valid @RequestBody TaskDTO taskDTO)
public ResponseEntity<TaskResponseDto> updateTask(@PathVariable(value = "id") UUID id, @Valid @RequestBody TaskDto taskDTO)
throws Exception {
return ResponseEntity.status(HttpStatus.OK).body(taskService.updateTask(id, taskDTO));
}
Expand All @@ -124,15 +125,15 @@ public ResponseEntity<TaskResponseDTO> updateTask(@PathVariable(value = "id") UU
tags = {"Tasks"},
responses = {
@ApiResponse(description = "Updated", responseCode = "200",
content = @Content(schema = @Schema(implementation = TaskResponseDTO.class))
content = @Content(schema = @Schema(implementation = TaskResponseDto.class))
),
@ApiResponse(description = "Bad Request", responseCode = "400", content = @Content),
@ApiResponse(description = "Unauthorized", responseCode = "401", content = @Content),
@ApiResponse(description = "Not Found", responseCode = "404", content = @Content),
@ApiResponse(description = "Internal Error", responseCode = "500", content = @Content),
}
)
public ResponseEntity<TaskPatchDTO> updateTaskSituation(@PathVariable(value = "id") UUID id, @Valid @RequestBody TaskPatchDTO taskPatchDTO)
public ResponseEntity<TaskPatchDto> updateTaskSituation(@PathVariable(value = "id") UUID id, @Valid @RequestBody TaskPatchDto taskPatchDTO)
throws Exception {
return ResponseEntity.status(HttpStatus.OK).body(taskService.updateTaskSituation(id, taskPatchDTO));
}
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/com/ws/taskmanager/data/DTO/JWTAuthResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.ws.taskmanager.data.DTO;


public class JWTAuthResponseDto {
private String accessToken;
private String tokenType = "Bearer";
private UserDto user;

public JWTAuthResponseDto() {
}

public JWTAuthResponseDto(String accessToken, String tokenType, UserDto user) {
this.accessToken = accessToken;
this.tokenType = tokenType;
this.user = user;
}

public String getAccessToken() {
return accessToken;
}

public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

public String getTokenType() {
return tokenType;
}

public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}

public UserDto getUser() {
return user;
}

public void setUser(UserDto user) {
this.user = user;
}
}
Loading

1 comment on commit 05bb111

@vercel
Copy link

@vercel vercel bot commented on 05bb111 Mar 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.