Start learning free

LESSON 98 OF 173 · BACKEND: USERS AND SECURITY

Validate Everything

Practice

A client can send anything: an email without an @, a password of one letter, a price of -5, a price written as text. Today the shop stores almost all of it. A safe backend validates every value before it stores it.

When a value is wrong, the shop answers 400 Bad Request with a message and the name of the field that is wrong, so an app can show the message next to that box. The starting code has a helper for that answer, invalid(w, field, message), and it already checks the password length. Go's strings package helps with the rest:

strings.Count("bo@shop.io", "@")       // 1
strings.Contains("bo @shop.io", " ")   // true: it has a space
strings.Split("bo@shop.io", "@")       // ["bo" "shop.io"]
data := map[string]string{}
data["email"]                          // "": a missing key gives the zero value

Two Go details matter. A JSON text like "120" can't go into an int field, so the decoder leaves the price at 0. And invalid only writes the answer: the handler keeps running after it, so stop it with return.

POST /register  {"email": "ana.example.com", "password": "secret123"}  →  400  {"error": "Enter a valid email, like ana@example.com", "field": "email"}
POST /register  {"password": "secret123"}  →  400  {"error": "Enter a valid email, like ana@example.com", "field": "email"}
POST /register  {"email": "ana@example.com", "password": "123"}  →  400  {"error": "The password needs at least 8 characters", "field": "password"}
POST /register  {"email": "ana@example.com", "password": "secret123"}  →  201  {"email": "ana@example.com", "id": 2}
PUT /me/password  {"old_password": "secret123", "new_password": "abc"}  (Ana's token)  →  400  {"error": "The password needs at least 8 characters", "field": "new_password"}
POST /products  {"name": "Desk", "price": -5}  (admin's token)  →  400  {"error": "The price must be a whole number from 1 to 10000", "field": "price"}
POST /products  {"name": "Desk", "price": "120"}  (admin's token)  →  400  {"error": "The price must be a whole number from 1 to 10000", "field": "price"}
POST /products  {"name": "Desk", "price": 120}  (admin's token)  →  201  {"id": 9, "name": "Desk", "price": 120}

Your task: write validEmail(email string) bool, then check the email in the POST /register handler and the price in addProduct, each answering with invalid and stopping with return.


Assignment
Follow the Coding Tutorial to write validEmail and add the email and price checks.


Hint
An email is valid when it has exactly one @, no space, a name before the @ and a dot after it. A price is wrong below 1 or above 10000; a price sent as text stays 0, so "below 1" catches it too.


STEP 1 OF 11
    Ctrl + Enter to check