Start learning free

LESSON 159 OF 173 · BACKEND: BACKEND WITH AI

The AI Left the Door Open

Practice

An AI assistant wrote the route the shop's admin uses to delete a product. Here is the AI's version:

@DeleteMapping("/products/{productId}")
Object deleteProduct(@PathVariable int productId, HttpServletRequest request) {
    int deleted = db.update("DELETE FROM products WHERE id = ?", productId);
    if (deleted == 0) {
        return ResponseEntity.status(404).body(Map.of("error", "Product not found"));
    }
    return ResponseEntity.noContent().build();
}

Every line is right, and a quick try works. The hole is a line that isn't there: the route never asks who is calling, so anyone on the internet can delete every product.

A route that changes data checks the caller first, and there are two ways to refuse. 401 means "we don't know who you are": no token, or a token the shop never gave out. 403 Forbidden means "we know who you are, and you may not do this". The helper currentRole(request) reads the token from the Authorization header and gives that user's role from TOKENS, or null. Here is the first check on another route:

@GetMapping("/account")
Object account(HttpServletRequest request) {
    String role = currentRole(request);
    if (role == null) {
        return ResponseEntity.status(401).body(Map.of("error", "Login required"));
    }
    return Map.of("role", role);
}

The tests run in this order, on one database:

DELETE /products/8   (no token)                →  401  {"error": "Login required"}
DELETE /products/8   Bearer ana-token-123      →  403  {"error": "Admins only"}
GET    /products/8                             →  200  {"id": 8, "name": "Gift card", "price": 50, "category": null, "stock": 999}
DELETE /products/8   Bearer admin-token-456    →  204  (empty)
GET    /products/8                             →  404  {"error": "Product not found"}
DELETE /products/8   Bearer admin-token-456    →  404  {"error": "Product not found"}
DELETE /products/3   Bearer let-me-in          →  401  {"error": "Login required"}
DELETE /products/99  (no token)                →  401  {"error": "Login required"}
GET    /products/3                             →  200  {"id": 3, "name": "Lamp", "price": 29, "category": "home", "stock": 1}

Your task: rewrite deleteProduct. Delete the product and answer 204, or 404 if there was none. Then add the checks at the top: 401 {"error": "Login required"} when there is no role, and 403 {"error": "Admins only"} when the role isn't "admin".


Assignment
Follow the Coding Tutorial to rewrite deleteProduct so only the admin can delete a product.


Hint
Both checks go before db.update: once the DELETE runs, the product is gone, whatever you answer. The 401 check (role == null) comes first, then !role.equals("admin") for the 403.


STEP 1 OF 9
    Ctrl + Enter to check