Skip to content

Commit 13446a7

Browse files
authored
Merge pull request #66 from devondragon/fix-metrics-config-placeholder-ip-dto
Fix metrics config placeholder ip dto
2 parents dfda55d + 91743a8 commit 13446a7

6 files changed

Lines changed: 68 additions & 7 deletions

File tree

.claude/settings.local.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(./gradlew build)",
5+
"Bash(./gradlew test)",
6+
"Bash(./gradlew:*)",
7+
"Bash(gh issue assign:*)",
8+
"Bash(gh issue close:*)",
9+
"Bash(gh issue create:*)",
10+
"Bash(gh issue edit:*)",
11+
"Bash(gh issue view:*)",
12+
"Bash(gh issue:*)",
13+
"Bash(gh pr create:*)",
14+
"Bash(gh pr:*)",
15+
"Bash(gh:*)",
16+
"Bash(git add:*)",
17+
"Bash(git branch:*)",
18+
"Bash(git checkout:*)",
19+
"Bash(git fetch:*)",
20+
"Bash(git log:*)",
21+
"Bash(git push:*)",
22+
"Bash(ls:*)",
23+
"Bash(find:*)",
24+
"Bash(git restore:*)"
25+
],
26+
"deny": []
27+
}
28+
}

AGENTS.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
Runtime code lives in `src/main/java/com/digitalsanctuary/cf/turnstile`, grouped by concern (`config`, `service`, `filter`, `dto`, `exception`). Shared configuration assets sit in `src/main/resources`, including `config/turnstile.properties` and Spring metadata under `META-INF`. Tests mirror the package layout in `src/test/java/com/digitalsanctuary/cf/test/turnstile`, while test fixtures and templates belong in `src/test/resources`. Build outputs flow to `build/`, and quality configurations are kept under `config/` (`checkstyle`, `pmd`).
5+
6+
## Build, Test, and Development Commands
7+
Use `./gradlew clean build` for a full verification and artifact assembly. `./gradlew test` launches the JUnit suite; add `-Porg.gradle.java.installations.auto-download=false` when relying on preinstalled JDKs. `./gradlew testAll` exercises the matrix on Java 17 and 21, mirroring CI. Run `./gradlew jacocoTestReport` to generate coverage reports in `build/reports/jacoco/test/html/index.html`. Publishing helpers exist for maintainers: `./gradlew publishLocal` installs to the local Maven cache, and `./gradlew publishReposilite` targets the private staging host.
8+
9+
## Coding Style & Naming Conventions
10+
Target Java 17+ and favor Lombok for boilerplate already in use. Follow Checkstyle guidance (`config/checkstyle/checkstyle.xml`): four-space indentation, braces on the same line, and public APIs documented with Javadoc. Keep packages lowercase, classes `PascalCase`, and fields/methods `camelCase`. PMD rules in `config/pmd/ruleset.xml` flag unused complexity; resolve warnings rather than suppressing unless justified.
11+
12+
## Testing Guidelines
13+
Tests rely on JUnit Jupiter with Spring’s test utilities. Name classes with the `*Test` suffix (e.g., `TurnstileValidationServiceTest`) and focus on observable behavior around validation, filters, and error handling. Run `./gradlew test` before every push, and refresh coverage via `./gradlew jacocoTestReport`; aim to keep line coverage above the current 48% threshold noted in the Gradle configuration even though enforcement is disabled.
14+
15+
## Commit & Pull Request Guidelines
16+
Write imperative, present-tense commit titles ("Add Turnstile captcha filter") and include one change per commit when practical. Reference issues or Dependabot tickets with `Fixes #<id>` in the body when closing them. Pull requests should summarize intent, list verification commands (Gradle tasks, coverage), and attach screenshots or logs when touching user-facing responses. Keep branches current with `main` and request review once tests pass.
17+
18+
## Configuration & Security Tips
19+
Store site keys and secrets outside version control; use environment overrides or Spring Boot configuration properties. Validate Cloudflare connectivity against non-production keys before promoting changes, and redact sensitive responses from logs when updating filters or exception handlers.

src/main/java/com/digitalsanctuary/cf/turnstile/config/TurnstileServiceConfig.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.digitalsanctuary.cf.turnstile.config;
22

3+
import java.util.Optional;
4+
import org.springframework.beans.factory.ObjectProvider;
5+
import org.springframework.beans.factory.annotation.Qualifier;
36
import org.springframework.boot.web.client.RestTemplateBuilder;
47
import org.springframework.context.annotation.Bean;
58
import org.springframework.context.annotation.Configuration;
@@ -8,6 +11,7 @@
811
import org.springframework.web.client.RestClient;
912
import org.springframework.web.client.RestTemplate;
1013
import com.digitalsanctuary.cf.turnstile.service.TurnstileValidationService;
14+
import io.micrometer.core.instrument.MeterRegistry;
1115
import lombok.RequiredArgsConstructor;
1216
import lombok.extern.slf4j.Slf4j;
1317

@@ -21,6 +25,7 @@
2125
public class TurnstileServiceConfig {
2226

2327
private final TurnstileConfigProperties properties;
28+
private final ObjectProvider<MeterRegistry> meterRegistryProvider;
2429

2530
/**
2631
* Creates a RestTemplate bean for Turnstile API interactions.
@@ -36,11 +41,13 @@ public RestTemplate turnstileRestTemplate(RestTemplateBuilder builder) {
3641
/**
3742
* Creates a TurnstileValidationService bean.
3843
*
44+
* @param restClient the preconfigured REST client for Turnstile calls
3945
* @return a configured TurnstileValidationService instance
4046
*/
4147
@Bean
42-
public TurnstileValidationService turnstileValidationService() {
43-
return new TurnstileValidationService(turnstileRestClient(), properties);
48+
public TurnstileValidationService turnstileValidationService(@Qualifier("turnstileRestClient") RestClient restClient) {
49+
Optional<MeterRegistry> optionalRegistry = Optional.ofNullable(meterRegistryProvider.getIfAvailable());
50+
return new TurnstileValidationService(restClient, properties, optionalRegistry);
4451
}
4552

4653
/**

src/main/java/com/digitalsanctuary/cf/turnstile/dto/TurnstileResponse.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class TurnstileResponse {
4646
/**
4747
* Timestamp of the challenge.
4848
*/
49+
@JsonProperty("challenge_ts")
4950
private String challengeTs;
5051

5152
/**

src/main/java/com/digitalsanctuary/cf/turnstile/service/TurnstileValidationService.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,14 @@ public String getClientIpAddress(ServletRequest request) {
505505
if (request instanceof HttpServletRequest httpRequest) {
506506
String[] headers = {"X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
507507
for (String header : headers) {
508-
String ip = httpRequest.getHeader(header);
509-
if (ip != null && !ip.isEmpty() && !UNKNOWN.equalsIgnoreCase(ip)) {
510-
return ip;
508+
String ipHeaderValue = httpRequest.getHeader(header);
509+
if (ipHeaderValue == null || ipHeaderValue.isBlank()) {
510+
continue;
511+
}
512+
513+
String candidate = ipHeaderValue.split(",", 2)[0].trim();
514+
if (!candidate.isEmpty() && !UNKNOWN.equalsIgnoreCase(candidate)) {
515+
return candidate;
511516
}
512517
}
513518
}

src/main/resources/config/turnstile.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Cloudflare Turnstile Configuration
2-
ds.cf.turnstile.sitekey= # Turnstile Site Key
3-
ds.cf.turnstile.secret= # Turnstile Secret
2+
# Provide site and secret keys via environment-specific configuration.
3+
ds.cf.turnstile.sitekey=
4+
ds.cf.turnstile.secret=
45
ds.cf.turnstile.url=https://challenges.cloudflare.com/turnstile/v0/siteverify
56

67
# Configuration for TurnstileCaptchaFilter component (for use with Spring Security Form Login, etc...)

0 commit comments

Comments
 (0)