Created
October 4, 2016 16:50
-
-
Save mileszs/adaa26e44d64604e8951e9b3077759ab to your computer and use it in GitHub Desktop.
Plug for authenticating via session or token
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ElixirJobBoard.Plugs.AuthenticateJobPoster do | |
import Plug.Conn | |
import Phoenix.Controller, only: [put_flash: 3, redirect: 2] | |
alias ElixirJobBoard.Repo | |
alias ElixirJobBoard.User | |
def init(opts), do: opts | |
def call(conn, _opts) do | |
user = get_user_from_session_or_token(conn) | |
if user do | |
conn |> assign(:current_user, user) | |
else | |
conn | |
|> put_flash(:info, "You must be logged in.") | |
|> redirect(to: "/") | |
|> halt | |
end | |
end | |
defp get_user_from_session_or_token(conn) do | |
case conn.assigns[:current_user] do | |
nil -> find_user(conn, user_id_from_session(conn)) | |
user -> user | |
end | |
end | |
defp user_id_from_session(conn) do | |
get_session(conn, :current_user) | |
end | |
defp find_user(conn, nil) do | |
conn = conn |> fetch_query_params() | |
find_user_by_token(conn.query_params["token"]) | |
end | |
defp find_user(conn, id) do | |
Repo.get(User, id) | |
end | |
defp find_user_by_token(nil), do: nil | |
defp find_user_by_token(token) do | |
Repo.get_by(User, token: token) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ElixirJobBoard.Plugs.AuthenticateJobPosterTest do | |
use ElixirJobBoard.ConnCase | |
import ElixirJobBoard.Factory | |
@session Plug.Session.init([ | |
store: :cookie, | |
key: "_app", | |
encryption_salt: "secret", | |
signing_salt: "secret", | |
encrypt: false | |
]) | |
test "user is redirected when current_user is not assigned and token is not present" do | |
job = insert(:job) | |
conn = build_conn(:get, "/jobs/#{job.id}/edit", "") | |
|> setup_session() | |
|> ElixirJobBoard.Plugs.AuthenticateJobPoster.call(%{}) | |
assert redirected_to(conn) == "/" | |
end | |
test "user is redirected when current_user is not assigned and token doesn't match a user" do | |
job = insert(:job) | |
token = String.duplicate("abcdefgh", 8) | |
conn = build_conn(:get, "/jobs/#{job.id}/edit?token=#{token}", "") | |
|> setup_session() | |
|> ElixirJobBoard.Plugs.AuthenticateJobPoster.call(%{}) | |
assert redirected_to(conn) == "/" | |
end | |
test "user passes through when current_user is assigned" do | |
user = insert(:user) | |
job = insert(:job) | |
conn = build_conn(:get, "/jobs/#{job.id}/edit", "") | |
|> setup_session() | |
|> put_session(:current_user, user.id) | |
|> ElixirJobBoard.Plugs.AuthenticateJobPoster.call(%{}) | |
assert conn.status != 302 | |
end | |
test "user passes through when token is present and matches a user" do | |
token = String.duplicate("abcdefgh", 8) | |
insert(:user, token: token) | |
job = insert(:job) | |
conn = build_conn(:get, "/jobs/#{job.id}/edit?token=#{token}", "") | |
|> setup_session() | |
|> ElixirJobBoard.Plugs.AuthenticateJobPoster.call(%{}) | |
assert conn.status != 302 | |
end | |
defp setup_session(conn) do | |
conn | |
|> Map.put(:secret_key_base, String.duplicate("abcdefgh", 8)) | |
|> Plug.Session.call(@session) | |
|> fetch_session() | |
|> fetch_flash() | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment