Addict allows you to manage users registration and authentication on your Phoenix Framework app easily.
For now, it enables your users to register, login, logout and recover/reset their passwords.
Addict is dependent on an ecto User model and a database connection interface.
The user model must have at least the following schema:
field :email, :string
field :encrypted_password, :string
1 - Add Addict to your dependencies:
{:addict, "~> 0.3"}
1a - Note that mailgun locks Poison to an old 1.4 version, which may cause conflicts (Poison). There's a fix in place that just hasn't been pushed to hex. Resolve by also adding to your dependencies:
{:mailgun, github: "chrismccord/mailgun", branch: "master", override: true}
2 - Generate Addict configs via:
mix addict.generate.configs
3 - Generate (opinionated) boilerplate:
mix addict.generate.boilerplate
4 - Add Addict routes to your router.ex
:
defmodule YourApp.Router do
(...)
use Addict.RoutesHelper
(...)
scope "/" do
# Note that the `addict :routes` call should be inside the global
# scope rather than your app's scope:
# (i.e.: `scope "/", YourApp do: ...` vs `scope "/", do ...`)
# otherwise Phoenix won't be able to find Addict's controllers.
addict :routes
end
end
5 - Visit any of these paths on your app
/login
/register
/recover_password
/reset_password
Addict depends on:
Optionally you can make Addict send e-mails for you too. At the moment only Mailgun is supported. Feel free to contribute with another service!
See all available configurations here.
Add the following to your router.ex
:
defmodule ExampleApp.Router do
use Phoenix.Router
use Addict.RoutesHelper
...
scope "/" do
addict :routes
end
end
This will generate the following routes:
register_path POST / register Addict.Controller.register/2
login_path POST / login Addict.Controller.login/2
logout_path DELETE / logout Addict.Controller.logout/2
recover_password_path POST / recover_password Addict.Controller.recover_password/2
reset_password_path POST / reset_password Addict.Controller.reset_password/2
You can also override the path
or controller
/action
for a given route:
addict :routes,
logout: [path: "/sign-out", controller: ExampleApp.UserController, action: :sign_out],
recover_password: "/password/recover",
reset_password: "/password/reset"
These overrides will generate the following routes:
register_path POST / register Addict.Controller.register/2
login_path POST / login Addict.Controller.login/2
logout_path DELETE / sign-out ExampleApp.UserController.sign_out/2
recover_password_path POST / password/recover Addict.Controller.recover_password/2
reset_password_path POST / password/reset Addict.Controller.reset_password/2
After you've added the router and generated the configs, please take look at the optional boilerplate and the Example App. Here are the interesting bits:
Addict saves information on the logged in user by setting current_user
on the user's Session.
You might want to use the Addict.Helper
module that encapsulates this logic:
Addict.Helper.current_user/1
: Provided theconn
, it returns the user model's hash representation, without any associations.Addict.Helper.is_logged_in/1
: Provided theconn
, it returnstrue
if the user is logged in,false
otherwise.
Use Addict.Plugs.Authenticated
plug to validate requests on your controllers:
defmodule MyAwesomeApp.PageController do
use Phoenix.Controller
plug Addict.Plugs.Authenticated when action in [:foobar]
plug :action
def foobar(conn, _params) do
render conn, "index.html"
end
end
If the user is not logged in and requests for the above action, they will be redirected to not_logged_in_url
.
For adding a custom Mailer just follow the conventions:
- Module must be
Addict.Mailers.TheEmailProvider
- Add the Mailer file in
/lib/addict/mailers
- Make sure the mailer implements the behaviour defined here
Once that is done, just set mail_service
configuration to :the_email_provider
.
Check the issues on this repository to check or track the ongoing improvements and new features.
Feel free to send your PR with improvements or corrections!
Special thanks to the folks at #elixir-lang on freenet for being so helpful every damn time!