Appearance
01. supabase-user-roles.sql
원본 파일: 'C:\Repository\loafacto-hub\docs\web-ui\01. supabase-user-roles.sql'
sql
-- =============================================================================
-- A방식: 애플리케이션 역할 테이블 (public.user_roles)
-- Supabase 대시보드 → SQL Editor에서 이 파일 내용을 순서대로 실행하세요.
-- =============================================================================
-- 1) 테이블 생성
CREATE TABLE IF NOT EXISTS public.user_roles (
user_id uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
role text NOT NULL CHECK (role IN ('super_admin', 'operator')),
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL
);
COMMENT ON TABLE public.user_roles IS '앱 레벨 사용자 역할 (관리자/운영자). auth.users를 건드리지 않음.';
-- 2) 인덱스 (선택, PK로 이미 조회 가능)
CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON public.user_roles(user_id);
-- 3) RLS 활성화
ALTER TABLE public.user_roles ENABLE ROW LEVEL SECURITY;
-- 4) 정책: 로그인한 사용자는 자신의 역할만 조회 가능
CREATE POLICY "Users can read own role"
ON public.user_roles
FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
-- 5) 정책: 역할 추가/수정/삭제는 service_role만 (대시보드 또는 백엔드에서만)
-- 첫 관리자는 아래 INSERT로 직접 넣거나, 대시보드 Table Editor에서 추가
CREATE POLICY "Only service role can modify user_roles"
ON public.user_roles
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
-- 6) RPC: 현재 사용자 역할 조회 (web-ui에서 호출)
CREATE OR REPLACE FUNCTION public.get_my_role()
RETURNS text
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
SELECT role FROM public.user_roles WHERE user_id = auth.uid() LIMIT 1;
$$;
COMMENT ON FUNCTION public.get_my_role() IS '현재 로그인 사용자의 역할(super_admin | operator) 반환. 없으면 null.';
-- 7) authenticated 역할에 RPC 실행 권한 부여
GRANT EXECUTE ON FUNCTION public.get_my_role() TO authenticated;
-- 8) (선택) 첫 관리자 부여 — 이메일로 유저 id 조회 후 INSERT
-- 아래에서 'YOUR_USER_EMAIL@example.com' 을 실제 이메일로 바꾸고 실행
-- INSERT INTO public.user_roles (user_id, role)
-- SELECT id, 'super_admin' FROM auth.users WHERE email = 'YOUR_USER_EMAIL@example.com'
-- ON CONFLICT (user_id) DO UPDATE SET role = EXCLUDED.role, updated_at = now();