57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
# app/supabase_auth.py
|
|
import os
|
|
import logging
|
|
from typing import Set
|
|
|
|
from supabase import create_client, Client
|
|
import redis
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# ---- 환경변수 ----
|
|
SUPABASE_URL = os.getenv("SUPABASE_URL", "")
|
|
SUPABASE_KEY = os.getenv("SUPABASE_KEY", "")
|
|
REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379/2") # 별도 DB 사용 권장
|
|
AUTH_CACHE_TTL = int(os.getenv("AUTH_CACHE_TTL", "3600")) # 1시간
|
|
|
|
# ---- 클라이언트 ----
|
|
if not SUPABASE_URL or not SUPABASE_KEY:
|
|
logger.warning("SUPABASE_URL 또는 SUPABASE_KEY가 설정되지 않았습니다.")
|
|
|
|
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
|
|
r = redis.Redis.from_url(REDIS_URL, decode_responses=True)
|
|
|
|
ALLOWED_LEVELS: Set[str] = {"premium", "vip"} # 권한 레벨
|
|
|
|
def _supabase_query_permission(user_id: str) -> bool:
|
|
"""실제 Supabase 조회(동기)"""
|
|
try:
|
|
res = supabase.table("users").select("id, membership_level").eq("id", user_id).execute()
|
|
logger.debug("Supabase response: %s", res.data)
|
|
if not res.data:
|
|
logger.info("유저를 찾을 수 없음: %s", user_id)
|
|
return False
|
|
level = res.data[0].get("membership_level")
|
|
return level in ALLOWED_LEVELS
|
|
except Exception:
|
|
logger.exception("Supabase 권한 체크 실패")
|
|
return False
|
|
|
|
def check_user_permission_cached(user_id: str, client_ip: str | None = None) -> bool:
|
|
"""
|
|
Redis 캐시 확인 후 없으면 Supabase 조회.
|
|
client_ip까지 키에 넣고 싶으면 넣고, 아니면 user_id만 써도 OK.
|
|
"""
|
|
key = f"auth:{user_id}"
|
|
if client_ip:
|
|
key += f":{client_ip}"
|
|
|
|
cached = r.get(key)
|
|
if cached is not None:
|
|
# "1" or "0" 저장한다고 가정
|
|
return cached == "1"
|
|
|
|
ok = _supabase_query_permission(user_id)
|
|
r.setex(key, AUTH_CACHE_TTL, "1" if ok else "0")
|
|
return ok
|