-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.ts
More file actions
101 lines (84 loc) · 3.59 KB
/
Copy pathproxy.ts
File metadata and controls
101 lines (84 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// proxy.ts
import { NextResponse, type NextRequest } from 'next/server';
import { createServerClient } from '@supabase/ssr';
import { isAdminTokenValid } from '@/lib/admin-auth';
// Public routes yang tidak perlu auth Supabase
const publicRoutes = ['/', '/login', '/share'];
export default async function proxy(request: NextRequest) {
const { pathname } = request.nextUrl;
// Skip static files & internal routes
if (
pathname.startsWith('/_next') ||
pathname.startsWith('/api') ||
pathname.startsWith('/auth') ||
pathname.match(/\.(jpg|jpeg|png|gif|ico|svg|webp)$/)
) {
return NextResponse.next();
}
// ── Admin routes ─────────────────────────────────────────────────────────────
if (pathname.startsWith('/admin')) {
if (pathname === '/admin/login') {
const token = request.cookies.get('admin_token')?.value;
if (await isAdminTokenValid(token)) {
return NextResponse.redirect(new URL('/admin', request.url));
}
return NextResponse.next();
}
const token = request.cookies.get('admin_token')?.value;
if (!await isAdminTokenValid(token)) {
return NextResponse.redirect(new URL('/admin/login', request.url));
}
return NextResponse.next();
}
// ── Public routes — skip Supabase check ──────────────────────────────────────
if (publicRoutes.some(r => pathname === r || pathname.startsWith(r + '/'))) {
return NextResponse.next();
}
// ── Protected routes — cek Supabase session ──────────────────────────────────
let response = NextResponse.next({ request: { headers: request.headers } });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() { return request.cookies.getAll(); },
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => {
request.cookies.set({ name, value, ...options });
response.cookies.set({ name, value, ...options });
});
},
},
}
);
// Ambil session DAN error dari Supabase
const { data: { session }, error } = await supabase.auth.getSession();
const guestCookie = request.cookies.get('wc_guest_mode');
const isGuest = guestCookie?.value === 'true';
// FIX: Jika ada error auth (seperti Invalid Refresh Token), langsung bersihkan cookie-nya
if (error) {
console.error('Middleware Auth Error, otomatis membersihkan sesi:', error.message);
const url = request.nextUrl.clone();
url.pathname = '/login';
// Kita hilangkan parameter ?redirect agar tidak loop, karena sesinya memang bermasalah
const errorResponse = NextResponse.redirect(url);
// Hapus semua cookie bawaan Supabase yang nyangkut (biasanya berawalan 'sb-')
request.cookies.getAll().forEach((cookie) => {
if (cookie.name.startsWith('sb-')) {
errorResponse.cookies.delete(cookie.name);
}
});
return errorResponse;
}
if (!session && !isGuest) {
const url = request.nextUrl.clone();
url.pathname = '/login';
url.searchParams.set('redirect', pathname);
return NextResponse.redirect(url);
}
return response;
}
export const config = {
// Fix: exclude /api/* dari matcher supaya API routes tidak disentuh middleware
matcher: ['/((?!_next/static|_next/image|favicon\\.ico|api/).*)',],
};