Guy14
What is the best way to set an authorization for the primary `:read` action when creating a linked Resource?
Hello!!
I have a UserEmotion Resource (it’s a join between User resource and Emotion resource).
In my User resource, I allow only users with role == :admin to access the :read action:
policy action(:read) do
authorize_if actor_attribute_equals(:role, :admin)
end
The UserEmotion exposes a create function named add_user_emotion which is quite basic:
create :add_user_emotion do
description "Adds a new entry to user_emotions."
argument :user, :uuid do
allow_nil? false
end
argument :emotion, :uuid do
allow_nil? false
end
change manage_relationship(:user, type: :append)
change manage_relationship(:emotion, type: :append)
end
I want this function to be available for all Users, including those who are not :admin (maybe I’ll populate the :user myself from the actor to ensure a User only adds Emotions for itself).
To fix the permission issue, I could:
- create a
:listfunction inUserresource, and I expose this function instead of:readin the API, so I put restricting policies on:listand I open all permissions on:read→ it doesn’t feel the right way to me, since there’s a breach if I later expose the:readfunction by mistake
OR - create an intermediary function before the
:add_user_emotionthat will set an actor likeactor: %{internal: true}, and then authorize this internal new actor in the policy like so:
policy action(:read) do
authorize_if actor_attribute_equals(:role, :admin)
authorize_if actor_attribute_equals(:internal, :true) // NEW ACTOR
end
None of my solutions seems good to me. Do you have any advice on this case? I guess it’s a common challenge, but I haven’t found a solution while checking at the docs (but I found many responses to other questions I had
).
P.S. I’ve also tried the accessing_from builtin policy, but It doesn’t work since my UserEmotion Resource is not yet created but on the path to be created…
policy action(:read) do
authorize_if actor_attribute_equals(:role, :admin)
authorize_if accessing_from(UserEmotion, :emotions)
end
Marked As Solved
zachdaniel
You can pass an authorize?: false option to manage_relationship if you want the parent action’s authorization rules to be the arbiter in this context. That might have helped with your original design.
Also Liked
sevenseacat
In this case you might also want an authorization rule for users, to let them read their own records. ie. authorize_if expr(id == ^actor(:id))
I think you still need to be able to read the user record, to use relate_actor!
FlyingNoodle
My feeling says use relate_actor and then if you need an admin to set any user you do something like:
create :add_user_emotion_admin do
argument :emotion, :uuid, allow_nil?: false
argument :user, :uuid, allow_nil?: false
change manage_relationship(:emotion, type: :append)
change manage_relationship(:user, type: :append)
end
policies
action(:add_user_emotion_admin) do
authorize_if actor_attribute_equals(:admin, true)
end
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









