Start learning free

LESSON 91 OF 173 · BACKEND: USERS AND SECURITY

Customers and Admins

Practice

So far every user is the same kind of user, so the shop can't tell its owner from a shopper. A role column fixes that: each user is a 'customer' or an 'admin', and only admins may add products.

A column with a DEFAULT fills itself in when an INSERT leaves it out. For example, an orders table could start every order as 'new', so an INSERT that gives only the user_id still gets a status:

db.Exec("CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, status TEXT NOT NULL DEFAULT 'new')")
db.Exec("INSERT INTO orders (user_id) VALUES (?)", 2)

A new column also changes SELECT *: it now gives one more column, and a Scan with fewer places fails. The login's query should name the three columns it scans.

There are two ways to say no. 401 means "I don't know who you are: log in". 403 Forbidden means "I know who you are, and you may not do this". A second wrapper, adminRequired, gives the 403. It goes inside loginRequired, which finds the user first and passes it on.

Nobody can sign up as an admin, so the shop creates its owner's account itself in newApp. Ana signs up after that, so she gets id 2:

POST /register  {"email": "ana@example.com", "password": "secret123"}  →  201  {"email": "ana@example.com", "id": 2}
GET /me  (Ana's token)  →  200  {"email": "ana@example.com", "id": 2, "role": "customer"}
POST /products  {"name": "Desk", "price": 120}  (Ana's token)  →  403  {"error": "Admins only"}
POST /products  {"name": "Desk", "price": 120}  (no token)  →  401  {"error": "Login required"}
POST /login  {"email": "admin@example.com", "password": "admin-pass-123"}  →  200  {"token": "…"}
GET /me  (admin's token)  →  200  {"email": "admin@example.com", "id": 1, "role": "admin"}
POST /products  {"name": "Desk", "price": 120}  (admin's token)  →  201  {"id": 9, "name": "Desk", "price": 120}
GET /products/9  →  200  {"category": null, "id": 9, "name": "Desk", "price": 120, "stock": 0}

Your task: give the users table a role column that defaults to 'customer', create the admin account in newApp, name the login's columns, select the role in currentUser, write the adminRequired wrapper, and route POST /products to the given addProduct through adminRequired, inside loginRequired.


Assignment
Follow the Coding Tutorial to give every user a role and let only admins add products.


Hint
Inside SQL written in double quotes, the text 'customer' takes single quotes. Keep loginRequired outside: adminRequired needs the user it finds, and Go's types won't accept the other order.


STEP 1 OF 12
    Ctrl + Enter to check