User Accounts#
Summary#
Boom needs a way for people to create and login to accounts. This allows data generated by each person to be associated with them and not mixed in with everyone else’s data. The user creates an account using an email and password. They receive a confirmation email and confirm their account, then are able to login with the email and password provided. Upon first sign-in, information such as Display Name, Native Language, and Target Langauge are collected.
Motivation#
If we have no user accounts, there’s no way to track data for each user.
With user accounts, there is potential for social interaction between users on the site.
Goals#
Users can create accounts
Users must activate account via email before using it
Users can reset password
Non-Goals#
Out of scope:
For now, social login is out of scope (too complex / too much setup)
Proposal#
Add a registration page asking for email, password, and password confirmation.
When handling form submission, create user in DB and send email with activation code link.
On the activation route, check the token for validity.
If valid, set account active and redirect.
Otherwise, display failure message.
User can login using email and password, receiving an auth token.
User can logout by deleting the auth token.
Design and implementation details#
User Story#
The user story is summarized by this flow chart.
Components#
None
Contexts#
Auth Context#
This context provides the current user object if the user is logged in. Otherwise, it returns undefined
.
It gets this information by making a request to the Get Current User Route
Pages#
Activation Failed Page#
This page displays a simple message telling the user that their account activation failed.
Components
Activation message
Home button
Requests
None
Dashboard Page#
This page contains a welcome message for the now logged-in user.
Components
Welcome text
Requests
None
Forgot Password Page#
On this page, the user types in their email and hits submit to send a request to the Forgot Password Route. After sending the request, it displays a confirmation message and a link to the home page.
Components
Email field
Submit button
Requests
Forgot Password Route
Onboard User Page#
On the page, the user sets up their display name and first LanguagePair. These are saved to their profile upon creation.
Upon submission, this page will submit to the Onboard User route.
Components
Display name field
Native language multi-select
Target language multi-select
Requests
Get Languages Route
Home Page#
The home page will contain sign up and login buttons somewhere.
If the user is already logged in, it will redirect to the dashboard.
Components
Welcome message
Login button (included in Layout)
Sign-up button (included in Layout)
Effects
Redirect if user is already logged in.
Requests
None - it uses the Auth Context to get information about the logged-in user and determine whether to redirect.
Login Page#
On this page, the user types in their email and password and presses enter / clicks the submit button. On error, the error message from the server is displayed. On success:
If User’s
name
field is undefined oractiveLanguagePairId
is undefined, redirect to Onboard User Page.Else, redirect to Dashboard Page.
Components
Email input
Password input
Requests
Login Route: called on submit
Register Page#
This page lets the user register. The fewest fields possible are included to get the user signed up as quickly as possible. Additional fields will be filled in after the user activates their account.
Components
Email field
Password field
Password Confirmation field
Requests
Register Route: Called on submit
Reset Password Page#
This page shows a form for the user to reset their password, including these components:
Components
Old password field
New password field
New password confirmation field
Submit button
Requests
Reset Password Route: Called on submit
Email Templates#
Activation Email#
This email contains a link to the Activate Route with a token as a GET variable.
Forgot Password Email#
This password contains a special link that the user can click to open the ResetPasswordPage and reset their password.
Routes#
Activate Route#
This route handles the link that is in the user’s activation email. It checks the code provided and, if valid, sets the user’s account o active.
Environment Variables
None
Inputs
POST this JSON object:
Field |
Type |
Description |
---|---|---|
|
|
Email of user being activated |
|
|
The activation code from the email. Corresponds to |
Example:
{
"email": "me@email.com",
"code": "abcdefghijklmnopqrstuvwxyz1234567890"
}
Output
A Route Response object
Side Effects
If code matches, user is set to active.
Forgot Password Route#
This route sends an email to reset a user’s password.
Environment Variables
None
Inputs
POST this JSON object:
Field |
Type |
Description |
---|---|---|
|
|
email for which account to reset |
Example:
{
"email": "me@email.com"
}
Output
A Route Response object.
Side Effects
If the user exists in the DB:
The user’s
activationCode
field has been reset to some new random value.A Forgot Password Email is sent to
email
with a link toResetPasswordPage
(containing theactivationCode
). Otherwise, it fails and returns an error.
Get Languages Route#
This route returns the list of currently supported languages from the Boom database.
Environment Variables
None
Inputs
None
Output
List of Language objects
Example:
[
{ "id": 1, ... },
{ "id": 2, ... } // Actual fields are omitted - see Language object below
]
Side Effects
None
Get Current User Route#
This route returns information about the currently logged-in user.
Environment Variables
None
Inputs
The only input is boom_auth
, a signed JWT provided to the user as the output of the Login Route.
boom_auth
: cookie containing JWT auth tokenboom_auth
: Authorization header containing JWT auth token (for mobile clients)
Example header:
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Output
The User object, with the following fields REMOVED for privacy/security purposes:
id
email
passwordHash
passwordSalt
Example:
{
"id": 1,
... // Further fields omitted, see User design
}
Side Effects
None
Login Route#
This route logs the user in if the user exists and the provided password matches the passwordHash
field in the User object. Note that the boom_auth
token is only provided in the output for mobile devices. Browsers should not store this credential using localStorage, which is not secure.
Environment Variables
None
Inputs
POST this JSON object:
Field |
Type |
Description |
---|---|---|
|
|
email for account |
|
|
password for account |
Example:
{
"email": "me@email.com",
"password": "N0tForYourEy3s!!!!!!"
}
Output
JSON object:
Field |
Type |
Description |
---|---|---|
|
|
Status of request |
|
|
Message describing error or “Success” |
|
|
The authorization JWT to use for making authenticated requests as the logged-in user or undefined on failure. |
Example:
{
"status": "success",
"message": "Success",
"boom_auth": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
Side Effects
HttpOnly Secure Cookie
boom_auth
is set.
Logout Route#
This route logs the user out by unsetting the boom_auth
cookie. The client-side is expected to delete any local auth credentials (for mobile).
Environment Variables
None
Inputs
None
Output
A Route Response object.
Side Effects
The boom_auth
cookie is unset.
Onboard User Route#
This route sets basic info for the user.
Environment Variables
None
Inputs
POST this JSON object:
Field |
Type |
Description |
---|---|---|
|
|
Display name for user |
|
|
ID of Language selected as Native |
|
|
ID of Language selected to learn |
Example:
{
"name": "George Language",
"nativeId": 1,
"targetId": 2
}
Output
A Route Response object.
Side Effects
Set the User’s
name
fieldCreated a LanguagePair with the given native/target languages and set it to active.
Register Route#
This route creates a new user object and sends an activation email.
Environment Variables
None
Inputs
POST this JSON object:
Field |
Type |
Description |
---|---|---|
|
|
User’s email |
|
|
User’s password |
|
|
User’s password confirmation |
Example:
{
"email": "me@email.com",
"password": "N0tForYourEy3s!!!!!!",
"passwordConfirmation": "N0tForYourEy3s!!!!!!"
}
Output
A Route Response object.
Side Effects
New User object has been generated.
User’s
activationCode
field is populated with a random string.An Activation Email has been sent to the user-provided email.
Reset Password Route#
This route changes the user’s password to the new one they provide.
Environment Variables
None
Inputs
POST this JSON object:
Field |
Type |
Description |
---|---|---|
|
|
User’s email |
|
|
Activation code |
|
|
New password |
|
|
New password confirmation |
Example:
{
"email": "me@email.com",
"code": "abcdefghijklmnopqrstuvwxyz1234567890",
"password": "N0tForYourEy3s!!!!!!",
"passwordConfirmation": "N0tForYourEy3s!!!!!!"
}
Output
A Route Response object.
Side Effects
User’s
passwordHash
andpasswordSalt
have been updated to match the new password.
Models#
These are data structures that are not stored in the database.
Route Response#
Generic response object to provide info on status/errors. Any output messages should be understandable enough to be displayed to the user.
Field |
Type |
Description |
---|---|---|
status |
‘success’ or ‘error’ |
whether the request succeeded |
message |
string |
User-facing message describing error or “Success” |
Example:
{
"status": "success",
"message": "Success"
}
DB Design#
Only the basic tables required for user accounts and language selection will be included in this design doc.
User#
User is implemented using a Prisma schema.
Field |
Type |
Description |
---|---|---|
id |
Int |
Auto-incremented unique id |
created |
DateTime |
Time of registration |
name |
String? |
Display name |
String |
Unique email |
|
passwordHash |
String |
Hashed password |
passwordSalt |
String |
Salt for password |
activationCode |
String |
Randomly generated string for email activation |
activeLanguagePairId |
|
The currently selected language pair |
Language Pair#
Field |
Type |
Description |
---|---|---|
id |
Int |
Auto-incremented unique id |
user |
User |
User who is learning this LanguagePair |
native |
Language |
Language you already know |
target |
Language |
Language you are learning |
Language#
Field |
Type |
Description |
---|---|---|
id |
Int |
Auto-incremented unique id |
name |
String |
Language name (English) |
code |
String |
Three letter ISO code for the language |
Alternative Solutions#
Make Boom a local-only application. It’s offline all the time, or a desktop app, and there is no way for users to interact. Kinda lame.