Index
House Keeping
There has been a ridiculous gap between the last post, and this one. During this gap a number of things have happened:
- Our daughter was born! :)
- I started working with a new company (in Elixir!)
- We moved to Barranquilla, Colombia (from Medellin) and are preparing to once again hop, this time back to Toronto (where I was born and raised)
- More frustrations on current editor (Vim/Emacs)
- I started learning Clojure (quite possibly the most fun I’ve had for a long time.)
- Other personal projects
At any rate, I do apologize for this. I would like to say that it won’t happen again, however, I know that moving back to Canada will once again throw me off my flow for a while…
Now that that is out of the way (must be a better way to say that that…) let’s get started.
Coherence
So, the last tutorial was on Phauxth which is great, but if you are looking for a more “batteries included” option - look no further! Coherence has two important things going for it (IMHO) it has a large user base and it is very simple to get up and running, so this tutorial should be a breeze.
Setup
Setting up an app is pretty straight forward. Once you have created your phoenix application (I just created a simple blog as before mix phx.new blog_coh
) do the following:
- Add dependency:
def deps do [{:coherence, "~> 0.5"}] end
- Make sure it is started:
def application do extra_applications: [:logger, :runtime_tools, :coherence] end
- Install the dependencies with
mix deps.get
thenmix deps.compile
- Change your router file as follows:
defmodule BlogCohWeb.Router do
use BlogCohWeb, :router
use Coherence.Router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug Coherence.Authentication.Session
end
pipeline :protected do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug Coherence.Authentication.Session, protected: true
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/" do
pipe_through :browser
coherence_routes()
end
scope "/" do
pipe_through :protected
coherence_routes :protected
end
scope "/", BlogCohWeb do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
# For public routes
end
scope "/", BlogCohWeb do
pipe_through :protected
# For private routes
end
# Other scopes may use custom stacks.
# scope "/api", BlogCohWeb do
# pipe_through :api
# end
end
- And lastly, run
mix coh.install --full
There is one point of interest I should address before moving forward, Coherence has a few options you should be aware of. We used the “–full” option which installs all options except “confirmable” and “invitable”. I chose this as it is quick and shows off some features that Coherence includes to get you running very quickly, however there are several other options you should be aware of:
- ”–install” by itself just adds authenticable option (no registration routes)
- ”–full-confirmable” adds the functionality to send confirmation emails to users upon registration
- ”–full-invitable” adds functionality to invite users
- Additionally there are the “–rememberable”, “–lockable”, and “–trackable” flags. You can read more at Coherence Github Page
You can also read through the lib/blog_coh/coherence/user.ex
file to see what the schema produced or the priv/repo/migrations/<date_stamp>_create_coherence_user.exs
file to see what a more thorough representation of the schema. You may notice that lockable, trackable, and recoverable were added with the “full” option we chose.
One final thing I like to do for convenience is edit the seeds file priv/repo/seeds.exs
as coherence suggests:
BlogCoh.Repo.delete_all BlogCoh.Coherence.User
BlogCoh.Coherence.User.changeset(%BlogCoh.Coherence.User{}, %{name: "Test User", email: "testuser@example.com", password: "secret", password_confirmation: "secret"})
|> BlogCoh.Repo.insert!
Which will remove all previous users, and add one to use for testing/development.
This is the point where we should add any additional customization that we may need, if not go ahead and run: mix ecto.setup
which will create the database if it does not exist, run the migrations, and our seeds file.
At the time of writing I received an error:
== Compilation error in file lib/blog_coh_web/coherence_messages.ex ==
** (ArgumentError) *gettext macros expect translation keys (msgid and msgid_plural) and
domains to expand to strings at compile-time, but the given msgid
doesn't.
Dynamic translations should be avoided as they limit gettext's
ability to extract translations from your source code. If you are
sure you need dynamic lookup, you can use the functions in the Gettext
module:
string = "hello world"
Gettext.gettext(BlogCohWeb.Gettext, string)
(gettext) lib/gettext/compiler.ex:213: Gettext.Compiler.expand_to_binary/4
expanding macro: BlogCohWeb.Gettext.dgettext_noop/2
lib/blog_coh_web/coherence_messages.ex:75: BlogCohWeb.Coherence.Messages.you_are_using_an_invalid_security_token/0
expanding macro: BlogCohWeb.Gettext.dgettext/2
lib/blog_coh_web/coherence_messages.ex:75: BlogCohWeb.Coherence.Messages.you_are_using_an_invalid_security_token/0
(elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6
A quick google search was able to resolve this, if you do see this change your gettext dependency to {:getext "0.13.1"}
Ready
You are not alone in thinking that was a lot of setup and indeed mystery going on. I personally try to avoid packages like this, as I think it will take less time to write the functionality I need then read through everything going on and keep up with problems that are inevitable to a package of this side, however there is no denying its attractiveness and I can see how someone would like to use a package like this to get going.
So what did all that get you? Let’s find out! Run mix phx.server
then, navigate to localhost:4000/sessions/new
and enter the email and password you setup in your seeds file. You will be redirected to the home link. Well, that isn’t much. Let’s add some private route and check that authentication is indeed working. Go to your PageController lib/blog_coh_web/controllers/page_controller.ex
and add this route:
def ppage(conn, _params) do
render conn, "ppage.html"
end
And of course create the template in lib/blog_coh_web/templates/page/ppage.html.eex
and add some random stuff:
<h2>You are accessing a private route!</h2>
Add the route to your routes file in the protected routes scope:
scope "/", BlogCohWeb do
pipe_through :protected
get "/private", PageController, :ppage
end
Restart the server, and navigate to localhost:4000/private
you should be redirected to login. Enter your login information and voila! You now have access to that private route.
Conclusion
Of course, this was just the tip of the iceberg. As this series is merely comparing three frameworks and detailing how to get started, I just wanted to quickly show you how to get to a jump off point. You can read up on Coherence github page for more details, or their source to really get your head around what’s going on. Like I previously stated, this is a very popular package and well maintained. I suppose I do not like it as it clashes with some of my ideas around how a package should behave (get the bloody hell out the way, or be perfectly transparent) and I do not think the functionality justifies the labour in terms of digging through their code to see what is going on. Phoenix is the framework I am using, but coherence feels like a mini-framework on top of that, and if that is something you like, great many people do, I am just not one of them. I of course mean no offense to the maintainers of Coherence, the code is well written, they are active, etc. In fact I think it would be of great value to peruse the code base and wrap your ahead around how they choose to implement authentication. Cheers!