Migrating from Coherence
Remove coherence
First we'll remove coherence.
- Remove
:coherence
config fromconfig/config.exs
(also any coherence config inconfig/dev.exs
,config/prod.exs
andconfig/test.exs
) - Delete
coherence_messages.ex
,coherence_web.ex
,coherence/redirects.ex
,emails/coherence
,templates/coherence
, andviews/coherence
. - Remove coherence from
user.ex
. This includes the coherence specific changeset methoddef changeset(model, params, :password)
, and the:email
field in schema. - Remove coherence from
router.ex
. Pipeline:public
can be removed entirely if it's only used for coherence, as well as scopes that only contains coherence routes. - Remove
:coherence
frommix.exs
and runmix deps.unlock coherence
Add Pow to your Ecto schema
Set up a migration file with the following change to continue using your users table:
def up do
alter table(:users) do
add :email_confirmation_token, :string
add :email_confirmed_at, :utc_datetime
add :unconfirmed_email, :string
end
create unique_index(:users, :email_confirmation_token)
end
def down do
alter table(:users) do
remove :email_confirmation_token
remove :email_confirmed_at
remove :unconfirmed_email
end
end
Add configuration:
config :my_app, :pow,
repo: MyApp.Repo,
user: MyApp.User,
extensions: [PowEmailConfirmation, PowResetPassword],
controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks,
mailer_backend: MyAppWeb.PowMailer
Set up user.ex
to use Pow:
defmodule MyApp.User do
use Ecto.Schema
use Pow.Ecto.Schema
use Pow.Extension.Ecto.Schema,
extensions: [PowEmailConfirmation, PowResetPassword]
schema "users" do
# ...
pow_user_fields()
timestamps()
end
# ...
@spec changeset(t(), map()) :: Changeset.t()
def changeset(model, params \\ %{}) do
model
|> cast(params, [:email])
|> pow_changeset(params)
|> pow_extension_changeset(params)
end
end
Continue with bcrypt hashing
Coherence uses bcrypt, so you'll have to switch to bcrypt in Pow:
Install comeonin for bcrypt in
mix.exs
:{:comeonin, "~> 3.0"}
Set up
user.ex
to use bcrypt for password hashing:defmodule MyApp.User do use Ecto.Schema use Pow.Ecto.Schema, password_hash_methods: {&Comeonin.Bcrypt.hashpwsalt/1, &Comeonin.Bcrypt.checkpw/2} # ... end
Mailer
Set up pow_mailer.ex
to enable emails:
defmodule MyAppWeb.PowMailer do
@moduledoc false
use Pow.Phoenix.Mailer
use Swoosh.Mailer, otp_app: :my_app
import Swoosh.Email
def cast(email) do
new()
|> from({"My App", "myapp@example.com"})
|> to({"", email.user.email})
|> subject(email.subject)
|> text_body(email.text)
|> html_body(email.html)
end
def process(email), do: deliver(email)
end
Phoenix
Add session plug to endpoint.ex
:
# After plug Plug.Session
plug Pow.Plug.Session, otp_app: :my_app
Set up router.ex
defmodule MyAppWeb.Router do
use Phoenix.Router
use Pow.Phoenix.Router
use Pow.Extension.Phoenix.Router, otp_app: :my_app
# pipelines ...
pipeline :protected do
plug Pow.Plug.RequireAuthenticated,
error_handler: Pow.Phoenix.PlugErrorHandler
end
scope "/" do
pipe_through :browser
pow_routes()
pow_extension_routes()
end
# routes ...
end
Change Routes.session_path
to Routes.pow_session_path
, and
Routes.registration_path
to Routes.pow_registration_path
. Any references to Coherence.current_user/1
, can be changed to Pow.Plug.current_user/1
.
That's it! You can now test out your Pow'ered app, and then remove all unused fields/tables after.
Keep confirmed_at and confirmation_token data
To keep confirmed_at and confirmation_token data from your past coherence setup, you should first add the coherence fields to your user schema:
field :confirmation_token, :string
field :confirmed_at, :utc_datetime
And then you can run the following:
alias MyApp.{User, Repo}
User
|> Repo.all()
|> Enum.each(fn user ->
user
|> Ecto.Changeset.change(%{
email_confirmation_token: user.confirmation_token,
email_confirmed_at: user.confirmed_at
})
|> Repo.update!()
end)