Skip to content

Commit 355bbb8

Browse files
committed
Add constraint for max num of query parameters
Signed-off-by: sdimitrov9 <stoyan.dimitrov@limechain.tech>
1 parent 24aa328 commit 355bbb8

3 files changed

Lines changed: 27 additions & 24 deletions

File tree

rest-java/src/main/java/org/hiero/mirror/restjava/common/Constants.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
public class Constants {
99

1010
public static final String ACCOUNT_ID = "account.id";
11+
public static final String DEFAULT_LIMIT = "25";
1112
public static final String HOOK_ID = "hook.id";
1213
public static final String RECEIVER_ID = "receiver.id";
1314
public static final String SENDER_ID = "sender.id";
@@ -16,5 +17,5 @@ public class Constants {
1617
public static final String TOKEN_ID = "token.id";
1718

1819
public static final int MAX_LIMIT = 100;
19-
public static final String DEFAULT_LIMIT = "25";
20+
public static final int MAX_REPEATED_QUERY_PARAMETERS = 100;
2021
}

rest-java/src/main/java/org/hiero/mirror/restjava/controller/HooksController.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import static org.hiero.mirror.restjava.common.Constants.DEFAULT_LIMIT;
66
import static org.hiero.mirror.restjava.common.Constants.HOOK_ID;
77
import static org.hiero.mirror.restjava.common.Constants.MAX_LIMIT;
8+
import static org.hiero.mirror.restjava.common.Constants.MAX_REPEATED_QUERY_PARAMETERS;
89
import static org.hiero.mirror.restjava.jooq.domain.Tables.HOOK;
910

1011
import com.google.common.collect.ImmutableSortedMap;
1112
import jakarta.validation.constraints.Max;
1213
import jakarta.validation.constraints.Positive;
14+
import jakarta.validation.constraints.Size;
1315
import java.util.Map;
1416
import java.util.function.Function;
1517
import lombok.RequiredArgsConstructor;
@@ -47,7 +49,8 @@ final class HooksController {
4749
@GetMapping("/{accountId}/hooks")
4850
ResponseEntity<HooksResponse> getHooks(
4951
@PathVariable EntityIdParameter accountId,
50-
@RequestParam(name = "hook.id", required = false) NumberRangeParameter[] hookIds,
52+
@RequestParam(name = "hook.id", required = false) @Size(max = MAX_REPEATED_QUERY_PARAMETERS)
53+
NumberRangeParameter[] hookIds,
5154
@RequestParam(defaultValue = DEFAULT_LIMIT) @Positive @Max(MAX_LIMIT) int limit,
5255
@RequestParam(defaultValue = "desc") Sort.Direction order) {
5356

rest-java/src/test/java/org/hiero/mirror/restjava/controller/HooksControllerTest.java

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
import static org.assertj.core.api.Assertions.assertThat;
66

77
import java.text.MessageFormat;
8-
import java.util.ArrayList;
9-
import java.util.Arrays;
10-
import java.util.Collections;
11-
import java.util.List;
8+
import java.util.*;
129
import java.util.stream.Collectors;
1310
import lombok.RequiredArgsConstructor;
1411
import org.hiero.mirror.common.domain.hook.Hook;
@@ -42,74 +39,78 @@ protected String getUrl() {
4239

4340
@Override
4441
protected RequestHeadersSpec<?> defaultRequest(RequestHeadersUriSpec<?> uriSpec) {
45-
// Persist at least one hook for the default request
42+
// given: at least one persisted hook for default request
4643
storeHook(accountId);
4744
return uriSpec.uri("");
4845
}
4946

5047
@Test
5148
void success() {
49+
// given
5250
final var hook1 = storeHook(accountId);
5351
final var hook2 = storeHook(accountId);
54-
55-
// Default order is 'desc', so the hook with the larger ID (hook2) comes first
5652
final var expectedHooks = hookMapper.map(List.of(hook2, hook1));
5753
final var expectedResponse = new HooksResponse();
5854
expectedResponse.setHooks(expectedHooks);
55+
56+
// when
5957
final var actual = restClient.get().uri("").retrieve().body(HooksResponse.class);
6058

59+
// then
6160
assertThat(actual).isNotNull().isEqualTo(expectedResponse);
6261
}
6362

6463
@Test
6564
void noHooksFound() {
66-
// Persist a hook for a *different* account to ensure filtering works
67-
storeHook(accountId + 1);
65+
// given
66+
storeHook(accountId + 1); // Different account
6867
final var expectedHooks = hookMapper.map(Collections.emptyList());
6968
final var expectedResponse = new HooksResponse();
7069
expectedResponse.setHooks(expectedHooks);
70+
71+
// when
7172
final var actual = restClient.get().uri("").retrieve().body(HooksResponse.class);
7273

74+
// then
7375
assertThat(actual).isNotNull().isEqualTo(expectedResponse);
7476
}
7577

7678
@Test
7779
void orderAsc() {
80+
// given
7881
final var hook1 = storeHook(accountId);
7982
final var hook2 = storeHook(accountId);
80-
81-
// 'asc' order, so the hook with the smaller ID (hook1) comes first
8283
final var expectedHooks = hookMapper.map(List.of(hook1, hook2));
8384
final var expectedResponse = new HooksResponse();
8485
expectedResponse.setHooks(expectedHooks);
86+
87+
// when
8588
final var actual = restClient.get().uri("?order=asc").retrieve().body(HooksResponse.class);
8689

90+
// then
8791
assertThat(actual).isNotNull().isEqualTo(expectedResponse);
8892
}
8993

9094
@Test
9195
void limitAndNextLink() {
96+
// given
9297
int limit = 2;
9398
storeHook(accountId);
9499
final var hook2 = storeHook(accountId);
95100
final var hook3 = storeHook(accountId);
96-
// Total 3 hooks. Default order=desc, limit=2
97-
98-
// Expected response contains the last 2 hooks (hook3, hook2)
99101
final var expectedHooks = hookMapper.map(List.of(hook3, hook2));
100-
101102
final var expectedResponse = new HooksResponse();
102103
expectedResponse.setHooks(expectedHooks);
103-
104-
// Expect a 'next' link pointing to items *before* the last item (hook2)
105104
final var links = new Links();
106105
links.setNext(String.format(
107106
"/api/v1/accounts/%d/hooks?limit=%d&hook.id=lt:%d", accountId, limit, hook2.getHookId()));
108107
expectedResponse.setLinks(links);
109108

109+
// when
110110
final var actual =
111111
restClient.get().uri("?limit=" + limit).retrieve().body(HooksResponse.class);
112112

113+
// then
113114
assertThat(actual).isNotNull().isEqualTo(expectedResponse);
114115
assertThat(actual.getHooks()).hasSize(limit);
115116
assertThat(actual.getLinks()).isNotNull();
@@ -127,32 +128,30 @@ void limitAndNextLink() {
127128
"'?hook.id=eq:{1}' | 1", // eq hook1's ID -> (hook1)
128129
})
129130
void hookIdBounds(String parameters, String expectedIndices) {
131+
// given
130132
final var hooks = new ArrayList<Hook>();
131133
for (int i = 0; i < 4; i++) {
132134
hooks.add(storeHook(accountId));
133135
}
134-
135-
// Map string indices "3, 2, 1" to List<Hook>
136136
final var expectedHookList = Arrays.stream(expectedIndices.split(","))
137137
.map(String::trim)
138138
.mapToInt(Integer::parseInt)
139139
.mapToObj(hooks::get)
140140
.collect(Collectors.toList());
141-
142141
final var expectedHooks = hookMapper.map(expectedHookList);
143-
144142
final var expectedResponse = new HooksResponse();
145143
expectedResponse.setHooks(expectedHooks);
146144

145+
// when
147146
final var formattedParams = MessageFormat.format(
148147
parameters,
149148
hooks.get(0).getHookId(),
150149
hooks.get(1).getHookId(),
151150
hooks.get(2).getHookId(),
152151
hooks.get(3).getHookId());
153-
154152
final var actual = restClient.get().uri(formattedParams).retrieve().body(HooksResponse.class);
155153

154+
// then
156155
assertThat(actual).isNotNull().isEqualTo(expectedResponse);
157156
}
158157

0 commit comments

Comments
 (0)