diff --git a/src/main/java/com/guams/review/configuration/Advice.java b/src/main/java/com/guams/review/configuration/Advice.java index 9eec97a..6e12a5d 100644 --- a/src/main/java/com/guams/review/configuration/Advice.java +++ b/src/main/java/com/guams/review/configuration/Advice.java @@ -3,7 +3,7 @@ package com.guams.review.configuration; import com.guams.review.exception.AlreadyExistsException; import com.guams.review.exception.InvalidNameOrPasswordException; import com.guams.review.exception.NotFoundException; -import com.guams.review.exception.ForbiddenExecption; +import com.guams.review.exception.UnauthorizedExecption; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -24,11 +24,11 @@ public class Advice { @ExceptionHandler(value = InvalidNameOrPasswordException.class) public ResponseEntity handleInvalidNameOrPassword(InvalidNameOrPasswordException exception) { - return new ResponseEntity<>(exception.getMessage(), HttpStatus.FORBIDDEN); + return new ResponseEntity<>(exception.getMessage(), HttpStatus.UNAUTHORIZED); } - @ExceptionHandler(value = ForbiddenExecption.class) - public ResponseEntity handleUnauthorizedExecption(ForbiddenExecption exception) { - return new ResponseEntity<>(exception.getMessage(), HttpStatus.FORBIDDEN); + @ExceptionHandler(value = UnauthorizedExecption.class) + public ResponseEntity handleUnauthorizedExecption(UnauthorizedExecption exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.UNAUTHORIZED); } } diff --git a/src/main/java/com/guams/review/configuration/JwtAuthenticationFilter.java b/src/main/java/com/guams/review/configuration/JwtAuthenticationFilter.java index 524fad3..fcca4b0 100644 --- a/src/main/java/com/guams/review/configuration/JwtAuthenticationFilter.java +++ b/src/main/java/com/guams/review/configuration/JwtAuthenticationFilter.java @@ -32,12 +32,12 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); // Retire le préfixe "Bearer " try { - String username = jwtTokenUtil.extractUsername(token); // Récupère l'utilisateur du token + String authorUuid = jwtTokenUtil.extractAuthorId(token); // Récupère l'UUID du token - if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { - UserDetails userDetails = authorService.loadUserByUsername(username); + if (authorUuid != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = authorService.loadUserByUsername(authorUuid); // Utilise le service pour charger l'auteur par UUID - if (jwtTokenUtil.validateToken(token, userDetails)) { + if (jwtTokenUtil.validateToken(token, userDetails, authorUuid)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); @@ -50,6 +50,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { } } + filterChain.doFilter(request, response); // Continue le traitement } } diff --git a/src/main/java/com/guams/review/configuration/JwtTokenUtil.java b/src/main/java/com/guams/review/configuration/JwtTokenUtil.java index 7855e08..61110c5 100644 --- a/src/main/java/com/guams/review/configuration/JwtTokenUtil.java +++ b/src/main/java/com/guams/review/configuration/JwtTokenUtil.java @@ -13,16 +13,16 @@ public class JwtTokenUtil { private final String SECRET_KEY = "9f87d7a0eb7dea860b98adf6bb94feefe4a33698022733bb012d662d92db8081"; private final long EXPIRATION_TIME = 1000 * 60 * 60 * 10; // 10 heures - public String generateToken(String username) { + public String generateToken(String authorId) { return Jwts.builder() - .setSubject(username) + .setSubject(authorId) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } - public String extractUsername(String token) { + public String extractAuthorId(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) @@ -30,11 +30,12 @@ public class JwtTokenUtil { .getSubject(); } - public boolean validateToken(String token, UserDetails userDetails) { - String username = extractUsername(token); - return username.equals(userDetails.getUsername()) && !isTokenExpired(token); + public boolean validateToken(String token, UserDetails userDetails, String expectedUuid) { + String extractedUuid = extractAuthorId(token); + return extractedUuid.equals(expectedUuid) && !isTokenExpired(token); } + private boolean isTokenExpired(String token) { return extractExpiration(token).before(new Date()); } diff --git a/src/main/java/com/guams/review/configuration/SpringSecurityConfig.java b/src/main/java/com/guams/review/configuration/SpringSecurityConfig.java index 7f89e97..9273709 100644 --- a/src/main/java/com/guams/review/configuration/SpringSecurityConfig.java +++ b/src/main/java/com/guams/review/configuration/SpringSecurityConfig.java @@ -74,5 +74,4 @@ public class SpringSecurityConfig { authenticationManagerBuilder.userDetailsService(authorService).passwordEncoder(passwordEncoder); return authenticationManagerBuilder.build(); } - } diff --git a/src/main/java/com/guams/review/controller/AuthorController.java b/src/main/java/com/guams/review/controller/AuthorController.java index 1c05303..42d21ab 100644 --- a/src/main/java/com/guams/review/controller/AuthorController.java +++ b/src/main/java/com/guams/review/controller/AuthorController.java @@ -2,7 +2,7 @@ package com.guams.review.controller; import com.guams.review.configuration.JwtTokenUtil; import com.guams.review.exception.AlreadyExistsException; -import com.guams.review.exception.ForbiddenExecption; +import com.guams.review.exception.UnauthorizedExecption; import com.guams.review.exception.InvalidNameOrPasswordException; import com.guams.review.exception.NotFoundException; import com.guams.review.model.AuthorRepository; @@ -52,9 +52,17 @@ public class AuthorController { } @PutMapping("/{id}") - public void updateUser(@PathVariable UUID id, @RequestBody Author updatedAuthor, Authentication authentication) { + public ReturnableAuthor updateUser(@PathVariable UUID id, @RequestBody Author updatedAuthor, Authentication authentication) { + System.out.println(updatedAuthor.getName() + " " + updatedAuthor.getPassword() + " " + updatedAuthor.getId()); Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); - authorService.insert(updatedAuthor.setId(authorToUpdate.getId())); + if (passwordEncoder.matches(updatedAuthor.getPassword(), authorToUpdate.getPassword())) { + return authorService.insert(updatedAuthor + .setId(authorToUpdate.getId()) + .setRole(authorToUpdate.getRole()) + .setPassword(authorToUpdate.getPassword())); + } else { + throw new UnauthorizedExecption("You are not authorized to update this author"); + } } @PutMapping(value = "{id}/avatar", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) @@ -84,11 +92,11 @@ public class AuthorController { @PostMapping("/login") public AuthorToken authorLogin(@RequestBody Author author) { try { + Author concernedAuthor = authorService.findByName(author.getName()).orElseThrow(() -> new NotFoundException("Author not found")); authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(author.getName(), author.getPassword()) + new UsernamePasswordAuthenticationToken(concernedAuthor.getId(), author.getPassword()) ); - - String token = jwtTokenUtil.generateToken(author.getName()); + String token = jwtTokenUtil.generateToken(concernedAuthor.getId().toString()); return new AuthorToken().setToken(token); } catch (Exception e) { throw new InvalidNameOrPasswordException(e.getMessage()); @@ -109,7 +117,7 @@ public class AuthorController { @GetMapping(value = "/me", produces = "application/json") public Author getAuthenticatedUser(Authentication authentication) { if (authentication == null || !authentication.isAuthenticated()) { - throw new ForbiddenExecption("You are not authorized to access this resource"); + throw new UnauthorizedExecption("You are not authorized to access this resource"); } Author author = authorService.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); diff --git a/src/main/java/com/guams/review/controller/CommentController.java b/src/main/java/com/guams/review/controller/CommentController.java index 86f71eb..f2923bf 100644 --- a/src/main/java/com/guams/review/controller/CommentController.java +++ b/src/main/java/com/guams/review/controller/CommentController.java @@ -1,5 +1,5 @@ package com.guams.review.controller; -import com.guams.review.exception.ForbiddenExecption; +import com.guams.review.exception.UnauthorizedExecption; import com.guams.review.exception.NotFoundException; import com.guams.review.model.AuthorRepository; import com.guams.review.model.dao.Author; @@ -42,7 +42,7 @@ public class CommentController { @PostMapping("/posts/{post-id}") public ResponseEntity addComment(@RequestBody Comment comment, Authentication authentication, @PathVariable("post-id") Long postId) { if (authentication == null || !authentication.isAuthenticated()) { - throw new ForbiddenExecption("You are not authorized to access this resource"); + throw new UnauthorizedExecption("You are not authorized to access this resource"); } Author author = authorRepository.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); @@ -64,14 +64,14 @@ public class CommentController { @PutMapping("/{id}") public void updateComment(@PathVariable Long id, @RequestBody CommentIds commentIds, Authentication authentication) { if (authentication == null || !authentication.isAuthenticated()) { - throw new ForbiddenExecption("You are not authorized to access this resource"); + throw new UnauthorizedExecption("You are not authorized to access this resource"); } Author author = authorService.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); Comment commentToUpdate = commentService.findById(id).orElseThrow(() -> new NotFoundException("Comment not found")); CommentIds concernedCommentIds = commentService.getCommentIdsByCommentId(id).orElseThrow(() -> new NotFoundException("Comment not found")); if (!author.getId().equals(concernedCommentIds.getAuthorId())) { - throw new ForbiddenExecption("You are not authorized to access this resource"); + throw new UnauthorizedExecption("You are not authorized to access this resource"); } commentService.insert(commentToUpdate diff --git a/src/main/java/com/guams/review/controller/PostController.java b/src/main/java/com/guams/review/controller/PostController.java index 67ff885..a95cbfb 100644 --- a/src/main/java/com/guams/review/controller/PostController.java +++ b/src/main/java/com/guams/review/controller/PostController.java @@ -1,6 +1,6 @@ package com.guams.review.controller; -import com.guams.review.exception.ForbiddenExecption; +import com.guams.review.exception.UnauthorizedExecption; import com.guams.review.exception.NotFoundException; import com.guams.review.model.dao.Author; import com.guams.review.model.dao.Comment; @@ -43,7 +43,7 @@ public class PostController { @PutMapping("/{id}") public void updatePost(@PathVariable Long id, @RequestBody Post updatedPost, Authentication authentication) { if (authentication == null) { - throw new ForbiddenExecption("You have to login to do that"); + throw new UnauthorizedExecption("You have to login to do that"); } Author authenticatedAuthor = authorService.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); //Si l'user authent possède ce post @@ -55,21 +55,21 @@ public class PostController { .setPublicationDate(postToUpdate.getPublicationDate()) .setIsUpdated(true)); } else { - throw new ForbiddenExecption("You do not have permission to update this post"); + throw new UnauthorizedExecption("You do not have permission to update this post"); } } @PutMapping(value = "{id}/illustration", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) public void updateIllustration(@PathVariable Long id, @RequestPart("illustration") MultipartFile illustration, Authentication authentication) throws IOException { if (authentication == null) { - throw new ForbiddenExecption("You have to login to do that"); + throw new UnauthorizedExecption("You have to login to do that"); } Author authenticatedAuthor = authorService.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); if (authorService.listPublicationOfAuthor(authenticatedAuthor.getId()).stream().map(Post::getId).toList().contains(id)) { Post postToUpdate = postService.findById(id).orElseThrow(() -> new NotFoundException("Post not found")); postService.insert(postToUpdate.setIllustration(illustration.getBytes())); } else { - throw new ForbiddenExecption("You do not have permission to update this post"); + throw new UnauthorizedExecption("You do not have permission to update this post"); } } @@ -77,7 +77,7 @@ public class PostController { public ResponseEntity addPost(@RequestBody Post postToCreate, Authentication authentication) { Assert.isNull(postToCreate.getId(), "Post id must be null"); if (authentication == null) { - throw new ForbiddenExecption("You have to login to do that"); + throw new UnauthorizedExecption("You have to login to do that"); } return new ResponseEntity<>(postService.insert(postToCreate .setPublicationDate(Timestamp.from(Instant.now())) @@ -92,14 +92,14 @@ public class PostController { @DeleteMapping("{id}") public void deletePost(@PathVariable Long id, Authentication authentication) { if (authentication == null) { - throw new ForbiddenExecption("You have to login to do that"); + throw new UnauthorizedExecption("You have to login to do that"); } Author authenticatedAuthor = authorService.findByName(authentication.getName()).orElseThrow(() -> new NotFoundException("Author not found")); if (authorService.listPublicationOfAuthor(authenticatedAuthor.getId()).stream().map(Post::getId).toList().contains(id)) { Post postToDelete = postService.findById(id).orElseThrow(() -> new NotFoundException("Post not found")); postService.delete(authenticatedAuthor.getId(), postToDelete.getId()); } else { - throw new ForbiddenExecption("You do not have permission to delete this post"); + throw new UnauthorizedExecption("You do not have permission to delete this post"); } } diff --git a/src/main/java/com/guams/review/exception/ForbiddenExecption.java b/src/main/java/com/guams/review/exception/ForbiddenExecption.java deleted file mode 100644 index d10ebf5..0000000 --- a/src/main/java/com/guams/review/exception/ForbiddenExecption.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.guams.review.exception; - -public class ForbiddenExecption extends RuntimeException { - public ForbiddenExecption(String message) { - super(message); - } -} diff --git a/src/main/java/com/guams/review/exception/UnauthorizedExecption.java b/src/main/java/com/guams/review/exception/UnauthorizedExecption.java new file mode 100644 index 0000000..579779a --- /dev/null +++ b/src/main/java/com/guams/review/exception/UnauthorizedExecption.java @@ -0,0 +1,7 @@ +package com.guams.review.exception; + +public class UnauthorizedExecption extends RuntimeException { + public UnauthorizedExecption(String message) { + super(message); + } +} diff --git a/src/main/java/com/guams/review/service/AuthorService.java b/src/main/java/com/guams/review/service/AuthorService.java index 108080d..f0618b1 100644 --- a/src/main/java/com/guams/review/service/AuthorService.java +++ b/src/main/java/com/guams/review/service/AuthorService.java @@ -1,7 +1,7 @@ package com.guams.review.service; import com.guams.review.exception.NotFoundException; -import com.guams.review.exception.ForbiddenExecption; +import com.guams.review.exception.UnauthorizedExecption; import com.guams.review.model.AuthorRepository; import com.guams.review.model.PostRepository; import com.guams.review.model.dao.Author; @@ -55,13 +55,13 @@ public class AuthorService implements UserDetailsService public Author verifyIfUserIsAuthorized(Authentication authentication, UUID id) { if (authentication == null || !authentication.isAuthenticated()) { - throw new ForbiddenExecption("You have to login first"); + throw new UnauthorizedExecption("You have to login first"); } Author author = findById(id).orElseThrow(() -> new NotFoundException("Author not found")); String username = authentication.getName(); Author authorAuthenticated = authorRepository.findByName(username).orElseThrow(() -> new NotFoundException("Author not found")); if (authorAuthenticated.getId().compareTo(author.getId()) != 0 && !authorAuthenticated.getRole().equals("ADMIN")) { - throw new ForbiddenExecption("Specified Author is not authorized to do that"); + throw new UnauthorizedExecption("Specified Author is not authorized to do that"); } return author; } @@ -75,8 +75,8 @@ public class AuthorService implements UserDetailsService } @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - Author author = authorRepository.findByName(username).orElseThrow(() -> new UsernameNotFoundException("Author not found")); + public UserDetails loadUserByUsername(String authorId) throws UsernameNotFoundException { + Author author = authorRepository.findById(UUID.fromString(authorId)).orElseThrow(() -> new UsernameNotFoundException("Author not found")); return new User(author.getName(), author.getPassword(), Collections.singletonList(new SimpleGrantedAuthority(author.getRole()))); } }