Store Last.fm API key with encrypted secret
This commit is contained in:
@@ -49,6 +49,21 @@ config :music_library, MusicLibrary.Repo,
|
|||||||
MusicLibrary.Repo.extension_path("unicode")
|
MusicLibrary.Repo.extension_path("unicode")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
cloak_encryption_key =
|
||||||
|
System.get_env("CLOAK_ENCRYPTION_KEY") ||
|
||||||
|
raise """
|
||||||
|
environment variable CLOAK_ENCRYPTION_KEY is missing.
|
||||||
|
Generate one with: iex> 32 |> :crypto.strong_rand_bytes() |> Base.encode64()
|
||||||
|
"""
|
||||||
|
|
||||||
|
config :music_library, MusicLibrary.Vault,
|
||||||
|
json_library: JSON,
|
||||||
|
ciphers: [
|
||||||
|
default:
|
||||||
|
{Cloak.Ciphers.AES.GCM,
|
||||||
|
tag: "AES.GCM.V1", key: Base.decode64!(cloak_encryption_key), iv_length: 12}
|
||||||
|
]
|
||||||
|
|
||||||
if config_env() == :prod do
|
if config_env() == :prod do
|
||||||
database_path =
|
database_path =
|
||||||
System.get_env("DATABASE_PATH") ||
|
System.get_env("DATABASE_PATH") ||
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ defmodule MusicLibrary.Application do
|
|||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
children = [
|
children = [
|
||||||
MusicLibraryWeb.Telemetry,
|
MusicLibraryWeb.Telemetry,
|
||||||
|
MusicLibrary.Vault,
|
||||||
MusicLibrary.Repo,
|
MusicLibrary.Repo,
|
||||||
MusicLibrary.ErrorRepo,
|
MusicLibrary.ErrorRepo,
|
||||||
MusicLibrary.BackgroundRepo,
|
MusicLibrary.BackgroundRepo,
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
defmodule MusicLibrary.Encrypted.Binary do
|
||||||
|
use Cloak.Ecto.Binary, vault: MusicLibrary.Vault
|
||||||
|
end
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
defmodule MusicLibrary.Secrets do
|
||||||
|
alias MusicLibrary.Repo
|
||||||
|
alias MusicLibrary.Secrets.Secret
|
||||||
|
|
||||||
|
def store(name, value) do
|
||||||
|
%Secret{}
|
||||||
|
|> Secret.changeset(%{name: name, value: value})
|
||||||
|
|> Repo.insert(on_conflict: :replace_all)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get!(name) do
|
||||||
|
Repo.get!(Secret, name)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
defmodule MusicLibrary.Secrets.Secret do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key {:name, :string, autogenerate: false}
|
||||||
|
schema "secrets" do
|
||||||
|
field :value, MusicLibrary.Encrypted.Binary
|
||||||
|
|
||||||
|
timestamps(type: :utc_datetime)
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(secret, attrs) do
|
||||||
|
secret
|
||||||
|
|> cast(attrs, [:name, :value])
|
||||||
|
|> validate_required([:name, :value])
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
defmodule MusicLibrary.Vault do
|
||||||
|
use Cloak.Vault, otp_app: :music_library
|
||||||
|
end
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
defmodule MusicLibraryWeb.LastFmController do
|
defmodule MusicLibraryWeb.LastFmController do
|
||||||
use MusicLibraryWeb, :controller
|
use MusicLibraryWeb, :controller
|
||||||
|
|
||||||
def callback(conn, %{"token" => token}) do
|
alias MusicLibrary.Secrets
|
||||||
case LastFm.get_session(token) do
|
|
||||||
{:ok, session} ->
|
|
||||||
conn
|
|
||||||
|> put_session(:last_fm_user, session.name)
|
|
||||||
|> put_session(:last_fm_key, session.key)
|
|
||||||
|> put_flash(:info, "Successfully authenticated with Last.fm.")
|
|
||||||
|> redirect(to: ~p"/")
|
|
||||||
|
|
||||||
|
def callback(conn, %{"token" => token}) do
|
||||||
|
with {:ok, session} <- LastFm.get_session(token),
|
||||||
|
{:ok, _secret} <- Secrets.store("last_fm_key", session.key) do
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, gettext("Successfully connected your Last.fm account"))
|
||||||
|
|> redirect(to: ~p"/")
|
||||||
|
else
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
conn
|
conn
|
||||||
|> put_flash(:error, "Failed to authenticate with Last.fm: #{reason}")
|
|> put_flash(:error, "Failed to connect your Last.fm account: #{reason}")
|
||||||
|> redirect(to: ~p"/")
|
|> redirect(to: ~p"/")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ defmodule MusicLibrary.MixProject do
|
|||||||
{:ecto_sql, "~> 3.10"},
|
{:ecto_sql, "~> 3.10"},
|
||||||
{:ecto_sqlite3, ">= 0.0.0"},
|
{:ecto_sqlite3, ">= 0.0.0"},
|
||||||
{:ecto_sqlite3_extras, "~> 1.2.2"},
|
{:ecto_sqlite3_extras, "~> 1.2.2"},
|
||||||
|
{:cloak_ecto, "~> 1.3"},
|
||||||
|
|
||||||
# UI
|
# UI
|
||||||
{:phoenix_html, "~> 4.2"},
|
{:phoenix_html, "~> 4.2"},
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
"castore": {:hex, :castore, "1.0.12", "053f0e32700cbec356280c0e835df425a3be4bc1e0627b714330ad9d0f05497f", [:mix], [], "hexpm", "3dca286b2186055ba0c9449b4e95b97bf1b57b47c1f2644555879e659960c224"},
|
"castore": {:hex, :castore, "1.0.12", "053f0e32700cbec356280c0e835df425a3be4bc1e0627b714330ad9d0f05497f", [:mix], [], "hexpm", "3dca286b2186055ba0c9449b4e95b97bf1b57b47c1f2644555879e659960c224"},
|
||||||
"cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"},
|
"cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"},
|
||||||
"circular_buffer": {:hex, :circular_buffer, "0.4.1", "477f370fd8cfe1787b0a1bade6208bbd274b34f1610e41f1180ba756a7679839", [:mix], [], "hexpm", "633ef2e059dde0d7b89bbab13b1da9d04c6685e80e68fbdf41282d4fae746b72"},
|
"circular_buffer": {:hex, :circular_buffer, "0.4.1", "477f370fd8cfe1787b0a1bade6208bbd274b34f1610e41f1180ba756a7679839", [:mix], [], "hexpm", "633ef2e059dde0d7b89bbab13b1da9d04c6685e80e68fbdf41282d4fae746b72"},
|
||||||
|
"cloak": {:hex, :cloak, "1.1.4", "aba387b22ea4d80d92d38ab1890cc528b06e0e7ef2a4581d71c3fdad59e997e7", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "92b20527b9aba3d939fab0dd32ce592ff86361547cfdc87d74edce6f980eb3d7"},
|
||||||
|
"cloak_ecto": {:hex, :cloak_ecto, "1.3.0", "0de127c857d7452ba3c3367f53fb814b0410ff9c680a8d20fbe8b9a3c57a1118", [:mix], [{:cloak, "~> 1.1.1", [hex: :cloak, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "314beb0c123b8a800418ca1d51065b27ba3b15f085977e65c0f7b2adab2de1cc"},
|
||||||
"credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"},
|
"credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"},
|
||||||
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
||||||
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
|
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
|
||||||
|
|||||||
@@ -779,3 +779,8 @@ msgstr ""
|
|||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Disc %{no}"
|
msgid "Disc %{no}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/controllers/last_fm_controller.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Successfully connected your Last.fm account"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -779,3 +779,8 @@ msgstr ""
|
|||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Disc %{no}"
|
msgid "Disc %{no}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/controllers/last_fm_controller.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Successfully connected your Last.fm account"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
defmodule MusicLibrary.Repo.Migrations.CreateSecrets do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:secrets, primary_key: false) do
|
||||||
|
add :name, :string, primary_key: true
|
||||||
|
add :value, :binary, null: false
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user