Hi!
I need to implement some permission check logic for my application, but I want to try to keep it decoupled from the rest business logic.
So let’s say I have User and Organisation models in my app. These entities are related to each other as “many to many”. When user tries to do something with the organisation I want to check if this user is a member of organisation or not
So my idea to implement some plug that will fetch User
and Organisation
and do the check in the following manner:
def check_is_member(conn, %{"organisation_id" => org_id}) do #org_id is fetch from request path param
user = conn.assigns[:current_user]
organisation = Organisations.get!(org_id) #database select
if not Organisations.has_member(organisation, user.id) do
raise Forbidden
else
conn
end
end
and then use this plug in router like this:
pipeline :organisation_related do
:check_is_member
end
scope "/:organisation_id", MyAppWeb do
pipe_through :organisation_related
resources "/", OrganisationController, only: [:show]
end
and `MyApp.OrganisationController has this function
def show(organisation_id) do
Organisation.get!(org_id) # one more database select!
end
So I initiate one database query on the level of the plug just for checking permissions. And then, when controller logic performs, one more query will be performed on the level of actual business logic.
My question is: will Ecto cache the result of the first query to reuse it for the second one? How many actual SELECT
s will be performed here?
In this approach, I really like that permission check logic is completely decoupled from what controller and underlying Contexts do. But I’m very worried about the database load.