id = 10
title = "Identity & Access"
instructions = """
Most real APIs don't let just anyone in. They require you to prove who you are.
That's where JWT comes in.

JWT (JSON Web Token) is the industry standard for stateless authentication.
After you log in, the server hands you a signed token. You attach it to every
protected request. The server verifies the signature without ever hitting a
session database. The token itself is the proof.

A JWT has three parts separated by dots:

  xxxxx.yyyyy.zzzzz
    │       │       └─ Signature : HMAC proof the server issued this
    │       └───────── Payload  : your claims (who you are, when it expires)
    └───────────────── Header   : algorithm (HS256) and type

You pass it on every protected request like this:

  -H "Authorization: Bearer <your-token>"

---

Briefing:
Your coworkers at the grocery store won’t stop talking about a new app called
“BookFace”. Owing to peer pressure and FOMO, you decide to make an account and
add a few coworkers but you do it via cURL cuz you're cool like that.

Base URL: http://localhost:8080

Available endpoints:
  POST /signup    : Create your account
  POST /login     : Authenticate and receive a JWT
  GET  /profile   : View your profile (JWT required)
  PUT  /friends   : Add friends to your profile (JWT required)

Your mission:
  1. Sign up with username "curl-quest" and a 6-12 character password.
  2. Log in, the server will return a JWT token.
  3. Use the token to GET /profile and see your empty friends list.
  4. Use the token to PUT /friends to add at least 2 friends.
  5. GET /profile again to confirm your friends appear.

---
  
"""

solutions = [
    """# 1. Sign up
curl -s -X POST -H "Content-Type: application/json" \\
     -d '{"username":"curl-quest","password":"hello123"}' \\
     http://localhost:8080/signup""",
    """# 2. Log in and grab the token
curl -s -X POST -H "Content-Type: application/json" \\
     -d '{"username":"curl-quest","password":"hello123"}' \\
     http://localhost:8080/login""",
    """# 3. View profile (replace <token> with what login returned)
TOKEN="<paste token here>"
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8080/profile""",
    """# 4. Add 2 friends
curl -s -X PUT -H "Content-Type: application/json" \\
     -H "Authorization: Bearer $TOKEN" \\
     -d '{"friends":["Alice","Bob"]}' \\
     http://localhost:8080/friends""",
    """# 5. Confirm
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8080/profile""",
]

[setup]
seed = [
    "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL)",
    "CREATE TABLE IF NOT EXISTS friends (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, friend_name TEXT NOT NULL, FOREIGN KEY(user_id) REFERENCES users(id))",
]

[server]
port = 8080

[[verify.checks]]
sql = "SELECT COUNT(*) FROM users WHERE username = 'curl-quest'"
expected = "1"
error = "No account found for 'curl-quest'. Sign up first: curl -X POST -H \"Content-Type: application/json\" -d '{\"username\":\"curl-quest\",\"password\":\"hello123\"}' http://localhost:8080/signup"

[[verify.checks]]
sql = "SELECT COUNT(*) FROM friends WHERE user_id = (SELECT id FROM users WHERE username = 'curl-quest')"
expected = "2"
error = "Expected 2 friends for 'curl-quest'. Use PUT /friends with your JWT: curl -X PUT -H \"Authorization: Bearer <token>\" -H \"Content-Type: application/json\" -d '{\"friends\":[\"Alice\",\"Bob\"]}' http://localhost:8080/friends"
