Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 25 additions & 15 deletions copi.owasp.org/lib/copi_web/live/player_live/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,36 @@ defmodule CopiWeb.PlayerLive.Show do

{:ok, dealt_card} = DealtCard.find(dealt_card_id)

vote = get_vote(dealt_card, player)

if vote do
Logger.debug("Player has voted: player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}")
Copi.Repo.delete!(vote)
game_card_ids =
game.players
|> Enum.flat_map(fn p -> p.dealt_cards end)
|> Enum.map(fn dc -> dc.id end)

if dealt_card.id not in game_card_ids do
Logger.warning("Unauthorized vote attempt: player_id: #{player.id}, dealt_card_id: #{dealt_card_id} does not belong to game_id: #{game.id}")
{:noreply, socket}
else
Logger.debug("Player has not voted: player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}")
case Copi.Repo.insert(%Copi.Cornucopia.Vote{dealt_card_id: String.to_integer(dealt_card_id), player_id: player.id}) do
{:ok, _vote} ->
Logger.debug("Vote added successfully for player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}")
{:error, changeset} ->
Logger.warning("Voting failed for player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}, errors: #{inspect(changeset.errors)}")
vote = get_vote(dealt_card, player)

if vote do
Logger.debug("Player has voted: player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}")
Copi.Repo.delete!(vote)
else
Logger.debug("Player has not voted: player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}")
case Copi.Repo.insert(%Copi.Cornucopia.Vote{dealt_card_id: String.to_integer(dealt_card_id), player_id: player.id}) do
{:ok, _vote} ->
Logger.debug("Vote added successfully for player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}")
{:error, changeset} ->
Logger.warning("Voting failed for player_id: #{player.id}, dealt_card_id: #{dealt_card_id}, game_id: #{game.id}, errors: #{inspect(changeset.errors)}")
end
end
end

{:ok, updated_game} = Game.find(game.id)
{:ok, updated_game} = Game.find(game.id)

CopiWeb.Endpoint.broadcast(topic(updated_game.id), "game:updated", updated_game)
CopiWeb.Endpoint.broadcast(topic(updated_game.id), "game:updated", updated_game)

{:noreply, assign(socket, :game, updated_game)}
{:noreply, assign(socket, :game, updated_game)}
end
end

def topic(game_id) do
Expand Down
34 changes: 34 additions & 0 deletions copi.owasp.org/test/copi_web/live/player_live/show_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -286,5 +286,39 @@ defmodule CopiWeb.PlayerLive.ShowTest do
{:ok, updated_dealt2} = Copi.Cornucopia.DealtCard.find(to_string(dealt.id))
assert length(updated_dealt2.votes) == 0
end

test "toggle_vote rejects vote on a dealt card from another game", %{conn: conn, player: player} do
game_id = player.game_id
{:ok, game} = Cornucopia.Game.find(game_id)

Copi.Repo.update!(
Ecto.Changeset.change(game, started_at: DateTime.truncate(DateTime.utc_now(), :second))
)

# Create a second game with its own player and dealt card
{:ok, other_game} = Cornucopia.create_game(%{name: "other game"})
{:ok, other_player} = Cornucopia.create_player(%{name: "Other Player", game_id: other_game.id})

{:ok, card} =
Cornucopia.create_card(%{
category: "C", value: "TV2", description: "D", edition: "webapp",
version: "2.2", external_id: "TV_CROSS1", language: "en", misc: "m",
owasp_scp: [], owasp_devguide: [], owasp_asvs: [], owasp_appsensor: [],
capec: [], safecode: [], owasp_mastg: [], owasp_masvs: []
})

other_dealt = Copi.Repo.insert!(%Copi.Cornucopia.DealtCard{
player_id: other_player.id, card_id: card.id, played_in_round: 1
})

{:ok, show_live, _html} = live(conn, "/games/#{game_id}/players/#{player.id}")

# Attempt to vote on a dealt card from the other game — should be rejected
render_click(show_live, "toggle_vote", %{"dealt_card_id" => to_string(other_dealt.id)})
:timer.sleep(100)

{:ok, unchanged_dealt} = Copi.Cornucopia.DealtCard.find(to_string(other_dealt.id))
assert length(unchanged_dealt.votes) == 0
end
end
end
Loading