-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from Nickforall/chore/tests
Add tests
- Loading branch information
Showing
13 changed files
with
353 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Based upon https://github.com/absinthe-graphql/absinthe/blob/master/.github/workflows/elixir.yml | ||
# Copyright (c) Bruce Williams, Ben Wilson | ||
|
||
name: CI | ||
|
||
on: | ||
push: | ||
pull_request: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
test: | ||
name: Elixir ${{matrix.elixir}} / OTP ${{matrix.otp}} | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
elixir: | ||
- "1.10" | ||
- "1.11" | ||
otp: | ||
- "22" | ||
- "23" | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
|
||
- name: Set up Elixir | ||
uses: erlef/setup-elixir@v1 | ||
with: | ||
elixir-version: ${{ matrix.elixir }} | ||
otp-version: ${{ matrix.otp }} | ||
|
||
- name: Restore deps cache | ||
uses: actions/cache@v2 | ||
with: | ||
path: | | ||
deps | ||
_build | ||
key: deps-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}-${{ github.sha }} | ||
restore-keys: | | ||
deps-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }} | ||
deps-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }} | ||
- name: Install package dependencies | ||
run: mix deps.get | ||
|
||
- name: Check Formatting | ||
run: mix format --check-formatted | ||
|
||
- name: Run unit tests | ||
run: | | ||
mix clean | ||
mix test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
defmodule ExFirebaseAuth.KeySource do | ||
@moduledoc false | ||
|
||
@callback fetch_certificates() :: :error | {:ok, list(JOSE.JWK.t())} | ||
|
||
def fetch_certificates do | ||
apply( | ||
Application.get_env(:ex_firebase_auth, :key_source, ExFirebaseAuth.KeySource.Google), | ||
:fetch_certificates, | ||
[] | ||
) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,46 +5,46 @@ defmodule ExFirebaseAuth.KeyStore do | |
|
||
require Logger | ||
|
||
@endpoint_url "https://www.googleapis.com/robot/v1/metadata/x509/[email protected]" | ||
|
||
def start_link(_) do | ||
GenServer.start_link(__MODULE__, %{}, name: ExFirebaseAuth.KeyStore) | ||
end | ||
|
||
def init(_) do | ||
find_or_create_ets_table() | ||
|
||
case fetch_certificates() do | ||
case ExFirebaseAuth.KeySource.fetch_certificates() do | ||
# when we could not fetch certs initially the application cannot run because all Auth will fail | ||
:error -> | ||
{:stop, "Initial certificate fetch failed"} | ||
|
||
{:ok, data} -> | ||
store_data_to_ets(data) | ||
schedule_refresh(1) | ||
|
||
Logger.debug("Fetched initial firebase auth certificates.") | ||
|
||
schedule_refresh() | ||
|
||
{:ok, %{}} | ||
end | ||
end | ||
|
||
# When the refresh `info` is sent, we want to fetch the certificates | ||
def handle_info(:refresh, state) do | ||
case fetch_certificates() do | ||
case ExFirebaseAuth.KeySource.fetch_certificates() do | ||
# keep trying with a lower interval, until then keep the old state | ||
:error -> | ||
Logger.warn("Fetching firebase auth certificates failed, using old state and retrying...") | ||
schedule_refresh(10) | ||
|
||
{:noreply, state} | ||
|
||
# if everything went okay, refresh at the regular interval and store the returned keys in state | ||
{:ok, jsondata} -> | ||
{:ok, keys} -> | ||
store_data_to_ets(keys) | ||
|
||
Logger.debug("Fetched new firebase auth certificates.") | ||
store_data_to_ets(jsondata) | ||
schedule_refresh() | ||
|
||
{:noreply, state} | ||
end | ||
|
||
{:noreply, state} | ||
end | ||
|
||
def find_or_create_ets_table do | ||
|
@@ -54,15 +54,8 @@ defmodule ExFirebaseAuth.KeyStore do | |
end | ||
end | ||
|
||
defp store_data_to_ets(jsondata) do | ||
jsondata | ||
|> Enum.map(fn {key, value} -> | ||
case JOSE.JWK.from_pem(value) do | ||
[] -> {key, nil} | ||
jwk -> {key, jwk} | ||
end | ||
end) | ||
|> Enum.filter(fn {_, value} -> not is_nil(value) end) | ||
defp store_data_to_ets(data) do | ||
data | ||
|> Enum.each(fn {key, value} -> | ||
:ets.insert(ExFirebaseAuth.KeyStore, {key, value}) | ||
end) | ||
|
@@ -71,16 +64,4 @@ defmodule ExFirebaseAuth.KeyStore do | |
defp schedule_refresh(after_s \\ 300) do | ||
Process.send_after(self(), :refresh, after_s * 1000) | ||
end | ||
|
||
# Fetch certificates from google's endpoint | ||
defp fetch_certificates do | ||
with {:ok, %Finch.Response{body: body}} <- | ||
Finch.build(:get, @endpoint_url) |> Finch.request(ExFirebaseAuthFinch), | ||
{:ok, jsondata} <- Jason.decode(body) do | ||
{:ok, jsondata} | ||
else | ||
_ -> | ||
:error | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
defmodule ExFirebaseAuth.KeySource.Google do | ||
@moduledoc false | ||
|
||
@endpoint_url "https://www.googleapis.com/robot/v1/metadata/x509/[email protected]" | ||
|
||
@behaviour ExFirebaseAuth.KeySource | ||
|
||
def fetch_certificates do | ||
with {:ok, %Finch.Response{body: body}} <- | ||
Finch.build(:get, @endpoint_url) |> Finch.request(ExFirebaseAuthFinch), | ||
{:ok, json_data} <- Jason.decode(body) do | ||
{:ok, convert_to_jose_keys(json_data)} | ||
else | ||
_ -> | ||
:error | ||
end | ||
end | ||
|
||
defp convert_to_jose_keys(json_data) do | ||
json_data | ||
|> Enum.map(fn {key, value} -> | ||
case JOSE.JWK.from_pem(value) do | ||
[] -> {key, nil} | ||
jwk -> {key, jwk} | ||
end | ||
end) | ||
|> Enum.filter(fn {_, value} -> not is_nil(value) end) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
defmodule ExFirebaseAuth.KeySource.Mock do | ||
@moduledoc false | ||
|
||
@behaviour ExFirebaseAuth.KeySource | ||
|
||
defp config do | ||
Application.get_env(:ex_firebase_auth, :key_source_mock, keys: []) | ||
end | ||
|
||
def fetch_certificates do | ||
{:ok, config()[:keys]} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
defmodule ExFirebaseAuth.KeyStoreTest do | ||
use ExUnit.Case | ||
|
||
setup do | ||
{kid, public_key, _} = ExFirebaseAuth.Mock.generate_key() | ||
|
||
Application.get_env(:ex_firebase_auth, :key_source, ExFirebaseAuth.KeySource.Mock) | ||
|
||
Application.put_env(:ex_firebase_auth, :key_source_mock, | ||
keys: [ | ||
{kid, public_key} | ||
] | ||
) | ||
|
||
%{kid: kid, key: public_key} | ||
end | ||
|
||
test "Does add new key to ets on refresh", %{kid: kid, key: public_key} do | ||
assert :ets.lookup(ExFirebaseAuth.KeyStore, kid) == [] | ||
|
||
Process.send(ExFirebaseAuth.KeyStore, :refresh, []) | ||
|
||
# TODO: there's probably a better way to test this behavior | ||
Process.sleep(100) | ||
|
||
assert :ets.lookup(ExFirebaseAuth.KeyStore, kid) == [{kid, public_key}] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
defmodule ExFirebaseAuth.MockTest do | ||
use ExUnit.Case | ||
|
||
alias ExFirebaseAuth.Mock | ||
|
||
setup do | ||
on_exit(fn -> | ||
:ok = Application.delete_env(:ex_firebase_auth, :mock) | ||
end) | ||
end | ||
|
||
describe "Token.generate_and_store_key_pair/0" do | ||
test "Fails when mock is disabled" do | ||
assert_raise( | ||
RuntimeError, | ||
~r/^Cannot generate mocked token, because ExFirebaseAuth.Mock is not enabled in your config./, | ||
fn -> | ||
Mock.generate_and_store_key_pair() | ||
end | ||
) | ||
end | ||
|
||
test "Creates ETS table and stores key" do | ||
Application.put_env(:ex_firebase_auth, :mock, enabled: true) | ||
|
||
assert :ets.whereis(ExFirebaseAuth.Mock) == :undefined | ||
Mock.generate_and_store_key_pair() | ||
|
||
[{_, %JOSE.JWK{} = _}] = :ets.lookup(ExFirebaseAuth.Mock, :ets.first(ExFirebaseAuth.Mock)) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
Application.put_env(:ex_firebase_auth, :key_source, ExFirebaseAuth.KeySource.Mock) | ||
|
||
ExUnit.start() |
Oops, something went wrong.