# Implementation Plan: Email/Password Login with Server-Side Sessions

## Overview

Add email/password authentication to the existing Flask app. Users can register,
log in, and log out. Sessions are stored server-side in the existing SQLite
database (not in Flask's default signed cookie), so sessions can be expired and
revoked. The `users` table already exists in `models.py` but is currently unused;
this plan wires it up.

Estimated scope: `app.py`, `models.py`, two new templates, one new test file.

## 1. Database (models.py)

- Inspect the existing `users` table and make sure it has the columns we need:
  `id`, `email` (unique), and `password_hash`. Add a migration if anything is
  missing.
- Add a `sessions` table: session token (primary key), `user_id` foreign key,
  creation time, and expiry time.
- Add data-access functions in `models.py`:
  - create a user
  - look a user up by email
  - create a session for a user
  - resolve a session token to a user
  - delete a session (logout / expiry)

## 2. Password handling

- Never store plaintext passwords. Use Werkzeug's password hashing helpers
  (`generate_password_hash` / `check_password_hash`), which ship with Flask,
  when creating users and when checking credentials at login.

## 3. Routes (app.py)

- `GET /register` — render the registration form.
- `POST /register` — validate the form, reject duplicate emails, hash the
  password, create the user, redirect to the login page.
- `GET /login` — render the login form.
- `POST /login` — look the user up by email, check the password, create a
  session row, set the session cookie, redirect to `/`.
- `POST /logout` (or GET) — delete the session row, clear the cookie,
  redirect to `/`.
- Add a `before_request` handler (or a helper) that reads the session cookie,
  loads the current user, and makes it available to templates via `g`.
- Add a `login_required` decorator and apply it to item creation so anonymous
  visitors can't create items.

## 4. Templates (templates/)

- `register.html` — email + password form, extends the base layout.
- `login.html` — email + password form with an error area for failed logins.
- Update the base/navigation template to show "Log in / Register" when logged
  out and the user's email + "Log out" when logged in.

## 5. Session cookie

- Cookie name: `session_id`, value: the session token (a long random string,
  e.g. from `secrets.token_urlsafe`).
- Set `HttpOnly` so JavaScript can't read it, `SameSite=Lax`, and `Secure`
  when running over HTTPS in production.
- Sessions expire after a fixed lifetime (e.g. 7 days); expired sessions are
  treated as logged out and cleaned up.

## 6. Tests (tests/test_auth.py)

Add pytest tests covering:

- registering a new user creates the account and hashing is applied
- registering with a duplicate email fails
- login with the correct password succeeds and sets a cookie
- login with a wrong password fails
- logout ends the session
- a protected route redirects anonymous users to /login

Run the full suite (`pytest`) plus the 3 existing tests to make sure nothing
regressed.

## 7. Security checklist

- Passwords hashed (Werkzeug), never logged or stored in plaintext.
- Login error messages should be generic ("invalid email or password") so the
  form doesn't reveal which emails are registered.
- Session tokens are random and unguessable; a fresh token is issued at login.
- Session cookie flagged HttpOnly + SameSite as above.

## Order of work

Database functions first, then password handling, then register, then
login/logout and current-user loading, then protecting routes, templates along
the way, tests at the end. Commit after each working piece.
