Skip to content

Commit

Permalink
Merge branch 'main' into movement-depending-on-time-instead-of-ticks
Browse files Browse the repository at this point in the history
  • Loading branch information
manucamejo committed Jun 17, 2024
2 parents 91cd75e + 1605aa4 commit c3f003b
Show file tree
Hide file tree
Showing 48 changed files with 938 additions and 225 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/central-brazil-testing-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
BOT_MANAGER_PORT: ${{ vars.BOT_MANAGER_PORT }}
BOT_MANAGER_HOST: ${{ vars.LOADTEST_CLIENT_HOST }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_PRIVATE_KEY_BASE_64: ${{ secrets.JWT_PRIVATE_KEY_BASE_64 }}
SECRET_KEY_BASE: ${{ secrets.SECRET_KEY_BASE }}
NEWRELIC_APP_NAME: ${{ vars.NEWRELIC_APP_NAME }}
NEWRELIC_KEY: ${{ secrets.NEWRELIC_KEY }}
Expand All @@ -68,6 +69,7 @@ jobs:
BOT_MANAGER_HOST=${BOT_MANAGER_HOST} \
DATABASE_URL=${DATABASE_URL} \
SECRET_KEY_BASE=${SECRET_KEY_BASE} \
JWT_PRIVATE_KEY_BASE_64=${JWT_PRIVATE_KEY_BASE_64} \
NEWRELIC_APP_NAME=${NEWRELIC_APP_NAME} \
NEWRELIC_KEY=${NEWRELIC_KEY} \
/home/${SSH_USERNAME}/deploy-script/deploy.sh
2 changes: 2 additions & 0 deletions .github/workflows/central-europe-testing-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
BOT_MANAGER_HOST: ${{ vars.LOADTEST_CLIENT_HOST }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
SECRET_KEY_BASE: ${{ secrets.SECRET_KEY_BASE }}
JWT_PRIVATE_KEY_BASE_64: ${{ secrets.JWT_PRIVATE_KEY_BASE_64 }}
NEWRELIC_APP_NAME: ${{ vars.NEWRELIC_APP_NAME }}
NEWRELIC_KEY: ${{ secrets.NEWRELIC_KEY }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
Expand All @@ -70,6 +71,7 @@ jobs:
BOT_MANAGER_HOST=${BOT_MANAGER_HOST} \
DATABASE_URL=${DATABASE_URL} \
SECRET_KEY_BASE=${SECRET_KEY_BASE} \
JWT_PRIVATE_KEY_BASE_64=${JWT_PRIVATE_KEY_BASE_64} \
NEWRELIC_APP_NAME=${NEWRELIC_APP_NAME} \
NEWRELIC_KEY=${NEWRELIC_KEY} \
/home/${SSH_USERNAME}/deploy-script/deploy.sh
1 change: 1 addition & 0 deletions apps/arena/lib/arena/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule Arena.Application do
Arena.GameLauncher,
Arena.GameBountiesFetcher,
Arena.GameTracker,
Arena.Authentication.GatewaySigner,
# Start a worker by calling: Arena.Worker.start_link(arg)
# {Arena.Worker, arg},
# Start to serve requests, typically the last entry
Expand Down
47 changes: 47 additions & 0 deletions apps/arena/lib/arena/authentication/gateway_signer.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
defmodule Arena.Authentication.GatewaySigner do
@moduledoc """
GenServer that calls gateway to fetch public key used for JWT authentication
The public key is converted into a Joken.Signer and cached for internal app usage
"""
use GenServer

def get_signer() do
GenServer.call(__MODULE__, :get_signer)
end

def start_link(_args) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end

@impl true
def init(_) do
Process.send_after(self(), :fetch_signer, 500)
{:ok, %{}}
end

@impl true
def handle_call(:get_signer, _, state) do
{:reply, state.signer, state}
end

@impl true
def handle_info(:fetch_signer, state) do
gateway_url = Application.get_env(:arena, :gateway_url)

result =
Finch.build(:get, "#{gateway_url}/auth/public-key", [{"content-type", "application/json"}])
|> Finch.request(Arena.Finch)

case result do
{:ok, %Finch.Response{status: 200, body: body}} ->
Process.send_after(self(), :fetch_signer, 3_600_000)
%{"jwk" => jwk} = Jason.decode!(body)
signer = Joken.Signer.create("Ed25519", jwk)
{:noreply, Map.put(state, :signer, signer)}

_else_error ->
Process.send_after(self(), :fetch_signer, 5_000)
{:noreply, state}
end
end
end
12 changes: 12 additions & 0 deletions apps/arena/lib/arena/authentication/gateway_token_manager.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule Arena.Authentication.GatewayTokenManager do
@moduledoc """
Module responsible to verify and validate the JWT emitted by gateway app.
"""
use Joken.Config, default_signer: nil

@impl Joken.Config
def token_config do
default_exp = Application.get_env(:joken, :default_exp)
default_claims(default_exp: default_exp)
end
end
16 changes: 15 additions & 1 deletion apps/arena/lib/arena/game_socket_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ defmodule Arena.GameSocketHandler do
Module that handles cowboy websocket requests
"""
require Logger
alias Arena.Authentication.GatewaySigner
alias Arena.Authentication.GatewayTokenManager
alias Arena.Utils
alias Arena.Serialization
alias Arena.GameUpdater
Expand All @@ -14,7 +16,19 @@ defmodule Arena.GameSocketHandler do

@impl true
def init(req, _opts) do
client_id = :cowboy_req.binding(:client_id, req)
## TODO: The only reason we need this is because bots are broken, we should fix bots in a way that
## we don't need to pass a real user_id (or none at all). Ideally we could have JWT that says "Bot Sever".
client_id =
case :cowboy_req.parse_qs(req) do
[{"gateway_jwt", jwt}] ->
signer = GatewaySigner.get_signer()
{:ok, %{"sub" => user_id}} = GatewayTokenManager.verify_and_validate(jwt, signer)
user_id

_ ->
:cowboy_req.binding(:client_id, req)
end

game_id = :cowboy_req.binding(:game_id, req)
game_pid = game_id |> Base58.decode() |> :erlang.binary_to_term([:safe])

Expand Down
8 changes: 6 additions & 2 deletions apps/arena/lib/arena/quick_game_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule Arena.QuickGameHandler do
@moduledoc """
Module that handles cowboy websocket requests
"""
alias Arena.Authentication.GatewayTokenManager
alias Arena.Authentication.GatewaySigner
alias Arena.GameLauncher
alias Arena.Serialization.GameState
alias Arena.Serialization.JoinedLobby
Expand All @@ -11,10 +13,12 @@ defmodule Arena.QuickGameHandler do

@impl true
def init(req, _opts) do
client_id = :cowboy_req.binding(:client_id, req)
[{"gateway_jwt", jwt}] = :cowboy_req.parse_qs(req)
signer = GatewaySigner.get_signer()
{:ok, %{"sub" => user_id}} = GatewayTokenManager.verify_and_validate(jwt, signer)
character_name = :cowboy_req.binding(:character_name, req)
player_name = :cowboy_req.binding(:player_name, req)
{:cowboy_websocket, req, %{client_id: client_id, character_name: character_name, player_name: player_name}}
{:cowboy_websocket, req, %{client_id: user_id, character_name: character_name, player_name: player_name}}
end

@impl true
Expand Down
8 changes: 6 additions & 2 deletions apps/arena/lib/arena/socket_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ defmodule Arena.SocketHandler do
Module that handles cowboy websocket requests
"""
require Logger
alias Arena.Authentication.GatewaySigner
alias Arena.Authentication.GatewayTokenManager
alias Arena.GameLauncher
alias Arena.Serialization.GameState
alias Arena.Serialization.JoinedLobby
Expand All @@ -14,10 +16,12 @@ defmodule Arena.SocketHandler do

@impl true
def init(req, _opts) do
client_id = :cowboy_req.binding(:client_id, req)
[{"gateway_jwt", jwt}] = :cowboy_req.parse_qs(req)
signer = GatewaySigner.get_signer()
{:ok, %{"sub" => user_id}} = GatewayTokenManager.verify_and_validate(jwt, signer)
character_name = :cowboy_req.binding(:character_name, req)
player_name = :cowboy_req.binding(:player_name, req)
{:cowboy_websocket, req, %{client_id: client_id, character_name: character_name, player_name: player_name}}
{:cowboy_websocket, req, %{client_id: user_id, character_name: character_name, player_name: player_name}}
end

@impl true
Expand Down
3 changes: 2 additions & 1 deletion apps/arena/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ defmodule Arena.MixProject do
{:exbase58, "~> 1.0.2"},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:plug_cowboy, "~> 2.5"},
{:toxiproxy_ex, "~> 1.1.1"}
{:toxiproxy_ex, "~> 1.1.1"},
{:joken, "~> 2.6"}
]
end

Expand Down
Loading

0 comments on commit c3f003b

Please sign in to comment.