From 1b4e6803a22aae1a075a9407efd92d434b33cc2e Mon Sep 17 00:00:00 2001 From: gahusb Date: Mon, 1 Jun 2026 15:13:59 +0900 Subject: [PATCH] =?UTF-8?q?fix(db):=20contact=5Frequests.phone=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=20=EB=B3=B4=EC=9E=A5=20+=20project=5Fmilestones=20ano?= =?UTF-8?q?n=20=EC=A0=84=EC=B2=B4=20CRUD=20=EC=A0=95=EC=B1=85=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - contact route가 phone을 INSERT하나 schema에 컬럼 부재 → 문의 DB 저장이 조용히 실패(이메일은 정상)할 수 있어 ADD COLUMN IF NOT EXISTS로 보장 - 003_fix_quotes_rls의 'Admin manage milestones'(anon FOR ALL USING true) 제거: 비로그인 누구나 고객 마일스톤 CRUD 가능한 보안 구멍. 실제 접근은 전부 service_role 서버 API라 제거해도 무영향 - schema.sql에 phone 동기화, contact route의 불필요한 created_at 명시 제거 Co-Authored-By: Claude Opus 4.8 (1M context) --- app/api/contact/route.ts | 1 - ...1-fix-contact-phone-and-milestones-rls.sql | 33 +++++++++++++++++++ supabase/schema.sql | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 supabase/migrations/2026-06-01-fix-contact-phone-and-milestones-rls.sql diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts index c402b17..4e71b12 100644 --- a/app/api/contact/route.ts +++ b/app/api/contact/route.ts @@ -109,7 +109,6 @@ export async function POST(request: Request) { service: service || null, message, user_id: userId, - created_at: new Date().toISOString(), }); } catch (dbError) { console.error('[Contact] DB insert error:', dbError); diff --git a/supabase/migrations/2026-06-01-fix-contact-phone-and-milestones-rls.sql b/supabase/migrations/2026-06-01-fix-contact-phone-and-milestones-rls.sql new file mode 100644 index 0000000..ca2a932 --- /dev/null +++ b/supabase/migrations/2026-06-01-fix-contact-phone-and-milestones-rls.sql @@ -0,0 +1,33 @@ +-- ============================================================ +-- 코드 점검 수정 (2026-06-01) +-- ① contact_requests.phone 컬럼 누락 → 문의 DB 저장 조용한 실패 방지 +-- ② project_milestones 의 위험한 anon 전체 CRUD 정책 제거 (보안) +-- Supabase Dashboard > SQL Editor 에서 실행하세요 +-- ============================================================ + +-- ── ① contact_requests.phone 보장 ────────────────────────── +-- app/api/contact/route.ts 가 phone 을 INSERT 하지만 schema 에 컬럼이 없으면 +-- INSERT 가 PGRST204 로 실패한다. contact route 는 DB 오류를 try/catch 로 +-- 삼키므로(이메일은 정상 발송) 그동안 contact_requests 저장이 조용히 실패했을 수 있다. +-- 이미 컬럼이 있으면 IF NOT EXISTS 로 무해. +ALTER TABLE public.contact_requests ADD COLUMN IF NOT EXISTS phone text; + +-- ── ② project_milestones anon 정책 제거 ──────────────────── +-- 003_fix_quotes_rls.sql 이 추가한 정책: +-- CREATE POLICY "Admin manage milestones" ON project_milestones +-- FOR ALL TO anon USING (true) WITH CHECK (true); +-- → 비로그인(anon)이 PostgREST 로 모든 고객 마일스톤을 읽기/수정/삭제 가능한 보안 구멍. +-- 실제 접근은 전부 service_role(서버 createAdminClient: /api/admin/milestones, +-- /api/projects)로 이뤄지고 service_role 은 RLS 를 우회하므로 이 정책은 불필요하다. +-- 002_project_milestones.sql 의 authenticated 본인 조회 정책은 유지된다. +DROP POLICY IF EXISTS "Admin manage milestones" ON public.project_milestones; + +-- (RLS 자체는 002 에서 이미 ENABLE 되어 있음 — 유지) +ALTER TABLE public.project_milestones ENABLE ROW LEVEL SECURITY; + +-- ── 확인 ─────────────────────────────────────────────────── +-- phone 컬럼 존재 / project_milestones 정책 목록 +SELECT column_name FROM information_schema.columns + WHERE table_schema = 'public' AND table_name = 'contact_requests' AND column_name = 'phone'; +SELECT policyname, roles, cmd FROM pg_policies + WHERE schemaname = 'public' AND tablename = 'project_milestones'; diff --git a/supabase/schema.sql b/supabase/schema.sql index 0fc2ec5..dc100a2 100644 --- a/supabase/schema.sql +++ b/supabase/schema.sql @@ -112,6 +112,7 @@ create table public.contact_requests ( user_id uuid references public.profiles(id) on delete set null, email text not null, name text, + phone text, -- 연락처 (선택) service text not null, -- 문의 서비스 종류 message text not null, status text default 'pending', -- 'pending' | 'in_progress' | 'completed'