Refactor my handlers to use the `Handler a` type instead of `IO a`; this allows
me to throwError inside of handlers that Servant properly handles. Previously I
was creating 500 errors unnecessarily.
Update my API type and handler types to reflect which handlers read and write
cookies.
TODO:
- Actually read from and write to Set-Cookie header
- Returning `pure NoContent` breaks my types, so I'm returning `undefined` now
TL;DR:
- Since POST /login is more rigorous, our accounts.csv needs to contain validly
hashed passwords; you can use tests/create-accounts.sh to create dummy
accounts
I still need to test the login flow and support:
- Tracking failed attempts (three maximum)
- Verifying accounts by sending emails to the users
For the past 3-4 Haskell projects on which I've worked, I've tried to habituate
the usage of the (&) operator, but I find that -- as petty as it may sound -- I
don't like the way that it looks, and I end up avoiding using it as a result.
This time around, I'm aliasing it to (|>) (i.e. Elixir style), and I'm hoping to
use it more.
TL;DR:
- introduce the Cryptonite library
- Remove the redundant language extensions, imports, deps from Persistent
- Prefer NoContent return type for POST /accounts
- Define custom {To,From}JSON instances for Role
Instead of sending and receiving JSON like "accountUsername", which leaks
implementation details and is a bit unwieldy, define custom instances that
prefer the shorter, more user-friendly "username" version.
Allow a user to delete a trip entry from the Trips table using the Primary
Key. While this type-checks and compiles, it doesn't appear to be working as
intended. Perhaps I should use an auto-incrementing integer as the Primary
Key. I'm not sure how I want to handle this, so I'm punting for now.
In the spirit of walking crawling before I walk, I'm preferring the less
powerful SQLite.Simple library to the more powerful (but mystifying) Persistent
library.
I believe data should be validated at each level of the stack:
- database
- server
- client
The database, in my opinion, is the most important layer at which to validate
because you can eliminate entire classes of bugs. However, the CHECK constraint
is limited, and the more complex the predicates are, the more expensive database
operations become.
At the server and client layers, the data validations can be more sophisticated
and return more useful error messages to help users better understand the shape
of the data that our application expects.
TL;DR:
- Created src/init.sql, which defines the tables
- Created a data/ directory to house .csv data to populate our db
- Updated the README with usage instructions
Query my SQLite database from within my Servant handlers. Nothing I've written
is domain-specific to the business logic yet -- I'm just making sure everything
integrates.