Quantcast
Channel: How to restrict access to certain routes in Phoenix? - Stack Overflow
Viewing all articles
Browse latest Browse all 4

Answer by tblev for How to restrict access to certain routes in Phoenix?

$
0
0

Building off of Chris Mccord you can actually do this without taking up a lot of space in the controller. Like this:

defmodule MyAppWeb.CategoryController do  use MyAppWeb, :controller  use MyApp.Helpers.Connection  plug :authorize_crud, %{action: :read, permissions: [:can_access_categories]} when action in [:index, :show]  plug :authorize_crud, %{action: :create, permissions: [:can_create_categories]} when action in [:new, :create]  plug :authorize_crud, %{action: :update, permissions: [:can_update_categories]} when action in [:edit, :update]  def index(conn, _params) do    conn  end  def new(conn, _params) do   conn  end  def create(conn, %{"category" => category_params}) do    conn  end  def update(conn, %{"id" => id, "category" => category_params}) do    conn  endend
defmodule MyApp.Helpers.Connection do  @spec authorize(%Plug.Conn{}, list(), list()) :: %Plug.Conn{}  def authorize(conn, user_permissions \\ [], required_permissions \\ []) do    import Plug.Conn     up = user_permissions |> MapSet.new()     rp = required_permissions |> MapSet.new()    case MapSet.subset?(rp, up) do      true ->        conn      false ->        conn        |> put_status(404)        |> Phoenix.Controller.render(MyAppWeb.ErrorView, "404.html", %{layout: false})        |> halt()    end  end  defmacro __using__(_) do    quote do      def authorize_crud(conn, opts = %{action: :read, permissions: permissions}) do        check(conn, permissions)      end      def authorize_crud(conn, opts = %{action: :create, permissions: permissions}) do        check(conn, permissions)      end      def authorize_crud(conn, opts = %{action: :update, permissions: permissions}) do        check(conn, permissions)      end      def authorize_crud(conn, opts = %{action: :destroy, permissions: permissions}) do        check(conn, permissions)      end      def check(conn, permissions) do        user = conn.assigns.current_user |> Repo.preload(:role)        MyApp.Helpers.Connection.authorize(conn, Accounts.list_permissions(user), permissions)      end    end  endend

Notes:

  1. When we use use Myapp.Helpers.Connection we get to use the imported function without a module name, this allows us to use it in the plug.
  2. The code defmacro __using__(_) is required because You have to include the using macro and put all the code that should be compiled into the using module in there
  3. The usage in my case is authorization functionality to restrict user access to certain controller actions. The authorize/3 function serves to return a true or false if the user has the required requirements.
  4. Inside of the defmacro we are overriding authorize_crud with pattern matching from what comes in from the plug call.
  5. An ideal list of data for Accounts.list_permissions(user) is
[:can_access_categories,:can_create_categories]
  1. The permissions coming in to match are whatever come in as permissions in the plug. So
[:can_access_categories]

Viewing all articles
Browse latest Browse all 4

Latest Images

Trending Articles





Latest Images