beejjorgensen / osu-cs493-assignment-2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Assignment 2

The goal of this assignment is to start using a real database to store application data. The assignment requirements are listed below.

You are provided some starter code in this repository that implements a solution to assignment 1. The starter code's API server is implemented in server.js, and individual routes are modularized within the api/ directory. Tests and a testing environment for the API are included in the tests/ directory. You can import these tests into either Postman or Insomnia and build on them if you like. Note that, depending on where you're running your API server, you may need to update the baseUrl variable in the included testing environment to reflect the URL for your own server.

The starter code also includes an openapi.yaml file in the public/ directory. You can import this file into the OpenAPI editor at https://editor.swagger.io/ to generate documentation for the server to see how its endpoints are set up.

Feel free to use this code as your starting point for this assignment. You may also use your own solution to assignment 1 as your starting point if you like.

Use a database to power your API

Your overarching goal for this assignment is to modify the API server to use a database to store the following resources:

  • Businesses
  • Reviews
  • Photos

You may choose either MySQL or MongoDB for this purpose (or another DB implementation you're interested in, with permission). Whichever database you choose, it should completely replace the starter code's existing JSON/in-memory storage for these resources. In other words, you should update all API endpoints in the original starter code to use your database.

You should use the official MySQL Docker image or the official MongoDB Docker image from Docker Hub to power your database. Whichever database you choose, your implementation should satisfy the criteria described below.

Database initialization

Before you run your application for the first time, you'll have to make sure your database is initialized and ready to store your application data. Use the mechanisms described below to initialize your database when you launch the database container, so the database is ready to use when you launch your app.

MySQL

If you're using MySQL, you should make sure to set the following environment variables when launching your database container:

  • MYSQL_ROOT_PASSWORD - This specifies the password that is set for the MySQL root user. You can also use MYSQL_RANDOM_ROOT_PASSWORD to allow the container to generate a random password.

  • MYSQL_DATABASE - This specifies the name of a MySQL database to be created when your container first starts.

  • MYSQL_USER and MYSQL_PASSWORD - These are used to create a new user, in addition to the root user, who will have permissions only for the database named in MYSQL_DATABASE. This is the user you should use to connect to your database from your API server.

If you use Sequelize to interact with your MySQL database, Sequelize will handle the creation of tables for you.

MongoDB

If you're using MongoDB, you should make sure to set the following environment variables when launching your database container:

  • MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD - These are used to create the MongoDB root user.

  • MONGO_INITDB_DATABASE - This specifies the name of a MongoDB database to be created when your container first starts.

While it is a security risk to do so in a production setting, it's fine if you interact with the database from your API server as the ROOT user for this assignment. Because MongoDB generally uses a "create on first use" approach, you won't have to worry about initializing collections.

Database organization

Your database should store all resource data (i.e. businesses, photos, and reviews) for the API. Because the resources you're working with are closely tied to each other (e.g. each review is tied to both a specific business and a specific user), you'll have to think carefully about how you organize and access them in your database. Some suggestions are included below for each database.

MySQL

If you're using MySQL, you will likely want to use foreign keys to link reviews and photos to their corresponding business. If you're using Sequelize, you can use associations to automatically manage foreign keys for you.

MongoDB

If you're using MongoDB, there are many valid ways to organize data in your database. For example, you could use three separate collections to store businesses, reviews, and photos. In this case, you can either use $lookup aggregation or multiple queries to gather data for a specific business (i.e. for the GET /businesses/{id} endpoint).

Alternatively, you could store all photos and reviews as subdocuments of their corresponding business document. In this case, you'll likely want to use a projection to omit the photo and review data from businesses when returning a list of all businesses (i.e. from the GET /businesses endpoint). You'll also have to think carefully about how you find data for a specific user, e.g. a specific user's photos or reviews. Do do this, you can use subdocument array queries to select businesses with reviews/photos by the specified user, and then you can use some custom JS to select only matching reviews/photos from those businesses. Alternatively, you can use MongoDB's aggregation pipeline to structure a single query to fetch exactly the reviews/photos you're interested in.

Connecting the API server to your database

Your API server should read the location (i.e. hostname, port, and database name) and credentials (i.e. username and password) for your database from environment variables.

Docker Compose specification

You should write a simple Docker Compose specification that launches your entire application (i.e. API server and database server) from scratch with a single command. Your Docker Compose specification in this case will specify two containers, one running your API server and one running your database server.

When defining your Compose specification, make sure to specify the correct environment variables to initialize the database container and to allow the API server to connect to the database container, and make sure you publish the appropriate port(s) so you can communicate with your API. Note that there is already a Dockerfile in this repository representing an image to run your API server, and you can reference this Dockerfile within your Compose specification.

It's a good idea to think about the Docker Compose specification as a "production" version of your app. In other words, get your server working the way you want them to without Docker before you worry about getting things working with Compose. It'll lengthen your development cycle too much if you continually need to restart the Compose application every time you make changes to your server code.

Extra credit: Use Mongoose

Mongoose is an object modeling tool for MongoDB that's very similar in spirit to Sequelize for MySQL. If you choose to use MongoDB as your database, you can earn up to 10 points of extra credit by using Mongoose instead of the native MongoDB driver for Node.js. To earn this extra credit, you must use Mongoose for all of your database interactions.

Submission

Make sure your completed files are committed and pushed by the assignment's deadline to the main branch of your GitHub repo. Check your repo to make sure your files are submitted there.

Grading criteria

In order to receive a grade, the following needs to work:

  1. Open a new shell, change to the project directory, and export necessary environment variables.
  2. In that shell, run docker compose up.
  3. Wait for the app to come up.
  4. Open another shell, change to the project directory, and export necessary environment variables.
  5. In that shell, run sh ./runtests.sh.

If you have your own cURL tests, you can put them in runtests.sh. If you are using the supplied Postman tests, put this in your runtests.sh:

cd tests
newman run -e api_tests.postman_environment.json api_tests.postman_collection.json

(And if you install newman, it should run the tests.)

If the steps above fail to appreciably complete, I'll let you know and you can fix it so I can grade it.

This assignment is worth 100 total points, broken down as follows:

  • 20 points: chosen database runs in a Docker container that is correctly initialized (e.g. by using appropriate environment variables the first time the container is launched)

  • 60 points: all existing API endpoints in the starter code are modified to use your database

  • 10 points: database connection parameters are correctly provided to API server via environment variables

  • 10 points: a Docker Compose specification can be used to launch the entire application from scratch

As described above, you can also earn up to 10 points of extra credit for using Mongoose in conjunction with MongoDB.

About


Languages

Language:JavaScript 99.2%Language:Dockerfile 0.8%