Skip to content

Commit 3409f8a

Browse files
Merge pull request #1 from adam-szalanski/todo-lists-functionality
Todo lists basic functionality
2 parents 6ab59fc + a7d5d5f commit 3409f8a

File tree

18 files changed

+281
-30
lines changed

18 files changed

+281
-30
lines changed

backend/pom.xml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@
4242
<groupId>org.springframework.boot</groupId>
4343
<artifactId>spring-boot-starter-web</artifactId>
4444
</dependency>
45-
<dependency>
46-
<groupId>org.springframework.boot</groupId>
47-
<artifactId>spring-boot-starter-webflux</artifactId>
48-
</dependency>
4945
<dependency>
5046
<groupId>org.liquibase</groupId>
5147
<artifactId>liquibase-core</artifactId>
@@ -126,9 +122,6 @@
126122
<configuration>
127123
<source>17</source>
128124
<target>17</target>
129-
<compilerArgs>
130-
<compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
131-
</compilerArgs>
132125
<annotationProcessorPaths>
133126
<path>
134127
<groupId>org.projectlombok</groupId>

backend/src/main/java/org/todolist/backend/exceptions/CustomExceptionHandler.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import org.springframework.web.bind.annotation.ControllerAdvice;
99
import org.springframework.web.bind.annotation.ExceptionHandler;
1010
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
11+
import org.todolist.backend.exceptions.custom.UserNotLoggedInException;
12+
13+
import java.nio.file.AccessDeniedException;
1114

1215
@ControllerAdvice
1316
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
@@ -16,15 +19,25 @@ public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
1619
private String USER_ALREADY_EXISTS;
1720
@Value("${application.security.user-not-found-message}")
1821
private String USER_NOT_FOUND;
22+
@Value("${application.security.user-not-logged-in-message}")
23+
private String USER_NOT_LOGGED_IN;
1924
@Value("${application.security.entity-not-found-message}")
2025
private String ENTITY_NOT_FOUND;
26+
@Value("${application.security.access-denied-message}")
27+
private String ACCESS_DENIED;
2128

2229
@ExceptionHandler(IllegalArgumentException.class)
2330
protected ResponseEntity<ErrorDetails> handleUserAlreadyExists() {
2431
ErrorDetails errorDetails = new ErrorDetails(HttpStatus.BAD_REQUEST.value(), USER_ALREADY_EXISTS);
2532
return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).body(errorDetails);
2633
}
2734

35+
@ExceptionHandler(UserNotLoggedInException.class)
36+
protected ResponseEntity<ErrorDetails> handleUserNotLoggedIn() {
37+
ErrorDetails errorDetails = new ErrorDetails(HttpStatus.BAD_REQUEST.value(), USER_NOT_LOGGED_IN);
38+
return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).body(errorDetails);
39+
}
40+
2841
@ExceptionHandler(UsernameNotFoundException.class)
2942
protected ResponseEntity<ErrorDetails> handleUserNotFound() {
3043
ErrorDetails errorDetails = new ErrorDetails(HttpStatus.NOT_FOUND.value(), USER_NOT_FOUND);
@@ -36,4 +49,10 @@ protected ResponseEntity<ErrorDetails> handleEntityNotFound() {
3649
ErrorDetails errorDetails = new ErrorDetails(HttpStatus.NOT_FOUND.value(), ENTITY_NOT_FOUND);
3750
return ResponseEntity.status(HttpStatus.NOT_FOUND.value()).body(errorDetails);
3851
}
52+
53+
@ExceptionHandler(AccessDeniedException.class)
54+
protected ResponseEntity<ErrorDetails> handleAccessDenied() {
55+
ErrorDetails errorDetails = new ErrorDetails(HttpStatus.UNAUTHORIZED.value(), ACCESS_DENIED);
56+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED.value()).body(errorDetails);
57+
}
3958
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.todolist.backend.exceptions.custom;
2+
3+
import org.springframework.http.HttpStatus;
4+
import org.springframework.web.bind.annotation.ResponseStatus;
5+
6+
@ResponseStatus(HttpStatus.BAD_REQUEST)
7+
public class UserNotLoggedInException extends RuntimeException {
8+
public UserNotLoggedInException(String message) {
9+
super(message);
10+
}
11+
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package org.todolist.backend.security.auth;
22

33
import lombok.RequiredArgsConstructor;
4+
import org.springframework.http.ResponseEntity;
45
import org.springframework.web.bind.annotation.PostMapping;
56
import org.springframework.web.bind.annotation.RequestBody;
67
import org.springframework.web.bind.annotation.RequestMapping;
78
import org.springframework.web.bind.annotation.RestController;
89
import org.todolist.backend.security.auth.dto.request.AuthenticationRequest;
910
import org.todolist.backend.security.auth.dto.request.RegistrationRequest;
1011
import org.todolist.backend.security.auth.dto.response.AuthenticationResponse;
11-
import reactor.core.publisher.Mono;
1212

1313
@RestController
1414
@RequestMapping("/auth")
@@ -17,12 +17,12 @@ public class AuthenticationController {
1717
private final AuthenticationService authenticationService;
1818

1919
@PostMapping("/register")
20-
public Mono<AuthenticationResponse> register(@RequestBody RegistrationRequest registrationRequest) {
21-
return Mono.just(authenticationService.register(registrationRequest));
20+
public ResponseEntity<AuthenticationResponse> register(@RequestBody RegistrationRequest registrationRequest) {
21+
return ResponseEntity.ok(authenticationService.register(registrationRequest));
2222
}
2323

2424
@PostMapping("/authenticate")
25-
public Mono<AuthenticationResponse> register(@RequestBody AuthenticationRequest authenticationRequest) {
26-
return Mono.just(authenticationService.authenticate(authenticationRequest));
25+
public ResponseEntity<AuthenticationResponse> authenticate(@RequestBody AuthenticationRequest authenticationRequest) {
26+
return ResponseEntity.ok(authenticationService.authenticate(authenticationRequest));
2727
}
2828
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.todolist.backend.security.config;
2+
3+
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4+
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
5+
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
6+
import io.swagger.v3.oas.annotations.info.Info;
7+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
8+
import io.swagger.v3.oas.annotations.security.SecurityScheme;
9+
import io.swagger.v3.oas.annotations.servers.Server;
10+
11+
@OpenAPIDefinition(
12+
info = @Info(
13+
description = "OpenApi documentation for Todo lists Backend",
14+
title = "OpenApi specification - Adam Szalanski",
15+
version = "1.0"
16+
),
17+
servers = {
18+
@Server(
19+
description = "Todo lists Backend",
20+
url = "http://localhost:8088"
21+
)
22+
},
23+
security = {
24+
@SecurityRequirement(
25+
name = "bearerAuth"
26+
)
27+
}
28+
)
29+
@SecurityScheme(
30+
name = "bearerAuth",
31+
description = "JWT auth description",
32+
scheme = "bearer",
33+
type = SecuritySchemeType.HTTP,
34+
bearerFormat = "JWT",
35+
in = SecuritySchemeIn.HEADER
36+
)
37+
public class OpenApiConfig {
38+
}

backend/src/main/java/org/todolist/backend/security/config/SecurityConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
2626
.csrf(AbstractHttpConfigurer::disable)
2727
.authorizeHttpRequests(
2828
authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
29-
.requestMatchers("/auth/**")
29+
.requestMatchers("/auth/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger", "/actuator/**")
3030
.permitAll()
3131
.anyRequest()
32-
.authenticated())
32+
.authenticated()
33+
)
3334
.sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
3435
.authenticationProvider(authenticationProvider)
3536
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

backend/src/main/java/org/todolist/backend/security/mapper/UserMapper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ public abstract class UserMapper {
1212
@Mapping(target = "lastName", source = "lastName")
1313
@Mapping(target = "email", source = "email")
1414
@Mapping(target = "isActive", constant = "false")
15-
@Mapping(target = "id", ignore = true)
15+
@Mapping(target = "userId", ignore = true)
1616
@Mapping(target = "password", ignore = true)
1717
@Mapping(target = "role", constant = "ROLE_USER")
18+
@Mapping(target = "todoList", expression = "java(new java.util.ArrayList<>())")
1819
public abstract User fromRequest(RegistrationRequest registrationRequest);
1920

2021
}

backend/src/main/java/org/todolist/backend/security/user/User.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
@Setter
2121
@NoArgsConstructor
2222
@AllArgsConstructor
23+
2324
public class User implements UserDetails {
2425
@Id
2526
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_generator")
@@ -29,8 +30,8 @@ public class User implements UserDetails {
2930
sequenceName = "public.user_id_seq",
3031
allocationSize = 1
3132
)
32-
@Column(name = "id")
33-
private Long id;
33+
@Column(name = "user_id")
34+
private Long userId;
3435
@Column(name = "first_name")
3536
private String firstName;
3637
@Column(name = "last_name")
@@ -45,7 +46,7 @@ public class User implements UserDetails {
4546
@Enumerated(EnumType.STRING)
4647
private Role role;
4748

48-
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
49+
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
4950
private List<TodoListEntity> todoList;
5051

5152
@Override
@@ -55,7 +56,6 @@ public Collection<? extends GrantedAuthority> getAuthorities() {
5556

5657

5758
@Override
58-
5959
public String getUsername() {
6060
return email;
6161
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.todolist.backend.security.util;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.beans.factory.annotation.Value;
5+
import org.springframework.security.core.Authentication;
6+
import org.springframework.security.core.context.SecurityContextHolder;
7+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
8+
import org.springframework.stereotype.Component;
9+
import org.todolist.backend.exceptions.custom.UserNotLoggedInException;
10+
import org.todolist.backend.security.user.User;
11+
import org.todolist.backend.security.user.UserRepository;
12+
13+
@Component
14+
@RequiredArgsConstructor
15+
public class CurrentUserUtility {
16+
private final UserRepository userRepository;
17+
@Value("${application.security.user-not-logged-in-message}")
18+
private String NOT_LOGGED_IN_MESSAGE;
19+
@Value("${application.security.user-not-found-message}")
20+
private String USER_NOT_FOUND_MESSAGE;
21+
22+
public User getCurrentUser() {
23+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
24+
if (authentication == null)
25+
throw new UserNotLoggedInException(NOT_LOGGED_IN_MESSAGE);
26+
return userRepository.findByEmail(authentication.getName()).orElseThrow(() -> new UsernameNotFoundException(USER_NOT_FOUND_MESSAGE));
27+
}
28+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.todolist.backend.todolists;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.http.ResponseEntity;
5+
import org.springframework.web.bind.annotation.*;
6+
import org.todolist.backend.todolists.dto.request.TodoRequest;
7+
import org.todolist.backend.todolists.dto.response.TodoResponse;
8+
9+
import java.nio.file.AccessDeniedException;
10+
import java.util.List;
11+
12+
@RestController
13+
@RequestMapping("/todo")
14+
@RequiredArgsConstructor
15+
public class TodoListController {
16+
private final TodoListService todoListService;
17+
18+
@GetMapping
19+
public ResponseEntity<List<TodoResponse>> getAllTodo() {
20+
return ResponseEntity.ok(todoListService.getAll());
21+
}
22+
23+
@GetMapping("/{id}")
24+
public ResponseEntity<TodoResponse> getOneTodo(@PathVariable("id") Long id) throws AccessDeniedException {
25+
return ResponseEntity.ok(todoListService.getOne(id));
26+
}
27+
28+
@PostMapping
29+
public ResponseEntity<TodoResponse> createTodo(@RequestBody TodoRequest todoRequest) {
30+
return ResponseEntity.ok(todoListService.create(todoRequest));
31+
}
32+
33+
@PutMapping("/{id}")
34+
public ResponseEntity<TodoResponse> updateTodo(@PathVariable("id") Long id, @RequestBody TodoRequest todoRequest) throws AccessDeniedException {
35+
return ResponseEntity.ok(todoListService.update(id, todoRequest));
36+
}
37+
38+
@DeleteMapping("/{id}")
39+
public ResponseEntity<TodoResponse> deleteTodo(@PathVariable("id") Long id) {
40+
todoListService.delete(id);
41+
return ResponseEntity.noContent().build();
42+
}
43+
44+
}

0 commit comments

Comments
 (0)