Next.js / Row Level Security

Row Level Security

Өгөгдлийн сан нээлттэй байвал аливаа хэрэглэгч бусдын өгөгдлийг унших, өөрчлөх боломжтой болно. Row Level Security (RLS) нь Supabase-н хамгийн чухал аюулгүй байдлын онцлог — хүснэгтийн мөр бүрд хэн хандаж болохыг SQL policy-р тодорхойлдог.

RLS идэвхжүүлэх

RLS-г хүснэгт бүрт тусад нь идэвхжүүлнэ. Supabase SQL Editor дотор:

sql
-- RLS идэвхжүүлэх
alter table profiles        enable row level security;
alter table lesson_progress enable row level security;
alter table project_submissions enable row level security;

RLS идэвхжүүлснээс хойш policy байхгүй бол хэн ч дурын өгөгдөл уншиж чадахгүй — анхны тохиргоогоор бүх хандалт хаалттай болдог.

Policy үүсгэх

Policy бол "хэн, ямар үйлдлийг хийж болох" гэдгийг тодорхойлсон дүрэм. using нь SELECT, with check нь INSERT/UPDATE/DELETE-д хэрэглэгддэг:

sql
-- Хэрэглэгч зөвхөн өөрийн профайлыг унших
create policy "Users read own profile"
  on profiles
  for select
  using (auth.uid() = id);

-- Хэрэглэгч зөвхөн өөрийн профайлыг шинэчлэх
create policy "Users update own profile"
  on profiles
  for update
  using (auth.uid() = id);

-- Хэрэглэгч зөвхөн өөрийн дэвшлийг унших
create policy "Users read own progress"
  on lesson_progress
  for select
  using (auth.uid() = user_id);

-- Хэрэглэгч зөвхөн өөрийн дэвшлийг нэмэх
create policy "Users insert own progress"
  on lesson_progress
  for insert
  with check (auth.uid() = user_id);

auth.uid() нь одоо нэвтэрсэн хэрэглэгчийн UUID-г буцаадаг Supabase-н дотоод функц.

Профайл автоматаар үүсгэх

Хэрэглэгч бүртгүүлэх үед profiles хүснэгтэд мөр автоматаар нэмэгдэх trigger:

sql
-- Шинэ хэрэглэгч бүртгүүлэхэд profile үүсгэх функц
create or replace function public.handle_new_user()
returns trigger as $$
begin
  insert into public.profiles (id)
  values (new.id);
  return new;
end;
$$ language plpgsql security definer;

-- auth.users хүснэгтэд шинэ мөр нэмэгдэх үед дуудах
create trigger on_auth_user_created
  after insert on auth.users
  for each row
  execute procedure public.handle_new_user();

Ингэснээр supabase.auth.signUp() дуудсан даруйд profiles хүснэгтэд автоматаар мөр үүснэ — гараар нэмэх шаардлагагүй.

Service role — policy-г давах

Зарим тохиолдолд сервер тал RLS policy-г тойрч бүх өгөгдөлд хандах хэрэгтэй болдог — жишээлбэл admin хэсэг. SUPABASE_SERVICE_ROLE_KEY ашигласан client нь RLS-г давдаг:

typescript
// app/api/admin/route.ts — зөвхөн серверт, хэзээ ч клиентэд ашиглахгүй
import { createClient } from "@supabase/supabase-js";

export async function GET() {
  // service role key → RLS-г тойрно
  const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!, // ← нууц key
  );

  const { data } = await supabase.from("profiles").select("*"); // бүх хэрэглэгчийн профайл харагдана

  return Response.json(data);
}

SUPABASE_SERVICE_ROLE_KEYNEXT_PUBLIC_ prefix-гүй тохируулсан тул клиентэд хэзээ ч очдоггүй — энэ нь маш чухал аюулгүй байдлын дүрэм.

Дараагийн хичээлд:

Next.js + TypeScript-н дэвшилтэт хэрэглээг судална. Generic, utility type, Supabase-н автоматаар үүсгэсэн type ашиглах аргыг ойлгоно.