Skip to content

labs15-music-meteorologist/backend

Repository files navigation

Music Meteorologist Frontend

Frontend Deployment (Coming Soon)

Visit Backend (See endpoints below)

Music Meteorologist is a fullstack web application that has been built during the Labs15 (1st August 2019 - 30 September 2019) by LambdaSchool students. Each student fulfills a role in the project to collectively build the application. (Roles listed below)

Music Meteorologist provides a web application where users can play a guessing game and get to know themself better. A sophisticated Machine Learning model will try to predict better than the user itself if a certain music song will be liked or not. For that a lot of different characteristics of a songs are considered. At the end the user can revisit the assessment of the model and give feedback about its correctness. To deliver this experience a Node.JS Backend and a React.JS Frontend were built.

Built With

  • JavaScript - Language used to make the webpage interactive
  • Node.js - JavaScript runtime for executing JavaScript at the server outside the browser
  • Express.js - Lightweight web framework to bootstrap Node.js APIs
  • PostgreSQL - An advanced object-relational database for production environments
  • Knex.js - A SQL query builder that helps abstracting migrations and DDLs for different database types into a single coherent structure
  • JWT - JSON Web Token for authorization and client side tokens for security
  • Moment.js - Lightweight module to handle dates and times
  • Supertest - A test module for HTTP assertions
  • JEST - Simple JavaScript testing framework

Endpoints

All endpoints are also documented in the automated Postman documentations:

The endpoints URLs are environment specific and contain a word that reflects the project/environment on Heroku.

General

GET [API RUNNING]
https://music-meteorology-production.herokuapp.com
https://music-meteorology-development.herokuapp.com
https://music-meteorology-staging1.herokuapp.com
https://music-meteorology-staging2.herokuapp.com
  • JWT protected (header) ❌
  • payload (body) ❌

API Running Response (200 OK):

Welcome to the [DB_ENV] environment API of Music Meteorologist!

USERS

The base url for user endpoints is /v1/users

GET [ALL USERS]
https://music-meteorology-production.herokuapp.com/v1/users
https://music-meteorology-development.herokuapp.com/v1/users
https://music-meteorology-staging1.herokuapp.com/v1/users
https://music-meteorology-staging2.herokuapp.com/v1/users
  • JWT protected (header) ❌
  • payload (body) ❌

Get Users Response (200 OK):

{
    "users": [
        {
            "id": 1,
            "email": "[email protected]",
            "spotify_user_id": "j3553svv444by33k1dqo189v",
            "user_spotify_api_key": "BQCYlQlNNQRvqFCeNL_XyPzElQoTf66R3lyaHnEHkshqk92oDcGWLrlGDFyGMoCVNg_t6oFpnbE8ELSc44sdsfAwl_DucbDqp7xUrR4W2eDdqv3Ze1Ph7r0g5ITOhno0v9ZSo958LhiEyCi3-5h5jiZQrlg9bgSfDaoj7yaGSnZsyXNM9mJjfBkzXhOfC5Fr45ohiS64Hi_p_pgw",
            "date_of_birth": "1990-08-09",
            "spotify_product_type": "premium",
            "display_name": "Firstname",
            "country": "DE",
            "profile_image_url": null
        },
        {
            "id": 21,
            "email": "[email protected]",
            "spotify_user_id": "j3553svv444gdfdfdf565tzv",
            "user_spotify_api_key": "BQCYlQlNNdfdFSR54XyPzElQoTf66R3lyaHnEHkshqk92oDcGWLrlGDFyGMoCVNg_t6oFpnbE8ELSc44sdsfAwl_DucbDqp7xUrR4W2eDdqv3Ze1Ph7r0g5ITOhno0v9ZSo958LhiEyCi3-5h5jiZQrlg9bgSfDaoj7yaGSnZsyXNM9mJjfBkzXhOfC5Fr45ohiS64Hi_p_pgw",
            "date_of_birth": "1995-02-10",
            "spotify_product_type": "premium",
            "display_name": "Firstname",
            "country": "EN",
            "profile_image_url": null
        }
    ]
}
GET [A USER BY SPOTIFY ID]
https://music-meteorology-production.herokuapp.com/v1/users/spotify/jgdpq16w0y44by33k1dqo189v
https://music-meteorology-development.herokuapp.com/v1/users/spotify/jgdpq16w0y44by33k1dqo189v
https://music-meteorology-staging1.herokuapp.com/v1/users/spotify/jgdpq16w0y44by33k1dqo189v
https://music-meteorology-staging2.herokuapp.com/v1/users/spotify/jgdpq16w0y44by33k1dqo189v
  • JWT protected (header) ❌
  • payload (body) ❌

Found user Response (200 OK):

{
    "id": 1,
    "email": "[email protected]",
    "spotify_user_id": "jgdpq16w0y44by33k1dqo189v",
    "user_spotify_api_key": "BQCYlQlNNQRvqFCeNL_XyPzElQoTf66R3lyaHnEHkshqk92oDcGWLrlGDFyGMoCVNg_t6oFpnbE8ELScwSaGuQGxAwl_DucbDqp7xUrR4W2eDdqv3Ze1Ph7r0g5ITOhno0v9ZSo958LhiEyCi3-5h5jiZQrlg9bgSfDaoj7yaGSnZsyXNM9mJjfBkzXhOfC5Fr45ohiS64Hi_p_pgw",
    "date_of_birth": "1993-08-09",
    "spotify_product_type": "premium",
    "display_name": "Sascha",
    "country": "DE",
    "profile_image_url": null,
    "spotify_playlist_id": null
}

Not found Response (404 NOT FOUND):

{
    "info": "The user with the spotify_id 1 was not found."
}

Server error Response (500 SERVER ERROR):

{
    "error": "An error occurred during fetching an user with the id 1."
}
GET [A USER BY ID]

https://music-meteorology-production.herokuapp.com/v1/users/1
https://music-meteorology-development.herokuapp.com/v1/users/1
https://music-meteorology-staging1.herokuapp.com/v1/users/1
https://music-meteorology-staging2.herokuapp.com/v1/users/1

  • JWT protected (header) ❌
  • payload (body) ❌
  • ID is defined with used route at the end
  • USER ID gets validated with validateUserId middleware - extra responses below

Found user Response (200 OK):


{
"id": 1,
"email": "[email protected]",
"spotify_user_id": "jgdpq16w0y44by33k1dqo189v",
"user_spotify_api_key": "BQCYlQlNNQRvqFCeNL_XyPzElQoTf66R3lyaHnEHkshqk92oDcGWLrlGDFyGMoCVNg_t6oFpnbE8ELScwSaGuQGxAwl_DucbDqp7xUrR4W2eDdqv3Ze1Ph7r0g5ITOhno0v9ZSo958LhiEyCi3-5h5jiZQrlg9bgSfDaoj7yaGSnZsyXNM9mJjfBkzXhOfC5Fr45ohiS64Hi_p_pgw",
"date_of_birth": "1993-08-09",
"spotify_product_type": "premium",
"display_name": "Sascha",
"country": "DE",
"profile_image_url": null
}

Not found Response (404 NOT FOUND):


{
"info": "The user with the id 1 was not found during validation."
}

Server error Response (500 SERVER ERROR):


{
"error": "An error occurred during fetching an user with the id 1."
}

POST [REGISTER A USER]

https://music-meteorology-production.herokuapp.com/v1/users/register
https://music-meteorology-development.herokuapp.com/v1/users/register
https://music-meteorology-staging1.herokuapp.com/v1/users/register
https://music-meteorology-staging2.herokuapp.com/v1/users/register

  • JWT protected (header) ❌
  • payload (body) ✔️

Example Request:


{
"email": "[email protected]",
"spotify_user_id": "dagsffrhr",
"user_spotify_api_key": "sdasdasdasd",
"date_of_birth": "1981-08-01",
"spotify_product_type": "premium",
"display_name": "Testgg",
"country": "UK",
"profile_image_url": "testdfdd"
}

Created user Response (201 CREATED):


{
"id": 2,
"email": "[email protected]",
"spotify_user_id": "dagsffrhr",
"user_spotify_api_key": "sdasdasdasd",
"date_of_birth": "1981-08-01",
"spotify_product_type": "premium",
"display_name": "Testgg",
"country": "UK",
"profile_image_url": "testdfdd"
}

User data not complete Response (400 BAD REQUEST):


{
"warning": "Not all information were provided to create a new user."
}

Server Error Response (500 SERVER ERROR):


{
"error": "An error occurred during the creation of a new user."
}

DELETE [DELETE A USER]

https://music-meteorology-production.herokuapp.com/v1/users/3
https://music-meteorology-development.herokuapp.com/v1/users/3
https://music-meteorology-staging1.herokuapp.com/v1/users/3
https://music-meteorology-staging2.herokuapp.com/v1/users/3

  • JWT protected (header) ❌
  • payload (body) ❌
  • USER ID gets validated with validateUserId middleware - extra responses below

Updated user Response (200 OK):


{
"message": "The user with the id of 3 was successfully deleted."
}

Database error Response (500 SERVER ERROR):


{
"error": "The user with the id of 3 could not be deleted."
}

PUT [UPDATE A USER]

https://music-meteorology-production.herokuapp.com/v1/users/3
https://music-meteorology-development.herokuapp.com/v1/users/3
https://music-meteorology-staging1.herokuapp.com/v1/users/3
https://music-meteorology-staging2.herokuapp.com/v1/users/3

  • JWT protected (header) ❌
  • payload (body) ✔️
  • USER ID gets validated with validateUserId middleware - extra responses below
  • USER gets validated with validateUser middleware - extra responses below

Example Request:


{
"email": "[email protected]",
"spotify_user_id": "update",
"user_spotify_api_key": "FromThe",
"date_of_birth": "2020-08-01",
"spotify_product_type": "premium",
"display_name": "Future",
"country": "US",
"profile_image_url": "nice"
}

Updated user Response (200 OK):


{
"message": "The user with the id 3 has been successfully updated!"
}

Database error Response (500 SERVER ERROR):


{
"error": "An error occurred within the database thus the user with the id 3 could not be updated."
}

Server error Response (500 SERVER ERROR):


{
"error": "An error occurred during updating the user with the id 3."
}

Middleware

Middleware is divided into 2 different types:

  • Middleware that restricts access to certain routes for authorization ❌ (Soon)
  • Middleware that validates request body payloads ✔️

Whenever for a route a certain ID or Resource object like a user is required these routes are protected by validation middleware and returning generic responses when used by badly shaped requests. Thus every endpoint documented has a indication of what generic validation responses it will provide when used incorrectly.

Authorization is handled through Java Web Token (JWT). A token authorizes a user to access JWT protected routes for 1 hour until it a relogin needs to happen.

To submit a JWT along a HTTP request add the JWT that can be acquired through the unprotected login route and then set it as "Authorization" "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWJqZWN0IjoxMSwiZW1haWwiOiJrZXZpbkB0ZXN0LmNvbTY2NiIsImlhdCI6MTU2NDY4MzgzMiwiZXhwIjoxNTY0Njg3NDMyfQ.t3LhcZ5VppqZMSPL4LAWcllEqKzI9nTZ8VNseMZzoVE" as a Header for the request.

The JWT is randomly generated and only the specific provided one from login will be valid.

Bad Authorization Response (401 UNAUTHORIZED):


{
"warning": "Authorization failed. Access denied!"
}

User validation no body data (400 BAD REQUEST):


{
"warning": "Missing user data entirely."
}

User validation user data not complete (400 BAD REQUEST):


{
"warning": "Missing required email or spotify_user_id or user_spotify_api_key or date_of_birth or spotify_product_type or display_name or country information for an user."
}

User ID validation user not found (404 NOT FOUND):


{
"info": "The user with the id 3 was not found during validation."
}

User ID validation server error (500 SERVER ERROR):


{
"error": "An error occurred during validation of the user."
}

JSON Responses

For JSON responses there are 4 different content types available:

  • A JSON containing a direct resource { "id": 1, "email": "[email protected]" } or a JSON containing a resource { "resource": [{"id": 1, "email": "[email protected]"}, {"id": 2, "email": "[email protected]"}] } or a JSON containing a message string { "message": "text" } means that the request was successful and data is returned to the client. So the request happened.
  • A JSON containing a { "info" : "text" } means that the request was semantically not useful as for example a deletion of no elements or search for no existing user. It happened but was useless.
  • A JSON containing a { "warning": "text"} means that something went wrong because of how the request was shaped and it did not happen.
  • A JSON containing a { "error" : "text" } means that something went wrong internally during the request and it did not happen.

HTTP Status Codes

Next to the custom JSON response system also HTTP Status Codes were used.

Installation

Local PostgreSQL Installation

Download and install the correct Installation Package for your OS.

During installation set a master password and keep it safe.

Start the PostgreSQL Shell (PSQL) and press multiple times enter until password is prompted. The password was set during the installation of PostgreSQL.

Create a new user by inserting this command and use a password of your choosing. Don't forget about the closing ; otherwise the command is incorrect.


CREATE ROLE music WITH LOGIN PASSWORD 'iamanunsecurepassword';

Set the newly created user to a superuser by inserting this command.


ALTER ROLE music superuser createrole createdb replication bypassrls;

Create a new database that can be used for the local development installation of the music meteorologist application. For that open pgadmin4, uncollapse servers, select a existing server and rightlick to create a new database.

The new database could be named music_dev for example. Make sure to use that name in the .env file as environment variable.

Rightclick on the database and click on Properties to assign a user to the database. Make sure to select the newly "music" user as the owner of the database.

Environment Variables

This application makes usage of environment variable to set the PORT the server listens on, to connect to the database and to let the application know in which environment it currently runs so it can behave accordingly.

On Heroku the Config Vars accepted configurations are:


DATABASE_URL=provided postgres connectioN URI
PORT=5000
DB_ENV=development OR deployedDevelopment OR staging1 OR staging2 or production
SERVER_URL=https://music-meteorology-development.herokuapp.com/ or https://music-meteorology-production.herokuapp.com/ or https://music-meteorology-staging1.herokuapp.com/ or https://music-meteorology-staging2.herokuapp.com/
DEPLOYMENT=development or production or staging1 or staging2

For a local installation and connection to a local PostgreSQL database accepted environmental variables are:

.env file


PORT=5000
DATABASE_DB=your_postgres_database_name
DATABASE_USER=your_postgres_database_user
DATABASE_PASSWORD=your_postgres_database_password
DB_ENV=development
SERVER_URL=localhost
DEPLOYMENT=localhost

Installing the Application

This application required a installation of Node.js to make JavaScript executable on the server side.

You can check with node -v in the terminal if Node.js was installed and which version you got.

Simply run this command in terminal on the folder level where package.json is located.


npm i

Now a package.lock and node_modules folder should be present containing all external modules and dependencies to start up the application.

To start the application simply run this command in command line on the same folder level where package.json is located.


npm run server

To start the server in on a remote server like Heroku a different start command is used:


npm start

Testing

Tests for the Backend are beeing handled through the npm module supertest. To run the tests use the following start script:


npm run test

Reporting / Logging

For reporting of applications errors Sentry is used. A new route that will always throw an error was established called:


https://music-meteorology-production.herokuapp.com/debug-sentry
https://music-meteorology-development.herokuapp.com/debug-sentry
https://music-meteorology-staging1.herokuapp.com/debug-sentry
https://music-meteorology-staging2.herokuapp.com/debug-sentry

Bugs with sentry are visible within the dashboard and can be intraged into a Slack channel.

Architecture and Workflow

The application is split into two tables. One User can have many taste_profiles. One taste_profile can have one user. This is because a user can like different kind of music like Metallica and Frank Sinatra at the same time. By capturing different tastes a more complete image of the users musical taste can be delivering to the datascience model

For the Backend Node.JS with Express.JS was used to bootstrap the server and thus the endpoints. For the database in development, staging1, staging2 and production environment locally and remotely PostgreSQL was used. For authorization and restriction of endpoints JWT between the Frontend client and the Backend was used. The deployment was made on Heroku where the environmental variables are configured and tweaks via Heroku Cli were made to execute knex migrations and seeds.

For testing of the server and endpoints supertest and JEST was used.

Project Requirements and Documentation

Database Schema

Authors

Role: Team Lead

Role: Full Stack Web Developer

Role: Data Scientist

License

This project is licensed under the MIT License - see the LICENSE file for details



About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published