comment delete et limite de 5 requete post toute les minutes
This commit is contained in:
		
							parent
							
								
									f41c830970
								
							
						
					
					
						commit
						40da59bd31
					
				| @ -1,4 +1,5 @@ | ||||
| package com.guams.review.configuration; | ||||
| 
 | ||||
| import com.guams.review.service.AuthorService; | ||||
| import io.jsonwebtoken.JwtException; | ||||
| import jakarta.servlet.FilterChain; | ||||
| @ -11,7 +12,11 @@ import org.springframework.security.core.userdetails.UserDetails; | ||||
| import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.web.filter.OncePerRequestFilter; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.time.Instant; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
| 
 | ||||
| @Component | ||||
| public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||||
| @ -19,6 +24,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||||
|     private final JwtTokenUtil jwtTokenUtil; | ||||
|     private final AuthorService authorService; | ||||
| 
 | ||||
|     // Map pour traquer les requêtes : UUID -> { dernière réinitialisation, compteur de requêtes } | ||||
|     private final ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>(); | ||||
| 
 | ||||
|     // Configuration du rate limiting | ||||
|     private static final int MAX_REQUESTS = 5; | ||||
|     private static final long TIME_WINDOW_MS = 60 * 1000; // 1 minute | ||||
| 
 | ||||
|     public JwtAuthenticationFilter(JwtTokenUtil jwtTokenUtil, AuthorService authorService) { | ||||
|         this.jwtTokenUtil = jwtTokenUtil; | ||||
|         this.authorService = authorService; | ||||
| @ -35,9 +47,16 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||||
|                 String authorUuid = jwtTokenUtil.extractAuthorId(token); // Récupère l'UUID du token | ||||
| 
 | ||||
|                 if (authorUuid != null && SecurityContextHolder.getContext().getAuthentication() == null) { | ||||
|                     UserDetails userDetails = authorService.loadUserByUsername(authorUuid); // Utilise le service pour charger l'auteur par UUID | ||||
|                     UserDetails userDetails = authorService.loadUserByUsername(authorUuid); // Charge l'auteur | ||||
| 
 | ||||
|                     if (jwtTokenUtil.validateToken(token, userDetails, authorUuid)) { | ||||
|                         // Applique le rate limiting | ||||
|                         if (isRateLimited(authorUuid, request)) { | ||||
|                             response.setStatus(429); // TOO MANY REQUESTS | ||||
|                             response.getWriter().write("Rate limit exceeded. Please try again later."); | ||||
|                             return; | ||||
|                         } | ||||
| 
 | ||||
|                         UsernamePasswordAuthenticationToken authentication = | ||||
|                                 new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | ||||
|                         authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||||
| @ -50,7 +69,42 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         filterChain.doFilter(request, response); // Continue le traitement | ||||
|     } | ||||
| 
 | ||||
|     private boolean isRateLimited(String authorUuid, HttpServletRequest request) { | ||||
|         // Ne limite que les requêtes POST | ||||
|         if (!"POST".equalsIgnoreCase(request.getMethod())) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // Récupère ou crée un RateLimiter pour l'utilisateur | ||||
|         RateLimiter limiter = rateLimiters.computeIfAbsent(authorUuid, k -> new RateLimiter()); | ||||
| 
 | ||||
|         synchronized (limiter) { | ||||
|             long now = Instant.now().toEpochMilli(); | ||||
|             if (now - limiter.lastReset > TIME_WINDOW_MS) { | ||||
|                 // Réinitialise la fenêtre de temps et le compteur | ||||
|                 limiter.lastReset = now; | ||||
|                 limiter.requestCount.set(0); | ||||
|             } | ||||
| 
 | ||||
|             if (limiter.requestCount.incrementAndGet() > MAX_REQUESTS) { | ||||
|                 return true; // Limite atteinte | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // Classe interne pour suivre les requêtes | ||||
|     private static class RateLimiter { | ||||
|         private long lastReset; | ||||
|         private AtomicInteger requestCount; | ||||
| 
 | ||||
|         public RateLimiter() { | ||||
|             this.lastReset = Instant.now().toEpochMilli(); | ||||
|             this.requestCount = new AtomicInteger(0); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -64,6 +64,12 @@ public class AuthorController { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| //    @PutMapping("/{id}/password") | ||||
| //    public void changePassword(@PathVariable UUID id, @RequestBody Author updatedAuthor, Authentication authentication) { | ||||
| //        Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); | ||||
| //        if (passwordEncoder.matches(updatedAuthor.getPassword(), authorToUpdate.getPassword())) {} | ||||
| //    } | ||||
| 
 | ||||
|     @PutMapping(value = "{id}/avatar", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) | ||||
|     public Author updateUserAvatar(@PathVariable UUID id, @RequestPart MultipartFile avatar, Authentication authentication) throws IOException { | ||||
|         Author authorToUpdate = authorService.verifyIfUserIsAuthorized(authentication, id); | ||||
|  | ||||
| @ -85,7 +85,7 @@ public class CommentController { | ||||
|             throw new UnauthorizedExecption("You are not authorized to access this resource"); | ||||
|         } | ||||
|         Comment commentToDelete = commentService.findById(id).orElseThrow(() -> new NotFoundException("Comment not found")); | ||||
|         commentService.delete(commentToDelete); | ||||
|         commentService.deleteAssociationByCommentId(commentToDelete.getId()); | ||||
|         commentService.delete(commentToDelete); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -107,7 +107,14 @@ public class PostController { | ||||
|         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")); | ||||
|             commentService.getCommentsByPostId(id).stream().map(mapper::mapCommentWithAuthor).forEach(commentService::delete); | ||||
|             commentService.getCommentsByPostId(id) | ||||
|                     .stream() | ||||
|                     .map(mapper::mapCommentWithAuthor) | ||||
|                     .forEach(comment -> commentService.deleteAssociationByCommentId(comment.getId())); | ||||
|             commentService.getCommentsByPostId(id) | ||||
|                     .stream() | ||||
|                     .map(mapper::mapCommentWithAuthor) | ||||
|                     .forEach(commentService::delete); | ||||
|             postService.delete(authenticatedAuthor.getId(), postToDelete.getId()); | ||||
|         } else { | ||||
|             throw new UnauthorizedExecption("You do not have permission to delete this post"); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Guams
						Guams