diff --git a/.gitignore b/.gitignore
index d186e5b..07c8651 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,5 +32,6 @@ npm-debug.log
# we ignore priv/static. You may want to comment
# this depending on your deployment strategy.
/priv/static/
+/priv/cert/
dev.secret.exs
\ No newline at end of file
diff --git a/README.md b/README.md
index 5af4e0c..b99d5ef 100644
--- a/README.md
+++ b/README.md
@@ -5,16 +5,29 @@ To start your Phoenix server:
* Install dependencies with `mix deps.get`
* Create and migrate your database with `mix ecto.setup`
* Install Node.js dependencies with `npm install` inside the `assets` directory
+ * Run `mix phx.gen.cert` to use HTTPS during development, required for OAuth
* Start Phoenix endpoint with `mix phx.server`
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
-## Learn more
+## Setting up OAuth
- * Official website: https://www.phoenixframework.org/
- * Guides: https://hexdocs.pm/phoenix/overview.html
- * Docs: https://hexdocs.pm/phoenix
- * Forum: https://elixirforum.com/c/phoenix-forum
- * Source: https://github.com/phoenixframework/phoenix
+Add the OAuth providers you'll be using to the providers array.
+
+```
+use Mix.Config
+config :ueberauth, Ueberauth,
+ providers: [
+ github: {Ueberauth.Strategy.Github, []}
+ ]
+```
+
+You'll need to visit each provider's site and set up OAuth. This usually entails creating an OAuth App to generate a client_id, and generating a client_secret. Then create a `dev.secret.exs` file in your config folder and add your client_id & secret to your provider's ueberauth config.
+
+```
+config :ueberauth, Ueberauth.Strategy.Github.OAuth,
+ client_id: "some_client_id",
+ client_secret: "some_secret_key"
+```
diff --git a/config/config.exs b/config/config.exs
index c69b935..dc21086 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -26,6 +26,11 @@ config :logger, :console,
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
+config :ueberauth, Ueberauth,
+ providers: [
+ github: {Ueberauth.Strategy.Github, [default_scope: "user:email", allow_private_emails: true]}
+ ]
+
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
diff --git a/config/dev.exs b/config/dev.exs
index 32f7656..82dcb83 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -17,6 +17,12 @@ config :entendu, Entendu.Repo,
# with webpack to recompile .js and .css sources.
config :entendu, EntenduWeb.Endpoint,
http: [port: System.get_env("PORT", "4000")],
+ https: [
+ port: 4001,
+ cipher_suite: :strong,
+ certfile: "priv/cert/selfsigned.pem",
+ keyfile: "priv/cert/selfsigned_key.pem"
+ ],
debug_errors: true,
code_reloader: true,
check_origin: false,
diff --git a/lib/entendu/application.ex b/lib/entendu/application.ex
index 6236043..0f4c3fc 100644
--- a/lib/entendu/application.ex
+++ b/lib/entendu/application.ex
@@ -6,12 +6,6 @@ defmodule Entendu.Application do
use Application
def start(_type, _args) do
- # topologies = [
- # chat: [
- # strategy: Cluster.Strategy.Gossip
- # ]
- # ]
-
topologies = [
k8s_entendu: [
strategy: Elixir.Cluster.Strategy.Kubernetes.DNS,
diff --git a/lib/entendu/user_from_auth.ex b/lib/entendu/user_from_auth.ex
index e69de29..ac67147 100644
--- a/lib/entendu/user_from_auth.ex
+++ b/lib/entendu/user_from_auth.ex
@@ -0,0 +1,47 @@
+defmodule Entendu.UserFromAuth do
+ @moduledoc """
+ Retrieve the user information from an auth request
+ """
+ require Logger
+ require Jason
+
+ alias Ueberauth.Auth
+
+ def find_or_create(%Auth{} = auth) do
+ {:ok, basic_info(auth)}
+ end
+
+ # github does it this way
+ defp avatar_from_auth(%{info: %{urls: %{avatar_url: image}}}), do: image
+
+ # facebook does it this way
+ defp avatar_from_auth(%{info: %{image: image}}), do: image
+
+ # default case if nothing matches
+ defp avatar_from_auth(auth) do
+ Logger.warn("#{auth.provider} needs to find an avatar URL!")
+ Logger.debug(Jason.encode!(auth))
+ nil
+ end
+
+ defp basic_info(auth) do
+ IO.inspect(auth)
+ %{id: auth.uid, name: name_from_auth(auth), avatar: avatar_from_auth(auth)}
+ end
+
+ defp name_from_auth(auth) do
+ if auth.info.name do
+ auth.info.name
+ else
+ name =
+ [auth.info.first_name, auth.info.last_name]
+ |> Enum.filter(&(&1 != nil and &1 != ""))
+
+ if Enum.empty?(name) do
+ auth.info.nickname
+ else
+ Enum.join(name, " ")
+ end
+ end
+ end
+end
diff --git a/lib/entendu_web/controllers/auth_controller.ex b/lib/entendu_web/controllers/auth_controller.ex
new file mode 100644
index 0000000..a92017b
--- /dev/null
+++ b/lib/entendu_web/controllers/auth_controller.ex
@@ -0,0 +1,41 @@
+defmodule EntenduWeb.AuthController do
+ @moduledoc """
+ Auth controller responsible for handling Ueberauth responses
+ """
+
+ use EntenduWeb, :controller
+
+ plug Ueberauth
+
+ alias Ueberauth.Strategy.Helpers
+ alias Entendu.UserFromAuth
+
+ def delete(conn, _params) do
+ conn
+ |> put_flash(:info, "You have been logged out!")
+ |> clear_session()
+ |> redirect(to: "/")
+ end
+
+ def callback(%{assigns: %{ueberauth_failure: _fails}} = conn, _params) do
+ conn
+ |> put_flash(:error, "Failed to authenticate.")
+ |> redirect(to: "/")
+ end
+
+ def callback(%{assigns: %{ueberauth_auth: auth}} = conn, _params) do
+ case UserFromAuth.find_or_create(auth) do
+ {:ok, user} ->
+ conn
+ |> put_flash(:info, "Successfully authenticated.")
+ |> put_session(:current_user, user)
+ |> configure_session(renew: true)
+ |> redirect(to: "/")
+
+ {:error, reason} ->
+ conn
+ |> put_flash(:error, reason)
+ |> redirect(to: "/")
+ end
+ end
+end
diff --git a/lib/entendu_web/controllers/link_controller.ex b/lib/entendu_web/controllers/link_controller.ex
new file mode 100644
index 0000000..7803b49
--- /dev/null
+++ b/lib/entendu_web/controllers/link_controller.ex
@@ -0,0 +1,11 @@
+defmodule EntenduWeb.LinkController do
+ @moduledoc """
+ Controller responsible for managing links responses
+ """
+
+ use EntenduWeb, :controller
+
+ def just(conn, _params) do
+ render(conn, "just.html")
+ end
+end
diff --git a/lib/entendu_web/controllers/page_controller.ex b/lib/entendu_web/controllers/page_controller.ex
new file mode 100644
index 0000000..796e15d
--- /dev/null
+++ b/lib/entendu_web/controllers/page_controller.ex
@@ -0,0 +1,11 @@
+defmodule EntenduWeb.PageController do
+ @moduledoc """
+ Static page controller
+ """
+
+ use EntenduWeb, :controller
+
+ def index(conn, _params) do
+ render(conn, "index.html", current_user: get_session(conn, :current_user))
+ end
+end
diff --git a/lib/entendu_web/live/link_live/for.ex b/lib/entendu_web/live/link_live/for.ex
deleted file mode 100644
index 8ab29b3..0000000
--- a/lib/entendu_web/live/link_live/for.ex
+++ /dev/null
@@ -1,13 +0,0 @@
-defmodule EntenduWeb.LinkLive.For do
- use EntenduWeb, :live_view
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok, socket |> assign(:step, 1)}
- end
-
- def handle_event("next_step", _, %{ assigns: %{ step: step } } = socket) do
- socket = socket |> assign(:step, step + 1)
- {:noreply, socket}
- end
-end
diff --git a/lib/entendu_web/live/link_live/for.html.leex b/lib/entendu_web/live/link_live/for.html.leex
deleted file mode 100644
index 41c7e79..0000000
--- a/lib/entendu_web/live/link_live/for.html.leex
+++ /dev/null
@@ -1,4 +0,0 @@
-
Create Link
-
-<%= live_component @socket, EntenduWeb.LinkLive.For.Step1Component, id: "step1", test: "test" %>
-On Step: <%= @step %>
diff --git a/lib/entendu_web/live/link_live/index.ex b/lib/entendu_web/live/link_live/index.ex
deleted file mode 100644
index 62df978..0000000
--- a/lib/entendu_web/live/link_live/index.ex
+++ /dev/null
@@ -1,46 +0,0 @@
-defmodule EntenduWeb.LinkLive.Index do
- use EntenduWeb, :live_view
-
- alias Entendu.Links
- alias Entendu.Links.Link
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok, assign(socket, :links, list_links())}
- end
-
- @impl true
- def handle_params(params, _url, socket) do
- {:noreply, apply_action(socket, socket.assigns.live_action, params)}
- end
-
- defp apply_action(socket, :edit, %{"id" => id}) do
- socket
- |> assign(:page_title, "Edit Link")
- |> assign(:link, Links.get_link!(id))
- end
-
- defp apply_action(socket, :new, _params) do
- socket
- |> assign(:page_title, "New Link")
- |> assign(:link, %Link{})
- end
-
- defp apply_action(socket, :index, _params) do
- socket
- |> assign(:page_title, "Listing Links")
- |> assign(:link, nil)
- end
-
- @impl true
- def handle_event("delete", %{"id" => id}, socket) do
- link = Links.get_link!(id)
- {:ok, _} = Links.delete_link(link)
-
- {:noreply, assign(socket, :links, list_links())}
- end
-
- defp list_links do
- Links.list_links()
- end
-end
diff --git a/lib/entendu_web/live/link_live/index.html.leex b/lib/entendu_web/live/link_live/index.html.leex
deleted file mode 100644
index 39a842f..0000000
--- a/lib/entendu_web/live/link_live/index.html.leex
+++ /dev/null
@@ -1,37 +0,0 @@
-Listing Links
-
-<%= if @live_action in [:new, :edit] do %>
- <%= live_modal @socket, EntenduWeb.LinkLive.FormComponent,
- id: @link.id || :new,
- title: @page_title,
- action: @live_action,
- link: @link,
- return_to: Routes.link_index_path(@socket, :index) %>
-<% end %>
-
-
-
-
- Expires |
- Burn after reading |
-
- |
-
-
-
- <%= for link <- @links do %>
-
- <%= link.expires %> |
- <%= link.burn_after_reading %> |
-
-
- <%= live_redirect "Show", to: Routes.link_show_path(@socket, :show, link) %>
- <%= live_patch "Edit", to: Routes.link_index_path(@socket, :edit, link) %>
- <%= link "Delete", to: "#", phx_click: "delete", phx_value_id: link.id, data: [confirm: "Are you sure?"] %>
- |
-
- <% end %>
-
-
-
-<%= live_patch "New Link", to: Routes.link_index_path(@socket, :new) %>
diff --git a/lib/entendu_web/live/link_live/steps/step1_component.ex b/lib/entendu_web/live/link_live/steps/step1_component.ex
deleted file mode 100644
index 8bd000f..0000000
--- a/lib/entendu_web/live/link_live/steps/step1_component.ex
+++ /dev/null
@@ -1,4 +0,0 @@
-defmodule EntenduWeb.LinkLive.For.Step1Component do
- use EntenduWeb, :live_component
-
-end
diff --git a/lib/entendu_web/live/link_live/steps/step1_component.html.leex b/lib/entendu_web/live/link_live/steps/step1_component.html.leex
deleted file mode 100644
index 36dc1be..0000000
--- a/lib/entendu_web/live/link_live/steps/step1_component.html.leex
+++ /dev/null
@@ -1,3 +0,0 @@
-This is step 1. <%= @test %>
-
-
diff --git a/lib/entendu_web/live/page_live.ex b/lib/entendu_web/live/page_live.ex
deleted file mode 100644
index 5d7d02d..0000000
--- a/lib/entendu_web/live/page_live.ex
+++ /dev/null
@@ -1,39 +0,0 @@
-defmodule EntenduWeb.PageLive do
- use EntenduWeb, :live_view
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok, assign(socket, query: "", results: %{})}
- end
-
- @impl true
- def handle_event("suggest", %{"q" => query}, socket) do
- {:noreply, assign(socket, results: search(query), query: query)}
- end
-
- @impl true
- def handle_event("search", %{"q" => query}, socket) do
- case search(query) do
- %{^query => vsn} ->
- {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")}
-
- _ ->
- {:noreply,
- socket
- |> put_flash(:error, "No dependencies found matching \"#{query}\"")
- |> assign(results: %{}, query: query)}
- end
- end
-
- defp search(query) do
- if not EntenduWeb.Endpoint.config(:code_reloader) do
- raise "action disabled when not in development"
- end
-
- for {app, desc, vsn} <- Application.started_applications(),
- app = to_string(app),
- String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"),
- into: %{},
- do: {app, vsn}
- end
-end
diff --git a/lib/entendu_web/live/page_live.html.leex b/lib/entendu_web/live/page_live.html.leex
deleted file mode 100644
index ee59e54..0000000
--- a/lib/entendu_web/live/page_live.html.leex
+++ /dev/null
@@ -1,18 +0,0 @@
-
- <%= gettext "Welcome to %{name}!", name: "Phoenix" %>
- Peace of mind from prototype to production
-
-
-
-
-
diff --git a/lib/entendu_web/router.ex b/lib/entendu_web/router.ex
index 8855bcd..db5f4ba 100644
--- a/lib/entendu_web/router.ex
+++ b/lib/entendu_web/router.ex
@@ -17,8 +17,16 @@ defmodule EntenduWeb.Router do
scope "/", EntenduWeb do
pipe_through :browser
- live "/", PageLive, :index
- live "/for", LinkLive.For
+ get "/", PageController, :index
+ get "/just", LinkController, :just
+ end
+
+ scope "/auth", EntenduWeb do
+ pipe_through :browser
+
+ get "/:provider", AuthController, :request
+ get "/:provider/callback", AuthController, :callback
+ delete "/logout", AuthController, :delete
end
# Other scopes may use custom stacks.
diff --git a/lib/entendu_web/templates/link/just.html.eex b/lib/entendu_web/templates/link/just.html.eex
new file mode 100644
index 0000000..0489925
--- /dev/null
+++ b/lib/entendu_web/templates/link/just.html.eex
@@ -0,0 +1,6 @@
+
+ Create a secret!
+ There will be a form here
+ And a file input here
+ Then a next button
+
diff --git a/lib/entendu_web/templates/page/index.html.eex b/lib/entendu_web/templates/page/index.html.eex
new file mode 100644
index 0000000..66d392e
--- /dev/null
+++ b/lib/entendu_web/templates/page/index.html.eex
@@ -0,0 +1,49 @@
+
+ Überauth + Phoenix Example
+
+ This is an application to show an example of how to wire up
+ Überauth with
+ Phoenix.
+
+ <%= if @current_user do %>
+ Welcome, <%= @current_user.name %>!
+
+

+
+ <%= link "Logout", to: Routes.auth_path(@conn, :delete), method: "delete", class: "button" %>
+
+ <% else %>
+
+ <% end %>
+
diff --git a/lib/entendu_web/views/link_view.ex b/lib/entendu_web/views/link_view.ex
new file mode 100644
index 0000000..e0a7af1
--- /dev/null
+++ b/lib/entendu_web/views/link_view.ex
@@ -0,0 +1,3 @@
+defmodule EntenduWeb.LinkView do
+ use EntenduWeb, :view
+end
diff --git a/lib/entendu_web/views/page_view.ex b/lib/entendu_web/views/page_view.ex
new file mode 100644
index 0000000..636bf57
--- /dev/null
+++ b/lib/entendu_web/views/page_view.ex
@@ -0,0 +1,3 @@
+defmodule EntenduWeb.PageView do
+ use EntenduWeb, :view
+end
diff --git a/mix.exs b/mix.exs
index 5696c69..c8d07ef 100644
--- a/mix.exs
+++ b/mix.exs
@@ -48,7 +48,8 @@ defmodule Entendu.MixProject do
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:libcluster, "~> 3.2"},
- {:ueberauth, "~> 0.6.3"}
+ {:ueberauth, "~> 0.7.0"},
+ {:ueberauth_github, "~> 0.8.1"}
]
end
diff --git a/mix.lock b/mix.lock
index ed168fb..4ea7ce5 100644
--- a/mix.lock
+++ b/mix.lock
@@ -1,4 +1,5 @@
%{
+ "certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
@@ -10,10 +11,16 @@
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"floki": {:hex, :floki, "0.31.0", "f05ee8a8e6a3ced4e62beeb2c79a63bc8e12ab98fbaaf6e6a3d9b76b1278e23f", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "b05afa372f5c345a5bf240ac25ea1f0f3d5fcfd7490ac0beeb4a203f9444891e"},
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
+ "hackney": {:hex, :hackney, "1.18.0", "c4443d960bb9fba6d01161d01cd81173089686717d9490e5d3606644c48d121f", [:rebar3], [{:certifi, "~>2.8.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "9afcda620704d720db8c6a3123e9848d09c87586dc1c10479c42627b905b5c5e"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
+ "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"libcluster": {:hex, :libcluster, "3.3.0", "f7d45ff56d88e9fb4c30aee662480cbab69ebc0e7f7da4ad8d01b1e4f7492da8", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ecdcdc88334ec8eb18b10a13a1d5f22a3319a970b5b1e66cfe71c7719a4ab6cc"},
- "mime": {:hex, :mime, "2.0.1", "0de4c81303fe07806ebc2494d5321ce8fb4df106e34dd5f9d787b637ebadc256", [:mix], [], "hexpm", "7a86b920d2aedce5fb6280ac8261ac1a739ae6c1a1ad38f5eadf910063008942"},
+ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
+ "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
+ "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
+ "oauth2": {:hex, :oauth2, "2.0.0", "338382079fe16c514420fa218b0903f8ad2d4bfc0ad0c9f988867dfa246731b0", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "881b8364ac7385f9fddc7949379cbe3f7081da37233a1aa7aab844670a91e7e7"},
+ "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
"phoenix": {:hex, :phoenix, "1.5.10", "3ee7d5c17ff9626d72d374d8fc8909bf00f4323fd15549fbe3abbbd38b5299c8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f9c2eaa5a8fe5a412610c6aa84ccdb6f3e92f333d4df7fbaeb0d5a157dbfb48d"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.3.0", "2c69a452c2e0ee8c93345ae1cdc1696ef4877ff9cbb15c305def41960c3c4ebf", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "0ac491924217550c8f42c81c1f390b5d81517d12ceaf9abf3e701156760a848e"},
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
@@ -26,8 +33,11 @@
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
"postgrex": {:hex, :postgrex, "0.15.10", "2809dee1b1d76f7cbabe570b2a9285c2e7b41be60cf792f5f2804a54b838a067", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "1560ca427542f6b213f8e281633ae1a3b31cdbcd84ebd7f50628765b8f6132be"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
+ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
"telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
- "ueberauth": {:hex, :ueberauth, "0.6.3", "d42ace28b870e8072cf30e32e385579c57b9cc96ec74fa1f30f30da9c14f3cc0", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "afc293d8a1140d6591b53e3eaf415ca92842cb1d32fad3c450c6f045f7f91b60"},
+ "ueberauth": {:hex, :ueberauth, "0.7.0", "9c44f41798b5fa27f872561b6f7d2bb0f10f03fdd22b90f454232d7b087f4b75", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2efad9022e949834f16cc52cd935165049d81fa9e925690f91035c2e4b58d905"},
+ "ueberauth_github": {:hex, :ueberauth_github, "0.8.1", "0be487b5afc29bc805fa5e31636f37c8f09d5159ef73fc08c4c7a98c9cfe2c18", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7.0", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "143d6130b945ea9bdbd0ef94987f40788f1d7e8090decbfc0722773155e7a74a"},
+ "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
}