package main

import "fmt"

// queryRentan membangun SQL dengan menyambung string mentah dari user.
// POLA INI RENTAN — hanya untuk demonstrasi, jangan dipakai di produksi.
func queryRentan(email string) string {
	return "SELECT id, nama FROM pengguna WHERE email = '" + email + "'"
}

// queryAman mengembalikan teks SQL tetap dan argumen terpisah untuk placeholder.
func queryAman(email string) (string, []any) {
	return "SELECT id, nama FROM pengguna WHERE email = $1", []any{email}
}

// kolomDiizinkan adalah allowlist nama kolom untuk fitur sorting.
var kolomDiizinkan = map[string]bool{
	"nama":       true,
	"email":      true,
	"created_at": true,
}

// querySorting memvalidasi kolom lewat allowlist sebelum disisipkan ke SQL.
func querySorting(kolom string) (string, bool) {
	if !kolomDiizinkan[kolom] {
		return "", false
	}
	return "SELECT id, nama FROM pengguna ORDER BY " + kolom, true
}

func main() {
	// Payload klasik: kutip penutup + kondisi yang selalu benar.
	payload := "' OR '1'='1"

	fmt.Println("== Pola rentan: penyambungan string ==")
	fmt.Println("input :", payload)
	fmt.Println("query :", queryRentan(payload))
	fmt.Println("query :", queryRentan("x'; DROP TABLE pengguna;--"))

	fmt.Println()
	fmt.Println("== Pola aman: parameter binding ==")
	email := "budi@example.com"
	q, args := queryAman(email)
	fmt.Println("query :", q)
	fmt.Println("args  :", args[0])

	fmt.Println()
	fmt.Println("== Kolom sorting: allowlist, bukan binding ==")
	for _, masukan := range []string{"nama", "password; DROP TABLE pengguna;--"} {
		q, ok := querySorting(masukan)
		if !ok {
			fmt.Printf("tolak %q: bukan kolom yang diizinkan\n", masukan)
			continue
		}
		fmt.Println("terima:", q)
	}
}
