diff --git a/lib/chess/auth/user.ex b/lib/chess/auth/user.ex index 00d7ca7..5090d85 100644 --- a/lib/chess/auth/user.ex +++ b/lib/chess/auth/user.ex @@ -10,6 +10,8 @@ defmodule Chess.Auth.User do field :password_hash, :string field :username, :string + has_many :games, Chess.Store.Game + timestamps() end diff --git a/lib/chess/store/game.ex b/lib/chess/store/game.ex index 0cd0625..d3e66ac 100644 --- a/lib/chess/store/game.ex +++ b/lib/chess/store/game.ex @@ -5,35 +5,39 @@ defmodule Chess.Store.Game do import Ecto.Changeset import Ecto.Query + alias Chess.Board + schema "games" do field :board, :map + belongs_to :user, Chess.Auth.User + timestamps() end @doc """ Builds a changeset based on the `struct` and `params`. """ - def changeset(struct) do + def create_changeset(struct, params \\ %{}) do struct - |> cast(%{}, [:board]) - |> set_default_board - |> validate_required([:board]) + |> cast(params, [:board, :user_id]) + |> put_change(:board, Board.default) + |> validate_required([:board, :user_id]) end - def changeset(struct, params) do + def changeset(struct, params \\ %{}) do struct - |> cast(params, [:board]) - |> validate_required([:board]) + |> cast(params, [:board, :user_id]) + |> validate_required([:board, :user_id]) + end + + def for_user(query, user) do + query + |> where([game], user_id: ^user.id) end def ordered(query) do query |> order_by([game], desc: game.inserted_at) end - - def set_default_board(changeset) do - changeset - |> put_change(:board, Chess.Board.default) - end end diff --git a/lib/chess_web/controllers/game_controller.ex b/lib/chess_web/controllers/game_controller.ex index f343d8a..4420783 100644 --- a/lib/chess_web/controllers/game_controller.ex +++ b/lib/chess_web/controllers/game_controller.ex @@ -5,12 +5,18 @@ defmodule ChessWeb.GameController do def index(conn, _params) do changeset = Game.changeset(%Game{}) - games = Game |> Game.ordered |> Repo.all + games = Game + |> Game.for_user(current_user(conn)) + |> Game.ordered + |> Repo.all render(conn, "index.html", games: games, changeset: changeset) end def create(conn, _params) do - changeset = Game.changeset(%Game{}) + changeset = Game.create_changeset( + %Game{}, + %{user_id: current_user(conn).id} + ) case Repo.insert(changeset) do {:ok, game} -> @@ -38,4 +44,8 @@ defmodule ChessWeb.GameController do |> put_flash(:info, "Game deleted successfully.") |> redirect(to: game_path(conn, :index)) end + + defp current_user(conn) do + Guardian.Plug.current_resource(conn) + end end diff --git a/priv/repo/migrations/20180202205842_add_user_id_to_games.exs b/priv/repo/migrations/20180202205842_add_user_id_to_games.exs new file mode 100644 index 0000000..4d0c77b --- /dev/null +++ b/priv/repo/migrations/20180202205842_add_user_id_to_games.exs @@ -0,0 +1,9 @@ +defmodule Chess.Repo.Migrations.AddUserIdToGames do + use Ecto.Migration + + def change do + alter table("games") do + add :user_id, references(:users) + end + end +end diff --git a/test/chess/store/game_test.exs b/test/chess/store/game_test.exs index 8ff9498..c9d133b 100644 --- a/test/chess/store/game_test.exs +++ b/test/chess/store/game_test.exs @@ -4,16 +4,30 @@ defmodule Chess.GameTest do describe "game" do alias Chess.Store.Game - @valid_attrs %{board: %{}} - @invalid_attrs %{} + test "game is valid with a board and user" do + attrs = %{board: %{}, user_id: 1} + changeset = Game.changeset(%Game{}, attrs) - test "changeset with valid attributes" do - changeset = Game.changeset(%Game{}, @valid_attrs) assert changeset.valid? end - test "changeset with invalid attributes" do - changeset = Game.changeset(%Game{}, @invalid_attrs) + test "game is invalid without a board" do + attrs = %{user_id: 1} + changeset = Game.changeset(%Game{}, attrs) + + refute changeset.valid? + end + + test "game is invalid without a user" do + attrs = %{board: %{}} + changeset = Game.changeset(%Game{}, attrs) + + refute changeset.valid? + end + + test "game is invalid without a board or user" do + changeset = Game.changeset(%Game{}, %{}) + refute changeset.valid? end end diff --git a/test/features/games_test.exs b/test/features/games_test.exs index c14f455..20d1cf2 100644 --- a/test/features/games_test.exs +++ b/test/features/games_test.exs @@ -1,8 +1,14 @@ defmodule Chess.GamesTest do use ChessWeb.FeatureCase - import Wallaby.Query, only: [css: 1, css: 2, button: 1, text_field: 1] - import Chess.Factory, only: [create_user: 2] + import Wallaby.Query, only: [ + css: 1, + css: 2, + button: 1, + text_field: 1, + link: 1, + ] + import Chess.Factory, only: [create_user: 2, create_game_for: 1] test "visit homepage", %{session: session} do session @@ -13,11 +19,21 @@ defmodule Chess.GamesTest do test "can create a new game", %{session: session} do session |> login() - |> take_screenshot() |> create_game() |> assert_has(css(".board")) end + test "can only see own games", %{session: session} do + user = create_user("zelda@hyrule.kingdom", "ganonsucks") + create_game_for(user) + + session + |> login() + |> create_game() + |> click(link("Back to games")) + |> assert_has(css(".table tr", count: 1)) + end + test "can move a piece", %{session: session} do session |> login() diff --git a/test/support/factory.ex b/test/support/factory.ex index 5389c5a..7393ad5 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -1,5 +1,6 @@ defmodule Chess.Factory do alias Chess.Auth.User + alias Chess.Store.Game alias Chess.Repo def create_user(username \\ "zelda", password \\ "password") do @@ -9,4 +10,12 @@ defmodule Chess.Factory do ) |> Repo.insert! end + + def create_game_for(user) do + Game.create_changeset( + %Game{}, + %{user_id: user.id} + ) + |> Repo.insert! + end end diff --git a/test/test_helper.exs b/test/test_helper.exs index 2ca555d..7a75db1 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -2,6 +2,6 @@ ExUnit.start() -Ecto.Adapters.SQL.Sandbox.mode(Chess.Repo, :manual) +Ecto.Adapters.SQL.Sandbox.mode(Chess.Repo, {:shared, self()}) Application.put_env(:wallaby, :base_url, ChessWeb.Endpoint.url)