Upgrade to 3.7.6 Broke FilterCheck
We're using Ash.Policy.FilterCheck and it seems the return type may have changed, we were returning true if all access, expr for subset access and false for no access.
After upgrading, the
true isn't letting any records come out. I saw the return type is either a keyword list or expression.
What is the keyword list we should return?
I've trued {:ok, true}, {:halt, true} and {:cont, true} but none of these let us have the previous behaviour of allowing all like before.116 Replies
That should work. But it depends on how you're using the check of course
What you're saying is you changed nothing and upgraded to 3.7.6 and it changed that behavior? What's happening instead? An error?
the tests are failing due to authorization
i can verify by running the test with autohrize?: fasle in the query
So a forbidden error? I think I know what's happening potentially.
this is also failing:
We may be being too strict with the final policy check due to a recent change. I will look into it shortly
Cont and halt aren't a thing
In filter checks
the typespec is
filter(actor :: term(), context(), options()) :: Keyword.t() | Ash.Expr.t()
so seems returning a boolean shouldnt' be correct, either?Booleans are expressions
cc @AngyL75
The policy in question
okay, makes sense why it was working before then π
Does it have an
access_type set?how can i see that?
It will be in the policies
Like `access_type :strict'
i don't think we have ever set that anywhere
Hmm...okay
so then it should probably be a default
:filter if it's on a read, no? πYeah it defaults to filter
Hmmmmmmmm
What if you return
expr(fragment("TRUE"))
That's just to tell me where the problem is, not something I actually want you to have to dostill fails
Oh
That was unexpected
i'm trying to turn on the debug logs for the queries
config :logger, level: :debug seems this doesn't work π
thinking maybe i can see somethign in the logsAre you capturing logs in your tests?
i have policy logs on, i could have sworn
config :ash, :policies, show_policy_breakdowns?: true
but nothing is coming up
i guess thats' for access
okay, found it now π
i mean for the debug logs
19:52:00.545 [debug] CauseBeacon.Organizations.MemberNote.read: skipped query run due to filter being false"
so looks like the filter is somehow being intreted as false when i'm returning true?
add that to get more logs
running with this:
config :ash, :policies, show_policy_breakdowns?: true, log_successful_policy_breakdowns: :error
true with a check?That implies that its authorizing the results of the query π€
sorry and after that:
19:55:37.197 [debug] CauseBeacon.Organizations.MemberNote.read: skipped query run due to filter being false"And to be clear all that you changed was that you updated ash?
so seems authorized and false?
correct
i was just doing my weekly mix deps update
i've updated ash, ash_postgres
ash_phoenix
pretty sure the culprits are probably ash, ash_postgres, ash_sql
1-3 of those
Yeah, its likely
ash
we changed this codeshould i explicitly set the check to filter?
do you mean
access_type :filter?yeah
cant hurt but probably not
I've set up the same thing in tests and its working as far as I can tell π€
yeah, no use
Okay
Do you have a few minutes to keep looking into this then?
My testing shows it working
So best thing here is to clone down Ash and poke around
so my can_read_feature can potentially be doing some querying of the database
i have a special function that can check data on a user, wondering that may be an issue
Have you confirmed that its returning what you expect in that test?
i.e
true or false?how can i best do that?
IO.inspect the return valuemove to anotehr function and cehck the return?
ok
let me try try
If its returning the wrong thing then that makes sense, and the policies may be a red herring
CanReadMemberNote filter: fragment("TRUE")
CanReadMemberNote filter: true
seems to be rightkk, so that s not the issue then.
alright, so next steps would be to clone down Ash
easy π
main?
yep
and
|> IO.inspect() on 1735
will have a big output probablyuhm
lol
is hthis right? {:ash, path: "../../ash/ash", override: true},
yes
maybe i need to clean?
in
lib/ash/policy/authorizer/authorizer.ex
Did you pull latest main?yeah, i just did a pull
weird
Possibly a clean then
π
here's what i have, still compiling
i'm about to lose my mind
what ma i doing wrong? π
lol
rm -rf _build? What commit of ash are you on?
Should be 381068e54437e17da344555628bdfdb425596dbca252301thats not latest
mainhmm
are you pulling from your fork's latest
main?
Do you need something like git pull upstream main?π€«
this didnt happen π
yeah, just occrured to me my code is behind haha
sorry
oh, it's massiv, sorry
no thats good
Okay, so, so far so good
oh, wait no I don't think that is the right one?
how do i know which is right?
it was the last one logged, so it hought it'd be right?
Look at the
resource and action keys
You can add some conditional logic in there
okay, thanks, let me try now π
i'm guessing the second element in the tuple being false is no bueno?
yep
okay, interesting π€
mix deps.update crux
Just in case
I don't think that will matterstill failing
i see
def strict_check_scenarios is a case statement, shall i check each branch to see where the answer is coming from?Alright, into
checker.ex we go
we want to know the branch we get into here:
Specifically the first or second one
in line 66
of checker.exline 66 is the def
yeah, just pointing the area
ok
okay, i turned off the previous tap, too, for now, reduce the log
or shit, i need that π
strict_check_scenarios boolean result: false
okay, into
policy.ex we goso the Policy.solve is false
line 88
More importantly probably here:
Each line of that pipeline
okay, running the test
blew out my buffer...
ok
Policy.solve expression: falseTry this:
i got it in anothe terminal, no worries
so that's false in teh expression
Policy.solve expression: false
strict_check_scenarios boolean result: false
strict_check_result: {:ok, false,
maybe you need this?
or maybei have the wrong logs? i was trying to cut it down to just what you need due to the setup data
That looks roughly right
but I don't see
Simplified policy expression there
Just Expanded constants expression
We're narrowing in on the issue
You could also try pinning {:crux, "== 0.1.1"} or 0.1.0 maybe we messed something up there, not sure.trying to, hard to follow here it is all
sorry, i'll just send youall: it's really really tough for me to try to cut it
okay, i'll do {:crux, "== 0.1.1"}
seems cux 0.1.1 fails
Okay, we can simplify for now by commenting out other policies for non-read actions
So we can test just this one action's policy expression
let me try to skip the policies
Can you also add the conditional logic?
wow, it's going to be a lot to try to skip
like
if authorizer.resource == ..
The ones you sent include other action calls as far as I can tellok
so i should still keep with the broken crux? cause it kills the test
no, use the new one π
@allenwyma DMd
Just going to run your app if you'll let me π
Okay
@allenwyma I've found the culprit
There is indeed a bug somewhere in our expression logic
its not a scary one because it will only prevent access, not add access
but it comes from having a trailing bypass
If you put that at the beginning and not the end (where I think you'd probably want it) then your policies will work.
π
Itβs in my app logic?
That is, yes
there is a bug
that shouldn't be preventing you
Yeah but still good to know. I have someone to hunt down π
Thanks so much for that!
We fixed abut around trailing bypasses, and were clearly too aggressive.
I might actually just make trailing bypasses raise an error lol
because it makes no sense to have a bypass that doesn't bypass anything
fix is on the way: https://github.com/ash-project/ash/pull/2404
yeah, i didn't examine the whole thing, but makes sense. i talked to the guy who wrote it and he also understood π
i'm also thinking maybe we shouold updat the docs with an example for filtercheck and the typespec? It wasn't clear to me that a boolean is an expression.
But, I think the Keywords part isnt' clear to me what keywords i can return?
i can submit a PR since this is on my mind if you can help to fill in the typespec details for me
The keyword part is the keyword filter syntax
i.e
[id: 10] or [score: [greater_than: 20]]oh, like siimilar to a expression sort of?
Thanks @Zach for the debugging... and the bypass at the end... was strange indeed π I still need to improve my coding π