The file structure now looks like this:
abc.cabal includes our dependencies and build information.
This file is read when we run
log includes two files that log out what browsers
the site and what
snaplets is where our snaplets store their files. In this
case we only have
heist there, which contains a
templates folder that includes the templates we use to
render the site.
static includes a simple stylesheet that is served when we
visit the site.
src is the folder we’re currently concerned with. It
includes three files:
This file contains some boilerplate for dynamic recompilation of a snap site. We’ll be leaving this file alone.
Here we define our App datatype with the snaplets we will be using.
In this case we are using
Then we make a call to
makeLenses does some things under the hood like creating
getters/setters and changing the names for the snaplets in
our app to remove the underscore. This means that
will be referred to as
auth in the rest of our app,
We then define an instance for the Heist Snaplet so we don’t
have to use
with heist every time we want to render a
template (More about this later).
and finally we declare a type alias so that we can use
AppHandler instead of the longer
Handler App App in the
type signatures for our routes.
This is where the meat of our site lives. The routing code, handlers and initialization for the entire app.
The first route is
"/login" which uses
with auth lets us work in the auth Snaplet for
Since we’re working in the auth Snaplet our type signature
for the handler has the type
Handler App (AuthManager App) (), which is slightly
different from the type we aliased in
loginUser is a function from the auth snaplet. It takes
username field and the
password field from a form
submission, a “remember” field, a failure function and a
success function, in that order. The type signature looks
So going back to
handleLoginSubmit we use:
the username field
"password" as the password field
Nothing as the remember field
_ -> handleLogin err as
our error function and
redirect "/" as our success
err is defined as
Just "Unknown user or password" which
matches up with the type from
handleLogin code will be covered in a Heist tutorial
at another time, but suffice it to say that
rendering the login form with the error that we’ve supplied
it (which is “Unknown user or password”).
"/logout" route is pretty simple. Just call the
snaplet-auth supplied function
logout and redirect to
"/new_user" does a similar thing, except it displays the
empty form on
GET request and handles a form submit on
Next we’ll replace the backend, currently a json file, with postgres.