-
-
Notifications
You must be signed in to change notification settings - Fork 2
refactor(shopping-lists): Share a list by its own id #160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
0ab0609
docs(agents): Record how to deliver review artifacts
OffCrazyFreak a2e6d1d
refactor(shopping-lists): Share a list by its own id, not a token
OffCrazyFreak ef396e7
refactor(shopping-lists): Serve owners and link visitors from one route
OffCrazyFreak 7cfbfa0
chore(pwa): Retire the share-token infrastructure
OffCrazyFreak 89f2c5b
feat(auth): Make usernames unique
OffCrazyFreak 629189d
fix(ui): Keep the select label still while it saves
OffCrazyFreak 6f9a4e9
feat(shopping-lists): Choose what a copy carries
OffCrazyFreak a378c3c
fix: Apply the 2026-08-06 review findings
OffCrazyFreak 3850c97
docs: Record sharing by list id and unique usernames
OffCrazyFreak f063b89
fix(shopping-lists): Answer the first review pass
OffCrazyFreak b6368d2
fix: Answer the multi-agent review
OffCrazyFreak 129e013
feat(shopping-lists): Copy a list in one transaction
OffCrazyFreak 100adf8
style: Cut the comments that restate the code
OffCrazyFreak d11d720
fix(auth): Let a username collision reach its 409
OffCrazyFreak 2ba88e4
fix(pwa): Purge both offline stores even when one fails
OffCrazyFreak 919663b
fix(ui): Address the reader in the title validation copy
OffCrazyFreak 9c4f4db
docs: Record the copy route and the provisioning transaction
OffCrazyFreak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
backend/src/main/java/disscount/config/UuidScopedRequestMatcher.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package disscount.config; | ||
|
|
||
| import jakarta.servlet.http.HttpServletRequest; | ||
| import org.springframework.http.HttpMethod; | ||
| import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | ||
| import org.springframework.security.web.util.matcher.RequestMatcher; | ||
|
|
||
| import java.util.regex.Pattern; | ||
|
|
||
| /** | ||
| * Matches one method and path only when the {@code id} segment is UUID-shaped. | ||
| * | ||
| * <p>An allowlist on both axes. A wildcard minus the authenticated routes would be a | ||
| * denylist inside an allowlist, silently exposing the next literal route somebody adds; | ||
| * requiring a UUID excludes {@code /me}, {@code /items} and any future literal for free. | ||
| * | ||
| * <p>Canonical dashed form only. Bare 32-hex is excluded because Spring's | ||
| * StringToUUIDConverter rejects it, so it would only buy an anonymous caller a logged 500. | ||
| */ | ||
| final class UuidScopedRequestMatcher implements RequestMatcher { | ||
|
|
||
| private static final Pattern UUID_SHAPE = Pattern.compile( | ||
| "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); | ||
|
|
||
| private final AntPathRequestMatcher delegate; | ||
|
|
||
| UuidScopedRequestMatcher(HttpMethod method, String pattern) { | ||
| this.delegate = new AntPathRequestMatcher(pattern, method.name()); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean matches(HttpServletRequest request) { | ||
| MatchResult result = delegate.matcher(request); | ||
| if (!result.isMatch()) { | ||
| return false; | ||
| } | ||
|
|
||
| String id = result.getVariables().get("id"); | ||
| return id != null && UUID_SHAPE.matcher(id).matches(); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: OffCrazyFreak/Disscount
Length of output: 1645
🌐 Web query:
Spring Security AntPathRequestMatcher matcher getVariables URI template variables💡 Result:
In Spring Security, the
AntPathRequestMatcher.extractUriTemplateVariables(HttpServletRequest request)method is deprecated [1][2][3]. WhileAntPathRequestMatcherimplements theRequestVariablesExtractorinterface, its primary purpose is request matching, and the ability to extract URI template variables via this class is no longer the recommended or standard way to handle path variables within Spring Security's authorization workflow [4][1][5]. If you need to access and use URI template variables for authorization purposes, the following approaches are recommended: 1. Spring Expression Language (SpEL) in Authorization Rules: You can use template variables directly in your security configuration using SpEL. If you define a pattern with a path variable (e.g., /user/{id}), you can reference that variable in an.access()expression. For example:.antMatchers("/user/{id}/").access("@mySecurityGuard.check(#id, authentication)") In this case, Spring Security automatically resolves the#idplaceholder from the path variable [6]. 2. Use PathPatternRequestMatcher: For modern Spring MVC applications, Spring Security recommends usingPathPatternRequestMatcher[7]. This matcher integrates more deeply with Spring MVC's URL matching logic and is better suited for applications that utilize sophisticated path pattern parsing [7]. 3. HandlerMapping: If you are working outside the standard security expression context and need to access the variables manually, you can retrieve them from the request attributes using the constantHandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE[6]. TheextractUriTemplateVariablesmethod onAntPathRequestMatcheris deprecated and should be avoided in favor of these more integrated approaches [1][3][8].Citations:
🏁 Script executed:
Repository: OffCrazyFreak/Disscount
Length of output: 256
🌐 Web query:
Spring Security 6.1.3 AntPathRequestMatcher RequestMatcher matcher getVariables API ant match variables request result💡 Result:
In Spring Security 6.1.3, the AntPathRequestMatcher class is designed for pattern matching against an HttpServletRequest URL (servletPath + pathInfo) and does not natively support capturing URI template variables via the matcher API in the way Spring MVC does [1][2]. While AntPathRequestMatcher implements the RequestVariablesExtractor interface, the implementation of matcher(HttpServletRequest) returns a MatchResult where the default implementation of getVariables returns an empty map [1]. Additionally, the method extractUriTemplateVariables(HttpServletRequest) is marked as
@Deprecated[1]. If your goal is to extract path variables from a request within Spring Security, you should consider the following approaches: 1. Use MvcRequestMatcher: This class utilizes Spring MVC's HandlerMappingIntrospector to match paths and is the standard way to handle path variables within Spring Security [3]. 2. Use PathPatternRequestMatcher: Available in more recent versions of Spring Security (specifically introduced/standardized for this purpose in later versions), this matcher is explicitly designed to handle path patterns with placeholders (e.g., /path/{value}/) and capture those values in RequestAuthorizationContext.getVariables [4][5]. For simple Ant-style matching where no variable extraction is required, AntPathRequestMatcher remains functional, but it should not be relied upon for extracting dynamic path parameters [1][2].Citations:
🏁 Script executed:
Repository: OffCrazyFreak/Disscount
Length of output: 301
🌐 Web query:
Spring Security 6.1.4 AntPathRequestMatcher RequestMatcher matcher HttpServletRequest MatchResult getVariables implementation💡 Result:
In Spring Security 6.1.4, the AntPathRequestMatcher implementation of the matcher(HttpServletRequest) method does not automatically extract path variables into the returned MatchResult [1]. The RequestMatcher interface defines the matcher(HttpServletRequest) method, which returns a MatchResult object [2][3]. By default, the RequestMatcher interface provides a default implementation for matcher(request) that invokes the matches(request) method and returns a MatchResult containing an empty map for variables [3]. While AntPathRequestMatcher implements RequestVariablesExtractor [1], its primary matcher(HttpServletRequest) method is generally used for simple boolean matching [1]. If you require extracted path variables (such as template variables), the recommended approach in modern Spring Security (especially for Spring MVC integration) is to use PathPatternRequestMatcher instead of AntPathRequestMatcher, as it is designed to align with Spring MVC's path pattern parsing and variable extraction logic [4]. Key details regarding the MatchResult and variables: 1. RequestMatcher.MatchResult: This class holds the match status (boolean) and a map of variables [5][3]. The getVariables method returns a Map<String, String> containing key-value pairs of extracted variable names and values [5][6]. 2. Default Behavior: When matcher(HttpServletRequest) is called on an AntPathRequestMatcher, it does not populate this map with path variables; it returns Collections.emptyMap [1][3]. 3. Alternative: For path variable extraction, use PathPatternRequestMatcher, which integrates directly with Spring MVC's pattern parsing [4].
Citations:
🌐 Web query:
Spring Security 6.1.4 PathPatternRequestMatcher builder patternMatch getVariables URI variables💡 Result:
In Spring Security, the PathPatternRequestMatcher.Builder allows you to define path patterns that can capture URI variables, which are then accessible through the RequestAuthorizationContext. When using patterns like /path/{value}/, the {value} segment is captured as a URI variable [1][2][3]. To use this functionality, you create a matcher using the builder, for example: PathPatternRequestMatcher.Builder mvc = PathPatternRequestMatcher.withDefaults.basePath("/api"); http.authorizeHttpRequests(authorize -> authorize.requestMatchers(mvc.matcher("/user/{id}/")).hasAuthority("user")); When a request matches the pattern, the captured variables (such as "id") are stored in the RequestAuthorizationContext [1][2][3]. You can access these variables during authorization by using the RequestAuthorizationContext object in your custom authorization logic: http.authorizeHttpRequests(authorize -> authorize.requestMatchers(mvc.matcher("/user/{id}/")).access((authentication, context) -> { Map<String, Object> variables = context.getVariables; String userId = (String) variables.get("id"); // Apply custom logic using userId return new AuthorizationDecision(true); })); Note that the PathPatternRequestMatcher returns a MatchResult when matcher(HttpServletRequest) is called [4][5][6]. While the default implementation of some matcher methods might return empty maps, the framework-level integration with authorizeHttpRequests automatically handles the extraction and population of these variables into the RequestAuthorizationContext for you to access as shown above [1][2][3]. Top results: [1][2][3]
Citations:
Use a matcher that captures path variables.
With Spring Boot 3.1,
AntPathRequestMatcher.matcher(...)returns aMatchResult, butgetVariables()stays empty, so this wrapper always rejects{id}paths. Replace the delegate withPathPatternRequestMatcheror another variable-aware matcher, and add tests for a UUID path and a literal path.🤖 Prompt for AI Agents