jj
Browse files- backend/api/auth.py +12 -1
- frontend/.env.production +1 -1
- frontend/src/services/apiClient.js +10 -0
- frontend/src/services/authService.js +12 -1
backend/api/auth.py
CHANGED
|
@@ -74,6 +74,9 @@ def register():
|
|
| 74 |
@auth_bp.route('/login', methods=['OPTIONS'])
|
| 75 |
def handle_login_options():
|
| 76 |
"""Handle OPTIONS requests for preflight CORS checks for login route."""
|
|
|
|
|
|
|
|
|
|
| 77 |
return '', 200
|
| 78 |
|
| 79 |
@auth_bp.route('/login', methods=['POST'])
|
|
@@ -90,10 +93,16 @@ def login():
|
|
| 90 |
JSON: Login result with JWT token
|
| 91 |
"""
|
| 92 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
data = request.get_json()
|
| 94 |
|
| 95 |
# Validate required fields
|
| 96 |
if not data or not all(k in data for k in ('email', 'password')):
|
|
|
|
| 97 |
return jsonify({
|
| 98 |
'success': False,
|
| 99 |
'message': 'Email and password are required'
|
|
@@ -111,12 +120,14 @@ def login():
|
|
| 111 |
response_data = jsonify(result)
|
| 112 |
response_data.headers.add('Access-Control-Allow-Origin', 'http://localhost:3000')
|
| 113 |
response_data.headers.add('Access-Control-Allow-Credentials', 'true')
|
|
|
|
| 114 |
return response_data, 200
|
| 115 |
else:
|
|
|
|
| 116 |
return jsonify(result), 401
|
| 117 |
|
| 118 |
except Exception as e:
|
| 119 |
-
current_app.logger.error(f"Login error: {str(e)}")
|
| 120 |
return jsonify({
|
| 121 |
'success': False,
|
| 122 |
'message': 'An error occurred during login'
|
|
|
|
| 74 |
@auth_bp.route('/login', methods=['OPTIONS'])
|
| 75 |
def handle_login_options():
|
| 76 |
"""Handle OPTIONS requests for preflight CORS checks for login route."""
|
| 77 |
+
from flask import current_app
|
| 78 |
+
current_app.logger.info(f"OPTIONS request for /login from {request.remote_addr}")
|
| 79 |
+
current_app.logger.info(f"Request headers: {dict(request.headers)}")
|
| 80 |
return '', 200
|
| 81 |
|
| 82 |
@auth_bp.route('/login', methods=['POST'])
|
|
|
|
| 93 |
JSON: Login result with JWT token
|
| 94 |
"""
|
| 95 |
try:
|
| 96 |
+
# Log the incoming request
|
| 97 |
+
current_app.logger.info(f"Login request received from {request.remote_addr}")
|
| 98 |
+
current_app.logger.info(f"Request headers: {dict(request.headers)}")
|
| 99 |
+
current_app.logger.info(f"Request data: {request.get_json()}")
|
| 100 |
+
|
| 101 |
data = request.get_json()
|
| 102 |
|
| 103 |
# Validate required fields
|
| 104 |
if not data or not all(k in data for k in ('email', 'password')):
|
| 105 |
+
current_app.logger.warning("Login failed: Missing email or password")
|
| 106 |
return jsonify({
|
| 107 |
'success': False,
|
| 108 |
'message': 'Email and password are required'
|
|
|
|
| 120 |
response_data = jsonify(result)
|
| 121 |
response_data.headers.add('Access-Control-Allow-Origin', 'http://localhost:3000')
|
| 122 |
response_data.headers.add('Access-Control-Allow-Credentials', 'true')
|
| 123 |
+
current_app.logger.info(f"Login successful for user {email}")
|
| 124 |
return response_data, 200
|
| 125 |
else:
|
| 126 |
+
current_app.logger.warning(f"Login failed for user {email}: {result.get('message', 'Unknown error')}")
|
| 127 |
return jsonify(result), 401
|
| 128 |
|
| 129 |
except Exception as e:
|
| 130 |
+
current_app.logger.error(f"Login error: {str(e)}", exc_info=True)
|
| 131 |
return jsonify({
|
| 132 |
'success': False,
|
| 133 |
'message': 'An error occurred during login'
|
frontend/.env.production
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# API Configuration
|
| 2 |
-
VITE_API_URL=https://zelyanoth-lin-cbfcff2.hf.space
|
| 3 |
|
| 4 |
# Environment
|
| 5 |
VITE_NODE_ENV=production
|
|
|
|
| 1 |
# API Configuration
|
| 2 |
+
VITE_API_URL=https://zelyanoth-lin-cbfcff2.hf.space/api
|
| 3 |
|
| 4 |
# Environment
|
| 5 |
VITE_NODE_ENV=production
|
frontend/src/services/apiClient.js
CHANGED
|
@@ -3,6 +3,8 @@ import cookieService from '../services/cookieService';
|
|
| 3 |
|
| 4 |
// Create axios instance with default config
|
| 5 |
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:5000';
|
|
|
|
|
|
|
| 6 |
const apiClient = axios.create({
|
| 7 |
baseURL: API_BASE_URL,
|
| 8 |
timeout: 30000,
|
|
@@ -15,6 +17,10 @@ const apiClient = axios.create({
|
|
| 15 |
// Request interceptor to add auth token
|
| 16 |
apiClient.interceptors.request.use(
|
| 17 |
async (config) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
// Get token from cookie service
|
| 19 |
const tokens = await cookieService.getAuthTokens();
|
| 20 |
if (tokens?.accessToken) {
|
|
@@ -23,6 +29,7 @@ apiClient.interceptors.request.use(
|
|
| 23 |
return config;
|
| 24 |
},
|
| 25 |
(error) => {
|
|
|
|
| 26 |
return Promise.reject(error);
|
| 27 |
}
|
| 28 |
);
|
|
@@ -30,9 +37,12 @@ apiClient.interceptors.request.use(
|
|
| 30 |
// Response interceptor to handle token refresh
|
| 31 |
apiClient.interceptors.response.use(
|
| 32 |
(response) => {
|
|
|
|
|
|
|
| 33 |
return response;
|
| 34 |
},
|
| 35 |
async (error) => {
|
|
|
|
| 36 |
const originalRequest = error.config;
|
| 37 |
|
| 38 |
// If error is 401 and we haven't retried yet
|
|
|
|
| 3 |
|
| 4 |
// Create axios instance with default config
|
| 5 |
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:5000';
|
| 6 |
+
console.log('API_BASE_URL:', API_BASE_URL);
|
| 7 |
+
|
| 8 |
const apiClient = axios.create({
|
| 9 |
baseURL: API_BASE_URL,
|
| 10 |
timeout: 30000,
|
|
|
|
| 17 |
// Request interceptor to add auth token
|
| 18 |
apiClient.interceptors.request.use(
|
| 19 |
async (config) => {
|
| 20 |
+
console.log('API Request:', config.method?.toUpperCase(), config.baseURL + config.url);
|
| 21 |
+
console.log('Request headers:', config.headers);
|
| 22 |
+
console.log('Request data:', config.data);
|
| 23 |
+
|
| 24 |
// Get token from cookie service
|
| 25 |
const tokens = await cookieService.getAuthTokens();
|
| 26 |
if (tokens?.accessToken) {
|
|
|
|
| 29 |
return config;
|
| 30 |
},
|
| 31 |
(error) => {
|
| 32 |
+
console.error('API Request Error:', error);
|
| 33 |
return Promise.reject(error);
|
| 34 |
}
|
| 35 |
);
|
|
|
|
| 37 |
// Response interceptor to handle token refresh
|
| 38 |
apiClient.interceptors.response.use(
|
| 39 |
(response) => {
|
| 40 |
+
console.log('API Response:', response.status, response.config.method?.toUpperCase(), response.config.baseURL + response.config.url);
|
| 41 |
+
console.log('Response data:', response.data);
|
| 42 |
return response;
|
| 43 |
},
|
| 44 |
async (error) => {
|
| 45 |
+
console.error('API Response Error:', error);
|
| 46 |
const originalRequest = error.config;
|
| 47 |
|
| 48 |
// If error is 401 and we haven't retried yet
|
frontend/src/services/authService.js
CHANGED
|
@@ -15,9 +15,12 @@ class AuthService {
|
|
| 15 |
*/
|
| 16 |
async register(userData) {
|
| 17 |
try {
|
|
|
|
| 18 |
const response = await apiClient.post('/auth/register', userData);
|
|
|
|
| 19 |
return response;
|
| 20 |
} catch (error) {
|
|
|
|
| 21 |
// Handle network errors
|
| 22 |
if (!error.response) {
|
| 23 |
throw new Error('Network error - please check your connection');
|
|
@@ -36,9 +39,12 @@ class AuthService {
|
|
| 36 |
*/
|
| 37 |
async login(credentials) {
|
| 38 |
try {
|
|
|
|
| 39 |
const response = await apiClient.post('/auth/login', credentials);
|
|
|
|
| 40 |
return response;
|
| 41 |
} catch (error) {
|
|
|
|
| 42 |
// Handle network errors
|
| 43 |
if (!error.response) {
|
| 44 |
throw new Error('Network error - please check your connection');
|
|
@@ -53,15 +59,17 @@ class AuthService {
|
|
| 53 |
*/
|
| 54 |
async logout() {
|
| 55 |
try {
|
|
|
|
| 56 |
// For logout, we don't need to send any data
|
| 57 |
// We just need to clear the token on the client side
|
| 58 |
// The server will handle token invalidation if needed
|
| 59 |
const response = await apiClient.post('/auth/logout');
|
|
|
|
| 60 |
return response;
|
| 61 |
} catch (error) {
|
|
|
|
| 62 |
// For logout, we don't want to throw errors as it should always succeed
|
| 63 |
// We just clear the local storage and let the UI handle it
|
| 64 |
-
console.warn('Logout error (continuing anyway):', error.message);
|
| 65 |
return { data: { success: true, message: 'Logged out successfully' } };
|
| 66 |
}
|
| 67 |
}
|
|
@@ -72,9 +80,12 @@ class AuthService {
|
|
| 72 |
*/
|
| 73 |
async getCurrentUser() {
|
| 74 |
try {
|
|
|
|
| 75 |
const response = await apiClient.get('/auth/user');
|
|
|
|
| 76 |
return response;
|
| 77 |
} catch (error) {
|
|
|
|
| 78 |
// Handle network errors
|
| 79 |
if (!error.response) {
|
| 80 |
throw new Error('Network error - please check your connection');
|
|
|
|
| 15 |
*/
|
| 16 |
async register(userData) {
|
| 17 |
try {
|
| 18 |
+
console.log('AuthService: Registering user', userData);
|
| 19 |
const response = await apiClient.post('/auth/register', userData);
|
| 20 |
+
console.log('AuthService: Registration response', response.data);
|
| 21 |
return response;
|
| 22 |
} catch (error) {
|
| 23 |
+
console.error('AuthService: Registration error', error);
|
| 24 |
// Handle network errors
|
| 25 |
if (!error.response) {
|
| 26 |
throw new Error('Network error - please check your connection');
|
|
|
|
| 39 |
*/
|
| 40 |
async login(credentials) {
|
| 41 |
try {
|
| 42 |
+
console.log('AuthService: Logging in user', credentials);
|
| 43 |
const response = await apiClient.post('/auth/login', credentials);
|
| 44 |
+
console.log('AuthService: Login response', response.data);
|
| 45 |
return response;
|
| 46 |
} catch (error) {
|
| 47 |
+
console.error('AuthService: Login error', error);
|
| 48 |
// Handle network errors
|
| 49 |
if (!error.response) {
|
| 50 |
throw new Error('Network error - please check your connection');
|
|
|
|
| 59 |
*/
|
| 60 |
async logout() {
|
| 61 |
try {
|
| 62 |
+
console.log('AuthService: Logging out user');
|
| 63 |
// For logout, we don't need to send any data
|
| 64 |
// We just need to clear the token on the client side
|
| 65 |
// The server will handle token invalidation if needed
|
| 66 |
const response = await apiClient.post('/auth/logout');
|
| 67 |
+
console.log('AuthService: Logout response', response.data);
|
| 68 |
return response;
|
| 69 |
} catch (error) {
|
| 70 |
+
console.warn('AuthService: Logout error (continuing anyway):', error.message);
|
| 71 |
// For logout, we don't want to throw errors as it should always succeed
|
| 72 |
// We just clear the local storage and let the UI handle it
|
|
|
|
| 73 |
return { data: { success: true, message: 'Logged out successfully' } };
|
| 74 |
}
|
| 75 |
}
|
|
|
|
| 80 |
*/
|
| 81 |
async getCurrentUser() {
|
| 82 |
try {
|
| 83 |
+
console.log('AuthService: Getting current user');
|
| 84 |
const response = await apiClient.get('/auth/user');
|
| 85 |
+
console.log('AuthService: Get user response', response.data);
|
| 86 |
return response;
|
| 87 |
} catch (error) {
|
| 88 |
+
console.error('AuthService: Get user error', error);
|
| 89 |
// Handle network errors
|
| 90 |
if (!error.response) {
|
| 91 |
throw new Error('Network error - please check your connection');
|