-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add authentication and session workflow
- Loading branch information
Showing
20 changed files
with
217 additions
and
124 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
defmodule JaxEx.Accounts.Auth do | ||
alias JaxEx.Accounts.{Encryption, User} | ||
|
||
def login(params, repo) do | ||
user = repo.get_by(User, username: String.downcase(params["username"])) | ||
case authenticate(user, params["password"]) do | ||
true -> {:ok, user} | ||
_ -> :error | ||
end | ||
end | ||
|
||
defp authenticate(user, password) do | ||
if user do | ||
{:ok, authenticated_user} = Encryption.validate_password(user, password) | ||
authenticated_user.username == user.username | ||
else | ||
nil | ||
end | ||
end | ||
|
||
def signed_in?(conn) do | ||
conn.assigns[:current_user] | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
defmodule JaxEx.Accounts.Encryption do | ||
alias Comeonin.Bcrypt | ||
alias JaxEx.Accounts.User | ||
|
||
def hash_password(password), do: Bcrypt.hashpwsalt(password) | ||
|
||
def validate_password(%User{} = user, password), do: Bcrypt.check_pass(user, password) | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,43 @@ | ||
defmodule JaxEx.Accounts.User do | ||
use Ecto.Schema | ||
import Ecto.Changeset | ||
alias JaxEx.Accounts.{User, Encryption} | ||
|
||
schema "users" do | ||
field :username, :string | ||
field :encrypted_password, :string | ||
|
||
field :password, :string, virtual: true | ||
field :password_confirmation, :string, virtual: true | ||
|
||
timestamps() | ||
end | ||
|
||
@doc false | ||
def changeset(user, attrs) do | ||
user | ||
|> cast(attrs, [:username]) | ||
|> cast(attrs, [:username, :password]) | ||
|> validate_required([:username]) | ||
|> validate_length(:password, min: 6) | ||
|> validate_confirmation(:password) | ||
|> validate_format(:username, ~r/^[a-z0-9][a-z0-9]+[a-z0-9]$/i) | ||
|> validate_length(:username, min: 3) | ||
|> unique_constraint(:username) | ||
|> downcase_username | ||
|> encrypt_password | ||
end | ||
|
||
defp encrypt_password(changeset) do | ||
password = get_change(changeset, :password) | ||
if password do | ||
encrypted_password = Encryption.hash_password(password) | ||
put_change(changeset, :encrypted_password, encrypted_password) | ||
else | ||
changeset | ||
end | ||
end | ||
|
||
defp downcase_username(changeset) do | ||
update_change(changeset, :username, &String.downcase/1) | ||
end | ||
end |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
defmodule JaxExWeb.SessionController do | ||
use JaxExWeb, :controller | ||
|
||
alias JaxEx.Accounts.Auth | ||
alias JaxEx.Repo | ||
|
||
def new(conn, _params) do | ||
render(conn, "new.html") | ||
end | ||
|
||
@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t() | ||
def create(conn, %{"session" => auth_params}) do | ||
case Auth.login(auth_params, Repo) do | ||
{:ok, user} -> | ||
conn | ||
|> put_session(:current_user_id, user.id) | ||
|> put_flash(:info, "Signed in successfully.") | ||
|> redirect(to: Routes.page_path(conn, :index)) | ||
:error -> | ||
conn | ||
|> put_flash(:error, "There was a problem with your username/password") | ||
|> render("new.html") | ||
end | ||
end | ||
|
||
def delete(conn, _params) do | ||
conn | ||
|> delete_session(:current_user_id) | ||
|> put_flash(:info, "Signed out successfully.") | ||
|> redirect(to: Routes.session_path(conn, :new)) | ||
end | ||
end |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
defmodule JaxExWeb.Plugs.Auth do | ||
import Plug.Conn | ||
import Phoenix.Controller | ||
|
||
alias JaxEx.Accounts | ||
|
||
def init(opts), do: opts | ||
|
||
def call(conn, _opts) do | ||
if user_id = Plug.Conn.get_session(conn, :current_user_id) do | ||
current_user = Accounts.get_user!(user_id) | ||
conn | ||
|> assign(:current_user, current_user) | ||
else | ||
conn | ||
|> redirect(to: "/login") | ||
|> halt() | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
defmodule JaxExWeb.Plugs.Guest do | ||
import Plug.Conn | ||
import Phoenix.Controller | ||
|
||
def init(opts), do: opts | ||
|
||
def call(conn, _opts) do | ||
if Plug.Conn.get_session(conn, :current_user_id) do | ||
conn | ||
|> redirect(to: JaxExWeb.Router.Helpers.page_path(conn, :index)) | ||
|> halt() | ||
end | ||
conn | ||
end | ||
end |
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<div class='row'> | ||
<div class='col s12 m6 offset-m3'> | ||
<div class='card'> | ||
<div class='card-content'> | ||
<span class='card-title'>LOGIN</span> | ||
<div class='row card-form'> | ||
<%= form_for @conn, Routes.session_path(@conn, :new), [as: :session], fn f -> %> | ||
<%= text_input f, :username, placeholder: "Username" %> | ||
<%= password_input f, :password, placeholder: "Password" %> | ||
<%= submit "Submit", class: "btn right secondary-color" %> | ||
<%= link "Register", to: Routes.user_path(@conn, :new), class: "btn secondary-color" %> | ||
<% end %> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
<h1>New User</h1> | ||
|
||
<%= render "form.html", Map.put(assigns, :action, Routes.user_path(@conn, :create)) %> | ||
|
||
<span><%= link "Back", to: Routes.user_path(@conn, :index) %></span> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
defmodule JaxExWeb.SessionView do | ||
use JaxExWeb, :view | ||
end |
This file contains 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
This file contains 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
9 changes: 9 additions & 0 deletions
9
priv/repo/migrations/20190912232358_add_encrypted_password_to_users.exs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
defmodule JaxEx.Repo.Migrations.AddEncryptedPasswordToUsers do | ||
use Ecto.Migration | ||
|
||
def change do | ||
alter table(:users) do | ||
add :encrypted_password, :string | ||
end | ||
end | ||
end |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,24 @@ | ||
defmodule JaxExWeb.PageControllerTest do | ||
use JaxExWeb.ConnCase | ||
|
||
test "GET /", %{conn: conn} do | ||
conn = get(conn, "/") | ||
assert html_response(conn, 200) =~ "Welcome to Phoenix!" | ||
alias JaxEx.Accounts | ||
|
||
@create_attrs %{username: "username"} | ||
|
||
describe "unauthenticated" do | ||
test "GET /", %{conn: conn} do | ||
conn = get(conn, "/") | ||
assert redirected_to(conn) == Routes.session_path(conn, :new) | ||
end | ||
end | ||
|
||
describe "authenticated" do | ||
test "GET /", %{conn: conn} do | ||
{:ok, user} = Accounts.create_user(@create_attrs) | ||
conn = Plug.Test.init_test_session(conn, current_user_id: user.id) | ||
|
||
conn = get(conn, "/") | ||
assert html_response(conn, 200) =~ "Welcome to Phoenix!" | ||
end | ||
end | ||
end |
Oops, something went wrong.