Commit graph

1659 commits

Author SHA1 Message Date
William Carroll
f1883b2790 Test that the JWT's iss field meets our expectations
The JWT should match "accounts.google.com" or "https://accounts.google.com". If
it doesn't, we produce a validation error.

TL;DR:
- Group all failed stringOrURI function calls as StringOrURIParseFailure errors
2020-08-08 14:08:11 +01:00
William Carroll
526728eb89 Test that an improperly encoded JWT returns a DecodeError
The subject of this commit message says it all.
2020-08-08 13:46:57 +01:00
William Carroll
d34b146702 Tests valid and invalid JWTs for the "aud" field
Test that when the JWT contains the client ID for my Google app, the JWT is
valid, and when it doesn't, it's invalid.
2020-08-08 13:44:22 +01:00
William Carroll
926d8e643e Update jwtIsValid API to return IO Bool
I need IO for:
- Getting the current time to validate `exp`
- Making an HTTP request to Google's token verifier endpoint
2020-08-08 11:18:49 +01:00
William Carroll
3eaf6e5aea Remove redundant deps from API.hs
Thank you, -Wall. You are truly an unsung hero.
2020-08-08 11:10:28 +01:00
William Carroll
7b8ec4170a Begin work for supporting GoogleSignIn server-side
I'm attempting to be an obedient boy and implement this and future features
using TDD.

TL;DR:
- Defined a few tests
- Defined an empty GoogleSignIn module
- Defined a Fixtures module to quickly create JWTs to test
2020-08-08 11:10:19 +01:00
William Carroll
9dcbd0d067 Define Utils module
Dumping grounds for personal, stylistic functions intended to improve readabily
and writability (in that order).
2020-08-08 11:06:53 +01:00
William Carroll
a7ddb56b9b Support echo server to test POST /verify
TL;DR:
- Add common dependencies like Servant, Aeson, Warp, Cors
- Define a POST /verify endpoint for our client to hit
- POST to /verify client-side onSignIn
2020-08-06 22:23:06 +01:00
William Carroll
1fc1087014 Support Google Sign-in client-side
TODO: Support Google Sign-in server-side

Also:
- Add Haskell to project's shell.nix
- Add stubbed Main.hs and Spec.hs
- Add common .ghci file
2020-08-06 21:54:25 +01:00
William Carroll
5f52077492 Re-type type using the altered keyboard
Remember: always read the instructions; that's the most important part.
2020-08-06 00:18:44 +01:00
William Carroll
e14fff7d4b Support Transforms.optimize
Partially optimize inputs and document rules for further optimizations we can
make.
2020-08-06 00:15:31 +01:00
William Carroll
d45685e245 Apply a series of transformation to a QWERTY keyboard
TL;DR:
- Accept input from the CLI
- Add a project README.md
2020-08-05 23:36:04 +01:00
William Carroll
244503bba9 Support App.transform
Apply the transform to a Keyboard. Onwards to the final demonstration!
2020-08-05 23:21:08 +01:00
William Carroll
61a2fb108d Support parsing the list of transforms
Using Haskell's Text.ParserCombinators.ReadP library for the first time, and I
enjoyed it thoroughly! It's nice avoiding a third-party library like MegaParsec.
2020-08-05 22:54:50 +01:00
William Carroll
d948ed9ebf Define an instance for Show for a Keyboard
This will help me debug.
2020-08-05 21:52:10 +01:00
William Carroll
1af0007a7d Create a Utils module
To stylize things...
2020-08-05 21:51:55 +01:00
William Carroll
40753e9f3b Add some the scaffolding for testing
As I attempt to habituate TDD, I should have some examples of tests to minimize
all friction preventing me from testing.
2020-08-05 21:37:08 +01:00
William Carroll
c4299558a7 Include instructions for building Tailwind CSS in README.md
After consuming my Elm boilerplate, I realized that I was missing this.
2020-08-04 16:37:45 +01:00
William Carroll
b1c403f6b9 Create small command line program that parses arguments
Before starting my take-home assignment, the instructions advised me to create a
"Hello, world" program in the language of my choice. Since I'm choosing Haskell,
I created this example as my starter boilerplate.
2020-08-04 16:36:31 +01:00
William Carroll
ee8e75231c Set -Wall and fix warnings
I think setting -Wall is a sensible default and @dmjio confirmed this. After
putting this in my project's .ghci file, a few dozen warnings emerged. This
commit changes the code that causes the warnings.
2020-08-04 09:19:48 +01:00
William Carroll
9a19942c03 Add .ghci configuration file
Create a project-local .ghci file to define sensible
defaults (e.g. -Wincomplete-patterns).

TODO: Discover more GHC options to put in this file.

I would prefer to keep this at the project root, but because I'm running the
project from the src directory, I need to keep .ghci there.
2020-08-03 11:37:57 +01:00
William Carroll
b9ed4a2dc1 Partially support federated login
Two things:
1. I've never attempted to support this before.
2. It seems surprisingly and perhaps deceptively simpler than what I
   expected. I'm unsure what to do once Google's API authenticates the user. I
   currently look-up the user's role, trips, etc. using their email address. The
   role is stored in the Accounts table alongside username, email, password. I
   will speak with the interviewer tomorrow about this.
2020-08-02 21:27:08 +01:00
William Carroll
d6b91b93cb Allow managers to delete users
Borrow the allUsers component

TODO: Move many of these CRUD tables into Common and DRY-up usages across User,
Admin, Manager.
2020-08-02 21:02:22 +01:00
William Carroll
c2419cd912 Support updating trips from the client
Edit existing trips.
2020-08-02 20:56:29 +01:00
William Carroll
239ff24c95 Use ORDER BY to sort the response for GET /trips
SQL is quite useful.
2020-08-02 19:50:28 +01:00
William Carroll
0cb9642a8a Use valid dates for Trips.endDate in trips.csv
TL;DR: My trips.csv had invalid dates for the endDate column. "2020-15-30" is an
"invalid date" (according to FromField instance for Calendar.Day) bc 15 is not a
valid month (i.e. [1,12]).

@dmjio helped me take a look. When we poked around the SQL, we discovered:

```sql
SELECT endDate FROM TRIPS;       -- shows three records
SELECT date(endDate) FROM TRIPS; -- shows two records
```
2020-08-02 19:44:23 +01:00
William Carroll
1d5cf2e4b5 Support Admins inviting users from the client
The title says it all.
2020-08-02 18:02:15 +01:00
William Carroll
a3d783025a Add friendlier and more accurate instructions in invitation email
Copy Example:

To accept the invitation:
  POST /accept-invitation username=<username>
    password=<password> email=you@domain.tld
    secret=8c6b5719-7b1c-471c-bdea-7807b6c0866c
2020-08-02 18:00:29 +01:00
William Carroll
2632dc10fd Ensure /accept-invitation is POST and not GET
Debugged this bug!
2020-08-02 18:00:05 +01:00
William Carroll
90d1451895 Render "<count> days until" for upcoming trips
Per the assignment spec.
2020-08-02 17:45:34 +01:00
William Carroll
e9e84f6a08 Support POST /accept-invitation
Allow users to accept invitations that we email to them.

TL;DR:
- I learned how to write FromHttpApiData instances, which allows me to
  parse/validate data at the edges of my application; this substantially cleans
  up my Handler code.
2020-08-02 16:30:28 +01:00
William Carroll
25334080b9 Support POST /invite
Allow Admin accounts to invite users to the application.
2020-08-02 16:07:35 +01:00
William Carroll
fe609bbe58 Support CRUDing records on Admin page
TL;DR:
- Prefer the more precise verbiage, "Accounts", to "Users"
- Add username field to Trip instead of relying on session.username
- Ensure that decodeRole can JD.fail for invalid inputs
2020-08-02 15:15:01 +01:00
William Carroll
81c3db20d4 Allow managers to CRUD all account types (not just admins)
Per the assignment's instructions.
2020-08-02 14:31:00 +01:00
William Carroll
803db7a5b2 Support printing user's itinerary
- Define print.css with media=print type (note: could've been handled with
  @media queries)
- Define printPage port to interop with window.print() JS function
- Support UI.wrapNoPrint to wrap components with a the no-print CSS
2020-08-02 14:23:38 +01:00
William Carroll
699892883c Support deleting trips from the client
TL;DR:
- Ensure Types.TripPK in Types.hs uses Calendar.Day for startDate
- Prefer verbiage "GotCreateTrip" to "CreatedTrip"
- Extend Utils.deleteWithCredentials to accept a body parameter
- Support a delete button in the UI
2020-08-02 11:16:24 +01:00
William Carroll
d5bc6f963d Protect views from a State with an empty Session
This should simplify UserHome among other views.
2020-08-02 11:13:54 +01:00
William Carroll
57b6472e2f Define defaults for init in State.elm
Problem: When I'm working on a feature, I save my code, and elm-live reloads the
browser. This is usually good, except that the application state is
reinitialized, which usually means that the view changes.

I defined two state configurations, and I expect to define more:
- prod: The initial state for the application
- userHome: The state I'd like to use when developing a feature for the UserHome
  page.

Idea: For more ad-hoc configurations, I can store the application state in
LocalStorage and restore it in between page refreshes.
2020-08-02 10:51:26 +01:00
William Carroll
ac9629cad0 Assign fixed width to error banners
This makes the banners easier to center horizontally.
2020-08-02 10:33:42 +01:00
William Carroll
249e3113ff Support creating Trips from the frontend
*sigh* ... spent way too much time encoding/decoding date types...

I need my database, server, client, and JSON need to agree on types.

TL;DR:
- Add CSS for elm/datepicker library
- Create Common.allErrors to display UI errors
- Prefer Data.Time.Calendar.Day instead of newtype Date wrapper around Text
2020-08-01 23:04:06 +01:00
William Carroll
54eb29eae0 Prefer RecordWildCard syntax for toFields functions
Refactoring old code to conform to the latest fashion.
2020-08-01 12:29:31 +01:00
William Carroll
83f4f8e9d6 Prevent non-admins from creating Manager or Admin accounts
Client-side, I'm not exposing the role option to users. Server-side, I'm
asserting that requests to create Manager and Admin accounts are attempted by
users with a session tied to an admin account.
2020-08-01 11:48:55 +01:00
William Carroll
a3732300e1 Add exhaustive patterns to FromJSON Role instance
When someone enters something like role=mgr, return a helpful error message to
the user.

Note: I should enable the exhaustive patterns check for GHC.
2020-08-01 11:46:41 +01:00
William Carroll
9666d5dce1 Support sign-up
Toggle b/w logging in or signing up.

TL;DR:
- From my previous submission's feedback, disallow users from signing themselves
  up as admins, managers; I just removed the UI element altogether, even though
  the server still support this (TODO)
2020-07-31 19:33:18 +01:00
William Carroll
cf5d211477 Support UI.disabledButton
While this isn't necessary, it tidies up the code a bit.
2020-07-31 19:32:30 +01:00
William Carroll
4d30a80487 Support UI.textButton
Create a text-only button.
2020-07-31 19:32:14 +01:00
William Carroll
421c71c892 Support a basic client-side login flow
I will need to remove some of the baggage like:

- Scrub any copy about restaurants
- delete Restaurant.elm
- Change Owner.elm -> Manager.elm
2020-07-31 18:57:35 +01:00
William Carroll
29a00dc571 Configure non-simple CORS server-side
@dmjio says (probably correctly) that it's best to just serve the client from
the server and circumvent CORS issues altogether.

One day I will set that up. For now, this works... *sigh*
2020-07-31 18:31:52 +01:00
William Carroll
cdaa449670 Prefer PUT to PATCH
It was always a PUT. Nothing to see here, folks.
2020-07-31 18:30:03 +01:00
William Carroll
35b218c543 Return a JSON Session on a successful POST /login
This will make the UX on a the client-side smoother.
2020-07-31 18:30:03 +01:00