From 595068abb727c45ee9bb4a3fc68a056f41b06aa1 Mon Sep 17 00:00:00 2001 From: Amin Arria Date: Fri, 14 Jun 2024 17:15:40 +0200 Subject: [PATCH] Fix support for JWT in arena_load_test --- .../lib/arena_load_test/application.ex | 3 +- .../arena_load_test/game_socket_handler.ex | 13 +++-- .../lib/arena_load_test/socket_handler.ex | 55 ++++++++++++------- .../lib/arena_load_test/socket_supervisor.ex | 4 +- .../lib/arena_load_test/token_fetcher.ex | 47 ---------------- 5 files changed, 46 insertions(+), 76 deletions(-) delete mode 100644 apps/arena_load_test/lib/arena_load_test/token_fetcher.ex diff --git a/apps/arena_load_test/lib/arena_load_test/application.ex b/apps/arena_load_test/lib/arena_load_test/application.ex index bd6ba478c..0397237dc 100644 --- a/apps/arena_load_test/lib/arena_load_test/application.ex +++ b/apps/arena_load_test/lib/arena_load_test/application.ex @@ -10,8 +10,7 @@ defmodule ArenaLoadTest.Application do children = [ ArenaLoadTest.SocketSupervisor, ArenaLoadTest.LoadtestManager, - {Finch, name: ArenaLoadTest.Finch}, - ArenaLoadTest.TokenFetcher + {Finch, name: ArenaLoadTest.Finch} # Starts a worker by calling: ArenaLoadTest.Worker.start_link(arg) # {ArenaLoadTest.Worker, arg} ] diff --git a/apps/arena_load_test/lib/arena_load_test/game_socket_handler.ex b/apps/arena_load_test/lib/arena_load_test/game_socket_handler.ex index 8419e1860..54d80c1c9 100644 --- a/apps/arena_load_test/lib/arena_load_test/game_socket_handler.ex +++ b/apps/arena_load_test/lib/arena_load_test/game_socket_handler.ex @@ -8,14 +8,15 @@ defmodule ArenaLoadTest.GameSocketHandler do alias ArenaLoadTest.Utils use WebSockex, restart: :transient - def start_link({client_id, game_id}) do - ws_url = ws_url(client_id, game_id) + def start_link({client_id, user_token, game_id}) do + ws_url = ws_url(client_id, user_token, game_id) WebSockex.start_link( ws_url, __MODULE__, %{ client_id: client_id, + user_token: user_token, game_id: game_id } ) @@ -109,15 +110,17 @@ defmodule ArenaLoadTest.GameSocketHandler do ]) end - defp ws_url(client_id, game_id) do + defp ws_url(client_id, user_token, game_id) do + query_params = "gateway_jwt=#{user_token}" + case System.get_env("TARGET_SERVER") do nil -> - "ws://localhost:4000/play/#{game_id}/#{client_id}" + "ws://localhost:4000/play/#{game_id}/#{client_id}?#{query_params}" target_server -> # TODO Replace this for a SSL connection using erlang credentials. # TODO https://github.com/lambdaclass/mirra_backend/issues/493 - "ws://#{Utils.get_server_ip(target_server)}:4000/play/#{game_id}/#{client_id}" + "ws://#{Utils.get_server_ip(target_server)}:4000/play/#{game_id}/#{client_id}?#{query_params}" end end diff --git a/apps/arena_load_test/lib/arena_load_test/socket_handler.ex b/apps/arena_load_test/lib/arena_load_test/socket_handler.ex index 11d9a7561..71cc239e8 100644 --- a/apps/arena_load_test/lib/arena_load_test/socket_handler.ex +++ b/apps/arena_load_test/lib/arena_load_test/socket_handler.ex @@ -9,13 +9,15 @@ defmodule ArenaLoadTest.SocketHandler do alias ArenaLoadTest.Utils def start_link(client_id) do - ws_url = ws_url(client_id) + user_token = create_user(client_id) + ws_url = ws_url(client_id, user_token) WebSockex.start_link( ws_url, __MODULE__, %{ - client_id: client_id + client_id: client_id, + user_token: user_token } ) end @@ -29,43 +31,44 @@ defmodule ArenaLoadTest.SocketHandler do end @impl true - def handle_frame({:binary, game_state}, state) do - game_id = Serialization.GameState.decode(game_state).game_id + def handle_frame({:binary, lobby_event}, state) do + case Serialization.LobbyEvent.decode(lobby_event) do + %{event: {:game, %{game_id: game_id}}} -> + case :ets.lookup(:clients, state.client_id) do + [{client_id, _}] -> + :ets.delete(:clients, client_id) - case :ets.lookup(:clients, state.client_id) do - [{client_id, _}] -> - :ets.delete(:clients, client_id) + [] -> + raise KeyError, message: "Client with ID #{state.client_id} doesn't exist." + end - [] -> - raise KeyError, message: "Client with ID #{state.client_id} doesn't exist." - end + {:ok, pid} = SocketSupervisor.add_new_player(state.client_id, state.user_token, game_id) - {:ok, pid} = - SocketSupervisor.add_new_player( - state.client_id, - game_id - ) + true = :ets.insert(:players, {state.client_id, game_id}) - true = :ets.insert(:players, {state.client_id, game_id}) + Process.send(pid, :send_action, []) - Process.send(pid, :send_action, []) + _ -> + :nothing + end {:ok, state} end # Private - defp ws_url(player_id) do + defp ws_url(player_id, user_token) do character = get_random_active_character() player_name = "Player_#{player_id}" + query_params = "gateway_jwt=#{user_token}" case System.get_env("TARGET_SERVER") do nil -> - "ws://localhost:4000/join/#{player_id}/#{character}/#{player_name}" + "ws://localhost:4000/join/#{player_id}/#{character}/#{player_name}?#{query_params}" target_server -> # TODO Replace this for a SSL connection using erlang credentials. # TODO https://github.com/lambdaclass/mirra_backend/issues/493 - "ws://#{Utils.get_server_ip(target_server)}:4000/join/#{player_id}/#{character}/#{player_name}" + "ws://#{Utils.get_server_ip(target_server)}:4000/join/#{player_id}/#{character}/#{player_name}?#{query_params}" end end @@ -75,4 +78,16 @@ defmodule ArenaLoadTest.SocketHandler do ["muflus", "h4ck", "uma"] |> Enum.random() end + + defp create_user(client_id) do + gateway_url = Application.get_env(:arena_load_test, :gateway_url) + payload = Jason.encode!(%{client_id: to_string(client_id)}) + + {:ok, %{status: 200, body: body}} = + Finch.build(:post, "#{gateway_url}/curse/users", [{"content-type", "application/json"}], payload) + |> Finch.request(ArenaLoadTest.Finch) + + Jason.decode!(body) + |> Map.get("gateway_jwt") + end end diff --git a/apps/arena_load_test/lib/arena_load_test/socket_supervisor.ex b/apps/arena_load_test/lib/arena_load_test/socket_supervisor.ex index 4698df67a..155ba4137 100644 --- a/apps/arena_load_test/lib/arena_load_test/socket_supervisor.ex +++ b/apps/arena_load_test/lib/arena_load_test/socket_supervisor.ex @@ -34,10 +34,10 @@ defmodule ArenaLoadTest.SocketSupervisor do @doc """ Initializes a websocket that handles the client connection in-game. """ - def add_new_player(client_id, game_id) do + def add_new_player(client_id, user_token, game_id) do DynamicSupervisor.start_child( __MODULE__, - {GameSocketHandler, {client_id, game_id}} + {GameSocketHandler, {client_id, user_token, game_id}} ) end diff --git a/apps/arena_load_test/lib/arena_load_test/token_fetcher.ex b/apps/arena_load_test/lib/arena_load_test/token_fetcher.ex deleted file mode 100644 index e68eefd9c..000000000 --- a/apps/arena_load_test/lib/arena_load_test/token_fetcher.ex +++ /dev/null @@ -1,47 +0,0 @@ -defmodule ArenaLoadTest.TokenFetcher do - @moduledoc """ - GenServer that calls gateway to create and refresh a JWT token used by the bots - """ - use GenServer - - def get_auth() do - GenServer.call(__MODULE__, :get_auth) - end - - def start_link(_args) do - GenServer.start_link(__MODULE__, [], name: __MODULE__) - end - - @impl true - def init(_) do - Process.send_after(self(), :fetch_token, 500) - {:ok, %{}} - end - - @impl true - def handle_call(:get_auth, _, state) do - {:reply, state, state} - end - - @impl true - def handle_info(:fetch_token, state) do - gateway_url = Application.get_env(:arena_load_test, :gateway_url) - secret = :crypto.strong_rand_bytes(32) |> Base.url_encode64 - payload = Jason.encode!(%{"bot_secret" => secret}) - - result = - Finch.build(:post, "#{gateway_url}/auth/generate-bot-token", [{"content-type", "application/json"}], payload) - |> Finch.request(ArenaLoadTest.Finch) - - case result do - {:ok, %Finch.Response{status: 200, body: body}} -> - Process.send_after(self(), :fetch_token, 1_800_000) - %{"token" => token} = Jason.decode!(body) - {:noreply, %{token: token, secret: secret}} - - _else_error -> - Process.send_after(self(), :fetch_token, 5_000) - {:noreply, state} - end - end -end