Start learning free

LESSON 102 OF 188 · BACKEND: USERS AND SECURITY

Project: Reviews by Logged-in Users

Practice

This project puts the module together. Logged-in customers can review a product: a number of stars and a short text. Each review is a row in a new reviews table that keeps the product and the user who wrote it.

The author comes from the login. @login_required already finds the user from the token and passes it to your function. Save user["id"] as the author, never a user_id from the body: the client writes the body, so it could claim to be anyone. The same idea on another route:

@app.post("/wishlist")
@login_required
def add_to_wishlist(user):
    data = request.get_json()
    db.execute("INSERT INTO wishlist (user_id, product_id) VALUES (?, ?)", (user["id"], data["product_id"]))
    db.commit()
    return jsonify({"message": "Added"}), 201

Before saving, check the request in this order: the product must exist (404 if not), the stars must be a whole number from 1 to 5 (400, naming the field), and the user must not have reviewed this product before (409 Conflict). A request without a login never reaches your function: the decorator answers 401.

Ana signs up (she gets id 2) and logs in; the admin, already in the table, is user 1. Your route must answer:

POST /products/3/reviews   no token       {"stars": 5, "text": "Small but bright"}
   →  401  {"error": "Login required"}
POST /products/3/reviews   Ana's token    {"stars": 5, "text": "Small but bright", "user_id": 1}
   →  201  {"id": 1, "product_id": 3, "stars": 5, "text": "Small but bright", "user_id": 2}
POST /products/3/reviews   Ana's token    {"stars": 1, "text": "Changed my mind"}
   →  409  {"error": "You already reviewed this product"}
POST /products/1/reviews   Ana's token    {"stars": 6, "text": "Best mug ever"}
   →  400  {"error": "Stars must be a whole number from 1 to 5", "field": "stars"}
POST /products/1/reviews   Ana's token    {"stars": 0, "text": "Broke on day one"}
   →  400  {"error": "Stars must be a whole number from 1 to 5", "field": "stars"}
POST /products/99/reviews  Ana's token    {"stars": 4, "text": "Nice"}
   →  404  {"error": "Product not found"}
POST /products/3/reviews   admin's token  {"stars": 3, "text": "Too dim for reading"}
   →  201  {"id": 2, "product_id": 3, "stars": 3, "text": "Too dim for reading", "user_id": 1}

Your task: create the reviews table and add POST /products/<int:product_id>/reviews with @login_required. Check the product, the stars and an earlier review by the same user, save the review with the logged-in user as its author, and answer 201 with the new review.


Assignment
Follow the Coding Tutorial to create the reviews table and build the add_review route, one check at a time.


Hint
The function gets user first, from the decorator, then product_id from the path, like get_order. Do the checks in the order product, stars, earlier review, and only then insert and commit.


STEP 1 OF 10
    Ctrl + Enter to check