import java.nio.charset.StandardCharsets;
import java.util.HexFormat;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class AlurAman {

    // Peran sederhana untuk contoh otorisasi.
    record Pengguna(String nama, String peran) { }

    public static void main(String[] args) throws Exception {
        proses("siti", "Saya suka <b>produk</b> ini & harganya bersahabat!");
        System.out.println();
        proses("../admin", "isi komentar");
    }

    static void proses(String nama, String komentar) throws Exception {
        System.out.println("=== Permintaan dari [" + nama + "] ===");

        // Lapis 1: validasi masukan (allowlist, fail closed).
        if (!nama.matches("[a-z]{3,16}")) {
            System.out.println(" Lapis 1 validasi  : DITOLAK - nama di luar allowlist");
            System.out.println(" Eksekusi berhenti di gerbang pertama (fail closed)");
            return;
        }
        System.out.println(" Lapis 1 validasi  : lolos - nama sesuai allowlist");

        // Lapis 2: otorisasi (peran menentukan aksi yang diizinkan).
        Pengguna pengguna = new Pengguna(nama, "anggota");
        if (!pengguna.peran().equals("anggota") && !pengguna.peran().equals("editor")) {
            System.out.println(" Lapis 2 otorisasi : DITOLAK - peran tidak berhak");
            return;
        }
        System.out.println(" Lapis 2 otorisasi : lolos - peran anggota boleh berkomentar");

        // Lapis 3: encoding keluaran (komentar akan dirender sebagai HTML).
        String komentarAman = escapeHtml(komentar);
        System.out.println(" Lapis 3 encoding  : " + komentarAman);

        // Lapis 4: integritas (tag HMAC untuk deteksi manipulasi data tersimpan).
        byte[] kunci = "kunci-demo-hmac".getBytes(StandardCharsets.UTF_8);
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(kunci, "HmacSHA256"));
        byte[] tag = mac.doFinal(komentarAman.getBytes(StandardCharsets.UTF_8));
        System.out.println(" Lapis 4 integritas: tag " + HexFormat.of().formatHex(tag));
    }

    // Encoder HTML mini dari bab Output Encoding.
    static String escapeHtml(String teks) {
        StringBuilder hasil = new StringBuilder(teks.length() + 16);
        for (int i = 0; i < teks.length(); i++) {
            switch (teks.charAt(i)) {
                case '&' -> hasil.append("&amp;");
                case '<' -> hasil.append("&lt;");
                case '>' -> hasil.append("&gt;");
                case '"' -> hasil.append("&quot;");
                case '\'' -> hasil.append("&#39;");
                default -> hasil.append(teks.charAt(i));
            }
        }
        return hasil.toString();
    }
}
