Registracija nuo pradžios iki galo
Dabar registracija nuo pradžios iki galo. Šeši failai kaip skirtukai, priklausomybių tvarka: auth.templ → util.go → handlers.go → auth.go → router.go → main.go (forma, pagalbininkas, struktūra, kuri gauna sesijų valdytoją, apdorotojas, maršrutai, sujungimas). Trys — pakeitimai; diff'ai perkelia 1–3 pamokas.
1. internal/web/auth.templ (naujas) — Register forma. Paprasti HTML laukai su minlength/maxlength, atitinkančiais 8–64 taisyklę. (Kol kas jokio CSRF lauko — 6 pamoka.)
2. internal/handlers/util.go (naujas) — vienas pagalbininkas, isUniqueViolation, atpažįstantis Postgres klaidą 23505 (unique-constraint), tad dublikato el. pašto lenktynės tampa draugišku pranešimu, o ne 500.
3. internal/handlers/handlers.go (modify) — Handlers struktūra gauna Sessions *session.Manager lauką, New jį ima, ir atsiranda mažas serverError pagalbininkas (užloguoja tikrą klaidą, grąžina bendrą 500). Home ir Health nepakito.
4. internal/handlers/auth.go (naujas) — RegisterForm (atvaizduoja formą) ir Register, kuris yra visas srautas:
if !validEmail(emailAddr) { fail("Please enter a valid email address."); return }
if password != confirm { fail("Passwords do not match."); return }
hash, err := auth.HashPassword(password) // bcrypt; ErrPasswordLength → draugiškas pranešimas
// dublikato patikra (gražus pranešimas) + CreateUser (lenktynes tvarko isUniqueViolation)
h.Sessions.Create(r.Context(), w, user.ID) // ← išduoda sesiją + nustato slapuką
http.Redirect(w, r, "/", http.StatusSeeOther)
Nukreipimas kol kas veda į / — skydelis prisijungusiems yra 5 pamokos darbas.
5. internal/handlers/router.go (modify) — du maršrutai: GET /register (forma) ir POST /register (apdorotojas).
6. cmd/signflow/main.go (modify) — sukurk valdytoją ir paduok jį:
sessions := session.NewManager(queries, cfg.IsProd())
h := handlers.New(cfg, queries, sessions, log)
Patikrink. Sugeneruok ir paleisk:
sqlc generate && templ generate
go run ./cmd/signflow
Atsidaryk http://localhost:8080/register, sukurk paskyrą (pvz. you@example.com / slaptažodis 8–64 simboliai). Būsi nukreiptas namo, o vartotojų skaičius paauga. Dabar apžiūrėk, kas nutiko:
$ psql signflow -c "SELECT email, left(password_hash, 7) AS hash_prefix FROM users;"
email | hash_prefix
------------------+-------------
you@example.com | $2a$12$ ← bcrypt, cost 12 ($2a$12$…)
$ psql signflow -c "SELECT left(token_hash, 12) AS stored, expires_at > now() AS live FROM sessions;"
stored | live
--------------+------
3f9a1c2e... | t ← SHA-256 MAIŠA, ne slapuko žetonas
O pats slapukas neša savo vėliavas:
$ curl -si -c /dev/null -X POST localhost:8080/register \
-d 'email=x@y.co&password=password123&confirm=password123' | grep -i set-cookie
Set-Cookie: signflow_session=Xa9...; Path=/; Expires=...; HttpOnly; SameSite=Lax
HttpOnly ir SameSite=Lax yra; Secure nėra, nes esam ant http dev aplinkoje (produkcijoje jis atsiranda). Slapuko žetonas nėra duomenų bazėje saugoma reikšmė — DB turi tik jo SHA-256.
Spąstai (bcrypt 72 baitų skardis). Pabandyk registruotis su 100 simbolių slaptažodžiu: gausi „Password must be between 8 and 64 characters." — atmesta mūsų ribos, prieš tai, kai bcrypt tyliai ignoruotų viską po 72-o baito. Be ribos, du skirtingi ilgi slaptažodžiai, sutampantys pirmais 72 baitais, būtų sukeičiami prisijungiant. Tvora svarbi.