RESTful API Project - Candy


The Project

The overview section for REST can be found here. The setup instructions for REST are here. Read on for details on the REST Candy project.

Candy

This FiveThirtyEight article explores a data-driven approach to understanding candy. We downloaded a snapshot of the data. You can read more about the data here about which candy is better, along with nutritional information and price. In this project, let’s assume that our RESTful API is maintaining this dataset on an ongoing basis.

A starter database schema would look like this:

DROP TABLE IF EXISTS candy;

CREATE TABLE candy(
    id              SERIAL PRIMARY KEY,
    competitorname	TEXT,
    chocolate	        BOOLEAN,
    fruity	          BOOLEAN,
    caramel	          BOOLEAN,
    peanutyalmondy	  BOOLEAN,
    nougat	          BOOLEAN,
    crispedricewafer  BOOLEAN,
    hard	            BOOLEAN,
    bar	              BOOLEAN,
    pluribus	        BOOLEAN,
    sugarpercent	    DECIMAL,
    pricepercent	    DECIMAL,
    winpercent        DECIMAL
);

You can use an PostgreSQL COPY command to copy this into the table directly. Or you can adapt the code for Bechdel to do a batch import via psycopg2.

REST1: Basic Resources and Resource Methods

We will still be following the merge request and tagging pattern. Please tag your code as rest1 on the master branch when it is merged.

In this initial iteration, we’re looking to get the basics working. In particular, we’ll be looking at getting a few types of resource methods working, to perform the following functions

  • List All Keys,
  • List All Candy, and
  • Show Candy Details.
    These are not the actual APIs, they are the descriptive names of the functionality provided by the APIs.
    Remember that RESTful APIs operate on resources. In the case of Candy data, the resource is the candy data itself.
    The APIs, will be various operations on the candy data. For example:
    List All Keys will return all of the data as primary keys; The api could look like /candy/keys
    List All Candy shows essentially the entire table, and could look like candy/ Show Candy Details will give the details about one row based on the primary key provided, and could look like `/candy/{id}.
    • Note that the id could be provided in the URL or as a query string

To do this, you will need to determine and name your resources, and then create endpoints and resource methods for those resources. All responses must be in JSON format and follow the RESTful guidelines.

Grading REST1 ( 40 points)

  • (15pts) APIs correctly implemented
  • (15pts) Test cases implemented & pass
  • (05pts) RESTful API standards followed
  • (05pts) Good code maintainability and quality

REST1 Candy

Beware of decimal conversion between PostgreSQL, Python, and JSON via HTTP. Reviewing how Decimal works in Python and psycopg2 may be worth your time.

Test Case Sketches

  • When using List All Keys, I should get 85 different keys
  • When I list List All Keys and List All Candy, I should get the same count
  • When I use List All Candy, the results should have an entry with the data from the Baby Ruth column, including the same digits of precision.
  • If I use Show Candy Details on Baby Ruth, I should get the data from that row, including all digits of precision

REST2: CRUD and Authentication

Create a branch rest2-dev. Please tag your code as rest2 on the master branch when it is merged.

This iteration, you will need to provide only two basic CRUD operations to your data: create and delete. Add those actions to your RESTful API using those conventions.

However, we can’t let just anyone come into the system and make changes, so we need to also provide authentication. Let’s assume that there is a separate way to set and reset accounts. You’ll implement just the core functionality: logging in and logging out - but will thorough testing of ‘happy path’ and ‘problem’ scenarios. From the client side, this will look like this:

  1. Send a POST request to your login endpoint with a username and password.
  • The username/ password should be in the BODY of the POST request
  1. System returns a message that your login was successful and gives you a session key, which is a large random number that nobody should be able to guess.
  2. When attempting to do a CRUD operation, the operation will only work if your request also has the session key. The session key should be sent in the HEADER of each subsequent API call
  3. If you send a request to the logout endpoint, then subsequent CRUD operations won’t work. Note that you must be logged in to trigger a logout, otherwise anyone can log you out!

You will create a users table with a username, password, and session_key field in your database. Your test data should have a user already registered. However, we must store our passwords securely. This means using a one-way encryption function called a hash digest . You can read more about hash digests and salts over on the Common Weakness Enumeration CWE-759. In pseudocode, the way you would compute the hash digest of a password would be: hashed_password = hash(password)

For this project, we’d like you to use the SHA-512 hash digest algorithm. Find a secure way to generate a session key within your technology choice as well, not just the default random number generator for your language.

From the server side, authentication would look like this:

  1. Client sends a request with their username and password to the login endpoint
  2. Server computes the proper hash digest of the password
  3. Server checks if that digest exists in the database table with that username
  4. If so, generate a secure session key. (Otherwise, return a message that login was not successful)
  5. Save the session key to the user’s record in the database
  6. Return a success message with the session key

For Python, these resources will be helpful:

Grading REST2 (70 points)

  • (20pts) CRUD operations work
  • (10pts) Authentication feature works
  • (30pts) Test cases implemented and pass
  • (05pts) RESTful API standards followed
  • (05pts) Good code maintainability and quality

Key Decisions

  • What are the conventions for CRUD operations based on your existing resource?
  • Does it make sense to refactor the meaning of your resource to better fit RESTful conventions?
  • What will be the structure of the APIs? How will you pass the arguments?

REST2 Candy

Test Case Sketches

In each test case, print out (clearly), the test being run and the result of the test. If there are multiple steps in a test case, list the steps/ results as they occur. Make sure you handle the results without crashing!

  • Login test cases.
    • Create a new user accout. Validate it is created
    • Try to login with a non-existent account
    • Try to login with a valid user but invalid password
    • User jason already has an account with the password halloween. The users table initially has a row with username jason, and the hashed (sha512) result of the password! An HTTP request is sent in to the login endpoint with jason and halloween as the credentials. A large session key is sent back.
    • Nobody is logged into the system. An HTTP request makes an attempt to delete Chiclets, and the system does not do the action because nobody is logged in.
      • Note: To safely delete a record, you should get the record for Chiclets, then use the primary key from that query to try and delete the record.
    • The above test case happens, but log in first and then the delete occurs correctly when the given session key is provided.
  • Logout test case. The login test case is first run, then a request to the logout endpoint occurs, providing the given session key. An HTTP delete is attempted and fails.
  • Unauthenticated logout. Log in with the test case above. Attempt to log out without providing a session key. All users remain logged in.
  • Try to logout a user who is not logged in
  • A new candy is added, Bertie Botts Beans. It’s a candy delight, despite it’s odd froggy flavor.
  • An update to a Candy is needed, when people realize that Haribo Twin Snakes is made from real snakes. The new winrate is 20.1 (Apparently some people don’t care).