Praktik 8: Supabase dan Prisma
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.docxPraktik 8/Koneksi Prisma ORM dan API Login/Membuat Koneksi Prisma ORM dan API Login.docxPraktik 8/Koneksi Prisma ORM dan API Login/File latihan/DATABASE_URL.txtPraktik 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:
localhostdanpostgres:postgresberasal dari PostgreSQL lokal Praktik 6, bukan dari Supabase.pgbouncer=truehanya 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.
Solusi
Section titled “Solusi”Untuk P8-1, GRANT EXECUTE ke PUBLIC
Section titled “Untuk P8-1, GRANT EXECUTE ke PUBLIC”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 textLANGUAGE plpgsqlSECURITY INVOKERSET search_path = extensions, public, pg_tempAS $$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.
Untuk P8-2, DATABASE_URL
Section titled “Untuk P8-2, DATABASE_URL”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.
Untuk P8-3, directUrl tanpa alasan
Section titled “Untuk P8-3, directUrl tanpa alasan”Tambahkan satu kalimat di modul sebelum langkahnya:
directUrldiperlukan karenaprisma migratememakai prepared statement, sedangkan PgBouncer pada port 6543 tidak mendukungnya.
schema.prisma di atas sudah memuat bentuk yang benar.
Untuk P8-4, menghapus isi .env
Section titled “Untuk P8-4, menghapus isi .env”Ganti instruksi “hapus semua isinya” menjadi menambahkan variabel, bukan mengganti berkas:
# Tambahkan dua baris ini, jangan hapus isi .env yang sudah adaDATABASE_URL="..."DIRECT_URL="..."Rahasia dari praktik sebelumnya, seperti JWT_SECRET, dengan begitu tetap utuh.
Untuk P8-5, tidak ada pemeriksaan koneksi
Section titled “Untuk P8-5, tidak ada pemeriksaan koneksi”Jalankan satu perintah sebelum melanjutkan:
node periksa-koneksi.mjs .envSkrip 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.
Untuk P8-6, CSV 3D
Section titled “Untuk P8-6, CSV 3D”Pakai skrip yang sama seperti Praktik 6:
node perbaiki-csv.mjs katalog_data_3d.csv katalog_data_3d.bersih.csvBerkas siap pakai
Section titled “Berkas siap pakai”| 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 |
Ringkasan
Section titled “Ringkasan”| 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 |