diff --git a/pom.xml b/pom.xml
index c42f36c..22a03b8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,7 +130,13 @@
jacoco-maven-plugin
0.8.11
- **/domain/**
+
+ **/springdoc/*
+ **/domain/**
+ **/infraestructure/security/SecurityConfigurations.class
+ **/AluraFlixApiApplication.class
+ **/infraestructure/security/SecurityFilter.class
+
diff --git a/src/main/java/com/alura/aluraflixapi/controller/CategoryController.java b/src/main/java/com/alura/aluraflixapi/controller/CategoryController.java
index e336784..c635186 100644
--- a/src/main/java/com/alura/aluraflixapi/controller/CategoryController.java
+++ b/src/main/java/com/alura/aluraflixapi/controller/CategoryController.java
@@ -10,6 +10,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -67,10 +68,11 @@ public ResponseEntity> getVideosByCategory(
}
@DeleteMapping(value = "/{id}", produces = "application/json")
+ @PreAuthorize("hasRole('Admin')")
public ResponseEntity deleteCategory(@NotBlank @PathVariable final String id) {
log.info("{} Request to Delete Category with Id: {}", PREFIX_LOGGING, id);
- final var response = this.categoryService.deleteCategory(id);
- return ResponseEntity.status(response).build();
+ this.categoryService.deleteCategory(id);
+ return ResponseEntity.ok().build();
}
}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/ControllerAdvice.java b/src/main/java/com/alura/aluraflixapi/controller/ControllerAdvice.java
index 11a17e0..9961e5c 100644
--- a/src/main/java/com/alura/aluraflixapi/controller/ControllerAdvice.java
+++ b/src/main/java/com/alura/aluraflixapi/controller/ControllerAdvice.java
@@ -1,36 +1,34 @@
package com.alura.aluraflixapi.controller;
-import com.alura.aluraflixapi.controller.dto.ErrorDto;
-import java.util.List;
+import com.alura.aluraflixapi.controller.dto.ErrorVO;
+import com.alura.aluraflixapi.infraestructure.exception.ErrorMessageVO;
+import com.alura.aluraflixapi.infraestructure.exception.ResourceNotFoundException;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
-import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
+import java.util.List;
+
@RestControllerAdvice
public class ControllerAdvice {
- /**
- * Handle Invalid fields
- * @return List of ErrorDto with invalid fields
- */
- @ExceptionHandler(MethodArgumentNotValidException.class)
- public ResponseEntity> handleInvalidFields(
- final MethodArgumentNotValidException ex) {
- var errors = ex.getFieldErrors();
- return ResponseEntity.badRequest().body(errors.stream().map(ErrorDto::new).toList());
- }
+ /**
+ * Handle Invalid fields
+ *
+ * @return List of ErrorDto with invalid fields
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity> handleInvalidFields(
+ final MethodArgumentNotValidException ex) {
+ var errors = ex.getFieldErrors();
+ return ResponseEntity.badRequest().body(errors.stream().map(ErrorVO::new).toList());
+ }
- /**
- * handle invalid credentials whe user atempt to login
- * @param ex HttpMessageNotReadableException
- * @return ResponseEntity status bad_request
- */
- @ExceptionHandler(HttpMessageNotReadableException.class)
- public ResponseEntity handleLoginException(
- final HttpMessageNotReadableException ex) {
- return ResponseEntity.badRequest().body("Invalid Credentials");
- }
+ @ExceptionHandler(ResourceNotFoundException.class)
+ public ResponseEntity handlerResourceNotFoundException(final ResourceNotFoundException ex) {
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorMessageVO(ex.getMessage(), HttpStatus.NOT_FOUND));
+ }
}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/UserController.java b/src/main/java/com/alura/aluraflixapi/controller/UserController.java
index aa1168d..3650554 100644
--- a/src/main/java/com/alura/aluraflixapi/controller/UserController.java
+++ b/src/main/java/com/alura/aluraflixapi/controller/UserController.java
@@ -3,37 +3,36 @@
import com.alura.aluraflixapi.domain.user.dto.UserDto;
import com.alura.aluraflixapi.infraestructure.service.UserService;
import jakarta.validation.Valid;
-import java.util.List;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.annotation.Secured;
-import org.springframework.web.bind.annotation.GetMapping;
-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;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
- private static final String PREFIX_LOGGIN = "[UserController]";
+ private static final String PREFIX_LOGGING = "[UserController]";
+ private final UserService service;
- @Autowired
- private UserService service;
+ public UserController(UserService service) {
+ this.service = service;
+ }
@PostMapping
- @Secured("ROLE_ADMIN")
+ @PreAuthorize("hasRole('Admin')")
public ResponseEntity saveUser(@RequestBody @Valid UserDto userDto) {
- log.info("{} Saving new User: {}", PREFIX_LOGGIN, userDto.toString());
+ log.info("{} Saving new User: {}", PREFIX_LOGGING, userDto.toString());
var newUser = this.service.saveUser(userDto);
return ResponseEntity.ok().body(newUser);
}
@GetMapping
+ @PreAuthorize("hasRole('Admin')")
public ResponseEntity> getUsers() {
- log.info("{} Retrieving Users", PREFIX_LOGGIN);
+ log.info("{} Retrieving Users", PREFIX_LOGGING);
var users = this.service.getUsers();
return ResponseEntity.ok(users);
}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/VideoController.java b/src/main/java/com/alura/aluraflixapi/controller/VideoController.java
index 57f7157..6b829ab 100644
--- a/src/main/java/com/alura/aluraflixapi/controller/VideoController.java
+++ b/src/main/java/com/alura/aluraflixapi/controller/VideoController.java
@@ -7,16 +7,21 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
+
import java.util.List;
import java.util.Optional;
+
import lombok.extern.slf4j.Slf4j;
+import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -34,80 +39,75 @@
@SecurityRequirement(name = "bearer-key")
public class VideoController {
- private static final String LOGGING_PREFIX = "[VideoController]";
+ private static final String LOGGING_PREFIX = "[VideoController]";
+
+ private final VideoService service;
+
+ @Autowired
+ public VideoController(final VideoService service) {
+ this.service = service;
+ }
+
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity> getVideos(@ParameterObject Pageable pageable) {
+ log.info("{} Request to get All videos", LOGGING_PREFIX);
+ final Page videos = this.service.getVideos(pageable);
+ log.info("{} Response {}: ", LOGGING_PREFIX, videos.getContent());
+ return ResponseEntity.ok().body(new PageImpl<>(videos.getContent(), pageable, pageable.getPageSize()));
+ }
+
- private final VideoService service;
+ @GetMapping("/{id}")
+ public ResponseEntity getById(@NotBlank @PathVariable final String id) {
+ log.info("{} Request to get a video by ID: {}", LOGGING_PREFIX, id);
+ return Optional.ofNullable(service.getById(id))
+ .map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
- @Autowired
- public VideoController(final VideoService service) {
- this.service = service;
- }
+ }
- @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity> getVideos(Pageable pageable) {
- log.info("{} Request to get All videos", LOGGING_PREFIX);
- final Page videos = this.service.getVideos(pageable);
- if (videos.hasContent()) {
- log.info("{} Response {}: ", LOGGING_PREFIX, videos);
- return ResponseEntity.ok().body(videos);
- } else {
- return ResponseEntity.noContent().build();
+ @PostMapping
+ public ResponseEntity save(@Valid @RequestBody final VideoDto dto,
+ final UriComponentsBuilder uriBuilder) {
+ log.info("{} Request to Save a new video: {}", LOGGING_PREFIX, dto);
+ final VideoDto videoDto = this.service.save(dto);
+ //good practices to return the Location in the Header to be searched by Id
+ //return Http code 201 and Location with Id
+ return ResponseEntity.created(uriBuilder.path("/videos/{id}").buildAndExpand(videoDto.id())
+ .toUri()).body(videoDto);
}
- }
-
-
- @GetMapping("/{id}")
- public ResponseEntity getById(@NotBlank @PathVariable final String id) {
- log.info("{} Request to get a video by ID: {}", LOGGING_PREFIX, id);
- return Optional.ofNullable(service.getById(id))
- .map(ResponseEntity::ok)
- .orElse(ResponseEntity.notFound().build());
-
- }
-
- @PostMapping
- public ResponseEntity save(@Valid @RequestBody final VideoDto dto,
- final UriComponentsBuilder uriBuilder) {
- log.info("{} Request to Save a new video: {}", LOGGING_PREFIX, dto);
- final VideoDto videoDto = this.service.save(dto);
- //good practices to return the Location in the Header to be search by Id
- //return Http code 201 and Localtion with Id
- return ResponseEntity.created(uriBuilder.path("/videos/{id}").buildAndExpand(videoDto.id())
- .toUri()).body(videoDto);
- }
-
- @PutMapping
- public ResponseEntity update(@Valid @RequestBody final UpdateVideoDto dto,
- final UriComponentsBuilder uriBuilder) {
- log.info("{} Request to update a video: {}", LOGGING_PREFIX, dto);
- final var videoDto = this.service.updateMovie(dto);
- //good practices to return the Location in the Header to be search by Id
- //return Http code 201 and Location with Id
- return ResponseEntity.created(uriBuilder.path("/videos/{id}")
- .buildAndExpand(videoDto.id())
- .toUri()).body(videoDto);
- }
-
- @DeleteMapping("/{id}")
- @Secured("ROLE_ADMIN")
- public ResponseEntity delete(@NotBlank @PathVariable final String id) {
- log.info("{} Request to Delete a video by ID: {}", LOGGING_PREFIX, id);
- final Optional dto = this.service.delete(id);
- return dto.map(videoDto -> ResponseEntity.status(HttpStatus.NO_CONTENT).body(videoDto))
- .orElseGet(() -> ResponseEntity.noContent().build());
- }
-
- @GetMapping("/title")
- public ResponseEntity> getVideosByTitle(
- @NotBlank @RequestParam("title") final String title) {
- log.info("{} Request to get a video by title: {}", LOGGING_PREFIX, title);
- final var videosByTitle = this.service.getVideosByTitle(title);
- if (videosByTitle.isEmpty()) {
- return ResponseEntity.noContent().build();
- } else {
- return ResponseEntity.status(HttpStatus.FOUND).body(videosByTitle);
+
+ @PutMapping
+ public ResponseEntity update(@Valid @RequestBody final UpdateVideoDto dto,
+ final UriComponentsBuilder uriBuilder) {
+ log.info("{} Request to update a video: {}", LOGGING_PREFIX, dto);
+ final var videoDto = this.service.updateMovie(dto);
+ //good practices to return the Location in the Header to be search by Id
+ //return Http code 201 and Location with Id
+ return ResponseEntity.created(uriBuilder.path("/videos/{id}")
+ .buildAndExpand(videoDto.id())
+ .toUri()).body(videoDto);
}
- }
+ @DeleteMapping("/{id}")
+ @PreAuthorize("hasRole('Admin')")
+ public ResponseEntity delete(@NotBlank @PathVariable final String id) {
+ log.info("{} Request to Delete a video by ID: {}", LOGGING_PREFIX, id);
+ final var dto = this.service.delete(id);
+ return ResponseEntity.ok(dto);
+ }
+
+ @GetMapping("/title")
+ public ResponseEntity> getVideosByTitle(
+ @NotBlank @RequestParam("title") final String title) {
+ log.info("{} Request to get a video by title: {}", LOGGING_PREFIX, title);
+ final var videosByTitle = this.service.getVideosByTitle(title);
+ if (videosByTitle.isEmpty()) {
+ return ResponseEntity.noContent().build();
+ } else {
+ return ResponseEntity.status(HttpStatus.FOUND).body(videosByTitle);
+ }
+
+ }
}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/dto/ErrorDto.java b/src/main/java/com/alura/aluraflixapi/controller/dto/ErrorDto.java
deleted file mode 100644
index d1d2af4..0000000
--- a/src/main/java/com/alura/aluraflixapi/controller/dto/ErrorDto.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.alura.aluraflixapi.controller.dto;
-
-import org.springframework.validation.FieldError;
-
-public record ErrorDto(String field, String message) {
-
- public ErrorDto(FieldError fieldError) {
- this(fieldError.getField(), fieldError.getDefaultMessage());
- }
-
-}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/dto/ErrorVO.java b/src/main/java/com/alura/aluraflixapi/controller/dto/ErrorVO.java
new file mode 100644
index 0000000..22f1f22
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/controller/dto/ErrorVO.java
@@ -0,0 +1,10 @@
+package com.alura.aluraflixapi.controller.dto;
+
+import org.springframework.validation.FieldError;
+
+public record ErrorVO(String field, String message) {
+
+ public ErrorVO(FieldError fieldError) {
+ this(fieldError.getField(), fieldError.getDefaultMessage());
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/domain/user/User.java b/src/main/java/com/alura/aluraflixapi/domain/user/User.java
index 0fadb14..7991394 100644
--- a/src/main/java/com/alura/aluraflixapi/domain/user/User.java
+++ b/src/main/java/com/alura/aluraflixapi/domain/user/User.java
@@ -6,6 +6,8 @@
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
+
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
@@ -39,7 +41,7 @@ public class User implements Serializable, UserDetails {
private String password;
@DBRef
- private List roles;
+ private Set roles;
@Override
public Collection extends GrantedAuthority> getAuthorities() {
diff --git a/src/main/java/com/alura/aluraflixapi/domain/user/dto/UserDto.java b/src/main/java/com/alura/aluraflixapi/domain/user/dto/UserDto.java
index 162ae12..f011e8c 100644
--- a/src/main/java/com/alura/aluraflixapi/domain/user/dto/UserDto.java
+++ b/src/main/java/com/alura/aluraflixapi/domain/user/dto/UserDto.java
@@ -2,7 +2,8 @@
import com.alura.aluraflixapi.domain.user.roles.Roles;
import jakarta.validation.constraints.NotBlank;
-import java.util.List;
+
+import java.util.Set;
public record UserDto(
String id,
@@ -10,6 +11,6 @@ public record UserDto(
String username,
@NotBlank
String password,
- List roles) {
+ Set roles) {
}
diff --git a/src/main/java/com/alura/aluraflixapi/domain/video/dto/VideoDto.java b/src/main/java/com/alura/aluraflixapi/domain/video/dto/VideoDto.java
index 1144eef..137ad8a 100644
--- a/src/main/java/com/alura/aluraflixapi/domain/video/dto/VideoDto.java
+++ b/src/main/java/com/alura/aluraflixapi/domain/video/dto/VideoDto.java
@@ -3,10 +3,8 @@
import com.alura.aluraflixapi.domain.category.dto.CategoryDto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
-import lombok.Builder;
import org.hibernate.validator.constraints.URL;
-@Builder
public record VideoDto(
String id,
@NotBlank
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/CategoryServiceException.java b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/CategoryServiceException.java
new file mode 100644
index 0000000..487be52
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/CategoryServiceException.java
@@ -0,0 +1,11 @@
+package com.alura.aluraflixapi.infraestructure.exception;
+
+public class CategoryServiceException extends RuntimeException {
+ public CategoryServiceException(String message) {
+ super(message);
+ }
+
+ public CategoryServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/CategoryTransactionException.java b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/CategoryTransactionException.java
deleted file mode 100644
index 65a6772..0000000
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/CategoryTransactionException.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.alura.aluraflixapi.infraestructure.exception;
-
-public class CategoryTransactionException extends RuntimeException {
-
- public CategoryTransactionException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/ErrorMessageVO.java b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/ErrorMessageVO.java
new file mode 100644
index 0000000..c6015ce
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/ErrorMessageVO.java
@@ -0,0 +1,6 @@
+package com.alura.aluraflixapi.infraestructure.exception;
+
+import org.springframework.http.HttpStatus;
+
+public record ErrorMessageVO(String message, HttpStatus httpStatus) {
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/ResourceNotFoundException.java b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/ResourceNotFoundException.java
new file mode 100644
index 0000000..32ff49a
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/ResourceNotFoundException.java
@@ -0,0 +1,7 @@
+package com.alura.aluraflixapi.infraestructure.exception;
+
+public class ResourceNotFoundException extends RuntimeException {
+ public ResourceNotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/VideoServiceException.java b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/VideoServiceException.java
new file mode 100644
index 0000000..6513451
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/VideoServiceException.java
@@ -0,0 +1,12 @@
+package com.alura.aluraflixapi.infraestructure.exception;
+
+public class VideoServiceException extends RuntimeException {
+
+ public VideoServiceException(String message) {
+ super(message);
+ }
+
+ public VideoServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/mapper/UserMapper.java b/src/main/java/com/alura/aluraflixapi/infraestructure/mapper/UserMapper.java
index 39a6927..2b3dcf0 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/mapper/UserMapper.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/mapper/UserMapper.java
@@ -12,11 +12,11 @@
public interface UserMapper {
@Mapping(target = "password", qualifiedByName = "encryptPassword")
- User mappToEntity(UserDto dto);
+ User mapToEntity(UserDto dto);
- UserDto mappToDto(User newUser);
+ UserDto mapToDto(User newUser);
- List mappToUsersDto(List users);
+ List mapToUsersDto(List users);
@Named("encryptPassword")
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java b/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java
index 0c24b17..0082d5f 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java
@@ -6,6 +6,5 @@
public interface UserRepository extends MongoRepository {
-
- UserDetails findByUsername(String username);
+ UserDetails findByUsername(String username);
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java
index 8cb037f..390feed 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java
@@ -9,18 +9,11 @@
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
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;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.CorsConfigurationSource;
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-
-import java.util.Arrays;
-import java.util.List;
/**
* Main Spring Security class configuration In Spring 3.0 the security configuration is done by
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java
index d559b86..e82f01b 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java
@@ -23,7 +23,6 @@ public class SecurityFilter extends OncePerRequestFilter {
private static final String PREFIX_LOGGING = "[SecurityFilter]";
public static final String AUTHORIZATION = "Authorization";
private final TokenService tokenService;
-
private final UserRepository userRepository;
public SecurityFilter(final TokenService tokenService, final UserRepository userRepository) {
@@ -43,8 +42,8 @@ protected void doFilterInternal(final HttpServletRequest request,
if (tokenJWT != null) {
//Retrieve user from Token JWT
- final var subject = tokenService.getSubject(tokenJWT);
- var user = userRepository.findByUsername(subject);
+ final var subject = this.tokenService.getSubject(tokenJWT);
+ var user = this.userRepository.findByUsername(subject);
//after retrieve the user we need to tell to Spring framework to authenticate him in the context
//this is done by calling UsernamePasswordAuthenticationToken and SecurityContextHolder methods
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java
index df966cd..7ac0640 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java
@@ -9,6 +9,8 @@
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
+
+import com.auth0.jwt.exceptions.JWTDecodeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -24,7 +26,7 @@ public class TokenService {
public String generateTokenJWT(User user) {
try {
- log.info("Generating JWt Token...");
+ log.info("Generating Token JWT ...");
return JWT.create()
.withIssuer(ALURA_FLIX_API)
//owner
@@ -39,7 +41,7 @@ public String generateTokenJWT(User user) {
.withExpiresAt(getExpireDate())
.sign(Algorithm.HMAC256(secret));
- } catch (JWTCreationException exception) {
+ } catch (NullPointerException exception) {
throw new JWTCreationException("Error to create JWT token", exception.getCause());
}
}
@@ -52,8 +54,8 @@ public String getSubject(String tokenJWT) {
.build()
.verify(tokenJWT)
.getSubject();
- } catch (JWTCreationException ex) {
- throw new JWTCreationException("Error verifying JWT Token", ex.getCause());
+ } catch (JWTDecodeException ex) {
+ throw new JWTDecodeException("Error verifying JWT Token", ex.getCause());
}
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryService.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryService.java
index ec3a7f9..ee32c34 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryService.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryService.java
@@ -13,7 +13,7 @@ public interface CategoryService {
CategoryDto findCategoryById(String id);
- HttpStatus deleteCategory(String id);
+ void deleteCategory(String id);
List getVideosByCategory(String rating);
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryServiceImpl.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryServiceImpl.java
index dfe2fae..cf3df29 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryServiceImpl.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/CategoryServiceImpl.java
@@ -2,12 +2,14 @@
import com.alura.aluraflixapi.domain.category.dto.CategoryDto;
import com.alura.aluraflixapi.domain.video.dto.VideoDto;
-import com.alura.aluraflixapi.infraestructure.exception.CategoryTransactionException;
+import com.alura.aluraflixapi.infraestructure.exception.CategoryServiceException;
import com.alura.aluraflixapi.infraestructure.mapper.CategoryMapper;
import com.alura.aluraflixapi.infraestructure.mapper.VideoMapper;
import com.alura.aluraflixapi.infraestructure.repository.CategoryRepository;
import com.alura.aluraflixapi.infraestructure.repository.VideoRepository;
+
import java.util.List;
+
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.MongoTransactionException;
import org.springframework.http.HttpStatus;
@@ -19,71 +21,70 @@
public class CategoryServiceImpl implements CategoryService {
- private final CategoryRepository categoryRepository;
+ private final CategoryRepository categoryRepository;
+
+ private final VideoRepository videoRepository;
- private final VideoRepository videoRepository;
+ private final VideoMapper videoMapper;
- private final VideoMapper videoMapper;
+ private final CategoryMapper categoryMapper;
- private final CategoryMapper categoryMapper;
+ public CategoryServiceImpl(CategoryRepository categoryRepository, VideoRepository videoRepository,
+ VideoMapper videoMapper, CategoryMapper categoryMapper) {
+ this.categoryRepository = categoryRepository;
+ this.videoRepository = videoRepository;
+ this.videoMapper = videoMapper;
+ this.categoryMapper = categoryMapper;
+ }
- public CategoryServiceImpl(CategoryRepository categoryRepository, VideoRepository videoRepository,
- VideoMapper videoMapper, CategoryMapper categoryMapper) {
- this.categoryRepository = categoryRepository;
- this.videoRepository = videoRepository;
- this.videoMapper = videoMapper;
- this.categoryMapper = categoryMapper;
- }
+ @Override
+ public List categories() {
+ return categoryRepository.findAll()
+ .stream()
+ .map(entity -> new CategoryDto(entity.getId(), entity.getRating(), entity.getTitle(),
+ entity.getColorHex()))
+ .toList();
+ }
- @Override
- public List categories() {
- return categoryRepository.findAll()
- .stream()
- .map(entity -> new CategoryDto(entity.getId(), entity.getRating(), entity.getTitle(),
- entity.getColorHex()))
- .toList();
- }
+ @Override
+ @Transactional
+ public CategoryDto create(CategoryDto categoryDto) {
+ try {
+ final var entity = this.categoryMapper.mapperToEntity(categoryDto);
+ final var categorySaved = categoryRepository.save(entity);
+ return this.categoryMapper.mapperToCategoryDto(categorySaved);
+ } catch (MongoTransactionException exception) {
+ throw new CategoryServiceException("Error to persist new category",
+ exception.getMostSpecificCause());
+ }
+ }
- @Override
- @Transactional
- public CategoryDto create(CategoryDto categoryDto) {
- try {
- final var entity = this.categoryMapper.mapperToEntity(categoryDto);
- final var categorySaved = categoryRepository.save(entity);
- return this.categoryMapper.mapperToCategoryDto(categorySaved);
- } catch (MongoTransactionException exception) {
- throw new CategoryTransactionException("Error to persist new category",
- exception.getMostSpecificCause());
+ @Override
+ public CategoryDto findCategoryById(String id) {
+ return this.categoryRepository.findById(id)
+ .map(
+ document -> new CategoryDto(document.getId(), document.getRating(), document.getTitle(),
+ document.getColorHex()))
+ .orElseThrow(() -> new CategoryServiceException("Category not found: " + id));
}
- }
-
- @Override
- public CategoryDto findCategoryById(String id) {
- return this.categoryRepository.findById(id)
- .map(
- document -> new CategoryDto(document.getId(), document.getRating(), document.getTitle(),
- document.getColorHex()))
- .orElse(null);
- }
-
- @Override
- @Transactional
- public HttpStatus deleteCategory(String id) {
- try {
- this.categoryRepository.deleteById(id);
- return HttpStatus.ACCEPTED;
- } catch (MongoTransactionException exception) {
- log.error("Error", exception.getCause());
- return HttpStatus.NO_CONTENT;
+
+ @Override
+ @Transactional
+ public void deleteCategory(String id) {
+
+ final var isCategoryPresent = this.categoryRepository.findById(id);
+ isCategoryPresent.ifPresentOrElse(this.categoryRepository::delete, () -> {
+ throw new CategoryServiceException("Category not found to delete with Id:" + id);
+ });
+
+ }
+
+ @Override
+ public List getVideosByCategory(String rating) {
+ final var category = categoryRepository.findCategoryByRating(rating);
+ return videoRepository.findVideosByCategories(category.getId())
+ .stream().map(this.videoMapper::mapToVideoDto)
+ .toList();
}
- }
-
- @Override
- public List getVideosByCategory(String rating) {
- final var category = categoryRepository.findCategoryByRating(rating);
- return videoRepository.findVideosByCategories(category.getId())
- .stream().map(this.videoMapper::mapToVideoDto)
- .toList();
- }
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserDetailsServiceImpl.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserDetailsServiceImpl.java
index 6fc96aa..1561047 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserDetailsServiceImpl.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserDetailsServiceImpl.java
@@ -2,12 +2,15 @@
import com.alura.aluraflixapi.infraestructure.repository.UserRepository;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
+import java.util.Objects;
+
/**
* User Details Service Impl that connect to database and retrieve a user previously registred
*/
@@ -15,24 +18,29 @@
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
- private static final String PREFIX_LOGGING = "[UserDetailsServiceImpl]";
+ private static final String PREFIX_LOGGING = "[UserDetailsServiceImpl]";
- private final UserRepository repository;
+ private final UserRepository repository;
- @Autowired
- public UserDetailsServiceImpl(UserRepository repository) {
- this.repository = repository;
- }
+ @Autowired
+ public UserDetailsServiceImpl(UserRepository repository) {
+ this.repository = repository;
+ }
- /**
- * Search in databse a user by username and return it
- * @return UserDestails
- */
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- log.info("{} Retrieving User by username: {}", PREFIX_LOGGING, username);
- final var user = this.repository.findByUsername(username);
- log.info("{} Retrieved User: {}", PREFIX_LOGGING, user);
- return user;
- }
+ /**
+ * Search in databse a user by username and return it
+ *
+ * @return UserDestails
+ */
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ log.info("{} Retrieving User by username: {}", PREFIX_LOGGING, username);
+ final var user = this.repository.findByUsername(username);
+ log.info("{} Retrieved User: {}", PREFIX_LOGGING, user);
+ if (Objects.isNull(user)) {
+ throw new UsernameNotFoundException(String.format("User not found for: %s", username));
+ } else {
+ return user;
+ }
+ }
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserServiceImpl.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserServiceImpl.java
index d87f2ba..619172d 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserServiceImpl.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/UserServiceImpl.java
@@ -26,17 +26,17 @@ public UserServiceImpl(final UserRepository repository, final RoleRepository rol
@Override
public UserDto saveUser(UserDto dto) {
- final User user = mapper.mappToEntity(dto);
+ final User user = mapper.mapToEntity(dto);
//first save Document Roles
this.roleRepository.saveAll(dto.roles());
//After save Document User
final User newUser = repository.save(user);
- return mapper.mappToDto(newUser);
+ return mapper.mapToDto(newUser);
}
@Override
public List getUsers() {
List users = repository.findAll();
- return mapper.mappToUsersDto(users);
+ return mapper.mapToUsersDto(users);
}
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoService.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoService.java
index bebed39..f80370e 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoService.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoService.java
@@ -17,7 +17,7 @@ public interface VideoService {
UpdateVideoDto updateMovie(UpdateVideoDto dto);
- Optional delete(String id);
+ VideoDto delete(String id);
VideoDto getById(String id);
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoServiceImpl.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoServiceImpl.java
index 646649d..fe98a4e 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoServiceImpl.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/VideoServiceImpl.java
@@ -6,6 +6,8 @@
import com.alura.aluraflixapi.domain.video.Video;
import com.alura.aluraflixapi.domain.video.dto.UpdateVideoDto;
import com.alura.aluraflixapi.domain.video.dto.VideoDto;
+import com.alura.aluraflixapi.infraestructure.exception.ResourceNotFoundException;
+import com.alura.aluraflixapi.infraestructure.exception.VideoServiceException;
import com.alura.aluraflixapi.infraestructure.mapper.VideoMapper;
import com.alura.aluraflixapi.infraestructure.repository.CategoryRepository;
import com.alura.aluraflixapi.infraestructure.repository.VideoRepository;
@@ -19,6 +21,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@Service
@@ -46,10 +49,10 @@ public Page getVideos(Pageable pageable) {
.forEach(video -> {
if (Objects.isNull(video.getCategory())) {
video.setCategory(Category.builder()
- .id(null)
+ .id("")
.rating(Rating.FREE.name())
- .title(null)
- .colorHex(null)
+ .title("")
+ .colorHex("")
.build());
}
});
@@ -66,7 +69,7 @@ public VideoDto save(VideoDto dto) {
log.info("{} New Video saved", LOGGING_PREFIX);
return videoMapper.mapToVideoDto(entityPersisted);
} catch (Exception e) {
- throw new RuntimeException("Error to persist entity", e.getCause());
+ throw new VideoServiceException("Error to persist entity", e.getCause());
}
}
@@ -81,30 +84,39 @@ public UpdateVideoDto updateMovie(UpdateVideoDto dto) {
videoRepository.save(entity);
return videoMapper.mapToUpdateVideoDto(entity);
} catch (Exception e) {
- throw new RuntimeException("Error to update movie", e.getCause());
+ throw new VideoServiceException("Error to update movie", e.getCause());
}
}
@Override
- public Optional delete(String id) {
- Optional