Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import java.util.Base64;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.beans.factory.annotation.Value;


@Component
Expand All @@ -51,30 +50,26 @@
public class PlatformFeedbackRateLimitFilter extends OncePerRequestFilter {

private final StringRedisTemplate redis;
@Value("${platform.feedback.ratelimit.pepper}")
private String pepper;
@Value("${platform.feedback.ratelimit.trust-forwarded-for:false}")
private boolean trustForwardedFor;
@Value("${platform.feedback.ratelimit.forwarded-for-header:X-Forwarded-For}")
private String forwardedForHeader;
private final String pepper;
private final boolean trustForwardedFor;
private final String forwardedForHeader;

// Limits & TTLs (tweak if needed)
@Value("${platform.feedback.ratelimit.minute-limit:10}")
private int MINUTE_LIMIT;
@Value("${platform.feedback.ratelimit.day-limit:100}")
private int DAY_LIMIT;
@Value("${platform.feedback.ratelimit.user-day-limit:50}")
private int USER_DAY_LIMIT; // for identified users
private Duration MINUTE_WINDOW = Duration.ofMinutes(1);
private Duration DAY_WINDOW = Duration.ofHours(48); // keep key TTL ~48h
@Value("${platform.feedback.ratelimit.fail-window-minutes:5}")
private Duration FAIL_COUNT_WINDOW;
private int FAILS_TO_BACKOFF = 3;
@Value("${platform.feedback.ratelimit.backoff-minutes:15}")
private Duration BACKOFF_WINDOW;

public PlatformFeedbackRateLimitFilter(StringRedisTemplate redis) {
private static final int MINUTE_LIMIT = 10;
private static final int DAY_LIMIT = 100;
private static final int USER_DAY_LIMIT = 50; // for identified users
private static final Duration MINUTE_WINDOW = Duration.ofMinutes(1);
private static final Duration DAY_WINDOW = Duration.ofHours(48); // keep key TTL ~48h
private static final Duration FAIL_COUNT_WINDOW = Duration.ofMinutes(5);
private static final int FAILS_TO_BACKOFF = 3;
private static final Duration BACKOFF_WINDOW = Duration.ofMinutes(15);

public PlatformFeedbackRateLimitFilter(StringRedisTemplate redis,
org.springframework.core.env.Environment env) {
this.redis = redis;
this.pepper = env.getProperty("platform.feedback.pepper", "");
this.trustForwardedFor = Boolean.parseBoolean(env.getProperty("platform.feedback.trust-forwarded-for", "true"));
this.forwardedForHeader = env.getProperty("platform.feedback.forwarded-for-header", "X-Forwarded-For");
}

@Override
Expand Down Expand Up @@ -218,4 +213,4 @@ private static String sha256Base64(String input) {
throw new RuntimeException("sha256 failure", ex);
}
}
}
}
26 changes: 17 additions & 9 deletions src/main/java/com/iemr/common/utils/FilterConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ public class FilterConfig {
@Value("${cors.allowed-origins}")
private String allowedOrigins;

@Value("${platform.feedback.ratelimit.enabled:false}")
private boolean enabled;


@Bean
public FilterRegistrationBean<JwtUserIdValidationFilter> jwtUserIdValidationFilter(
JwtAuthenticationUtil jwtAuthenticationUtil) {
Expand All @@ -67,13 +63,25 @@ public FilterRegistrationBean<JwtUserIdValidationFilter> jwtUserIdValidationFilt
*/
@Bean
public FilterRegistrationBean<PlatformFeedbackRateLimitFilter> platformFeedbackRateLimitFilter(
StringRedisTemplate stringRedisTemplate) {
StringRedisTemplate stringRedisTemplate,
Environment env) {

// Read flag from environment (property file or env var)
boolean enabled = Boolean.parseBoolean(env.getProperty("platform.feedback.ratelimit.enabled", "false"));

// Allow optional override for order if needed
int order = Ordered.HIGHEST_PRECEDENCE + 10;

PlatformFeedbackRateLimitFilter filter = new PlatformFeedbackRateLimitFilter(stringRedisTemplate);
int defaultOrder = Ordered.HIGHEST_PRECEDENCE + 10;
int order = defaultOrder;
String orderStr = env.getProperty("platform.feedback.ratelimit.order");
if (orderStr != null) {
try {
order = Integer.parseInt(orderStr);
} catch (NumberFormatException e) {
log.warn("Invalid platform.feedback.ratelimit.order value '{}', using default {}", orderStr, defaultOrder);
}
}

PlatformFeedbackRateLimitFilter filter = new PlatformFeedbackRateLimitFilter(stringRedisTemplate, env);

FilterRegistrationBean<PlatformFeedbackRateLimitFilter> reg = new FilterRegistrationBean<>(filter);

Expand All @@ -91,4 +99,4 @@ public FilterRegistrationBean<PlatformFeedbackRateLimitFilter> platformFeedbackR

return reg;
}
}
}