Skip to content

Commit

Permalink
Deliver login email
Browse files Browse the repository at this point in the history
  • Loading branch information
sutherland committed Jun 19, 2019
1 parent 24d03c7 commit 1721bda
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 2 deletions.
2 changes: 2 additions & 0 deletions config/config.exs
Expand Up @@ -7,6 +7,8 @@
# General application configuration
use Mix.Config

config :passwordless, Passwordless.Mailer, adapter: Bamboo.LocalAdapter

config :passwordless,
ecto_repos: [Passwordless.Repo]

Expand Down
15 changes: 15 additions & 0 deletions lib/passwordless/accounts/tokens.ex
@@ -0,0 +1,15 @@
defmodule Passwordless.Accounts.Tokens do
alias Phoenix.Token
alias PasswordlessWeb.Endpoint

@login_request_max_age 60 * 15 # 15 minutes
@login_request_salt "login request salt"

def sign_login_request(login_request) do
Token.sign(Endpoint, @login_request_salt, login_request.id)
end

def verify_login_request(token) do
Token.verify(Endpoint, @login_request_salt, token, max_age: @login_request_max_age)
end
end
15 changes: 15 additions & 0 deletions lib/passwordless/email.ex
@@ -0,0 +1,15 @@
defmodule Passwordless.Email do
use Bamboo.Phoenix, view: PasswordlessWeb.EmailView
import Bamboo.Email

alias Passwordless.Accounts.Tokens

def login_request(user, login_request) do
new_email()
|> to(user.email)
|> from("support@example.com")
|> subject("Log in to Passwordless")
|> assign(:token, Tokens.sign_login_request(login_request))
|> render("login_request.html")
end
end
3 changes: 3 additions & 0 deletions lib/passwordless/mailer.ex
@@ -0,0 +1,3 @@
defmodule Passwordless.Mailer do
use Bamboo.Mailer, otp_app: :passwordless
end
8 changes: 7 additions & 1 deletion lib/passwordless_web/controllers/login_request_controller.ex
Expand Up @@ -2,14 +2,20 @@ defmodule PasswordlessWeb.LoginRequestController do
use PasswordlessWeb, :controller

alias Passwordless.Accounts.LoginRequests
alias Passwordless.Email
alias Passwordless.Mailer

def new(conn, _params) do
render(conn, "new.html")
end

def create(conn, %{"login_request" => %{"email" => email}}) do
case LoginRequests.create(email) do
{:ok, _changes, _user} ->
{:ok, %{login_request: login_request}, user} ->
user
|> Email.login_request(login_request)
|> Mailer.deliver_now()

conn
|> put_flash(:info, "We just emailed you a temporary login link. Please check your inbox.")
|> redirect(to: Routes.home_path(conn, :index))
Expand Down
4 changes: 4 additions & 0 deletions lib/passwordless_web/router.ex
Expand Up @@ -13,6 +13,10 @@ defmodule PasswordlessWeb.Router do
plug :accepts, ["json"]
end

if Mix.env == :dev do
forward "/sent-emails", Bamboo.SentEmailViewerPlug
end

scope "/", PasswordlessWeb do
pipe_through :browser

Expand Down
5 changes: 5 additions & 0 deletions lib/passwordless_web/templates/email/login_request.html.eex
@@ -0,0 +1,5 @@
<p>Hello!</p>

<p>Use the link below to log in to your Passwordless account. <strong>This link expires in 15 minutes.</strong></p>

<p><%= link "Log in to Passwordless", to: "#todo" %></p>
3 changes: 3 additions & 0 deletions lib/passwordless_web/views/email_view.ex
@@ -0,0 +1,3 @@
defmodule PasswordlessWeb.EmailView do
use PasswordlessWeb, :view
end
3 changes: 2 additions & 1 deletion mix.exs
Expand Up @@ -42,7 +42,8 @@ defmodule Passwordless.MixProject do
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"}
{:plug_cowboy, "~> 2.0"},
{:bamboo, "~> 1.2"}
]
end

Expand Down
9 changes: 9 additions & 0 deletions mix.lock
@@ -1,4 +1,6 @@
%{
"bamboo": {:hex, :bamboo, "1.2.0", "8aebd24f7c606c32d0163c398004a11608ca1028182a169b2e527793bfab7561", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm"},
Expand All @@ -8,8 +10,13 @@
"ecto_sql": {:hex, :ecto_sql, "3.1.5", "b5201fe99fa6bf6a93f64adb2d4976ded3d201f932b7c5bd4c44468642f4fb1f", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0 or ~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"},
"gettext": {:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2", [:mix], [], "hexpm"},
"hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.4.8", "c72dc3adeb49c70eb963a0ea24f7a064ec1588e651e84e1b7ad5ed8253c0b4a2", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
Expand All @@ -20,5 +27,7 @@
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"postgrex": {:hex, :postgrex, "0.14.3", "5754dee2fdf6e9e508cbf49ab138df964278700b764177e8f3871e658b345a1e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
}

0 comments on commit 1721bda

Please sign in to comment.