Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Feb 9, 2021. It is now read-only.

Commit e0d0afb

Browse files
committed
Import all content from Phoenix Auth chapter
So far so good. I've been copying and pasting all the code snippets from the book into the app and everything has worked well so far.
1 parent 58daf40 commit e0d0afb

File tree

16 files changed

+175
-13
lines changed

16 files changed

+175
-13
lines changed

‎config/test.exs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ config :platform, Platform.Repo,
1616
database: "platform_test",
1717
hostname: "localhost",
1818
pool: Ecto.Adapters.SQL.Sandbox
19+
20+
# Reduce bcrypt rounds to speed up tests
21+
config :bcrypt_elixir, :log_rounds, 4

‎lib/platform/accounts/accounts.ex‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ defmodule Platform.Accounts do
5151
"""
5252
def create_player(attrs \\ %{}) do
5353
%Player{}
54-
|> Player.changeset(attrs)
54+
|> Player.registration_changeset(attrs)
5555
|> Repo.insert()
5656
end
5757

‎lib/platform/accounts/player.ex‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,29 @@ defmodule Platform.Accounts.Player do
1919
|> cast(attrs, [:display_name, :password, :score, :username])
2020
|> validate_required([:username])
2121
|> unique_constraint(:username)
22+
|> validate_length(:username, min: 2, max: 100)
23+
|> validate_length(:password, min: 2, max: 100)
24+
|> put_pass_digest()
25+
end
26+
27+
@doc false
28+
def registration_changeset(player, attrs) do
29+
player
30+
|> cast(attrs, [:password, :username])
31+
|> validate_required([:password, :username])
32+
|> unique_constraint(:username)
33+
|> validate_length(:username, min: 2, max: 100)
34+
|> validate_length(:password, min: 2, max: 100)
35+
|> put_pass_digest()
36+
end
37+
38+
defp put_pass_digest(changeset) do
39+
case changeset do
40+
%Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
41+
put_change(changeset, :password_digest, Comeonin.Bcrypt.hashpwsalt(pass))
42+
43+
_ ->
44+
changeset
45+
end
2246
end
2347
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
defmodule PlatformWeb.PageController do
22
use PlatformWeb, :controller
33

4+
plug :authenticate when action in [:index]
5+
46
def index(conn, _params) do
57
render(conn, "index.html")
68
end
9+
10+
defp authenticate(conn, _opts) do
11+
if conn.assigns.current_user() do
12+
conn
13+
else
14+
conn
15+
|> put_flash(:error, "You must be signed in to access that page.")
16+
|> redirect(to: Routes.player_path(conn, :new))
17+
|> halt()
18+
end
19+
end
720
end
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
defmodule PlatformWeb.PlayerAuthController do
2+
import Plug.Conn
3+
4+
alias Platform.Accounts.Player
5+
6+
def init(opts) do
7+
Keyword.fetch!(opts, :repo)
8+
end
9+
10+
def call(conn, repo) do
11+
player_id = get_session(conn, :player_id)
12+
player = player_id && repo.get(Player, player_id)
13+
assign(conn, :current_user, player)
14+
end
15+
16+
def sign_in(conn, player) do
17+
conn
18+
|> assign(:current_user, player)
19+
|> put_session(:player_id, player.id)
20+
|> configure_session(renew: true)
21+
end
22+
23+
def sign_in_with_username_and_password(conn, username, given_pass, opts) do
24+
repo = Keyword.fetch!(opts, :repo)
25+
player = repo.get_by(Player, username: username)
26+
27+
cond do
28+
player && Comeonin.Bcrypt.checkpw(given_pass, player.password_digest) ->
29+
{:ok, sign_in(conn, player)}
30+
31+
player ->
32+
{:error, :unauthorized, conn}
33+
34+
true ->
35+
Comeonin.Bcrypt.dummy_checkpw()
36+
{:error, :not_found, conn}
37+
end
38+
end
39+
40+
def sign_out(conn) do
41+
configure_session(conn, drop: true)
42+
end
43+
end

‎lib/platform_web/controllers/player_controller.ex‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ defmodule PlatformWeb.PlayerController do
1818
case Accounts.create_player(player_params) do
1919
{:ok, player} ->
2020
conn
21+
|> PlatformWeb.PlayerAuthController.sign_in(player)
2122
|> put_flash(:info, "Player created successfully.")
2223
|> redirect(to: Routes.player_path(conn, :show, player))
2324

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
defmodule PlatformWeb.PlayerSessionController do
2+
use PlatformWeb, :controller
3+
4+
def new(conn, _) do
5+
render(conn, "new.html")
6+
end
7+
8+
def create(conn, %{"session" => %{"username" => user, "password" => pass}}) do
9+
case PlatformWeb.PlayerAuthController.sign_in_with_username_and_password(
10+
conn,
11+
user,
12+
pass,
13+
repo: Platform.Repo
14+
) do
15+
{:ok, conn} ->
16+
conn
17+
|> put_flash(:info, "Welcome back!")
18+
|> redirect(to: Routes.page_path(conn, :index))
19+
20+
{:error, _reason, conn} ->
21+
conn
22+
|> put_flash(:error, "Invalid username/password combination.")
23+
|> render("new.html")
24+
end
25+
end
26+
27+
def delete(conn, _) do
28+
conn
29+
|> PlatformWeb.PlayerAuthController.sign_out()
30+
|> redirect(to: Routes.player_session_path(conn, :new))
31+
end
32+
end

‎lib/platform_web/router.ex‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ defmodule PlatformWeb.Router do
77
plug :fetch_flash
88
plug :protect_from_forgery
99
plug :put_secure_browser_headers
10+
plug PlatformWeb.PlayerAuthController, repo: Platform.Repo
1011
end
1112

1213
pipeline :api do
@@ -18,6 +19,7 @@ defmodule PlatformWeb.Router do
1819

1920
get "/", PageController, :index
2021
resources "/players", PlayerController
22+
resources "/sessions", PlayerSessionController, only: [:new, :create, :delete]
2123
end
2224

2325
# Other scopes may use custom stacks.

‎lib/platform_web/templates/layout/app.html.eex‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212
<section class="container">
1313
<nav role="navigation">
1414
<ul>
15-
<li><a href="https://hexdocs.pm/phoenix/overview.html">Get Started</a></li>
15+
<%= if @current_user do %>
16+
<p>Signed in as <strong><%= @current_user.username %></strong></p>
17+
<%= link "Sign Out", to: Routes.player_session_path(@conn, :delete, @current_user), method: "delete", class: "button" %>
18+
<% else %>
19+
<%= link "Sign Up", to: Routes.player_path(@conn, :new), class: "button" %>
20+
<%= link "Sign In", to: Routes.player_session_path(@conn, :new), class: "button" %>
21+
<% end %>
1622
</ul>
1723
</nav>
1824
<a href="http://phoenixframework.org/" class="phx-logo">
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<h1>Player Sign In</h1>
2+
3+
<%= form_for @conn, Routes.player_session_path(@conn, :create), [as: :session], fn f -> %>
4+
<%= label f, :username %>
5+
<%= text_input f, :username %>
6+
<%= error_tag f, :username %>
7+
8+
<%= label f, :password %>
9+
<%= password_input f, :password %>
10+
<%= error_tag f, :password %>
11+
12+
<div>
13+
<%= submit "Sign In" %>
14+
</div>
15+
<% end %>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /