Repository navigation
Feat: Add conditional (AND) resource rules - #3705
Blacks-Army wants to merge 2 commits into
Conversation
044d9d8 to
3020fa3
Compare
3020fa3 to
a406a7e
Compare
a9ac442 to
c6c12f1
Compare
Resolves #1408. A rule with match "METHOD" carries a comma-separated list of HTTP methods in its value, e.g. "POST,PUT", and applies when the request method is in that list. This makes it possible to leave GET public while sending POST and PUT to auth, which rules could not express before because both share the same path. No new columns: the methods live in the existing rule value, so this needs no migration and every existing rule keeps working unchanged. The UI offers the ten registered methods. Blueprints and the API accept any method token, so extension methods such as the WebDAV verbs can be targeted too, and the UI preserves them when a rule set that way is edited later.
A rule with match "AND" carries a JSON array of conditions in its
value and applies only when every one of them matches, e.g.
[{"match":"PATH","value":"/api/*"},
{"match":"METHOD","value":"POST,PUT"}]
Until now every rule was a single match, so "POST to /api" could not
be expressed at all: a PATH rule caught every method and a METHOD rule
caught every path.
As with METHOD, the conditions live in the existing rule value, so
this needs no new columns and no migration.
The per-condition matching that checkRules did inline moves into
matchesCondition, which both a plain rule and an AND rule go through.
Existing rules keep behaving exactly as before.
Blueprints spell the conditions out rather than embedding JSON:
rules:
- action: pass
match: and
conditions:
- match: path
value: /api/*
- match: method
value: POST,PUT
In the UI an AND rule opens a dialog to edit its conditions.
a406a7e to
5e62fb3
Compare
|
Thanks for the effort on this! Really appreciate it. Having tested it in the UI we are thinking we would rather do a rework of the rules to support a higher level and where multiple rules get anded together instead of handling it this way. I think we will handle this one internally. |
😕 Can we expect this feature to be addressed in an upcoming release? The feature request for supporting AND rules has been open for quite some time, but there hasn’t been any progress on it from anyone so far. |
|
I think we are going to try to work it in soon because right now we
are certainly hampered by this restriction in the rules.
|
Follow-up to #3704, which should go in first.
Community Contribution License Agreement
By creating this pull request, I grant the project maintainers an unlimited,
perpetual license to use, modify, and redistribute these contributions under any terms they
choose, including both the AGPLv3 and the Fossorial Commercial license terms. I
represent that I have the right to grant this license for all contributed content.
AI Disclosure
Claude Code (Opus) helped me with this one, including the implementation. I set the design constraints from your review of #2131, went through every hunk myself and verified the result before opening this.
Description
Every rule is a single match today, so "POST to
/api" cannot be expressed at all: aPATHrule catches every method and aMETHODrule catches every path. That combination is what people were actually after in #2131 and #1408.A rule with match
ANDcarries a JSON array of conditions in its value and applies only when every one of them matches:[{"match": "COUNTRY", "value": "DE"}, {"match": "METHOD", "value": "POST,PUT"}, {"match": "ASN", "value": "AS3320"}]Two conditions or more, any match type, no nesting. OR stays what it always was: several rules with the same action. As in #3704, the conditions live in the existing rule value, so there is still no migration and existing rules are untouched.
On
checkRules: you asked to keepverifySessionsmall and not to move rule processing into a new file. Nothing moves out of the file, but the per-condition matching the loop used to do inline is now a singlematchesCondition(match, value, context)that a plain rule and anANDrule both go through. Duplicating that dispatch instead would have let the two copies drift. The translation is mechanical: each formercontinuebecomes areturn false, which has the same effect because the chain iselse ifthroughout. Happy to reshape it if you would rather have it another way.A value that is not a well-formed condition list is skipped and logged rather than applied, and an empty list counts as malformed, since it would otherwise match every request.
Blueprints spell the conditions out instead of embedding JSON, with
valueandconditionsmutually exclusive. In the UI anANDrule shows a summary of its conditions and opens a dialog to edit them.The matching engine in
pangolin-nodeneeds the same change, as it did in fosrl/pangolin-node#89.How to test?
All Ofand two conditions:PATH/api/*andMETHODPOST,PUT, actionPASS.curl -X GET .../api/itemsis served,curl -X POST .../api/itemsis sent to auth,curl -X POST .../otheris unaffected.Blueprint variant:
npx tsc --noEmitis clean andnpx tsx server/lib/validators.test.tspasses, covering the round-trip, rejection of nestedAND, per-condition validation and malformed input.