Final Project
GIFTR
Due before 11:59 pm on Thursday April 20, 2023.
This is the final deadline. There will be no extensions.
Counts for 30% of your MAD9124 final grade.
# Joint Project
The final project will be a two part joint assignment between MAD9124 and MAD9022. You will build a complete full-stack solution. The web service API portion will be graded for MAD9124, and the front-end application functionality, design, and usability will be graded for MAD9022.
# The Brief
Using Node.js, Express, Mongoose and MongoDB, you will build the RESTful API web service for a prototype of a fictitious application to track gift ideas for your friends. This initial proof of concept (PoC) will have limited capabilities but should demonstrate the potential of a full-scale application.
Each registered user can create a list of people for whom they are collecting gift ideas. The user can then add one or more gift ideas for each person on their list.
Your PoC will allow authenticated users to perform basic CRUD operations on two primary resources: people and gifts. The Person
model represent the people for whom you are collecting gift ideas and will have an array of embedded Gift
models. It will also have a ownerId relationship to the owning User
model.
# Core Requirements
Implement basic user user management functions
- authentication with Google OAuth and JWT
- logout current user
Protected API routes require a valid JWT in the
Authorization
header.Middleware functions should be employed to avoid repetitive route handler code.
Single resource requests should return any related resources as fully populated embedded documents.
Resource list requests should return an array of the primary resource objects only, without populating any related objects.
All requests containing user/client supplied data should be sanitized to protect against XSS and Query Injection attacks.
All schema validation errors should be caught and returned to the client with the correct status code and error message.
# Response Payload
- All responses will be in the form of a JSON formatted object.
- This payload object must include one of (but not both at the same time) a
data
property or anerror
property. - For "list" routes, the
data
property must be populated an array of zero or more of the requested resource objects. - For "retrieve" routes, the
data
property must be populated with a single resource object. - If the requested single resource, or sub-resource (embedded document) does not exist, a 404 error response should be sent.
# Example Data Response
GET /api/people
{
"data": [
{
"_id": "641f45cc4de5a0f56bbc702e",
"name": "Caitlin",
"dob": "2023-03-25T19:04:43.966Z"
}
]
}
# Example Errors Response
GET /api/people/[bad_id]
// Status 404
{
"error": "Person with id [bad_id] not found"
}
# Example Unauthenticated Response
GET /api/people/ headers: { Authorization: 'Invalid or missing JWT' }
// Status 401
{
"error": "JWT error: invalid token"
}
# Auth Routes
The user management actions will be exposed separately from the main API routes and will use the /auth
route prefix.
Action | Method | Resource Path |
---|---|---|
Authenticate User | GET | /auth/google?redirect_url |
Accept google response | GET | /auth/google/callback |
Logout User | GET | /auth/logout |
Successful authenticresation response from google at auth/google/callback
will redirect to the redirect_url
provided to auth/google
, and will include the jwt token in the response query params. Ex http://localhost:3000/login-succes?token=ey.asdfasdf...
# API Routes
The primary application capabilities will be grouped under the /api
resource route prefix. All routes will be limited to authorized users. The client application must send a valid JWT in the Authorization
header property for all /api
routes.
# Person Routes
Action | Method | Resource Path | Notes |
---|---|---|---|
List all people | GET | /api/people | Gift ideas not populated |
Get details for a person | GET | /api/people/:id | Gift ideas fully populated |
Create a person | POST | /api/people | |
Replace a person | PUT | /api/people/:id | |
Update a person | PATCH | /api/people/:id | |
Remove a person | DELETE | /api/people/:id |
Users should only see and be able to act on their own people.
All gift ideas for a given person should be returned as an array of embedded documents with the requested Person object.
# Gift Routes
Action | Method | Resource Path |
---|---|---|
List all gifts | GET | /api/people/:id/gifts |
Get details for a gift | GET | /api/people/:id/gifts/:giftId |
Create a gift | POST | /api/people/:id/gifts |
Update a gift | PATCH | /api/people/:id/gifts/:giftId |
Remove a gift | DELETE | /api/people/:id/gifts/:giftId |
Users should only see and be able to act on gifts associated to their people.
# Resource Schema
There are three required model classes. Their schema requirements are listed below.
Remember
Mongoose will automatically create the _id
property for all objects.
# Person
Property | Type | Required | Max (length/value) | Default |
---|---|---|---|---|
name | String | true | ||
dob | Date | true | ||
ownerId | ObjectId, ref: 'User' | true | Current user | |
gifts | [ Gift ] | |||
createdAt | Date | Date.now() | ||
updatedAt | Date | Date.now() |
The createdAt
and updatedAt
properties should be set automatically by the database (opens new window). Any client supplied data for these two properties should be discarded.
The gifts
property takes an array of zero or more Gift sub-documents (opens new window).
The ownerId
property takes a single User ID.
# Gift
Property | Type | Required |
---|---|---|
txt | String | true |
store | String | true |
url | String | true |
createdAt | Date | handled by mongoose |
updatedAt | Date | handled by mongoose |
# User
Property | Type | Required | Default | Unique | Notes |
---|---|---|---|---|---|
name | String | true | comes from google | ||
googleId | String | true | true | comes from google | |
createdAt | Date | true | handled by mongoose | ||
updatedAt | Date | true | handled by mongoose |
# Logistics
- Create a new
private
repository on Github. - Clone the repo to your laptop.
- Initialize the repository
yarn init
(make sure to fill it out with correct values) - Install dependencies with
yarn
. - Build the project on your laptop.
- Test each route with Postman, making sure to test both valid and invalid data.
- Make git commits as you complete each requirement.
- When everything is complete, push the final commit back up to GitHub
- Submit both two URLs on Brightspace: the GitHub repo URL and the URL to your deployed Render API.
Remember
Pay attention to clean code practices.