Redirect / restrict access to specified route if doesn't have session :xxxxx

  1. is phoenix has before_request method
  2. how do i redirect or restrict access to specify route if doesn’t have session :userame (nil) (because if i write session check in every route, it’s very inefficient

thankyou !

No, Plug do not have anything like before_request, however as Plug is just pipeline in rough form of:

conn
|> Plug1.call(Plug1.init(opts_1))
|> Plug2.call(Plug2.init(opts_2))
# …
|> PlugN.call(PlugN.init(opts_n))

You can just insert new plug before passing it to your controller function, and as Phoenix.Controller provides similar API to Plug.Builder you can do:

defmodule ProtectedController do
  use Phoenix.Controller

  plug(:check_session_username)

  def index(conn, params) do
    # …
    conn
  end

  def check_session_username(conn, _opts) do
    if get_username_from_session(conn) do
      conn
    else
      conn
      |> send_resp(:unauthorized, "Login to proceed")
      |> halt() # this one is important as this will "brake" processing
    end
  end
end
2 Likes

but how i define that only in one file, not in every controller ?

Define Plug, ex.:

defmodule CheckSessionUsernamePlug do
  @behaviour Plug

  import Plug.Conn

  def init(opts) do
    opts
  end

  def call(conn, _opts) do
    if get_username_from_session(conn) do
      conn
    else
      conn
      |> send_resp(:unauthorized, "Login to proceed")
      |> halt() # this one is important as this will "brake" processing
    end
  end
end

And then you can use this within your controllers/router/endpoint like:

plug CheckSessionUsernamePlug

And that is it. Just remember that it will be called for ALL paths that will go through this Plug, so be careful to not lock out session creation.

4 Likes

okay, after using @hauleth solution, this is my before_request-like solution

in lib/web/endpoint.ex

  # you will need to check session in CheckSessionPlug, to prevent
  # session not fetched error, call `plug :fetch_session` before
  # plug CheckSessionPlug
  plug :fetch_session

  # Before request-like function that check is cookie has logged
  # session or not, if not redirect to "/login", this function
  # works on all route except /login
  plug CheckSessionPlug

  plug MyWeebWeb.Router

note must be in correct order, fetch_session -> checksession -> actual router

CheckSessionPlug module :

defmodule CheckSessionPlug do
  use MyweebWeb, :controller

  @behaviour Plug

  import Plug.Conn

  def init(opts) do
    opts
  end

  def call(conn, _opts) do
    is_login = conn.request_path =~ "login"

    if is_login == false do
      # need fetch_session
      username = get_session(conn, :username)

      if username == nil do
        redirect(conn, to: "/login")
      end
    end

    # pass to actual route
    conn
  end
end