Start learning free

LESSON 102 OF 173 · BACKEND: USERS AND SECURITY

Project: Reviews by Logged-in Users in TypeScript

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. loginRequired already finds the user from the token and stores it in req.user, a UserInfo. Save req.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", loginRequired, (req: Request, res: Response) => {
  const data = req.body;
  db.prepare("INSERT INTO wishlist (user_id, product_id) VALUES (?, ?)").run(req.user.id, data.product_id);
  res.status(201).json({ message: "Added" });
});

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 middleware 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/:productId/reviews with loginRequired and typed req and res. 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 reviews route, one check at a time.


Hint
The logged-in user is in req.user, stored by loginRequired, and the product's id comes from req.params.productId, turned into a number like orderId in the orders route. Do the checks in the order product, stars, earlier review, and only then insert.


STEP 1 OF 9
    Ctrl + Enter to check

    Auth Reviews Project in TypeScript

    Keep going with TypeScript1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free