rairo commited on
Commit
212aec9
·
verified ·
1 Parent(s): 19f67b5

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +93 -19
main.py CHANGED
@@ -319,32 +319,58 @@ def image_proxy():
319
  return jsonify({'error': 'Internal server error processing the image request.'}), 500
320
 
321
  # -----------------------------------------------------------------------------
322
- # 3. AUTHENTICATION & USER MANAGEMENT
323
  # -----------------------------------------------------------------------------
324
 
325
  @app.route('/api/auth/signup', methods=['POST'])
326
  def signup():
 
 
 
 
327
  try:
328
  data = request.get_json()
329
  email, password = data.get('email'), data.get('password')
330
- if not email or not password: return jsonify({'error': 'Email and password are required'}), 400
 
 
 
 
331
 
332
- user = auth.create_user(email=email, password=password)
 
 
 
 
 
 
 
333
  user_ref = db_ref.child(f'users/{user.uid}')
334
- user_data = {'email': email, 'credits': 15, 'is_admin': False, 'createdAt': datetime.utcnow().isoformat()}
 
 
 
 
 
 
335
  user_ref.set(user_data)
 
 
336
  return jsonify({'success': True, 'uid': user.uid, **user_data}), 201
 
337
  except Exception as e:
 
 
 
 
338
  return jsonify({'error': str(e)}), 400
339
 
340
  @app.route('/api/auth/social-signin', methods=['POST'])
341
  def social_signin():
342
  """
343
- Ensures a user record exists in the Realtime Database after a social login
344
- (like Google Sign-In). The client should call this endpoint immediately after
345
- a successful Firebase authentication on their side, sending the
346
- Firebase ID Token. This creates the user's profile in our database if it's
347
- their first time.
348
  """
349
  uid = verify_token(request.headers.get('Authorization'))
350
  if not uid:
@@ -354,39 +380,87 @@ def social_signin():
354
  user_data = user_ref.get()
355
 
356
  if user_data:
357
- # User already has a profile in our DB, return it.
 
 
 
 
 
 
 
 
 
 
 
 
358
  return jsonify({'uid': uid, **user_data}), 200
359
  else:
360
- # This is a new user (first social login), create their profile.
 
361
  try:
362
- # Get user details from Firebase Auth service. [8]
363
  firebase_user = auth.get_user(uid)
364
-
365
- # Create the user profile in our Realtime Database
366
  new_user_data = {
367
  'email': firebase_user.email,
368
- 'credits': 15, # Standard starting credits
 
369
  'is_admin': False,
370
  'createdAt': datetime.utcnow().isoformat()
371
  }
372
  user_ref.set(new_user_data)
373
 
374
- # Return the newly created profile
375
  return jsonify({'success': True, 'uid': uid, **new_user_data}), 201
376
  except Exception as e:
377
- print(f"Error creating profile for new social user {uid}: {e}")
378
  return jsonify({'error': f'Failed to create user profile: {str(e)}'}), 500
379
 
 
380
  @app.route('/api/user/profile', methods=['GET'])
381
  def get_user_profile():
 
 
 
 
382
  uid = verify_token(request.headers.get('Authorization'))
383
- if not uid: return jsonify({'error': 'Invalid or expired token'}), 401
 
384
 
385
  user_data = db_ref.child(f'users/{uid}').get()
386
- if not user_data: return jsonify({'error': 'User not found'}), 404
 
387
 
388
  return jsonify({'uid': uid, **user_data})
389
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  # -----------------------------------------------------------------------------
391
  # 4. FEEDBACK AND CREDIT REQUESTS (USER-FACING)
392
  # -----------------------------------------------------------------------------
 
319
  return jsonify({'error': 'Internal server error processing the image request.'}), 500
320
 
321
  # -----------------------------------------------------------------------------
322
+ # 3. AUTHENTICATION & USER MANAGEMENT (Corrected Version)
323
  # -----------------------------------------------------------------------------
324
 
325
  @app.route('/api/auth/signup', methods=['POST'])
326
  def signup():
327
+ """
328
+ Handles new user sign-up with email/password.
329
+ ✅ FIX: Now accepts an optional 'displayName' and saves it.
330
+ """
331
  try:
332
  data = request.get_json()
333
  email, password = data.get('email'), data.get('password')
334
+ # Get the optional displayName
335
+ display_name = data.get('displayName') # Will be None if not provided
336
+
337
+ if not email or not password:
338
+ return jsonify({'error': 'Email and password are required'}), 400
339
 
340
+ # Create the user in Firebase Authentication, including the displayName if available
341
+ user = auth.create_user(
342
+ email=email,
343
+ password=password,
344
+ display_name=display_name
345
+ )
346
+
347
+ # Create the corresponding user profile in the Realtime Database
348
  user_ref = db_ref.child(f'users/{user.uid}')
349
+ user_data = {
350
+ 'email': email,
351
+ 'displayName': display_name, # Save the name to the database
352
+ 'credits': 15,
353
+ 'is_admin': False,
354
+ 'createdAt': datetime.utcnow().isoformat()
355
+ }
356
  user_ref.set(user_data)
357
+
358
+ logger.info(f"New user signed up: {user.uid}, Name: {display_name}")
359
  return jsonify({'success': True, 'uid': user.uid, **user_data}), 201
360
+
361
  except Exception as e:
362
+ logger.error(f"Signup failed: {e}")
363
+ # Provide a more specific error for existing users
364
+ if 'EMAIL_EXISTS' in str(e):
365
+ return jsonify({'error': 'An account with this email already exists.'}), 409
366
  return jsonify({'error': str(e)}), 400
367
 
368
  @app.route('/api/auth/social-signin', methods=['POST'])
369
  def social_signin():
370
  """
371
+ Ensures a user record exists and is up-to-date in the Realtime Database.
372
+ IMPROVEMENT: Now backfills the displayName for existing social users
373
+ if it's missing from the database.
 
 
374
  """
375
  uid = verify_token(request.headers.get('Authorization'))
376
  if not uid:
 
380
  user_data = user_ref.get()
381
 
382
  if user_data:
383
+ # User already exists. Check if their displayName is missing.
384
+ if 'displayName' not in user_data or user_data['displayName'] is None:
385
+ try:
386
+ # The name is missing in our DB, let's sync it from Auth.
387
+ firebase_user = auth.get_user(uid)
388
+ if firebase_user.display_name:
389
+ logger.info(f"Backfilling missing displayName for existing user {uid}.")
390
+ user_ref.update({'displayName': firebase_user.display_name})
391
+ # Get the updated data to return to the client
392
+ user_data = user_ref.get()
393
+ except Exception as e:
394
+ logger.error(f"Could not backfill displayName for user {uid}: {e}")
395
+
396
  return jsonify({'uid': uid, **user_data}), 200
397
  else:
398
+ # This is a new user (first social login), create their full profile.
399
+ logger.info(f"New social user detected: {uid}. Creating database profile.")
400
  try:
 
401
  firebase_user = auth.get_user(uid)
 
 
402
  new_user_data = {
403
  'email': firebase_user.email,
404
+ 'displayName': firebase_user.display_name,
405
+ 'credits': 15,
406
  'is_admin': False,
407
  'createdAt': datetime.utcnow().isoformat()
408
  }
409
  user_ref.set(new_user_data)
410
 
411
+ logger.info(f"Successfully created profile for new social user: {uid}")
412
  return jsonify({'success': True, 'uid': uid, **new_user_data}), 201
413
  except Exception as e:
414
+ logger.error(f"Error creating profile for new social user {uid}: {e}")
415
  return jsonify({'error': f'Failed to create user profile: {str(e)}'}), 500
416
 
417
+
418
  @app.route('/api/user/profile', methods=['GET'])
419
  def get_user_profile():
420
+ """
421
+ Retrieves the user's profile from the Realtime Database.
422
+ ✅ FIX: This now correctly includes the 'displayName' in the response.
423
+ """
424
  uid = verify_token(request.headers.get('Authorization'))
425
+ if not uid:
426
+ return jsonify({'error': 'Invalid or expired token'}), 401
427
 
428
  user_data = db_ref.child(f'users/{uid}').get()
429
+ if not user_data:
430
+ return jsonify({'error': 'User not found'}), 404
431
 
432
  return jsonify({'uid': uid, **user_data})
433
 
434
+ @app.route('/api/user/profile', methods=['PUT'])
435
+ def update_user_profile():
436
+ """
437
+ ✅ NEW: Allows a logged-in user to update their profile, specifically their displayName.
438
+ """
439
+ uid = verify_token(request.headers.get('Authorization'))
440
+ if not uid:
441
+ return jsonify({'error': 'Invalid or expired token'}), 401
442
+
443
+ data = request.get_json()
444
+ new_display_name = data.get('displayName')
445
+
446
+ if not new_display_name or not isinstance(new_display_name, str) or len(new_display_name.strip()) == 0:
447
+ return jsonify({'error': 'A valid displayName is required.'}), 400
448
+
449
+ try:
450
+ # Step 1: Update the user record in Firebase Authentication
451
+ auth.update_user(uid, display_name=new_display_name)
452
+
453
+ # Step 2: Update the user profile in the Realtime Database
454
+ user_ref = db_ref.child(f'users/{uid}')
455
+ user_ref.update({'displayName': new_display_name})
456
+
457
+ logger.info(f"User {uid} updated their displayName to '{new_display_name}'.")
458
+ return jsonify({'success': True, 'message': 'Profile updated successfully.'}), 200
459
+
460
+ except Exception as e:
461
+ logger.error(f"Error updating profile for user {uid}: {e}")
462
+ return jsonify({'error': f'Failed to update profile: {str(e)}'}), 500
463
+
464
  # -----------------------------------------------------------------------------
465
  # 4. FEEDBACK AND CREDIT REQUESTS (USER-FACING)
466
  # -----------------------------------------------------------------------------