Tema
/
Interneto svetainių serverio dalies kūrimas GO
📖 Teorija

Autorizacija užklausoje: 404 ne 403, ir juodraščio taisyklė

Praėjusią pamoką galėjai įkelti dokumentą; dar negalėjai jo peržiūrėti. Ši pamoka stato savininko paviršių — peržiūra, atsisiuntimas, juodraščio trynimas — ir iš tiesų tai pamoka apie tai, kur gyvena autorizacija.

Nuosavybės patikrą dėk į užklausą, ne po jos. Viliojanti forma tokia: paimk dokumentą pagal ID, tada if doc.OwnerID != me { 403 }. Ji veikia, bet patikra yra atskiras žingsnis, kurį ateities pakeitimas gali pamiršti. Stipresnė forma įtraukia nuosavybę į WHERE:

-- name: GetDocumentForOwner :one
SELECT * FROM documents
WHERE id = $1 AND owner_id = $2;

Dabar kito vartotojo dokumento tiesiog nėra rezultatų aibėje — užklausa grąžina pgx.ErrNoRows, lygiai kaip neegzistuojančiam ID. Nėra „paimta, bet uždrausta" būsenos, kurią būtų galima netinkamai tvarkyti. Autorizacija yra duomenų prieigos savybė, ne po jos prikaltas sargas.

404, ne 403 — ir kodėl skirtumas svarbus. Kai kažkas prašo dokumento, kurio neturi, sąžiningai atrodantis atsakymas yra 403 Forbidden. Bet 403 patvirtina, kad dokumentas egzistuoja — užpuolikas, bandantis ID, sužino, kurie tikri. 404 Not Found neatskleidžia nieko: „tokio dokumento tau nėra" yra tas pats atsakymas, ar ID netikras, ar tiesiog kažkieno kito. Kadangi GetDocumentForOwner sulieja abu atvejus į ErrNoRows, grąžinti 404 abiem yra natūralu — valdiklis net negali jų atskirti.

Pirma tikra verslo taisyklė: trinti galima tik juodraštį. Dokumento gyvavimo ciklas — draft → sent → completed. Kai jis išsiųstas pasirašyti, jo įrašas nekintamas — negali jo ištraukti iš po žmonių, kurių paprašei pasirašyti. Ta taisyklė gyvena pačioje trynimo užklausoje:

-- name: DeleteDraftDocument :execrows
DELETE FROM documents
WHERE id = $1 AND owner_id = $2 AND status = 'draft';

:execrows grąžina ištrintų eilučių skaičių. Išsiųstas dokumentas, svetimas dokumentas, neegzistuojantis ID — visi ištrina nulį eilučių. Valdiklis išlaiko draugišką išankstinę patikrą (išsiųstas dokumentas gauna aiškų 422), bet užtikrinimas yra WHERE: net jei pašalintum Go patikrą, duomenų bazė vis tiek atsisakytų.

HTMX vėl — sąrašas gydosi pats. Trynimas siunčia su hx-post ir taikosi į #doc-list; valdiklis atsako atnaujintu sąrašo fragmentu, kuris pasikeičia vietoje. Jokio perkrovimo, jokios rankinės DOM chirurgijos — serveris iš naujo atvaizduoja tiesą, o htmx ją įdeda. Tai — viso kurso argumentas vienoje sąveikoje: serveris valdo HTML, o puslapis vis tiek jaučiasi gyvas.

Ši pamoka: dvi savininkui apribotos užklausos, ant jų pastatyti peržiūros / atsisiuntimo / trynimo valdikliai, dokumento detalės puslapis ir eilučių veiksmai skydelyje.