From 221ae2a0491b502e6fe5e1eaec6cdc48d1085764 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 12 Dec 2025 00:44:18 +0300 Subject: [PATCH] logs --- mnemo_cards_admin/src/pages/DashboardPage.tsx | 9 ++++++ mnemo_cards_admin/src/pages/LoginPage.tsx | 21 +++++++++++- .../lib/api/v2/admin_auth_api_v2.dart | 2 -- .../lib/api/v2/authorize_v2.dart | 32 ++++++++++++------- .../lib/api/v2/jwt_service.dart | 31 +++--------------- 5 files changed, 53 insertions(+), 42 deletions(-) diff --git a/mnemo_cards_admin/src/pages/DashboardPage.tsx b/mnemo_cards_admin/src/pages/DashboardPage.tsx index d1dcbe2..6000beb 100644 --- a/mnemo_cards_admin/src/pages/DashboardPage.tsx +++ b/mnemo_cards_admin/src/pages/DashboardPage.tsx @@ -4,21 +4,30 @@ import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContai import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { analyticsApi, type DashboardData, type ChartDataPoint } from '@/api/analytics' +import { useAuthStore } from '@/stores/authStore' export default function DashboardPage() { + const { isAuthenticated, token } = useAuthStore() + + // Only make requests if authenticated and token exists + const isReady = isAuthenticated && !!token && !!localStorage.getItem('admin_token') + const { data: dashboardData, isLoading: dashboardLoading } = useQuery({ queryKey: ['dashboard'], queryFn: analyticsApi.getDashboard, + enabled: isReady, }) const { data: usersChartData } = useQuery<{ data: ChartDataPoint[] }>({ queryKey: ['users-chart'], queryFn: analyticsApi.getUsersChart, + enabled: isReady, }) const { data: revenueChartData } = useQuery<{ data: ChartDataPoint[] }>({ queryKey: ['revenue-chart'], queryFn: analyticsApi.getRevenueChart, + enabled: isReady, }) if (dashboardLoading) { diff --git a/mnemo_cards_admin/src/pages/LoginPage.tsx b/mnemo_cards_admin/src/pages/LoginPage.tsx index 9b96253..8e8c1be 100644 --- a/mnemo_cards_admin/src/pages/LoginPage.tsx +++ b/mnemo_cards_admin/src/pages/LoginPage.tsx @@ -94,9 +94,28 @@ export default function LoginPage() { setIsVerifying(false) console.log('Login successful, setting token and user') + console.log('Token received:', data.token ? `Token exists, length: ${data.token.length}` : 'NO TOKEN!') + console.log('User received:', data.user) + + // Save token first login(data.token, data.user) + + // Verify token was saved + const savedToken = localStorage.getItem('admin_token') + console.log('Token saved verification:', savedToken ? `Token exists, length: ${savedToken.length}` : 'Token NOT saved!') + + if (!savedToken) { + console.error('CRITICAL: Token was not saved to localStorage!') + toast.error('Failed to save authentication token') + return + } + toast.success('Welcome back!') - navigate('/') + + // Small delay to ensure token is available for subsequent requests + setTimeout(() => { + navigate('/') + }, 100) }, onError: (error: unknown) => { console.error('Verify code error:', error) diff --git a/mnemo_cards_backend/lib/api/v2/admin_auth_api_v2.dart b/mnemo_cards_backend/lib/api/v2/admin_auth_api_v2.dart index 3a0a452..6c1b16e 100644 --- a/mnemo_cards_backend/lib/api/v2/admin_auth_api_v2.dart +++ b/mnemo_cards_backend/lib/api/v2/admin_auth_api_v2.dart @@ -159,9 +159,7 @@ class AdminAuthApiV2 { } // Generate JWT token using JwtService (same as regular auth) - print('[ADMIN AUTH] Generating tokens for admin user ${user.id}'); final tokens = await _jwtService.generateTokens(user); - print('[ADMIN AUTH] Generated access token, length: ${tokens.accessToken.length}'); return _json({ 'success': true, diff --git a/mnemo_cards_backend/lib/api/v2/authorize_v2.dart b/mnemo_cards_backend/lib/api/v2/authorize_v2.dart index 89bec66..50b8c09 100644 --- a/mnemo_cards_backend/lib/api/v2/authorize_v2.dart +++ b/mnemo_cards_backend/lib/api/v2/authorize_v2.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:mnemo_cards_backend/api/v2/jwt_service.dart'; import 'package:mnemo_cards_backend/user/user_manager.dart'; import 'package:shelf/shelf.dart'; @@ -89,12 +91,14 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) { // Shelf normalizes headers to lowercase, so we check 'authorization' final authHeader = request.headers['authorization']; - // Debug logging for admin endpoints + // Debug logging for admin endpoints - use stderr to ensure it's visible if (normalizedPath.startsWith('/admin/')) { - print('[AUTH DEBUG] Path: $normalizedPath'); - print('[AUTH DEBUG] All headers: ${request.headers}'); - print('[AUTH DEBUG] Authorization header: $authHeader'); - print('[AUTH DEBUG] Authorization header type: ${authHeader.runtimeType}'); + stderr.writeln('[AUTH DEBUG] Path: $normalizedPath'); + stderr.writeln('[AUTH DEBUG] Authorization header present: ${authHeader != null}'); + if (authHeader != null) { + stderr.writeln('[AUTH DEBUG] Authorization header length: ${authHeader.length}'); + stderr.writeln('[AUTH DEBUG] Authorization header starts with Bearer: ${authHeader.startsWith('Bearer ')}'); + } } final hasBearerToken = @@ -113,11 +117,11 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) { final token = authHeader.substring(7); // Remove "Bearer " prefix - // Debug logging for admin endpoints + // Debug logging for admin endpoints - use stderr if (normalizedPath.startsWith('/admin/')) { - print('[AUTH DEBUG] Verifying token for path: $normalizedPath'); - print('[AUTH DEBUG] Token length: ${token.length}'); - print('[AUTH DEBUG] Token preview: ${token.length > 50 ? token.substring(0, 50) + "..." : token}'); + stderr.writeln('[AUTH DEBUG] Verifying token for path: $normalizedPath'); + stderr.writeln('[AUTH DEBUG] Token length: ${token.length}'); + stderr.writeln('[AUTH DEBUG] Token preview: ${token.length > 50 ? token.substring(0, 50) + "..." : token}'); } final userId = jwtService.verifyAccessToken(token); @@ -125,13 +129,13 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) { if (userId == null) { // Additional debug info for admin endpoints if (normalizedPath.startsWith('/admin/')) { - print('[AUTH DEBUG] Token verification failed for path: $normalizedPath'); + stderr.writeln('[AUTH DEBUG] Token verification failed for path: $normalizedPath'); // Try to extract payload to see what's wrong try { final payload = jwtService.extractPayload(token); - print('[AUTH DEBUG] Extracted payload: $payload'); + stderr.writeln('[AUTH DEBUG] Extracted payload: $payload'); } catch (e) { - print('[AUTH DEBUG] Could not extract payload: $e'); + stderr.writeln('[AUTH DEBUG] Could not extract payload: $e'); } } return Response( @@ -140,6 +144,10 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) { body: '{"error":"Unauthorized","message":"Invalid or expired token"}', ); } + + if (normalizedPath.startsWith('/admin/')) { + stderr.writeln('[AUTH DEBUG] Token verified successfully, userId: $userId'); + } // Get user from database final userIdInt = int.tryParse(userId); diff --git a/mnemo_cards_backend/lib/api/v2/jwt_service.dart b/mnemo_cards_backend/lib/api/v2/jwt_service.dart index 621b988..74fe121 100644 --- a/mnemo_cards_backend/lib/api/v2/jwt_service.dart +++ b/mnemo_cards_backend/lib/api/v2/jwt_service.dart @@ -46,10 +46,6 @@ class JwtService { // Create JWT tokens with proper HMAC-SHA256 signing final accessToken = _createSimpleJwt(accessTokenPayload); final refreshToken = _createSimpleJwt(refreshTokenPayload); - - print('[JWT DEBUG] Generated access token for user ${user.id}'); - print('[JWT DEBUG] Access token payload: $accessTokenPayload'); - print('[JWT DEBUG] Access token length: ${accessToken.length}'); // Store refresh token for invalidation final userId = user.id; @@ -71,37 +67,25 @@ class JwtService { try { final payload = _verifySimpleJwt(token); if (payload == null) { - print('[JWT DEBUG] Token verification failed: payload is null'); return null; } - print('[JWT DEBUG] Token payload: $payload'); - // Check if token is expired final exp = payload['exp'] as int?; if (exp != null) { final expiryTime = DateTime.fromMillisecondsSinceEpoch(exp * 1000); - final now = DateTime.now(); - print('[JWT DEBUG] Token expiry: $expiryTime, now: $now, expired: ${now.isAfter(expiryTime)}'); - if (now.isAfter(expiryTime)) { - print('[JWT DEBUG] Token is expired'); + if (DateTime.now().isAfter(expiryTime)) { return null; } } // Check token type - final tokenType = payload['type']; - print('[JWT DEBUG] Token type: $tokenType'); - if (tokenType != 'access') { - print('[JWT DEBUG] Token type mismatch: expected "access", got "$tokenType"'); + if (payload['type'] != 'access') { return null; } - final userId = payload['userId']?.toString(); - print('[JWT DEBUG] Extracted userId: $userId'); - return userId; + return payload['userId']?.toString(); } catch (e) { - print('[JWT DEBUG] Token verification exception: $e'); return null; } } @@ -162,7 +146,6 @@ class JwtService { try { final parts = token.split('.'); if (parts.length != 3) { - print('[JWT DEBUG] Invalid token format: expected 3 parts, got ${parts.length}'); return null; } @@ -177,19 +160,13 @@ class JwtService { final expectedSignatureB64 = base64UrlEncode(expectedSignature); if (signatureB64 != expectedSignatureB64) { - print('[JWT DEBUG] Invalid signature'); - print('[JWT DEBUG] Expected: $expectedSignatureB64'); - print('[JWT DEBUG] Got: $signatureB64'); return null; // Invalid signature } // Decode payload final payloadJson = utf8.decode(base64Url.decode(payloadB64)); - final payload = jsonDecode(payloadJson) as Map; - print('[JWT DEBUG] Decoded payload: $payload'); - return payload; + return jsonDecode(payloadJson) as Map; } catch (e) { - print('[JWT DEBUG] Exception during token verification: $e'); return null; } }