Assignment 3.2: Generic Social Media Backend

Written by Michael, with help and feedback from Kashif Nazir. Inspired by the Flutterer assignment from CS106AX

Due Sat May 27 11:59pm PT

Submissions not accepted after Mon May 29 11:59pm PT.

Backstory: Whoops! The person who wrote the backend for the app just ghosted [vague acquaintance]. They left the server running, but y'all don't have access to the code, so [vague acquaintance] can't add their cool new feature. Guess you'll have to rewrite the API from scratch first. (Your acquaintance says they're too busy working on the five year feature roadmap to do it themself... Something about this division of labor and compensation scheme feels off, but no time to think about that right now, gotta keep moving!)

This assignment closes the loop on assignment 3.1 by having you implement the API backend for the Generic Social Media App.

Learning goals

Through this assignment, you will

Overview

Before starting this assignment, you will need to install MongoDB. Follow the instructions on that page, which include steps to verify your installation is successful.

Then download the starter code and run npm install as usual. You will implement the API in api/index.js.

You don't need a fully working assignment 3.1 to work on this assignment, but it may be helpful for end-to-end testing. To use your assignment 3.1 code, copy all the files from the public/js folder in your assign3.1 into this assignment's public/js folder. Then, uncomment the line in apirequest.js to set API_URL to "/api". This will have your apiRequest function use the API you write for this assignment.

We have provided a small page that you can use to make API requests. When you go to localhost:1930, you will see links to the API tester (HTML in test_api.html) and the app (HTML in social.html). The API tester works like this:

Before using the API tester, open js/test_api.js and fill in REMOTE_API_URL with your API URL from assignment 3.1. This will allow you to compare the structure of your API responses with ours. You may also find it useful to review the code in _doReq to confirm how requests are formed.

Database structure

You will store the data for your app in a MongoDB database. In your code, you must use the DATABASE_NAME variable to select the database to store and retrieve data. This is set up so we can point your API at a different database for grading. The default database name is set to cs193x_assign3.

The database contains two collections: users and posts. The documents in each collection have the following fields:

users

  • id: the user's ID. This should always be unique. This won't be enforced by MongoDB, so you should be careful not to store two user documents with the same id.
  • name: the user's display name.
  • avatarURL: the user's avatar URL.
  • following: an array of the users this user is following. Each element of the array is a user ID. The IDs in the array should be unique (again, not enforced by MongoDB).

posts

  • userId: the user ID of the poster.
  • time: the date/time the user made the post. This is a JavaScript Date object.
  • text: the text of the post.

Initialization

To initialize (or reset) the database, run mongosh init_db.mongodb from your terminal. (On Windows, replace mongosh with the full path to mongosh.exe, e.g. "PATH_WHERE_YOU_EXTRACTED_THE_ZIP_FILE\bin\mongosh.exe"; use tab completion to enter the path more easily.)

After running this command, your database will look like this:

> use cs193x_assign3
switched to db cs193x_assign3
> db.users.find()
{ "_id" : ObjectId(<...>), "id" : "mchang", "name" : "Michael", "avatarURL" : "images/stanford.png", "following" : [ ] }
> db.posts.find()
{ "_id" : ObjectId(<...>), "userId" : "mchang", "time" : ISODate(<...>), "text" : "Welcome to the Generic Social Media App!" }

API description

You are implementing the same API as you used in assignment 3.1. A few assignment 3.2 specific details:

  • All API endpoints are under the /api prefix.
  • You can assume the request body, if present, will be a well-formed JSON object. That is, you don't have to worry about body-parser failing to parse the request body.
  • You are expected to generate all of the errors listed in the specification. For each, you should set the HTTP status according to the spec, and your response should be an object that includes an error key with a message describing the error. Your messages should be human-readable and descriptive. They don't need to match ours exactly.
  • You do not need to edit the / route to match the example in the spec.
  • You do not need to handle any concurrency issues, e.g. getting two requests at the same time to create the same user.

Here are a few tips for implementing these endpoints:

Submitting

When you are finished, please submit your assign3.2 folder (without node_modules) to Paperless.