There’s a good discussion here about where to do the authorization of nested associations. I’m curious about the details of actually doing it.
I can authorize a basic action easily:
# any user can create a document
def authorize(:create_document, %{}, _), do: true
# only the owner of a document can update it
def authorize(:update_document, %{id: user_id}, %{user_id: user_id}), do: true
# reject anything that didn't pass other checks
def authorize(_, _, _), do: false
But it gets messy very quickly when I allow associating a document with other items…
def authorize(:create_document, user, %{folder_ids: folder_ids}) do
folders = Folders.list_folders(folder_ids: folder_ids)
Enum.all?(folders, fn folder -> authorize(:update_folder, user, folder) end)
end
def authorize(:update_folder, %{id: user_id}, %{user_id: user_id}), do: true
...
It’s even worse for an update_document
, as the user_id
could be in the Document or params.
How do all of you handle this? Do you even try to authorize nested data like this, or do you just do a fetch of the association by id + user_id to filter out any they don’t own?
Thanks!