mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
User can login and create games
This commit is contained in:
parent
dda4bf0c5a
commit
1299d4f5e5
@ -23,9 +23,10 @@ config :logger, :console,
|
||||
metadata: [:request_id]
|
||||
|
||||
# Configure authentication provider
|
||||
# Replace secret_key in prod.secret.exs
|
||||
config :chess, Chess.Auth.Guardian,
|
||||
issuer: "chess",
|
||||
secret_key: System.get_env("GUARDIAN_SECRET_KEY")
|
||||
secret_key: "vd2vXkrYTTFKSKmNMoS2/Hk4Fxn8BkyzsVArRkxJazdQ3mr6bI4YgAC6f8ODiWlM"
|
||||
|
||||
# Import environment specific config. This must remain at the bottom
|
||||
# of this file so it overrides the configuration defined above.
|
||||
|
||||
@ -3,10 +3,10 @@ defmodule Chess.Auth.ErrorHandler do
|
||||
|
||||
import Plug.Conn
|
||||
|
||||
def auth_error(conn, {type, _reason}, _opts) do
|
||||
body = to_string(type)
|
||||
def auth_error(conn, {_type, _reason}, _opts) do
|
||||
conn
|
||||
|> put_resp_content_type("text/plain")
|
||||
|> send_resp(401, body)
|
||||
|> Phoenix.Controller.put_flash(:info, "You must be logged in")
|
||||
|> Phoenix.Controller.redirect(to: "/")
|
||||
|> halt()
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
defmodule Chess.Auth.Guardian do
|
||||
use Guardian, otp_app: :auth_ex
|
||||
use Guardian, otp_app: :chess
|
||||
|
||||
alias Chess.Auth
|
||||
|
||||
@ -10,8 +10,7 @@ defmodule Chess.Auth.Guardian do
|
||||
def resource_from_claims(claims) do
|
||||
user = claims["sub"]
|
||||
|> Auth.get_user!
|
||||
{:ok, user}
|
||||
|
||||
# If something goes wrong here return {:error, reason}
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
@ -35,7 +35,8 @@ defmodule ChessWeb do
|
||||
namespace: ChessWeb
|
||||
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
|
||||
import Phoenix.Controller,
|
||||
only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
|
||||
|
||||
# Use all HTML functionality (forms, tags, etc)
|
||||
use Phoenix.HTML
|
||||
|
||||
@ -3,6 +3,7 @@ defmodule ChessWeb.SessionController do
|
||||
|
||||
alias Chess.Auth
|
||||
alias Chess.Auth.User
|
||||
alias Chess.Auth.Guardian
|
||||
|
||||
def new(conn, _params) do
|
||||
changeset = User.changeset(%User{})
|
||||
@ -14,8 +15,9 @@ defmodule ChessWeb.SessionController do
|
||||
%{"user" => %{"username" => username, "password" => password}}
|
||||
) do
|
||||
case Auth.authenticate_user(username, password) do
|
||||
{:ok, _user} ->
|
||||
{:ok, user} ->
|
||||
conn
|
||||
|> Guardian.Plug.sign_in(user)
|
||||
|> put_flash(:info, "You are signed in")
|
||||
|> redirect(to: game_path(conn, :index))
|
||||
{:error, _error} ->
|
||||
@ -25,4 +27,11 @@ defmodule ChessWeb.SessionController do
|
||||
|> render("new.html", changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, _params) do
|
||||
conn
|
||||
|> Guardian.Plug.sign_out()
|
||||
|> put_flash(:info, "You are logged out")
|
||||
|> redirect(to: page_path(conn, :index))
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,21 +5,37 @@ defmodule ChessWeb.Router do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_flash
|
||||
# plug :protect_from_forgery
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
end
|
||||
|
||||
pipeline :auth do
|
||||
plug Chess.Auth.Pipeline
|
||||
end
|
||||
|
||||
pipeline :ensure_auth do
|
||||
plug Guardian.Plug.EnsureAuthenticated
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
end
|
||||
|
||||
scope "/", ChessWeb do
|
||||
pipe_through :browser # Use the default browser stack
|
||||
pipe_through [:browser, :auth] # Use the default browser stack
|
||||
|
||||
get "/", PageController, :index
|
||||
resources "/games", GameController, only: [:index, :create, :show, :delete]
|
||||
resources "/session", SessionController, only: [:new, :create], singleton: true
|
||||
resources "/registration", RegistrationController, only: [:new, :create], singleton: true
|
||||
resources "/session", SessionController,
|
||||
only: [:new, :create, :delete], singleton: true
|
||||
resources "/registration", RegistrationController,
|
||||
only: [:new, :create], singleton: true
|
||||
end
|
||||
|
||||
scope "/", ChessWeb do
|
||||
pipe_through [:browser, :auth, :ensure_auth]
|
||||
|
||||
resources "/games", GameController,
|
||||
only: [:index, :create, :show, :delete]
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
|
||||
@ -15,9 +15,15 @@
|
||||
<div class="container">
|
||||
<header role="banner">
|
||||
<nav role="user">
|
||||
<%= if current_user = Guardian.Plug.current_resource(@conn) do %>
|
||||
<%= current_user.username %>
|
||||
|
|
||||
<%= link("Log out", to: session_path(@conn, :delete), method: :delete) %>
|
||||
<% else %>
|
||||
<%= link("Register", to: registration_path(@conn, :new)) %>
|
||||
|
|
||||
<%= link("Log in", to: session_path(@conn, :new)) %>
|
||||
<% end %>
|
||||
</nav>
|
||||
<h1>Chess</h1>
|
||||
</header>
|
||||
|
||||
@ -2,26 +2,32 @@ defmodule Chess.GameControllerTest do
|
||||
use ChessWeb.ConnCase
|
||||
|
||||
alias Chess.Store.Game
|
||||
alias Chess.Auth.User
|
||||
alias Chess.Auth.Guardian
|
||||
@valid_attrs %{}
|
||||
|
||||
test "lists all entries on index", %{conn: conn} do
|
||||
conn = login(conn)
|
||||
conn = get conn, game_path(conn, :index)
|
||||
assert html_response(conn, 200) =~ "Listing games"
|
||||
end
|
||||
|
||||
test "creates resource and redirects when data is valid", %{conn: conn} do
|
||||
conn = login(conn)
|
||||
conn = post conn, game_path(conn, :create), game: @valid_attrs
|
||||
game = Repo.one(Game)
|
||||
assert redirected_to(conn) == game_path(conn, :show, game)
|
||||
end
|
||||
|
||||
test "shows chosen resource", %{conn: conn} do
|
||||
conn = login(conn)
|
||||
game = Repo.insert! %Game{}
|
||||
conn = get conn, game_path(conn, :show, game)
|
||||
assert html_response(conn, 200) =~ "<div id=\"app\" data-game-id=\"#{game.id}\">"
|
||||
end
|
||||
|
||||
test "renders page not found when id is nonexistent", %{conn: conn} do
|
||||
conn = login(conn)
|
||||
assert_error_sent 404, fn ->
|
||||
get conn, game_path(conn, :show, -1)
|
||||
end
|
||||
@ -29,8 +35,22 @@ defmodule Chess.GameControllerTest do
|
||||
|
||||
test "deletes chosen resource", %{conn: conn} do
|
||||
game = Repo.insert! %Game{}
|
||||
conn = login(conn)
|
||||
conn = delete conn, game_path(conn, :delete, game)
|
||||
assert redirected_to(conn) == game_path(conn, :index)
|
||||
refute Repo.get(Game, game.id)
|
||||
end
|
||||
|
||||
defp login(conn) do
|
||||
user = create_user()
|
||||
conn |> Guardian.Plug.sign_in(user)
|
||||
end
|
||||
|
||||
defp create_user() do
|
||||
changeset = User.changeset(
|
||||
%User{},
|
||||
%{username: "link@hyrule.kingdom", password: "ilovezelda"}
|
||||
)
|
||||
Repo.insert!(changeset)
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
defmodule Chess.GamesTest do
|
||||
use ChessWeb.FeatureCase
|
||||
|
||||
import Wallaby.Query, only: [css: 1, css: 2, button: 1]
|
||||
import Wallaby.Query, only: [css: 1, css: 2, button: 1, text_field: 1]
|
||||
|
||||
alias Chess.Auth.User
|
||||
|
||||
test "visit homepage", %{session: session} do
|
||||
session
|
||||
@ -11,12 +13,14 @@ defmodule Chess.GamesTest do
|
||||
|
||||
test "can create a new game", %{session: session} do
|
||||
session
|
||||
|> login()
|
||||
|> create_game()
|
||||
|> assert_has(css(".board"))
|
||||
end
|
||||
|
||||
test "can move a piece", %{session: session} do
|
||||
session
|
||||
|> login()
|
||||
|> create_game()
|
||||
|
||||
session
|
||||
@ -30,6 +34,24 @@ defmodule Chess.GamesTest do
|
||||
|> assert_has(square_containing("f4-r3", "white.pawn"))
|
||||
end
|
||||
|
||||
defp login(session) do
|
||||
create_user()
|
||||
|
||||
session
|
||||
|> visit("/session/new")
|
||||
|> fill_in(text_field("Username"), with: "link@hyrule.kingdom")
|
||||
|> fill_in(text_field("Password"), with: "ilovezelda")
|
||||
|> click(button("Sign in"))
|
||||
end
|
||||
|
||||
defp create_user() do
|
||||
changeset = User.changeset(
|
||||
%User{},
|
||||
%{username: "link@hyrule.kingdom", password: "ilovezelda"}
|
||||
)
|
||||
Repo.insert!(changeset)
|
||||
end
|
||||
|
||||
defp create_game(session) do
|
||||
session
|
||||
|> visit("/games")
|
||||
|
||||
@ -42,6 +42,25 @@ defmodule Chess.SessionTest do
|
||||
|> click(button("Sign in"))
|
||||
|
||||
assert session |> has_text?("You are signed in")
|
||||
assert session |> has_text?("Listing games")
|
||||
assert session |> has_text?("link@hyrule.kingdom")
|
||||
end
|
||||
|
||||
test "user can sign out", %{session: session} do
|
||||
create_user()
|
||||
|
||||
session
|
||||
|> visit("/")
|
||||
|> click(link("Log in"))
|
||||
|> fill_in(text_field("Username"), with: "link@hyrule.kingdom")
|
||||
|> fill_in(text_field("Password"), with: "ilovezelda")
|
||||
|> click(button("Sign in"))
|
||||
|
||||
session
|
||||
|> visit("/")
|
||||
|> click(link("Log out"))
|
||||
|
||||
assert session |> has_text?("You are logged out")
|
||||
end
|
||||
|
||||
defp create_user() do
|
||||
|
||||
Loading…
Reference in New Issue
Block a user