Hello,
How can I execute a plug after a route has matched, and know the controller and action that are to be executed?
Example is authorization:
# admin is allowed access to /users/edit
def authorized?(:admin, {Admin.UserController, :edit}), do: :ok
# all other users are unauthorized
def authorized?(_, {Admin.UserController, :edit}), do: {:error, :unauthorized}
I could enforce authorization rules inside each controller that needs authorization like:
plug :authorize_user_update when action in [:edit, :update, :delete]
But instead, I would like to have all the authorization rules (authorized?
functions) in a centralized single file (Authorizor.ex
) without needing to add anything to the controller.
In order to achieve this I think I just need the conn
that I am still able to halt/redirect, the controller, the action, and pass these to a plug function that is called after the router has found the match (controller/action). That plug would call the function clauses above and the plug will halt/redirect in case of an authorization error.
Note: the reason for not having these in the controller, is
- to have all these rules in a single centralized place;
- if someone forgets to protect a controller, it’s not easily detected; dev errors happen and that would compromise security; missing authorization rules are easier to detect if those are centralized.