Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatting #141

Merged
merged 1 commit into from
Nov 19, 2023
Merged
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
12 changes: 12 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Used by "mix format" and to export configuration.
export_locals_without_parens = [
plug: 1,
plug: 2,
get: 2
]

[
inputs: ["{mix,.formatter}.exs", "{integration,lib,test}/**/*.{ex,exs}"],
locals_without_parens: export_locals_without_parens,
export: [locals_without_parens: export_locals_without_parens]
]
17 changes: 16 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ on:
workflow_call:

jobs:
lint:
runs-on: ubuntu-latest
name: Linter
env:
MIX_ENV: test
steps:
- uses: actions/checkout@v3
- uses: erlef/setup-beam@v1
with:
otp-version: 26.0
elixir-version: 1.15
- run: mix deps.get
- run: mix compile --warnings-as-errors
- run: mix credo --strict --ignore design.tagtodo
- run: mix format --check-formatted

test:
strategy:
matrix:
Expand All @@ -32,4 +48,3 @@ jobs:
- run: mix deps.get
- run: mix compile --warnings-as-errors
- run: mix test
- run: mix credo --ignore design.tagtodo
23 changes: 12 additions & 11 deletions integration/server.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ defmodule IntegrationServer.Router do
{:ok, modules} = :application.get_key(:assent, :modules)

@path_modules modules
|> Enum.map(&{Module.split(&1), &1})
|> Enum.map(fn
{["Assent", "Strategy", uri], module} -> {uri, module}
_any -> nil
end)
|> Enum.reject(&is_nil/1)
|> Enum.into(%{})

defp secret_key_base(conn, _opts),
do: %{conn | secret_key_base: "LG8WiSkAlUlwVJpISmRYsi7aJV/Qlv65FXyxwWXxp1QUzQY3hzEfg73YKfKZPpe0"}
|> Enum.map(&{Module.split(&1), &1})
|> Enum.map(fn
{["Assent", "Strategy", uri], module} -> {uri, module}
_any -> nil
end)
|> Enum.reject(&is_nil/1)
|> Enum.into(%{})

defp secret_key_base(conn, _opts) do
%{conn | secret_key_base: "LG8WiSkAlUlwVJpISmRYsi7aJV/Qlv65FXyxwWXxp1QUzQY3hzEfg73YKfKZPpe0"}
end

get "/" do
list =
Expand All @@ -50,7 +51,7 @@ defmodule IntegrationServer.Router do

{:ok, %{url: url, session_params: session_params}} = module.authorize_url(config!(provider))

Logger.info("Redirecting to #{inspect url} with session params #{inspect session_params}")
Logger.info("Redirecting to #{inspect(url)} with session params #{inspect(session_params)}")

html = Plug.HTML.html_escape(url)
body = "<html><body>You are being <a href=\"#{html}\">redirected</a>.</body></html>"
Expand Down
10 changes: 5 additions & 5 deletions lib/assent.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ defmodule Assent do
defexception [:key]

def message(exception) do
"CSRF detected with param key #{inspect exception.key}"
"CSRF detected with param key #{inspect(exception.key)}"
end
end

defmodule MissingParamError do
defexception [:expected_key, :params]

def message(exception) do
expected_key = inspect exception.expected_key
params = inspect Map.keys(exception.params)
expected_key = inspect(exception.expected_key)
params = inspect(Map.keys(exception.params))

"Expected #{expected_key} in params, got: #{params}"
end
Expand Down Expand Up @@ -75,11 +75,11 @@ defmodule Assent do
"""
The server was unreachable.

HTTP Adapter: #{inspect exception.http_adapter}
HTTP Adapter: #{inspect(exception.http_adapter)}
Request URL: #{url}

Reason:
#{inspect exception.reason}
#{inspect(exception.reason)}
"""
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/assent/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Assent.Config do
defexception [:key]

def message(exception) do
"Key #{inspect exception.key} not found in config"
"Key #{inspect(exception.key)} not found in config"
end
end

Expand All @@ -22,7 +22,7 @@ defmodule Assent.Config do
def fetch(config, key) do
case Keyword.fetch(config, key) do
{:ok, value} -> {:ok, value}
:error -> {:error, MissingKeyError.exception(key: key)}
:error -> {:error, MissingKeyError.exception(key: key)}
end
end

Expand Down
21 changes: 11 additions & 10 deletions lib/assent/http_adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ defmodule Assent.HTTPAdapter do
"""

@type header :: {binary(), binary()}
@type t :: %__MODULE__{
http_adapter: atom(),
request_url: binary(),
status: integer(),
headers: [header()],
body: binary() | term()
}
@type t :: %__MODULE__{
http_adapter: atom(),
request_url: binary(),
status: integer(),
headers: [header()],
body: binary() | term()
}

defstruct http_adapter: nil, request_url: nil, status: 200, headers: [], body: ""

def format(response) do
[request_url | _rest] = String.split(response.request_url, "?", parts: 2)

"""
HTTP Adapter: #{inspect response.http_adapter}
HTTP Adapter: #{inspect(response.http_adapter)}
Request URL: #{request_url}

Response status: #{response.status}
Expand All @@ -56,7 +56,7 @@ defmodule Assent.HTTPAdapter do
#{Enum.reduce(response.headers, "", fn {k, v}, acc -> acc <> "\n#{k}: #{v}" end)}

Response body:
#{inspect response.body}
#{inspect(response.body)}
"""
end
end
Expand All @@ -65,7 +65,8 @@ defmodule Assent.HTTPAdapter do
@type body :: binary() | nil
@type headers :: [{binary(), binary()}]

@callback request(method(), binary(), body(), headers(), Keyword.t()) :: {:ok, map()} | {:error, any()}
@callback request(method(), binary(), body(), headers(), Keyword.t()) ::
{:ok, map()} | {:error, any()}

@doc """
Sets a user agent header
Expand Down
59 changes: 35 additions & 24 deletions lib/assent/http_adapter/finch.ex
Original file line number Diff line number Diff line change
@@ -1,35 +1,46 @@
if Code.ensure_loaded?(Finch) do
defmodule Assent.HTTPAdapter.Finch do
@moduledoc """
HTTP adapter module for making http requests with Finch.
defmodule Assent.HTTPAdapter.Finch do
@moduledoc """
HTTP adapter module for making http requests with Finch.

The Finch adapter must be configured with the supervisor by passing it as an
option:
The Finch adapter must be configured with the supervisor by passing it as an
option:

http_adapter: {Assent.HTTPAdapter.Finch, [supervisor: MyFinch]}
http_adapter: {Assent.HTTPAdapter.Finch, [supervisor: MyFinch]}

See `Assent.HTTPAdapter` for more.
"""
alias Assent.{HTTPAdapter, HTTPAdapter.HTTPResponse}
See `Assent.HTTPAdapter` for more.
"""
alias Assent.{HTTPAdapter, HTTPAdapter.HTTPResponse}

@behaviour HTTPAdapter
@behaviour HTTPAdapter

@impl HTTPAdapter
def request(method, url, body, headers, finch_opts \\ nil) do
headers = headers ++ [HTTPAdapter.user_agent_header()]
opts = finch_opts || []
@impl HTTPAdapter
def request(method, url, body, headers, finch_opts \\ nil) do
headers = headers ++ [HTTPAdapter.user_agent_header()]
opts = finch_opts || []

supervisor = Keyword.get(opts, :supervisor) || raise "Missing `:supervisor` option for the #{inspect __MODULE__} configuration"
build_opts = Keyword.get(opts, :build, [])
request_opts = Keyword.get(opts, :request, [])
supervisor =
Keyword.get(opts, :supervisor) ||
raise "Missing `:supervisor` option for the #{inspect(__MODULE__)} configuration"

method
|> Finch.build(url, headers, body, build_opts)
|> Finch.request(supervisor, request_opts)
|> case do
{:ok, response} -> {:ok, %HTTPResponse{status: response.status, headers: response.headers, body: response.body}}
{:error, error} -> {:error, error}
build_opts = Keyword.get(opts, :build, [])
request_opts = Keyword.get(opts, :request, [])

method
|> Finch.build(url, headers, body, build_opts)
|> Finch.request(supervisor, request_opts)
|> case do
{:ok, response} ->
{:ok,
%HTTPResponse{
status: response.status,
headers: response.headers,
body: response.body
}}

{:error, error} ->
{:error, error}
end
end
end
end
end
56 changes: 37 additions & 19 deletions lib/assent/http_adapter/httpc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ defmodule Assent.HTTPAdapter.Httpc do

headers = headers ++ [HTTPAdapter.user_agent_header()]
request = httpc_request(url, body, headers)
opts = parse_httpc_ssl_opts(httpc_opts, url)
opts = parse_httpc_ssl_opts(httpc_opts, url)

method
|> :httpc.request(request, opts, [])
|> format_response()
end

defp raise_on_missing_httpc! do
Code.ensure_loaded?(:httpc) || raise """
#{inspect __MODULE__} requires `:httpc` to be included in your
Code.ensure_loaded?(:httpc) ||
raise """
#{inspect(__MODULE__)} requires `:httpc` to be included in your
application.

Please add `:inets` to `:extra_applications`:
Expand All @@ -51,38 +52,45 @@ defmodule Assent.HTTPAdapter.Httpc do
end

defp httpc_request(url, body, headers) do
url = to_charlist(url)
headers = Enum.map(headers, fn {k, v} -> {to_charlist(k), to_charlist(v)} end)
url = to_charlist(url)
headers = Enum.map(headers, fn {k, v} -> {to_charlist(k), to_charlist(v)} end)

do_httpc_request(url, body, headers)
end

defp do_httpc_request(url, nil, headers) do
{url, headers}
end

defp do_httpc_request(url, body, headers) do
{content_type, headers} = split_content_type_headers(headers)
body = to_charlist(body)
body = to_charlist(body)

{url, headers, content_type, body}
end

defp split_content_type_headers(headers) do
case List.keytake(headers, 'content-type', 0) do
nil -> {'text/plain', headers}
case List.keytake(headers, ~c"content-type", 0) do
nil -> {~c"text/plain", headers}
{{_, ct}, headers} -> {ct, headers}
end
end

defp format_response({:ok, {{_, status, _}, headers, body}}) do
headers = Enum.map(headers, fn {key, value} -> {String.downcase(to_string(key)), to_string(value)} end)
body = IO.iodata_to_binary(body)
headers =
Enum.map(headers, fn {key, value} ->
{String.downcase(to_string(key)), to_string(value)}
end)

body = IO.iodata_to_binary(body)

{:ok, %HTTPResponse{status: status, headers: headers, body: body}}
end

defp format_response({:error, error}), do: {:error, error}

defp parse_httpc_ssl_opts(nil, url), do: parse_httpc_ssl_opts([], url)

defp parse_httpc_ssl_opts(opts, url) do
uri = URI.parse(url)

Expand Down Expand Up @@ -113,21 +121,30 @@ defmodule Assent.HTTPAdapter.Httpc do
# OTP >= 22
hostname_match_check =
try do
[customize_hostname_check: [match_fun: :public_key.pkix_verify_hostname_match_fun(:https)]]
[
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
rescue
_e in UndefinedFunctionError -> []
end

Keyword.merge([
verify: :verify_peer,
depth: 99,
verify_fun: {&:ssl_verify_hostname.verify_fun/3, check_hostname: to_charlist(uri.host)}
] ++ hostname_match_check, ssl_opts)
end
Keyword.merge(
[
verify: :verify_peer,
depth: 99,
verify_fun:
{&:ssl_verify_hostname.verify_fun/3, check_hostname: to_charlist(uri.host)}
] ++ hostname_match_check,
ssl_opts
)
end
end

defp raise_on_missing_ssl_verify_fun! do
Code.ensure_loaded?(:ssl_verify_hostname) || raise """
Code.ensure_loaded?(:ssl_verify_hostname) ||
raise """
This request can NOT be verified for valid SSL certificate.

Please add `:ssl_verify_fun` to your projects dependencies:
Expand Down Expand Up @@ -158,7 +175,8 @@ defmodule Assent.HTTPAdapter.Httpc do
end

defp raise_on_missing_certifi! do
Code.ensure_loaded?(:certifi) || raise """
Code.ensure_loaded?(:certifi) ||
raise """
This request requires a CA trust store.

Please add `:certifi` to your projects dependencies:
Expand Down
Loading
Loading