adds Firebase communication stump

- Firebase connection via Pigeon library
- sends bump to a single token at the moment
- encrypted test is sent as notification message
This commit is contained in:
Raphael Maenle 2021-12-30 13:06:26 +01:00
parent 8262b61085
commit 745b0dc4f2
10 changed files with 148 additions and 45 deletions

2
.gitignore vendored
View File

@ -42,3 +42,5 @@ npm-debug.log
# secret information # secret information
/config/*.secret.exs /config/*.secret.exs
/secret/*

View File

@ -47,6 +47,11 @@ config :logger, :console,
# Use Jason for JSON parsing in Phoenix # Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason config :phoenix, :json_library, Jason
config :bump, Bump.FCM,
adapter: Pigeon.FCM,
project_id: "bump-ce0f4",
service_account_json: File.read!("secret/service-account.json")
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs" import_config "#{config_env()}.exs"

39
google-services.json Normal file
View File

@ -0,0 +1,39 @@
{
"project_info": {
"project_number": "613845155515",
"project_id": "bump-ce0f4",
"storage_bucket": "bump-ce0f4.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:613845155515:android:93e5c4b67c8f8104de739e",
"android_client_info": {
"package_name": "com.maenle.bump"
}
},
"oauth_client": [
{
"client_id": "613845155515-vdo4q6nfab9tc0nt0ukorduh24unlmo1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDMDJChUVMG7TBmSgi5FNECgUICn4jmHZI"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "613845155515-vdo4q6nfab9tc0nt0ukorduh24unlmo1.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@ -15,15 +15,17 @@ defmodule Bump.Application do
# Start the PubSub system # Start the PubSub system
{Phoenix.PubSub, name: Bump.PubSub}, {Phoenix.PubSub, name: Bump.PubSub},
# Start the Endpoint (http/https) # Start the Endpoint (http/https)
BumpWeb.Endpoint BumpWeb.Endpoint,
# Start a worker by calling: Bump.Worker.start_link(arg) # Start a worker by calling: Bump.Worker.start_link(arg)
# {Bump.Worker, arg} # {Bump.Worker, arg}
Bump.FCM
] ]
# See https://hexdocs.pm/elixir/Supervisor.html # See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options # for other strategies and supported options
opts = [strategy: :one_for_one, name: Bump.Supervisor] opts = [strategy: :one_for_one, name: Bump.Supervisor]
Supervisor.start_link(children, opts) Supervisor.start_link(children, opts)
end end
# Tell Phoenix to update the endpoint configuration # Tell Phoenix to update the endpoint configuration

62
lib/bump/database.ex Normal file
View File

@ -0,0 +1,62 @@
defmodule Bump.Database do
alias Bump.Repo
alias Bump.Messages.Message
import Ecto.Query
def pop(sender) do
query = from m in "messages",
where: m.sender == ^sender,
order_by: [desc: m.timestamp],
limit: 1,
select: %{id: m.id, data: m.data, timestamp: m.timestamp}
res = Repo.one(query)
if not is_nil(res) do
Repo.delete_all(from m in "messages", where: m.id == ^res.id)
%{data: res.data, timestamp: res.timestamp}
else
%{}
end
end
def peek(sender) do
query = from m in "messages",
where: m.sender == ^sender,
order_by: [desc: m.timestamp],
limit: 1,
select: %{data: m.data, timestamp: m.timestamp}
Repo.one(query)
end
def list(sender, minutes) do
ago = DateTime.utc_now
|> Timex.shift(minutes: -minutes)
|> DateTime.truncate(:second)
query = from m in "messages",
where: m.sender == ^sender and
m.timestamp >= ^ago,
select: %{data: m.data, timestamp: m.timestamp}
Repo.all(query)
end
def clear(sender) do
query = from m in "messages",
where: m.sender == ^sender
Repo.delete_all(query)
end
def push(sender, message) do
time = DateTime.utc_now |> DateTime.truncate(:second)
Repo.insert(%Message{sender: sender, data: message, timestamp: time})
end
end

14
lib/bump/firebase.ex Normal file
View File

@ -0,0 +1,14 @@
defmodule Bump.Firebase do
def test() do
IO.puts "Hello, world!"
end
def push(sender, message) do
IO.puts "Pushing #{message} to #{sender}"
n = Pigeon.FCM.Notification.new({:token, "dTm8S2bfTdKYQTjrxnwFFg:APA91bHGgM7IdRS5uxD0ljmwmP6cAec2icX0VBs69iRB2ApsohyOWzTzontO7cBkjNYbWV87zvxrXIs5jHkJ-8mSWa_-RiU2Y8-XEy3g-Fep3z6dhDeM3KazP58jDRgbdB5cVpDcIEWL"}, %{"body" => message})
Bump.FCM.push(n)
%{status: 'cheese'}
end
end

View File

@ -1,61 +1,26 @@
defmodule Bump.Messages do defmodule Bump.Messages do
alias Bump.Repo alias Bump.Database
alias Bump.Messages.Message alias Bump.Firebase
import Ecto.Query
def pop(sender) do def pop(sender) do
query = from m in "messages", Database.pop(sender)
where: m.sender == ^sender,
order_by: [desc: m.timestamp],
limit: 1,
select: %{id: m.id, data: m.data, timestamp: m.timestamp}
res = Repo.one(query)
if not is_nil(res) do
Repo.delete_all(from m in "messages", where: m.id == ^res.id)
%{data: res.data, timestamp: res.timestamp}
else
%{}
end
end end
def peek(sender) do def peek(sender) do
query = from m in "messages", Database.peek(sender)
where: m.sender == ^sender,
order_by: [desc: m.timestamp],
limit: 1,
select: %{data: m.data, timestamp: m.timestamp}
Repo.one(query)
end end
def list(sender, minutes) do def list(sender, minutes) do
Database.list(sender, minutes)
ago = DateTime.utc_now
|> Timex.shift(minutes: -minutes)
|> DateTime.truncate(:second)
query = from m in "messages",
where: m.sender == ^sender and
m.timestamp >= ^ago,
select: %{data: m.data, timestamp: m.timestamp}
Repo.all(query)
end end
def clear(sender) do def clear(sender) do
query = from m in "messages", Database.clear(sender)
where: m.sender == ^sender
Repo.delete_all(query)
end end
def push(sender, message) do def push(sender, message) do
time = DateTime.utc_now |> DateTime.truncate(:second) Database.push(sender, message)
Firebase.push(sender, message)
Repo.insert(%Message{sender: sender, data: message, timestamp: time})
end end

4
lib/fcm.ex Normal file
View File

@ -0,0 +1,4 @@
# lib/fcm.ex
defmodule Bump.FCM do
use Pigeon.Dispatcher, otp_app: :bump
end

View File

@ -49,10 +49,13 @@ defmodule Bump.MixProject do
{:timex, "~> 3.0"}, {:timex, "~> 3.0"},
{:gettext, "~> 0.18"}, {:gettext, "~> 0.18"},
{:jason, "~> 1.2"}, {:jason, "~> 1.2"},
{:plug_cowboy, "~> 2.5"} {:plug_cowboy, "~> 2.5"},
{:pigeon, "~> 2.0.0-rc.0"},
{:kadabra, "~> 0.6.0"}
] ]
end end
# Aliases are shortcuts or tasks specific to the current project. # Aliases are shortcuts or tasks specific to the current project.
# For example, to install project dependencies and perform other setup tasks, run: # For example, to install project dependencies and perform other setup tasks, run:
# #

View File

@ -14,10 +14,16 @@
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"floki": {:hex, :floki, "0.32.0", "f915dc15258bc997d49be1f5ef7d3992f8834d6f5695270acad17b41f5bcc8e2", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "1c5a91cae1fd8931c26a4826b5e2372c284813904c8bacb468b5de39c7ececbd"}, "floki": {:hex, :floki, "0.32.0", "f915dc15258bc997d49be1f5ef7d3992f8834d6f5695270acad17b41f5bcc8e2", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "1c5a91cae1fd8931c26a4826b5e2372c284813904c8bacb468b5de39c7ececbd"},
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"}, "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
"goth": {:hex, :goth, "1.3.0-rc.3", "734a0a381c29df82af33039874aac02ad292199e155a25ad4320872788209dee", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:jose, "~> 1.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "ab61d5ab6f59a5ea0404d332c9ad3f2463ae4072aabe4f9ef96d624e271254af"},
"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"}, "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"},
"hpack": {:hex, :hpack_erl, "0.2.3", "17670f83ff984ae6cd74b1c456edde906d27ff013740ee4d9efaa4f1bf999633", [:rebar3], [], "hexpm", "06f580167c4b8b8a6429040df36cc93bba6d571faeaec1b28816523379cbb23a"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "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"}, "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"joken": {:hex, :joken, "2.4.1", "63a6e47aaf735637879f31babfad93c936d63b8b7d01c5ef44c7f37689e71ab4", [:mix], [{:jose, "~> 1.11.2", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "d4fc7c703112b2dedc4f9ec214856c3a07108c4835f0f174a369521f289c98d1"},
"jose": {:hex, :jose, "1.11.2", "f4c018ccf4fdce22c71e44d471f15f723cb3efab5d909ab2ba202b5bf35557b3", [:mix, :rebar3], [], "hexpm", "98143fbc48d55f3a18daba82d34fe48959d44538e9697c08f34200fa5f0947d2"},
"kadabra": {:hex, :kadabra, "0.6.0", "8d8de886802f38d86d2c250eb9416e3208b5e4b78ce8409b40b4d57f21d21fc9", [:mix], [{:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:hpack, "~> 0.2.3", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "0cdaf72fc6205cba62da9e49ee6b24b7c50adb6d9f8b0e92b4b1847959371403"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"}, "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
@ -30,6 +36,7 @@
"phoenix_live_view": {:hex, :phoenix_live_view, "0.16.4", "5692edd0bac247a9a816eee7394e32e7a764959c7d0cf9190662fc8b0cd24c97", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "754ba49aa2e8601afd4f151492c93eb72df69b0b9856bab17711b8397e43bba0"}, "phoenix_live_view": {:hex, :phoenix_live_view, "0.16.4", "5692edd0bac247a9a816eee7394e32e7a764959c7d0cf9190662fc8b0cd24c97", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "754ba49aa2e8601afd4f151492c93eb72df69b0b9856bab17711b8397e43bba0"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
"phoenix_view": {:hex, :phoenix_view, "1.0.0", "fea71ecaaed71178b26dd65c401607de5ec22e2e9ef141389c721b3f3d4d8011", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "82be3e2516f5633220246e2e58181282c71640dab7afc04f70ad94253025db0c"}, "phoenix_view": {:hex, :phoenix_view, "1.0.0", "fea71ecaaed71178b26dd65c401607de5ec22e2e9ef141389c721b3f3d4d8011", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "82be3e2516f5633220246e2e58181282c71640dab7afc04f70ad94253025db0c"},
"pigeon": {:hex, :pigeon, "2.0.0-rc.0", "143a56262abe2eb79febedeea65ccae607abec5c59008af48796105098b5b89f", [:mix], [{:goth, "~> 1.3.0-rc.2", [hex: :goth, repo: "hexpm", optional: false]}, {:httpoison, "~> 0.7 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:joken, "~> 2.1", [hex: :joken, repo: "hexpm", optional: false]}, {:kadabra, "~> 0.6.0", [hex: :kadabra, repo: "hexpm", optional: false]}], "hexpm", "b28da517e6a27bd1804fcbbe748e770cf43383a79b488fa33df62da3d3e078a8"},
"plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"}, "plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"},
"plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},