fix: login redirect, admin auth guard, JWT_SECRET env
This commit is contained in:
+46
-1
@@ -1481,6 +1481,8 @@ export default function AdminPage() {
|
||||
const [activeSection, setActiveSection] = useState('dashboard');
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [toasts, setToasts] = useState<{ id: number; message: string; type: string }[]>([]);
|
||||
const [authChecked, setAuthChecked] = useState(false);
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
|
||||
const [slides, setSlides] = useState<Slide[]>([]);
|
||||
const [rooms, setRooms] = useState<Room[]>([]);
|
||||
@@ -1504,8 +1506,20 @@ export default function AdminPage() {
|
||||
setToasts(prev => prev.filter(t => t.id !== id));
|
||||
}, []);
|
||||
|
||||
/* ── Auth check ── */
|
||||
useEffect(() => {
|
||||
fetch('/api/auth/me', { credentials: 'include' })
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.authenticated) setIsAuthenticated(true);
|
||||
setAuthChecked(true);
|
||||
})
|
||||
.catch(() => setAuthChecked(true));
|
||||
}, []);
|
||||
|
||||
/* ── Data fetching ── */
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) return;
|
||||
const fetchAll = async () => {
|
||||
try {
|
||||
const [slidesRes, roomsRes, calRes, socialRes, menuRes, placesRes, reviewsRes, imagesRes] = await Promise.all([
|
||||
@@ -1529,7 +1543,7 @@ export default function AdminPage() {
|
||||
} catch (err) { console.error('Failed to load admin data:', err); }
|
||||
};
|
||||
fetchAll();
|
||||
}, []);
|
||||
}, [isAuthenticated]);
|
||||
|
||||
const deleteImage = async (id: number) => {
|
||||
try {
|
||||
@@ -1567,6 +1581,35 @@ export default function AdminPage() {
|
||||
{/* Toasts */}
|
||||
{toasts.map(t => <Toast key={t.id} message={t.message} type={t.type} onClose={() => removeToast(t.id)} />)}
|
||||
|
||||
{/* Auth loading */}
|
||||
{!authChecked && (
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<div style={{ fontSize: '32px', marginBottom: '16px' }}>⏳</div>
|
||||
<div style={{ fontSize: '16px', color: C.text }}>Checking authentication...</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Not authenticated - show login prompt */}
|
||||
{authChecked && !isAuthenticated && (
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<div style={{ textAlign: 'center', maxWidth: 400, padding: '40px', background: '#fff', borderRadius: 16, boxShadow: C.shadow }}>
|
||||
<div style={{ fontSize: '48px', marginBottom: '16px' }}>🔒</div>
|
||||
<h2 style={{ margin: '0 0 12px', fontSize: '24px', color: C.navy }}>Admin Access Required</h2>
|
||||
<p style={{ margin: '0 0 24px', fontSize: '14px', color: C.textLight }}>
|
||||
Please log in to access the admin panel.
|
||||
</p>
|
||||
<a href="/login" style={{ display: 'inline-block', padding: '12px 32px', background: C.gold, color: '#fff', borderRadius: 8, textDecoration: 'none', fontWeight: 600, fontSize: '15px' }}>
|
||||
Go to Login
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Authenticated - show admin panel */}
|
||||
{authChecked && isAuthenticated && (
|
||||
<>
|
||||
{/* Mobile sidebar toggle */}
|
||||
<div style={{ display: 'none' }} /> {/* placeholder */}
|
||||
|
||||
@@ -1608,6 +1651,8 @@ export default function AdminPage() {
|
||||
{renderSection()}
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+5
-20
@@ -6,29 +6,14 @@ import type { NextRequest } from 'next/server';
|
||||
// In a production environment, you would want to verify the token
|
||||
export function middleware(request: NextRequest) {
|
||||
const { pathname } = request.nextUrl;
|
||||
|
||||
// Protect admin routes
|
||||
if (pathname.startsWith('/admin')) {
|
||||
// Get session token from cookies
|
||||
const token = request.cookies.get('session')?.value;
|
||||
|
||||
// If no token, redirect to login
|
||||
if (!token) {
|
||||
return NextResponse.redirect(new URL('/login', request.url));
|
||||
}
|
||||
// Protect admin routes - let page handle auth UI
|
||||
// No redirect here; the admin page shows login prompt if not authenticated
|
||||
|
||||
// Note: In a real implementation, you would verify the token here
|
||||
// For now, we're just checking that a token exists
|
||||
}
|
||||
|
||||
// Redirect authenticated users from login page to home
|
||||
if (pathname === '/login') {
|
||||
const token = request.cookies.get('session')?.value;
|
||||
if (token) {
|
||||
// In a real implementation, you would verify the token and check role
|
||||
// For now, we'll just redirect to home
|
||||
return NextResponse.redirect(new URL('/', request.url));
|
||||
}
|
||||
// If logged in and trying to access login, redirect to admin
|
||||
if (pathname === '/login' && token) {
|
||||
return NextResponse.redirect(new URL('/admin', request.url));
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
|
||||
Reference in New Issue
Block a user