feat(web): 관리자 CRM 웹페이지 — admin role + 4개 페이지

- migration: profiles.role 컬럼 + admin RLS 정책
- admin-guard.ts: RSC용 admin 권한 체크
- /admin: CRM 대시보드 (총 유저, 유료 구독자, API 호출, 만료 예정)
- /admin/users: 유저 목록 (검색/필터/페이지네이션)
- /admin/users/[id]: 유저 상세 (프로필+구독+30일 사용량)
- /admin/subscriptions: 구독 목록 (상태 필터)
- /admin/usage: 사용량 집계 (7/14/30일)
- Sidebar에 Admin 네비게이션 추가
This commit is contained in:
윤찬 2026-04-12 20:24:26 +09:00
parent d3c2a4348d
commit 667c09242b
10 changed files with 816 additions and 0 deletions

View file

@ -0,0 +1,32 @@
// apps/web/src/lib/admin-guard.ts
// RSC용 admin 가드 — profile.role='admin' 체크, 실패 시 redirect
import { redirect } from 'next/navigation'
import { getSupabaseServerClient } from './supabase-server'
interface AdminProfile {
id: string
name: string | null
role: string
}
export async function requireAdmin(): Promise<AdminProfile> {
const supabase = await getSupabaseServerClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) {
redirect('/login')
}
const { data: profile } = await supabase
.from('profiles')
.select('id, name, role')
.eq('id', user.id)
.maybeSingle()
if (!profile || (profile as { role: string }).role !== 'admin') {
redirect('/dashboard')
}
return profile as AdminProfile
}