Lewati ke konten

Praktik 8: Supabase dan Prisma

InternalSebagian terujiArti badge ini

Materi Praktik 8 memuat dua bagian: menyiapkan PostgreSQL dan PostGIS di Supabase lalu menyambungnya dari DBeaver dan QGIS, dan menyambungkan Prisma ORM ke database itu untuk membuat API login.

Berkas yang diperiksa:

  • Praktik 8/Database di Supabase + PostGIS + Koneksi dari DBeaver/Modul Setup Cloud PostgreSQL + PostGIS + Koneksi Dbeaver.docx
  • Praktik 8/Koneksi Prisma ORM dan API Login/Membuat Koneksi Prisma ORM dan API Login.docx
  • Praktik 8/Koneksi Prisma ORM dan API Login/File latihan/DATABASE_URL.txt
  • Praktik 8/Koneksi Prisma ORM dan API Login/File latihan/skema prisma.txt

P8-1. GRANT EXECUTE ke PUBLIC membuka fungsi ke peran anon (Kritikal)

Section titled “P8-1. GRANT EXECUTE ke PUBLIC membuka fungsi ke peran anon (Kritikal)”

Materi meminta menjalankan blok SQL ini di SQL Editor Supabase:

GRANT EXECUTE ON FUNCTION public.addgeometrycolumn
TO PUBLIC, postgres, anon, authenticated, service_role;

PUBLIC berarti setiap peran di database, termasuk anon. Kunci anon Supabase dirancang untuk ditaruh di browser dan bersifat publik. Dengan grant itu, siapa pun yang memegangnya bisa memanggil addgeometrycolumn.

Kedua fungsi wrapper juga ditulis tanpa SET search_path, sehingga nama fungsi di dalamnya bisa dibajak lewat schema lain bila ada yang bisa membuat schema.

P8-2. Berkas DATABASE_URL.txt memuat gabungan dua konteks (Tinggi)

Section titled “P8-2. Berkas DATABASE_URL.txt memuat gabungan dua konteks (Tinggi)”

Isi berkasnya:

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/geoportal?pgbouncer=true&schema=public"

Nilai itu mencampur dua konteks yang berbeda:

  • localhost dan postgres:postgres berasal dari PostgreSQL lokal Praktik 6, bukan dari Supabase.
  • pgbouncer=true hanya berlaku untuk pooler Supabase pada port 6543. Pada port 5432 parameter itu tidak berpengaruh.

Peserta yang menyalin nilai ini akan mengira sudah terhubung ke Supabase, padahal masih menunjuk ke database lokal.

P8-3. directUrl diminta ditambahkan tanpa dijelaskan (Sedang)

Section titled “P8-3. directUrl diminta ditambahkan tanpa dijelaskan (Sedang)”

Materi meminta menambahkan directUrl di schema.prisma, tetapi skema prisma.txt yang disertakan hanya memuat generator dan datasource:

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

Tanpa directUrl, prisma migrate gagal di port 6543 karena PgBouncer tidak mendukung prepared statement yang dibutuhkan migrasi. Materi tidak menyebut alasan itu.

P8-4. Instruksi menghapus isi .env berisiko menghapus rahasia lain (Sedang)

Section titled “P8-4. Instruksi menghapus isi .env berisiko menghapus rahasia lain (Sedang)”

Materi meminta:

Hapus semua isinya kemudian copy .env.local dari Supabase dan paste ke .env di NextJS kita

Peserta yang sudah mengisi JWT_SECRET pada Praktik 9 akan kehilangan nilainya tanpa peringatan. Akibatnya token yang sudah diterbitkan menjadi tidak valid, dan gejalanya muncul sebagai sesi yang tiba-tiba berakhir.

P8-5. Tidak ada langkah pemeriksaan koneksi (Sedang)

Section titled “P8-5. Tidak ada langkah pemeriksaan koneksi (Sedang)”

Rangkaian Praktik 8 panjang, dan setiap kegagalan datang dengan pesan yang berbeda dari Prisma, DBeaver, QGIS, atau Supabase. Tidak ada langkah pemeriksaan terpisah yang bisa dijalankan sebelum melanjutkan.

P8-6. CSV 3D memakai masalah yang sama dengan Praktik 6 (Rendah)

Section titled “P8-6. CSV 3D memakai masalah yang sama dengan Praktik 6 (Rendah)”

katalog_data_3d.csv juga memakai pemisah pipa pada berkas berakhiran .csv.

Cabut hak dari PUBLIC, anon, dan authenticated, lalu berikan hanya kepada peran yang membutuhkannya. Jalankan blok ini di SQL Editor Supabase:

REVOKE ALL ON FUNCTION public.addgeometrycolumn(
character varying, character varying, character varying,
character varying, integer, character varying, integer) FROM PUBLIC, anon, authenticated;
GRANT EXECUTE ON FUNCTION public.addgeometrycolumn(
character varying, character varying, character varying,
character varying, integer, character varying, integer) TO postgres;

Tulis ulang kedua fungsi wrapper dengan SECURITY INVOKER dan search_path terkunci:

CREATE OR REPLACE FUNCTION public.addgeometrycolumn(
catalog_name character varying, schema_name character varying,
table_name character varying, column_name character varying,
new_srid integer, new_type character varying, new_dim integer
) RETURNS text
LANGUAGE plpgsql
SECURITY INVOKER
SET search_path = extensions, public, pg_temp
AS $$
BEGIN
RETURN extensions.AddGeometryColumn(schema_name, table_name, column_name, new_srid, new_type, new_dim);
EXCEPTION WHEN OTHERS THEN
RETURN public.AddGeometryColumn(schema_name, table_name, column_name, new_srid, new_type, new_dim);
END;
$$;

search_path yang terkunci mencegah nama fungsi dibajak lewat schema lain. Berkas 01_perbaikan-grant-postgis.sql memuat versi lengkapnya untuk kedua schema, beserta pemeriksaan spatial_ref_sys.

Pakai dua nilai terpisah, satu untuk aplikasi dan satu untuk migrasi:

DATABASE_URL="postgresql://postgres.PROJECT_REF:asisten01@example.com:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://postgres.PROJECT_REF:asisten01@example.com:5432/postgres"

Port 6543 memakai PgBouncer untuk aplikasi, port 5432 untuk migrasi. Lalu daftarkan directUrl di schema.prisma:

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
}

Hapus berkas DATABASE_URL.txt dari paket materi, atau ganti isinya dengan placeholder tanpa kredensial, supaya nilai lokal tidak tertukar dengan nilai Supabase.

Tambahkan satu kalimat di modul sebelum langkahnya:

directUrl diperlukan karena prisma migrate memakai prepared statement, sedangkan PgBouncer pada port 6543 tidak mendukungnya.

schema.prisma di atas sudah memuat bentuk yang benar.

Ganti instruksi “hapus semua isinya” menjadi menambahkan variabel, bukan mengganti berkas:

Terminal window
# Tambahkan dua baris ini, jangan hapus isi .env yang sudah ada
DATABASE_URL="..."
DIRECT_URL="..."

Rahasia dari praktik sebelumnya, seperti JWT_SECRET, dengan begitu tetap utuh.

Jalankan satu perintah sebelum melanjutkan:

Terminal window
node periksa-koneksi.mjs .env

Skrip itu memeriksa keberadaan berkas .env, menguraikan DATABASE_URL, mendeteksi placeholder [YOUR-PASSWORD], mendeteksi kredensial bawaan postgres:postgres, menguji jangkauan TCP, dan bila kunci anon Supabase tersedia, membaca daftar tabel lewat PostgREST.

Pakai skrip yang sama seperti Praktik 6:

Terminal window
node perbaiki-csv.mjs katalog_data_3d.csv katalog_data_3d.bersih.csv
Berkas Isi
Praktik 8/sql/01_perbaikan-grant-postgis.sql Cabut grant dari PUBLIC dan kunci search_path
Praktik 8/tools/periksa-koneksi.mjs Periksa .env, DATABASE_URL, TCP, dan PostGIS
Butir Tingkat Inti
P8-1 Kritikal GRANT EXECUTE ke PUBLIC membuka fungsi ke peran anon
P8-2 Tinggi DATABASE_URL mencampur kredensial lokal dan parameter Supabase
P8-3 Sedang directUrl diminta tanpa alasan yang dijelaskan
P8-4 Sedang Menghapus .env berisiko menghapus rahasia dari praktik sebelumnya
P8-5 Sedang Tidak ada langkah pemeriksaan koneksi
P8-6 Rendah CSV 3D memakai pemisah pipa