Apply rate limiter for replying a comment (#4135)

#### What type of PR is this?

/kind feature
/area core
/milestone 2.7.x

#### What this PR does / why we need it:

Apply rate limiter for replying a comment as well. This feature is supplement of <https://github.com/halo-dev/halo/pull/4084>.

#### Special notes for your reviewer:

Try to reply any comments 11 times within 1 minute.

#### Does this PR introduce a user-facing change?

```release-note
对评论回复添加频率限制
```
pull/4139/head
John Niang 2023-06-28 15:38:11 +08:00 committed by GitHub
parent 02e7068ee0
commit ff33608fed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 3 deletions

View File

@ -198,7 +198,9 @@ public class CommentFinderEndpoint implements CustomEndpoint {
.defaultIfEmpty(reply); .defaultIfEmpty(reply);
}) })
.flatMap(reply -> replyService.create(commentName, reply)) .flatMap(reply -> replyService.create(commentName, reply))
.flatMap(comment -> ServerResponse.ok().bodyValue(comment)); .flatMap(comment -> ServerResponse.ok().bodyValue(comment))
.transformDeferred(createIpBasedRateLimiter(request))
.onErrorMap(RequestNotPermitted.class, RateLimitExceededException::new);
} }
private boolean checkReplyOwner(Reply reply, Boolean onlySystemUser) { private boolean checkReplyOwner(Reply reply, Boolean onlySystemUser) {

View File

@ -80,5 +80,5 @@ resilience4j.ratelimiter:
comment-creation: comment-creation:
limitForPeriod: 10 limitForPeriod: 10
limitRefreshPeriod: 1m limitRefreshPeriod: 1m
timeoutDuration: 10s timeoutDuration: 0s

View File

@ -145,7 +145,7 @@ class CommentFinderEndpointTest {
.limitRefreshPeriod(Duration.ofSeconds(1)) .limitRefreshPeriod(Duration.ofSeconds(1))
.timeoutDuration(Duration.ofSeconds(10)) .timeoutDuration(Duration.ofSeconds(10))
.build(); .build();
RateLimiter rateLimiter = RateLimiter.of("comment-creation-from-ip-" + "0:0:0:0:0:0:0:0", RateLimiter rateLimiter = RateLimiter.of("comment-creation-from-ip-" + "0:0:0:0:0:0:0:0",
config); config);
when(rateLimiterRegistry.rateLimiter(anyString(), anyString())).thenReturn(rateLimiter); when(rateLimiterRegistry.rateLimiter(anyString(), anyString())).thenReturn(rateLimiter);
@ -183,8 +183,13 @@ class CommentFinderEndpointTest {
replyRequest.setContent("content"); replyRequest.setContent("content");
replyRequest.setAllowNotification(true); replyRequest.setAllowNotification(true);
when(rateLimiterRegistry.rateLimiter("comment-creation-from-ip-127.0.0.1",
"comment-creation"))
.thenReturn(RateLimiter.ofDefaults("comment-creation"));
webTestClient.post() webTestClient.post()
.uri("/comments/test-comment/reply") .uri("/comments/test-comment/reply")
.header("X-Forwarded-For", "127.0.0.1")
.bodyValue(replyRequest) .bodyValue(replyRequest)
.exchange() .exchange()
.expectStatus() .expectStatus()
@ -196,5 +201,8 @@ class CommentFinderEndpointTest {
assertThat(value.getSpec().getIpAddress()).isNotNull(); assertThat(value.getSpec().getIpAddress()).isNotNull();
assertThat(value.getSpec().getUserAgent()).isNotNull(); assertThat(value.getSpec().getUserAgent()).isNotNull();
assertThat(value.getSpec().getQuoteReply()).isNull(); assertThat(value.getSpec().getQuoteReply()).isNull();
verify(rateLimiterRegistry).rateLimiter("comment-creation-from-ip-127.0.0.1",
"comment-creation");
} }
} }