fix(db): contact_requests.phone 컬럼 보장 + project_milestones anon 전체 CRUD 정책 제거

- 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) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 15:13:59 +09:00
parent 3dc6a28979
commit 1b4e6803a2
3 changed files with 34 additions and 1 deletions

View File

@@ -109,7 +109,6 @@ export async function POST(request: Request) {
service: service || null, service: service || null,
message, message,
user_id: userId, user_id: userId,
created_at: new Date().toISOString(),
}); });
} catch (dbError) { } catch (dbError) {
console.error('[Contact] DB insert error:', dbError); console.error('[Contact] DB insert error:', dbError);

View File

@@ -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';

View File

@@ -112,6 +112,7 @@ create table public.contact_requests (
user_id uuid references public.profiles(id) on delete set null, user_id uuid references public.profiles(id) on delete set null,
email text not null, email text not null,
name text, name text,
phone text, -- 연락처 (선택)
service text not null, -- 문의 서비스 종류 service text not null, -- 문의 서비스 종류
message text not null, message text not null,
status text default 'pending', -- 'pending' | 'in_progress' | 'completed' status text default 'pending', -- 'pending' | 'in_progress' | 'completed'