Add authorisation plug
This commit is contained in:
parent
626063ee76
commit
37985ac1cf
1 changed files with 52 additions and 0 deletions
52
lib/real_estate_web/plugs/ensure_role_plug.ex
Normal file
52
lib/real_estate_web/plugs/ensure_role_plug.ex
Normal file
|
@ -0,0 +1,52 @@
|
|||
defmodule RealEstateWeb.EnsureRolePlug do
|
||||
@moduledoc """
|
||||
This plug ensures that a user has a particular role before accessing a given route.
|
||||
|
||||
## Example
|
||||
Let's suppose we have three roles: :admin, :manager and :user.
|
||||
|
||||
If you want a user to have at least manager role, so admins and managers are authorised to access a given route
|
||||
plug RealEstateWeb.EnsureRolePlug, [:admin, :manager]
|
||||
|
||||
If you want to give access only to an admin:
|
||||
plug RealEstateWeb.EnsureRolePlug, :admin
|
||||
"""
|
||||
import Plug.Conn
|
||||
|
||||
alias RealEstate.Accounts
|
||||
alias RealEstate.Accounts.User
|
||||
alias Phoenix.Controller
|
||||
alias Plug.Conn
|
||||
|
||||
@doc false
|
||||
@spec init(any()) :: any()
|
||||
def init(config), do: config
|
||||
|
||||
@doc false
|
||||
@spec call(Conn.t(), atom() | [atom()]) :: Conn.t()
|
||||
def call(conn, roles) do
|
||||
user_token = get_session(conn, :user_token)
|
||||
|
||||
(user_token &&
|
||||
Accounts.get_user_by_session_token(user_token))
|
||||
|> has_role?(roles)
|
||||
|> maybe_halt(conn)
|
||||
end
|
||||
|
||||
defp has_role?(%User{} = user, roles) when is_list(roles),
|
||||
do: Enum.any?(roles, &has_role?(user, &1))
|
||||
|
||||
defp has_role?(%User{role: role}, role), do: true
|
||||
defp has_role?(_user, _role), do: false
|
||||
|
||||
defp maybe_halt(true, conn), do: conn
|
||||
|
||||
defp maybe_halt(_any, conn) do
|
||||
conn
|
||||
|> Controller.put_flash(:error, "Unauthorised")
|
||||
|> Controller.redirect(to: signed_in_path(conn))
|
||||
|> halt()
|
||||
end
|
||||
|
||||
defp signed_in_path(_conn), do: "/"
|
||||
end
|
Loading…
Reference in a new issue