diff --git a/db/migrate/20170803171814_make_email_unique.rb b/db/migrate/20170803171814_make_email_unique.rb new file mode 100644 index 0000000..c516d8e --- /dev/null +++ b/db/migrate/20170803171814_make_email_unique.rb @@ -0,0 +1,6 @@ +class MakeEmailUnique < ActiveRecord::Migration + def change + remove_index :users, name: "index_users_on_email" + add_index :users, :email, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 379aa22..3ecdccc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170728221839) do +ActiveRecord::Schema.define(version: 20170803171814) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -81,7 +81,7 @@ ActiveRecord::Schema.define(version: 20170728221839) do end add_index "users", ["auth_token"], name: "index_users_on_auth_token", using: :btree - add_index "users", ["email"], name: "index_users_on_email", using: :btree + add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree add_index "users", ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true, using: :btree add_index "users", ["username"], name: "index_users_on_username", using: :btree diff --git a/lib/asciinema/accounts/accounts.ex b/lib/asciinema/accounts/accounts.ex index 540bae0..df7d1cb 100644 --- a/lib/asciinema/accounts/accounts.ex +++ b/lib/asciinema/accounts/accounts.ex @@ -80,12 +80,12 @@ defmodule Asciinema.Accounts do {:ok, url} end - defp signup_url(email) do + def signup_url(email) do token = Phoenix.Token.sign(AsciinemaWeb.Endpoint, "signup", email) AsciinemaWeb.Router.Helpers.users_url(AsciinemaWeb.Endpoint, :new, t: token) end - defp login_url(%User{id: id, last_login_at: last_login_at}) do + def login_url(%User{id: id, last_login_at: last_login_at}) do last_login_at = last_login_at && Timex.to_unix(last_login_at) token = Phoenix.Token.sign(AsciinemaWeb.Endpoint, "login", {id, last_login_at}) AsciinemaWeb.Router.Helpers.session_url(AsciinemaWeb.Endpoint, :new, t: token) diff --git a/lib/asciinema/accounts/user.ex b/lib/asciinema/accounts/user.ex index a4ffc80..6fb61ba 100644 --- a/lib/asciinema/accounts/user.ex +++ b/lib/asciinema/accounts/user.ex @@ -38,6 +38,7 @@ defmodule Asciinema.Accounts.User do |> create_changeset(attrs) |> cast(attrs, [:email]) |> validate_required([:email]) + |> unique_constraint(:email, name: "index_users_on_email") end def login_changeset(user) do diff --git a/test/asciinema/users_test.exs b/test/asciinema/accounts_test.exs similarity index 69% rename from test/asciinema/users_test.exs rename to test/asciinema/accounts_test.exs index bdd1f8b..3a70fcb 100644 --- a/test/asciinema/users_test.exs +++ b/test/asciinema/accounts_test.exs @@ -3,6 +3,7 @@ defmodule Asciinema.AccountsTest do use Asciinema.DataCase use Bamboo.Test alias Asciinema.Email + alias Asciinema.Accounts.User describe "send_login_email/1" do import Asciinema.Accounts, only: [send_login_email: 1] @@ -34,4 +35,18 @@ defmodule Asciinema.AccountsTest do assert_no_emails_delivered() end end + + describe "verify_signup_token/1" do + import Asciinema.Accounts, only: [verify_signup_token: 1, signup_url: 1] + + test "invalid token" do + assert verify_signup_token("invalid") == {:error, :token_invalid} + end + + test "valid token" do + token = "test@example.com" |> signup_url |> String.split("?t=") |> List.last + assert {:ok, %User{}} = verify_signup_token(token) + assert verify_signup_token(token) == {:error, :email_taken} + end + end end