Skip to content

Commit

Permalink
Add Confirmation, code is a little messy.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisfls committed Apr 12, 2017
1 parent 7b03767 commit d777db3
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 19 deletions.
49 changes: 40 additions & 9 deletions lib/heborn_migration/controller/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule HEBornMigration.Controller.Account do

alias HEBornMigration.Model.Account
alias HEBornMigration.Model.Claim
alias HEBornMigration.Model.Confirmation
alias HEBornMigration.Repo

@spec claim(display_name :: String.t) ::
Expand All @@ -14,9 +15,9 @@ defmodule HEBornMigration.Controller.Account do
|> Repo.insert()

case result do
{:ok, claim = %Claim{}} ->
{:ok, claim} ->
{:ok, claim.token}
{:error, reason = %Ecto.Changeset{}} ->
{:error, reason} ->
{:error, reason}
end
end
Expand All @@ -26,19 +27,49 @@ defmodule HEBornMigration.Controller.Account do
| {:error, Ecto.Changeset.t}
def migrate(token, email, password) do
Repo.transaction fn ->
claim = Repo.get(Claim, token)

result =
Claim
|> Repo.get(token)
claim
|> Account.create(email, password)
|> Repo.insert()

case result do
{:ok, account = %Account{}} ->
# TODO: send email here
account
{:error, reason = %Ecto.Changeset{}} ->
with {:ok, account} <- result do
Repo.delete(claim)
account
else
{:error, reason} ->
Repo.rollback(reason)
end
end
end

@spec confirm(Confirmation.code) ::
:ok
| :error
def confirm(code) do
{status, _} =
Repo.transaction(fn ->
with \
confirmation = %Confirmation{} <- Repo.get(Confirmation, code),

changeset =
confirmation
|> Repo.preload(:account)
|> Confirmation.confirm(),

{:ok, confirmation} <- Repo.update(changeset),
{:ok, confirmation} <- Repo.delete(confirmation)
do
confirmation.account
else
{:error, reason} ->
Repo.rollback(reason)
nil ->
Repo.rollback(:notfound)
end
end)

status
end
end
11 changes: 9 additions & 2 deletions lib/heborn_migration/model/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule HEBornMigration.Model.Account do

alias Comeonin.Bcrypt
alias HEBornMigration.Model.Claim
alias HEBornMigration.Model.Confirmation

import Ecto.Changeset

Expand All @@ -28,6 +29,9 @@ defmodule HEBornMigration.Model.Account do
field :confirmed, :boolean,
default: false

has_one :confirmation, Confirmation,
foreign_key: :id

timestamps()
end

Expand All @@ -38,7 +42,10 @@ defmodule HEBornMigration.Model.Account do
"""
def create(claim, email, password) do
params = %{claim: claim, email: email, password: password}
changeset(%__MODULE__{}, params)

%__MODULE__{}
|> changeset(params)
|> put_assoc(:confirmation, Confirmation.create())
end

@spec confirm(t) ::
Expand All @@ -50,7 +57,7 @@ defmodule HEBornMigration.Model.Account do
do: changeset(struct, %{confirmed: true})

@doc false
def changeset(struct, params \\ %{}) do
def changeset(struct, params) do
# no display_name validation is being done here as it was already
# validated on Claim model
struct
Expand Down
4 changes: 3 additions & 1 deletion lib/heborn_migration/model/claim.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ defmodule HEBornMigration.Model.Claim do
field :display_name, :string, size: 15
end

@spec create(String.t) :: Ecto.Changeset.t
@spec create(String.t) ::
Ecto.Changeset.t
def create(display_name),
do: changeset(%{display_name: display_name})

@doc false
def changeset(struct \\ %__MODULE__{}, params) do
struct
|> cast(params, [:display_name])
Expand Down
44 changes: 44 additions & 0 deletions lib/heborn_migration/model/confirmation.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
defmodule HEBornMigration.Model.Confirmation do

use Ecto.Schema

alias HEBornMigration.Controller.Token
alias HEBornMigration.Model.Account

import Ecto.Changeset

@type code :: String.t

@type t :: %__MODULE__{
code: String.t,
id: Account.id
}

@primary_key false
schema "confirmations" do
field :code, :string,
primary_key: true

field :id, :integer

belongs_to :account, Account,
foreign_key: :id,
define_field: false
end

@spec create ::
Ecto.Changeset.t
def create do
%__MODULE__{code: Token.generate()}
end

@spec confirm(t) ::
Ecto.Changeset.t
def confirm(struct) do
struct
|> cast(%{}, [])
|> foreign_key_constraint(:id)
|> unique_constraint(:id)
|> put_assoc(:account, Account.confirm(struct.account))
end
end
12 changes: 12 additions & 0 deletions priv/repo/migrations/20170412171747_create_confirmations.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule HEBornMigration.Repo.Migrations.CreateConfirmations do
use Ecto.Migration

def change do
create table(:confirmations, primary_key: false) do
add :code, :string, primary_key: true
add :id, references(:accounts, on_delete: :delete_all), null: false
end

create unique_index(:confirmations, [:id])
end
end
12 changes: 12 additions & 0 deletions test/controller/account_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,16 @@ defmodule HEBornMigration.Controller.AccountTest do
assert {:error, %Ecto.Changeset{}} = result
end
end

describe "confirm/1" do
test "succeeds with valid input" do
account = Factory.insert(:account)

assert :ok == Controller.confirm(account.confirmation.code)
end

test "fails with invalid input" do
assert :error == Controller.confirm("00000000")
end
end
end
2 changes: 1 addition & 1 deletion test/model/claim_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule HEBornMigration.Model.ClaimTest do

alias HEBornMigration.Model.Claim

describe "create/2" do
describe "create/1" do
test "succeeds with valid input" do
cs = Claim.create("Example")

Expand Down
12 changes: 6 additions & 6 deletions test/support/factory.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule HEBornMigration.Factory do
alias HEBornMigration.Model.Claim
alias HEBornMigration.Repo

@type thing :: :claim | :account
@type thing :: :account | :claim

@spec changeset(thing, map | Keyword.t) ::
Ecto.Changeset.t
Expand Down Expand Up @@ -57,24 +57,24 @@ defmodule HEBornMigration.Factory do

@spec params_for(thing) ::
map
def params_for(:claim),
do: %{display_name: String.slice(Burette.Internet.username(), 0..14)}
def params_for(:account) do
%{
claim: build(:claim),
email: Burette.Internet.email(),
password: Burette.Internet.password()
}
end
def params_for(:claim),
do: %{display_name: String.slice(Burette.Internet.username(), 0..14)}

@spec fabricate_changeset(thing, map) ::
Ecto.Changeset.t
defp fabricate_changeset(:claim, params) do
Claim.create(params.display_name)
end
defp fabricate_changeset(:account, params) do
Account.create(params.claim, params.email, params.password)
end
defp fabricate_changeset(:claim, params) do
Claim.create(params.display_name)
end

defp to_map(x = %{}),
do: x
Expand Down

0 comments on commit d777db3

Please sign in to comment.