diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..2721138
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,16 @@
+# Builder stage
+FROM openjdk:17-jdk-alpine as builder
+WORKDIR application
+ARG JAR_FILE=target/*.jar
+COPY ${JAR_FILE} application.jar
+RUN java -Djarmode=layertools -jar application.jar extract
+
+# Final stage
+FROM openjdk:17-jdk-alpine
+WORKDIR application
+COPY --from=builder application/dependencies/ ./
+COPY --from=builder application/spring-boot-loader/ ./
+COPY --from=builder application/snapshot-dependencies/ ./
+COPY --from=builder application/application/ ./
+ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
+EXPOSE 8080
diff --git a/car-sharing-app-db-model.mwb b/car-sharing-app-db-model.mwb
deleted file mode 100644
index aee404e..0000000
Binary files a/car-sharing-app-db-model.mwb and /dev/null differ
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..a748af9
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,44 @@
+name: car-sharing-application
+services:
+ mysqldb:
+ image: mysql:8.0.36-oracle
+ restart: unless-stopped
+ env_file:
+ - ./.env
+ environment:
+ - MYSQL_DATABASE=$MYSQLDB_DATABASE
+ - MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD
+ ports:
+ - $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
+ healthcheck:
+ test: [ "CMD-SHELL", "mysqladmin ping -h localhost -u${MYSQLDB_USER} -p${MYSQLDB_ROOT_PASSWORD}" ]
+ interval: 30s
+ timeout: 30s
+ retries: 30
+ app:
+ depends_on:
+ - mysqldb
+ image: car-sharing-image
+ restart: on-failure
+ container_name: app
+ build: .
+ env_file: ./.env
+ ports:
+ - $SPRING_LOCAL_PORT:$SPRING_DOCKER_PORT
+ - $DEBUG_PORT:$DEBUG_PORT
+ environment:
+ SPRING_APPLICATION_JSON: '{
+ "spring.datasource.url" : "jdbc:mysql://mysqldb:$MYSQLDB_DOCKER_PORT/$MYSQLDB_DATABASE?createDatabaseIfNotExist=true&characterEncoding=UTF-8&serverTimezone=UTC",
+ "spring.datasource.username" : "$MYSQLDB_USER",
+ "spring.datasource.password" : "$MYSQLDB_ROOT_PASSWORD",
+ "spring.jpa.hibernate.ddl-auto" : "validate",
+ "spring.jpa.show-sql" : "true",
+ "jwt.expiration" : "$JWT_EXPIRATION_TIME",
+ "jwt.secret" : "$JWT_SECRET",
+ "STRIPE_APY_KEY" : "$STRIPE_APY_KEY",
+ "STRIPE_SUCCESS_LINK" : "$STRIPE_SUCCESS_LINK",
+ "STRIPE_CANCEL_LINK" : "$STRIPE_CANCEL_LINK",
+ "TELEGRAM_BOT_TOKEN" : "$TELEGRAM_BOT_TOKEN",
+ "TELEGRAM_BOT_USERNAME" : "$TELEGRAM_BOT_USERNAME"
+ }'
+ JAVA_TOOL_OPTIONS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
diff --git a/pom.xml b/pom.xml
index 558d5fb..adc2b87 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,7 @@
1.19.4
6.9.0
24.19.0
+ 2.17.0
@@ -136,6 +137,17 @@
stripe-java
${stripe.version}
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson.version}
+
diff --git a/src/main/java/mate/academy/carsharing/annotation/UserRoleDescription.java b/src/main/java/mate/academy/carsharing/annotation/UserRoleDescription.java
new file mode 100644
index 0000000..9daa30b
--- /dev/null
+++ b/src/main/java/mate/academy/carsharing/annotation/UserRoleDescription.java
@@ -0,0 +1,12 @@
+package mate.academy.carsharing.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UserRoleDescription {
+
+}
diff --git a/src/main/java/mate/academy/carsharing/annotation/UserRoleDescriptionCustomizer.java b/src/main/java/mate/academy/carsharing/annotation/UserRoleDescriptionCustomizer.java
new file mode 100644
index 0000000..a59aa17
--- /dev/null
+++ b/src/main/java/mate/academy/carsharing/annotation/UserRoleDescriptionCustomizer.java
@@ -0,0 +1,31 @@
+package mate.academy.carsharing.annotation;
+
+import io.swagger.v3.oas.models.Operation;
+import org.springdoc.core.customizers.OperationCustomizer;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+
+@Component
+public class UserRoleDescriptionCustomizer implements OperationCustomizer {
+ @Override
+ public Operation customize(Operation operation, HandlerMethod handlerMethod) {
+ UserRoleDescription userRoleAnnotation =
+ handlerMethod.getMethodAnnotation(UserRoleDescription.class);
+ if (userRoleAnnotation != null) {
+ PreAuthorize preAuthorizeAnnotation =
+ handlerMethod.getMethodAnnotation(PreAuthorize.class);
+ if (preAuthorizeAnnotation != null
+ && preAuthorizeAnnotation.value().contains("ROLE_")) {
+ String description = operation.getDescription() == null
+ ? "" : (operation.getDescription()/* + "\n"*/);
+ int firstBraceIndex = preAuthorizeAnnotation.value().indexOf('(');
+ int lastBraceIndex = preAuthorizeAnnotation.value().lastIndexOf(')');
+ String rolesString = preAuthorizeAnnotation.value()
+ .substring(firstBraceIndex + 1, lastBraceIndex);
+ operation.setDescription(description + " Required roles: " + rolesString + '.');
+ }
+ }
+ return operation;
+ }
+}
diff --git a/src/main/java/mate/academy/carsharing/config/OpenApiConfig.java b/src/main/java/mate/academy/carsharing/config/OpenApiConfig.java
new file mode 100644
index 0000000..d8a7fdf
--- /dev/null
+++ b/src/main/java/mate/academy/carsharing/config/OpenApiConfig.java
@@ -0,0 +1,20 @@
+package mate.academy.carsharing.config;
+
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityScheme;
+import io.swagger.v3.oas.annotations.security.SecuritySchemes;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@OpenAPIDefinition(info = @Info(title = "Car-Sharing-App REST API", version = "1.0",
+ description = "REST API for Car-Sharing-App. Register, Login and use JWT token."),
+ security = {@SecurityRequirement(name = "bearerToken")}
+)
+@SecuritySchemes({@SecurityScheme(name = "bearerToken", type = SecuritySchemeType.HTTP,
+ scheme = "bearer", bearerFormat = "JWT")}
+)
+public class OpenApiConfig {
+}
diff --git a/src/main/java/mate/academy/carsharing/config/SecurityConfig.java b/src/main/java/mate/academy/carsharing/config/SecurityConfig.java
index 8694f59..2b991f8 100644
--- a/src/main/java/mate/academy/carsharing/config/SecurityConfig.java
+++ b/src/main/java/mate/academy/carsharing/config/SecurityConfig.java
@@ -37,6 +37,9 @@ public SecurityFilterChain securityFilterChain(UserDetailsService userDetailsSer
// list cars.
.requestMatchers(HttpMethod.GET, "api/cars", "api/cars/{id}")
.permitAll()
+ .requestMatchers(HttpMethod.GET,
+ "api/payments/cancel", "api/payments/success")
+ .permitAll()
.requestMatchers("api/auth/**", "/swagger-ui/**", "/v3/api-docs/**")
.permitAll()
.anyRequest()
diff --git a/src/main/java/mate/academy/carsharing/controller/AuthenticationController.java b/src/main/java/mate/academy/carsharing/controller/AuthenticationController.java
index e32d891..d6e1e48 100644
--- a/src/main/java/mate/academy/carsharing/controller/AuthenticationController.java
+++ b/src/main/java/mate/academy/carsharing/controller/AuthenticationController.java
@@ -1,5 +1,6 @@
package mate.academy.carsharing.controller;
+import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@@ -17,7 +18,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-@Tag(name = "Authentication manager", description = "Endpoints for registration")
+@Tag(name = "Authentication controller", description = "Endpoints for registration and login.")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/auth")
@@ -26,6 +27,7 @@ public class AuthenticationController {
private final AuthenticationService authenticationService;
@ResponseStatus(HttpStatus.CREATED)
+ @Operation(summary = "Register a new user.", description = "Register a new user.")
@PostMapping("/registration")
public UserResponseDto register(@RequestBody @Valid UserRegistrationRequestDto request)
throws RegistrationException {
@@ -33,6 +35,8 @@ public UserResponseDto register(@RequestBody @Valid UserRegistrationRequestDto r
}
@PostMapping("/login")
+ @Operation(summary = "Login to the app.",
+ description = "Login to the app, get JWT Token and use it to request data.")
public UserLoginResponseDto login(@RequestBody @Valid UserLoginRequestDto requestDto) {
return authenticationService.authentication(requestDto);
}
diff --git a/src/main/java/mate/academy/carsharing/controller/CarController.java b/src/main/java/mate/academy/carsharing/controller/CarController.java
index 30f3647..ba7f5df 100644
--- a/src/main/java/mate/academy/carsharing/controller/CarController.java
+++ b/src/main/java/mate/academy/carsharing/controller/CarController.java
@@ -6,6 +6,7 @@
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
+import mate.academy.carsharing.annotation.UserRoleDescription;
import mate.academy.carsharing.dto.car.CarResponseDto;
import mate.academy.carsharing.dto.car.CreateCarRequestDto;
import mate.academy.carsharing.service.CarService;
@@ -25,13 +26,14 @@
@RestController
@RequiredArgsConstructor
@RequestMapping(path = "/api/cars")
-@Tag(name = "Car management", description = "Cars Management Endpoints")
+@Tag(name = "Car management", description = "Cars Management Endpoints.")
public class CarController {
private final CarService carService;
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Create a new car", description = "Create a new car")
+ @UserRoleDescription
+ @Operation(summary = "Create a new car.", description = "Create a new car.")
@PostMapping
public CarResponseDto create(@RequestBody @Valid CreateCarRequestDto carDto) {
return carService.save(carDto);
@@ -39,7 +41,8 @@ public CarResponseDto create(@RequestBody @Valid CreateCarRequestDto carDto) {
@ResponseStatus(HttpStatus.NO_CONTENT)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Delete a car by id", description = "Delete car with specified id")
+ @UserRoleDescription
+ @Operation(summary = "Delete a car by id.", description = "Delete car with specified id.")
@DeleteMapping("/{id}")
public void deleteById(@PathVariable Long id) {
carService.deleteById(id);
@@ -47,7 +50,8 @@ public void deleteById(@PathVariable Long id) {
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Update a car by id", description = "Update car with specified id")
+ @UserRoleDescription
+ @Operation(summary = "Update a car by id.", description = "Update car with specified id.")
@PutMapping("/{id}")
public CarResponseDto updateById(@PathVariable Long id,
@RequestBody @Valid CreateCarRequestDto requestDto) {
@@ -56,7 +60,8 @@ public CarResponseDto updateById(@PathVariable Long id,
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasAnyRole('ROLE_MANAGER', 'ROLE_CUSTOMER', 'ROLE_ANONYMOUS')")
- @Operation(summary = "Get a car by id", description = "Get a car with specified id")
+ @UserRoleDescription
+ @Operation(summary = "Get a car by id.", description = "Get a car with specified id.")
@GetMapping("/{id}")
public CarResponseDto getById(@PathVariable Long id) {
return carService.getById(id);
@@ -64,10 +69,11 @@ public CarResponseDto getById(@PathVariable Long id) {
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("permitAll()")
- @Operation(summary = "Get all cars", description = "Get a list of all cars")
+ @UserRoleDescription
+ @Operation(summary = "Get all cars.", description = "Get a list of all cars.")
@Parameter(name = "page", description = "page index, default value = 0")
@Parameter(name = "size", description = "elements per page, default value = 20")
- @Parameter(name = "sort", description = "sort criteria", example = "title,Desc")
+ @Parameter(name = "sort", description = "sort criteria", example = "brand,Desc")
@GetMapping
public List getAll(Pageable pageable) {
return carService.getAll(pageable);
diff --git a/src/main/java/mate/academy/carsharing/controller/PaymentController.java b/src/main/java/mate/academy/carsharing/controller/PaymentController.java
index 4fdd08c..e0c2bfb 100644
--- a/src/main/java/mate/academy/carsharing/controller/PaymentController.java
+++ b/src/main/java/mate/academy/carsharing/controller/PaymentController.java
@@ -1,13 +1,16 @@
package mate.academy.carsharing.controller;
import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
+import mate.academy.carsharing.annotation.UserRoleDescription;
import mate.academy.carsharing.dto.payment.CreatePaymentRequestDto;
import mate.academy.carsharing.dto.payment.PaymentResponseDto;
import mate.academy.carsharing.dto.payment.PaymentSearchParametersDto;
+import mate.academy.carsharing.dto.payment.RenewPaymentRequestDto;
import mate.academy.carsharing.service.PaymentService;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
@@ -30,7 +33,8 @@ public class PaymentController {
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Create new payment", description = "Create new payment session")
+ @UserRoleDescription
+ @Operation(summary = "Create new payment.", description = "Create new payment session.")
@PostMapping()
public PaymentResponseDto createPayment(
@RequestBody @Valid CreatePaymentRequestDto requestDto) {
@@ -39,6 +43,12 @@ public PaymentResponseDto createPayment(
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasAnyRole('ROLE_MANAGER', 'ROLE_CUSTOMER')")
+ @UserRoleDescription
+ @Operation(summary = "Search payments.", description = "User can view own payments. "
+ + "Admin can view all payments.")
+ @Parameter(name = "page", description = "page index, default value = 0")
+ @Parameter(name = "size", description = "elements per page, default value = 20")
+ @Parameter(name = "sort", description = "sort criteria", example = "amountToPay,Desc")
@GetMapping("/search")
public List searchPayments(Authentication authentication,
PaymentSearchParametersDto searchParameters, Pageable pageable) {
@@ -47,8 +57,9 @@ public List searchPayments(Authentication authentication,
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("permitAll()")
- @Operation(summary = "Stripe redirection endpoint",
- description = "Mark payment as success, send message to Telegram")
+ @UserRoleDescription
+ @Operation(summary = "Stripe redirection endpoint marks payment as success.",
+ description = "Mark payment as success, send message to Telegram.")
@GetMapping("/success")
public PaymentResponseDto processSuccessfulPayment(
@RequestParam(name = "session_id") String sessionId) {
@@ -57,11 +68,24 @@ public PaymentResponseDto processSuccessfulPayment(
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("permitAll()")
- @Operation(summary = "Stripe redirection endpoint",
- description = "Mark payment as canceled, send message to Telegram")
+ @UserRoleDescription
+ @Operation(summary = "Stripe redirection endpoint marks payment as canceled",
+ description = "Marks payment as canceled, send message to Telegram.")
@GetMapping("/cancel")
public PaymentResponseDto processCanceledPayment(
@RequestParam(name = "session_id") String sessionId) {
return paymentService.processCanceledPayment(sessionId);
}
+
+ @ResponseStatus(HttpStatus.OK)
+ @PreAuthorize("hasAnyRole('ROLE_MANAGER', 'ROLE_CUSTOMER')")
+ @UserRoleDescription
+ @Operation(summary = "Renew expired session.",
+ description = "User can renew expired session and get new payment link.")
+ @PostMapping("/renew")
+ public PaymentResponseDto renewPaymentSession(
+ @RequestBody @Valid RenewPaymentRequestDto requestDto,
+ Authentication authentication) {
+ return paymentService.renewPaymentSession(requestDto.paymentId(), authentication.getName());
+ }
}
diff --git a/src/main/java/mate/academy/carsharing/controller/RentalController.java b/src/main/java/mate/academy/carsharing/controller/RentalController.java
index a43b454..009e521 100644
--- a/src/main/java/mate/academy/carsharing/controller/RentalController.java
+++ b/src/main/java/mate/academy/carsharing/controller/RentalController.java
@@ -6,6 +6,7 @@
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
+import mate.academy.carsharing.annotation.UserRoleDescription;
import mate.academy.carsharing.dto.rental.CreateRentalRequestDto;
import mate.academy.carsharing.dto.rental.RentalResponseDto;
import mate.academy.carsharing.dto.rental.RentalSearchParametersDto;
@@ -22,7 +23,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-@Tag(name = "Rental managing", description = "Endpoint to rentals managing")
+@Tag(name = "Rental managing", description = "Endpoint for managing rentals")
@RequiredArgsConstructor
@RestController
@RequestMapping("api/rentals")
@@ -31,7 +32,8 @@ public class RentalController {
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Create a new rental", description = "Admin creates a new rental")
+ @UserRoleDescription
+ @Operation(summary = "Create a new rental.", description = "Admin can create a new rental.")
@PostMapping()
public RentalResponseDto create(@RequestBody @Valid CreateRentalRequestDto requestDto) {
return rentalService.save(requestDto);
@@ -39,8 +41,9 @@ public RentalResponseDto create(@RequestBody @Valid CreateRentalRequestDto reque
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Get list of rentals", description = "Admin can get list of "
- + "active/nonactive rentals for any number of specified users or for all users")
+ @UserRoleDescription
+ @Operation(summary = "Get list of rentals.", description = "Admin can get list of "
+ + "active/nonactive rentals for any number of specified users or for all users.")
@Parameter(name = "user_id", description = "Get rentals for users with specified 'user_id'."
+ "To get rentals for all users do not specify any value.", example = "2, 57")
@Parameter(name = "is_active", description = "Specify 'true' to get active rentals or "
@@ -54,7 +57,8 @@ public List searchRentals(
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('ROLE_CUSTOMER')")
- @Operation(summary = "Get rental info by id", description = "Get rental info by id")
+ @UserRoleDescription
+ @Operation(summary = "Get rental info by id.", description = "Get rental info by id.")
@Parameter(name = "id", description = "Rental id", example = "247")
@GetMapping("/{id}")
public RentalResponseDto getRental(@PathVariable Long id, Authentication authentication) {
@@ -63,7 +67,8 @@ public RentalResponseDto getRental(@PathVariable Long id, Authentication authent
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('ROLE_MANAGER')")
- @Operation(summary = "Return rental", description = "Admin can return rental by id")
+ @UserRoleDescription
+ @Operation(summary = "Return rental.", description = "Admin can return rental by id.")
@Parameter(name = "id", description = "Rental id", example = "247")
@PostMapping("/{id}/return")
public RentalResponseDto returnRental(@PathVariable Long id) {
diff --git a/src/main/java/mate/academy/carsharing/controller/UserController.java b/src/main/java/mate/academy/carsharing/controller/UserController.java
index 4ae06a9..487641c 100644
--- a/src/main/java/mate/academy/carsharing/controller/UserController.java
+++ b/src/main/java/mate/academy/carsharing/controller/UserController.java
@@ -4,6 +4,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
+import mate.academy.carsharing.annotation.UserRoleDescription;
import mate.academy.carsharing.dto.user.UserResponseDto;
import mate.academy.carsharing.dto.user.UserResponseDtoWithRoles;
import mate.academy.carsharing.dto.user.UserUpdateInfoRequestDto;
@@ -21,7 +22,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-@Tag(name = "Users managing", description = "Endpoints to user managing")
+@Tag(name = "Users managing", description = "Endpoints for managing users")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/users")
@@ -29,8 +30,10 @@ public class UserController {
private final UserService userService;
@ResponseStatus(HttpStatus.OK)
- @Operation(summary = "Update user role", description = "Manager updates role for specify user")
+ @Operation(summary = "Update user role.",
+ description = "Manager updates role for specify user.")
@PreAuthorize("hasRole('ROLE_MANAGER')")
+ @UserRoleDescription
@PutMapping("/{id}/role")
public UserResponseDtoWithRoles updateRole(@PathVariable Long id,
@RequestBody @Valid UserUpdateRoleRequestDto requestDto) {
@@ -39,8 +42,9 @@ public UserResponseDtoWithRoles updateRole(@PathVariable Long id,
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('ROLE_CUSTOMER')")
- @Operation(summary = "Update info about user",
- description = "Update firstName, lastName or password")
+ @UserRoleDescription
+ @Operation(summary = "Update info about user.",
+ description = "User can update firstName, lastName or password.")
@PatchMapping("/me")
public UserResponseDto updateUserInfo(Authentication authentication,
@RequestBody @Valid UserUpdateInfoRequestDto requestDto) {
@@ -49,7 +53,8 @@ public UserResponseDto updateUserInfo(Authentication authentication,
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasAnyRole('ROLE_MANAGER', 'ROLE_CUSTOMER')")
- @Operation(summary = "Get user info", description = "Get info about user")
+ @UserRoleDescription
+ @Operation(summary = "Get user info.", description = "Get info about user.")
@GetMapping("/me")
public UserResponseDtoWithRoles getUserInfo(Authentication authentication) {
return userService.getUserInfo(authentication.getName());
diff --git a/src/main/java/mate/academy/carsharing/dto/payment/RenewPaymentRequestDto.java b/src/main/java/mate/academy/carsharing/dto/payment/RenewPaymentRequestDto.java
new file mode 100644
index 0000000..53906a1
--- /dev/null
+++ b/src/main/java/mate/academy/carsharing/dto/payment/RenewPaymentRequestDto.java
@@ -0,0 +1,8 @@
+package mate.academy.carsharing.dto.payment;
+
+import jakarta.validation.constraints.NotNull;
+
+public record RenewPaymentRequestDto(
+ @NotNull
+ Long paymentId) {
+}
diff --git a/src/main/java/mate/academy/carsharing/dto/user/UserUpdateInfoRequestDto.java b/src/main/java/mate/academy/carsharing/dto/user/UserUpdateInfoRequestDto.java
index 9aeb369..91bf687 100644
--- a/src/main/java/mate/academy/carsharing/dto/user/UserUpdateInfoRequestDto.java
+++ b/src/main/java/mate/academy/carsharing/dto/user/UserUpdateInfoRequestDto.java
@@ -1,10 +1,12 @@
package mate.academy.carsharing.dto.user;
-import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
public record UserUpdateInfoRequestDto(
- @NotNull(message = "First name cannot be null")
String firstName,
- @NotNull(message = "Last name cannot be null")
- String lastName) {
+ String lastName,
+ @Size(min = 8, message = PASSWORD_MUST_CONTAIN_AT_LEAST_8_CHARACTERS)
+ String password) {
+ private static final String PASSWORD_MUST_CONTAIN_AT_LEAST_8_CHARACTERS
+ = "Password must contain at least 8 characters";
}
diff --git a/src/main/java/mate/academy/carsharing/exception/CustomGlobalExceptionHandler.java b/src/main/java/mate/academy/carsharing/exception/CustomGlobalExceptionHandler.java
index 3c817e7..b987682 100644
--- a/src/main/java/mate/academy/carsharing/exception/CustomGlobalExceptionHandler.java
+++ b/src/main/java/mate/academy/carsharing/exception/CustomGlobalExceptionHandler.java
@@ -84,4 +84,14 @@ protected ResponseEntity