jcbowyer commited on
Commit
0de4fbe
Β·
verified Β·
1 Parent(s): 6dcf9fc

Deploy: Consolidated gold tables, fixed nginx docs routing

Browse files
api/routes/auth.py CHANGED
@@ -272,6 +272,12 @@ async def oauth_callback(
272
 
273
  # Exchange code for access token
274
  try:
 
 
 
 
 
 
275
  async with httpx.AsyncClient() as client:
276
  token_response = await client.post(
277
  config['token_url'],
@@ -285,7 +291,12 @@ async def oauth_callback(
285
  headers={'Accept': 'application/json'}
286
  )
287
 
 
 
288
  if token_response.status_code != 200:
 
 
 
289
  # Parse error response for user-friendly message
290
  error_msg = "Authentication failed"
291
  try:
@@ -317,20 +328,27 @@ async def oauth_callback(
317
  return RedirectResponse(url=f"{redirect_url}?{params}")
318
 
319
  token_data = token_response.json()
 
320
  access_token = token_data.get('access_token')
321
 
322
  if not access_token:
 
323
  logger.error(f"No access token in response from {provider}: {token_data}")
324
  frontend_url = os.getenv('FRONTEND_URL', '')
325
  redirect_url = oauth_state.redirect_uri or (frontend_url if frontend_url and 'localhost' not in frontend_url else '/')
326
  params = urlencode({'error': f'{provider.title()} login failed: No access token received'})
327
  return RedirectResponse(url=f"{redirect_url}?{params}")
328
 
 
 
329
  # Get user info from provider
 
330
  user_info = await get_user_info(provider, access_token, config)
 
331
 
332
  # Validate we got user info (email is now always set, even if placeholder for Facebook)
333
  if not user_info:
 
334
  logger.error(f"Could not retrieve user info from {provider}. Check API response logs above.")
335
  frontend_url = os.getenv('FRONTEND_URL', '')
336
  redirect_url = oauth_state.redirect_uri or (frontend_url if frontend_url and 'localhost' not in frontend_url else '/')
@@ -415,38 +433,61 @@ async def get_user_info(provider: str, access_token: str, config: dict) -> dict:
415
  elif provider == 'facebook':
416
  # Facebook uses access token as query parameter, not Bearer header
417
  userinfo_url_with_token = f"{config['userinfo_url']}&access_token={access_token}"
418
- resp = await client.get(userinfo_url_with_token)
419
 
420
- # Log response for debugging
421
- logger.info(f"Facebook API response status: {resp.status_code}")
422
- logger.info(f"Facebook API response: {resp.text[:500]}")
423
 
424
- if resp.status_code != 200:
425
- logger.error(f"Facebook userinfo request failed: {resp.status_code} - {resp.text}")
426
- return None
427
-
428
- data = resp.json()
429
-
430
- # Validate we got required data
431
- if not data.get('id'):
432
- logger.error(f"Facebook did not return user ID. Response: {data}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
  return None
434
-
435
- # Facebook may not return email if permission not approved in App Review
436
- # Generate a placeholder email using Facebook ID if email not available
437
- email = data.get('email')
438
- if not email:
439
- fb_id = data.get('id')
440
- email = f"facebook_{fb_id}@communityone.placeholder"
441
- logger.warning(f"Facebook did not return email for user {fb_id}. Using placeholder: {email}")
442
-
443
- user_info = {
444
- 'email': email,
445
- 'oauth_id': str(data.get('id')),
446
- 'full_name': data.get('name'),
447
- 'avatar_url': data.get('picture', {}).get('data', {}).get('url') if isinstance(data.get('picture'), dict) else None,
448
- 'username': data.get('name', '').replace(' ', '_').lower(),
449
- }
450
 
451
  elif provider == 'github':
452
  # Get user profile
 
272
 
273
  # Exchange code for access token
274
  try:
275
+ logger.info(f"πŸ” [{provider.upper()}] Starting token exchange")
276
+ logger.info(f"πŸ” [{provider.upper()}] Token URL: {config['token_url']}")
277
+ logger.info(f"πŸ” [{provider.upper()}] Callback URL: {callback_url}")
278
+ logger.info(f"πŸ” [{provider.upper()}] Client ID configured: {bool(client_id)}")
279
+ logger.info(f"πŸ” [{provider.upper()}] Client Secret configured: {bool(client_secret)}")
280
+
281
  async with httpx.AsyncClient() as client:
282
  token_response = await client.post(
283
  config['token_url'],
 
291
  headers={'Accept': 'application/json'}
292
  )
293
 
294
+ logger.info(f"πŸ“Š [{provider.upper()}] Token response status: {token_response.status_code}")
295
+
296
  if token_response.status_code != 200:
297
+ logger.error(f"❌ [{provider.upper()}] Token exchange failed!")
298
+ logger.error(f"❌ [{provider.upper()}] Response: {token_response.text}")
299
+
300
  # Parse error response for user-friendly message
301
  error_msg = "Authentication failed"
302
  try:
 
328
  return RedirectResponse(url=f"{redirect_url}?{params}")
329
 
330
  token_data = token_response.json()
331
+ logger.info(f"βœ… [{provider.upper()}] Token response keys: {list(token_data.keys())}")
332
  access_token = token_data.get('access_token')
333
 
334
  if not access_token:
335
+ logger.error(f"❌ [{provider.upper()}] No access token in response!")
336
  logger.error(f"No access token in response from {provider}: {token_data}")
337
  frontend_url = os.getenv('FRONTEND_URL', '')
338
  redirect_url = oauth_state.redirect_uri or (frontend_url if frontend_url and 'localhost' not in frontend_url else '/')
339
  params = urlencode({'error': f'{provider.title()} login failed: No access token received'})
340
  return RedirectResponse(url=f"{redirect_url}?{params}")
341
 
342
+ logger.info(f"βœ… [{provider.upper()}] Got access token (first 20 chars): {access_token[:20]}...")
343
+
344
  # Get user info from provider
345
+ logger.info(f"πŸ” [{provider.upper()}] Fetching user info...")
346
  user_info = await get_user_info(provider, access_token, config)
347
+ logger.info(f"πŸ“Š [{provider.upper()}] User info result: {user_info is not None}")
348
 
349
  # Validate we got user info (email is now always set, even if placeholder for Facebook)
350
  if not user_info:
351
+ logger.error(f"❌ [{provider.upper()}] Could not retrieve user info! Check API response logs above.")
352
  logger.error(f"Could not retrieve user info from {provider}. Check API response logs above.")
353
  frontend_url = os.getenv('FRONTEND_URL', '')
354
  redirect_url = oauth_state.redirect_uri or (frontend_url if frontend_url and 'localhost' not in frontend_url else '/')
 
433
  elif provider == 'facebook':
434
  # Facebook uses access token as query parameter, not Bearer header
435
  userinfo_url_with_token = f"{config['userinfo_url']}&access_token={access_token}"
 
436
 
437
+ logger.info(f"πŸ” [FACEBOOK] Requesting user info from: {config['userinfo_url']}")
438
+ logger.info(f"πŸ” [FACEBOOK] Access token (first 20 chars): {access_token[:20]}...")
 
439
 
440
+ try:
441
+ resp = await client.get(userinfo_url_with_token)
442
+
443
+ # Enhanced logging for debugging
444
+ logger.info(f"πŸ“Š [FACEBOOK] API response status: {resp.status_code}")
445
+ logger.info(f"πŸ“Š [FACEBOOK] API response headers: {dict(resp.headers)}")
446
+ logger.info(f"πŸ“Š [FACEBOOK] API response body: {resp.text[:1000]}")
447
+
448
+ if resp.status_code != 200:
449
+ logger.error(f"❌ [FACEBOOK] Userinfo request failed!")
450
+ logger.error(f"❌ [FACEBOOK] Status: {resp.status_code}")
451
+ logger.error(f"❌ [FACEBOOK] Full response: {resp.text}")
452
+ return None
453
+
454
+ data = resp.json()
455
+ logger.info(f"βœ… [FACEBOOK] Successfully parsed JSON response")
456
+ logger.info(f"βœ… [FACEBOOK] Data keys: {list(data.keys())}")
457
+
458
+ # Validate we got required data
459
+ if not data.get('id'):
460
+ logger.error(f"❌ [FACEBOOK] Missing user ID in response!")
461
+ logger.error(f"❌ [FACEBOOK] Full response data: {data}")
462
+ return None
463
+
464
+ logger.info(f"βœ… [FACEBOOK] Got user ID: {data.get('id')}")
465
+
466
+ # Facebook may not return email if permission not approved in App Review
467
+ # Generate a placeholder email using Facebook ID if email not available
468
+ email = data.get('email')
469
+ if not email:
470
+ fb_id = data.get('id')
471
+ email = f"facebook_{fb_id}@communityone.placeholder"
472
+ logger.warning(f"⚠️ [FACEBOOK] No email returned for user {fb_id}. Using placeholder: {email}")
473
+ else:
474
+ logger.info(f"βœ… [FACEBOOK] Got email: {email}")
475
+
476
+ user_info = {
477
+ 'email': email,
478
+ 'oauth_id': str(data.get('id')),
479
+ 'full_name': data.get('name'),
480
+ 'avatar_url': data.get('picture', {}).get('data', {}).get('url') if isinstance(data.get('picture'), dict) else None,
481
+ 'username': data.get('name', '').replace(' ', '_').lower(),
482
+ }
483
+ logger.info(f"βœ… [FACEBOOK] Created user_info: {user_info}")
484
+
485
+ except Exception as e:
486
+ logger.error(f"❌ [FACEBOOK] Exception during user info fetch: {str(e)}")
487
+ logger.error(f"❌ [FACEBOOK] Exception type: {type(e).__name__}")
488
+ import traceback
489
+ logger.error(f"❌ [FACEBOOK] Traceback: {traceback.format_exc()}")
490
  return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
 
492
  elif provider == 'github':
493
  # Get user profile
api/static/index.html CHANGED
@@ -85,7 +85,7 @@
85
  }
86
  }
87
  </script>
88
- <script type="module" crossorigin src="/assets/index-1WOv19wf.js"></script>
89
  <link rel="stylesheet" crossorigin href="/assets/index-DHPGfrfk.css">
90
  </head>
91
  <body>
 
85
  }
86
  }
87
  </script>
88
+ <script type="module" crossorigin src="/assets/index-BiXTU5yP.js"></script>
89
  <link rel="stylesheet" crossorigin href="/assets/index-DHPGfrfk.css">
90
  </head>
91
  <body>
frontend/src/pages/HomeModern.tsx CHANGED
@@ -1465,7 +1465,7 @@ export default function HomeModern() {
1465
  <path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/>
1466
  </svg>
1467
  </a>
1468
- <a href="https://github.com/getcommunityone/open-navigator-for-engagement" target="_blank" rel="noopener noreferrer" className="text-gray-400 hover:text-white transition-colors" aria-label="GitHub">
1469
  <svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
1470
  <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
1471
  </svg>
 
1465
  <path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/>
1466
  </svg>
1467
  </a>
1468
+ <a href="https://github.com/getcommunityone" target="_blank" rel="noopener noreferrer" className="text-gray-400 hover:text-white transition-colors" aria-label="GitHub">
1469
  <svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
1470
  <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
1471
  </svg>