Update main.py
Browse files
main.py
CHANGED
|
@@ -144,33 +144,62 @@ def signup():
|
|
| 144 |
if not email or not password:
|
| 145 |
return jsonify({'error': 'Email and password are required'}), 400
|
| 146 |
|
| 147 |
-
|
| 148 |
user = auth.create_user(email=email, password=password)
|
|
|
|
| 149 |
|
| 150 |
-
# Create corresponding user entry in Firebase Realtime Database
|
| 151 |
user_ref = db.reference(f'users/{user.uid}')
|
| 152 |
-
|
| 153 |
'email': email,
|
| 154 |
'credits': 10,
|
| 155 |
'is_admin': False,
|
| 156 |
'created_at': datetime.utcnow().isoformat(),
|
| 157 |
-
'suspended': False
|
| 158 |
}
|
| 159 |
-
|
| 160 |
-
logging.info(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
return jsonify({
|
| 163 |
'success': True,
|
| 164 |
'user': {
|
| 165 |
'uid': user.uid,
|
| 166 |
-
**
|
| 167 |
}
|
| 168 |
}), 201
|
| 169 |
-
except
|
| 170 |
-
logging.
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
|
|
|
| 174 |
return jsonify({'error': str(e)}), 400
|
| 175 |
|
| 176 |
@app.route('/api/user/profile', methods=['GET'])
|
|
@@ -220,35 +249,58 @@ def google_signin():
|
|
| 220 |
decoded_token = auth.verify_id_token(token)
|
| 221 |
uid = decoded_token['uid']
|
| 222 |
email = decoded_token.get('email')
|
|
|
|
| 223 |
|
| 224 |
user_ref = db.reference(f'users/{uid}')
|
| 225 |
-
|
|
|
|
| 226 |
|
| 227 |
-
if not
|
| 228 |
-
|
| 229 |
-
|
| 230 |
'email': email,
|
| 231 |
'credits': 10,
|
| 232 |
'is_admin': False,
|
| 233 |
'created_at': datetime.utcnow().isoformat(),
|
| 234 |
'suspended': False
|
| 235 |
}
|
| 236 |
-
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
else:
|
| 239 |
-
logging.info(f"Existing Google user {uid} logged in.")
|
|
|
|
| 240 |
|
| 241 |
return jsonify({
|
| 242 |
'success': True,
|
| 243 |
'user': {
|
| 244 |
'uid': uid,
|
| 245 |
-
**
|
| 246 |
}
|
| 247 |
}), 200
|
| 248 |
|
| 249 |
-
except Exception as e:
|
| 250 |
logging.error(f"Google sign-in error: {e}")
|
| 251 |
-
|
|
|
|
| 252 |
|
| 253 |
@app.route('/api/user/request-credits', methods=['POST'])
|
| 254 |
@credit_required(cost=0)
|
|
|
|
| 144 |
if not email or not password:
|
| 145 |
return jsonify({'error': 'Email and password are required'}), 400
|
| 146 |
|
| 147 |
+
logging.info(f"Attempting to create Firebase Auth user for email: {email}")
|
| 148 |
user = auth.create_user(email=email, password=password)
|
| 149 |
+
logging.info(f"Firebase Auth user CREATED successfully: {user.uid} for email: {email}")
|
| 150 |
|
|
|
|
| 151 |
user_ref = db.reference(f'users/{user.uid}')
|
| 152 |
+
user_data_to_set = {
|
| 153 |
'email': email,
|
| 154 |
'credits': 10,
|
| 155 |
'is_admin': False,
|
| 156 |
'created_at': datetime.utcnow().isoformat(),
|
| 157 |
+
'suspended': False
|
| 158 |
}
|
| 159 |
+
|
| 160 |
+
logging.info(f"Attempting to write user profile to DB for UID: {user.uid}. Data: {user_data_to_set}")
|
| 161 |
+
try:
|
| 162 |
+
user_ref.set(user_data_to_set)
|
| 163 |
+
logging.info(f"DB WRITE: user_ref.set() CALLED for UID: {user.uid}.")
|
| 164 |
+
|
| 165 |
+
# VERIFICATION STEP: Immediately try to read the data back
|
| 166 |
+
time.sleep(0.5) # Small delay to allow for potential eventual consistency
|
| 167 |
+
retrieved_data = user_ref.get()
|
| 168 |
+
if retrieved_data and retrieved_data.get('email') == email:
|
| 169 |
+
logging.info(f"DB VERIFICATION SUCCESS: Data for UID {user.uid} read back successfully: {retrieved_data}")
|
| 170 |
+
else:
|
| 171 |
+
logging.error(f"DB VERIFICATION FAILED: Data for UID {user.uid} NOT found or mismatched after set. Retrieved: {retrieved_data}")
|
| 172 |
+
# This is a critical failure point if it happens
|
| 173 |
+
try:
|
| 174 |
+
auth.delete_user(user.uid)
|
| 175 |
+
logging.info(f"Auth user {user.uid} deleted due to DB verification failure.")
|
| 176 |
+
except Exception as auth_delete_err:
|
| 177 |
+
logging.error(f"Failed to delete Auth user {user.uid} after DB verification failure: {auth_delete_err}")
|
| 178 |
+
return jsonify({'error': 'Failed to reliably save user profile to database after creation.'}), 500
|
| 179 |
+
|
| 180 |
+
except Exception as db_error:
|
| 181 |
+
logging.error(f"DATABASE WRITE EXCEPTION during user_ref.set() for new user UID {user.uid}: {db_error}")
|
| 182 |
+
logging.error(traceback.format_exc())
|
| 183 |
+
try:
|
| 184 |
+
auth.delete_user(user.uid)
|
| 185 |
+
logging.info(f"Cleaned up Firebase Auth user {user.uid} due to DB write exception.")
|
| 186 |
+
except Exception as auth_delete_err:
|
| 187 |
+
logging.error(f"Failed to cleanup Firebase Auth user {user.uid} after DB write exception: {auth_delete_err}")
|
| 188 |
+
return jsonify({'error': f'User created in Auth, but failed to save profile to database: {str(db_error)}'}), 500
|
| 189 |
|
| 190 |
return jsonify({
|
| 191 |
'success': True,
|
| 192 |
'user': {
|
| 193 |
'uid': user.uid,
|
| 194 |
+
**user_data_to_set
|
| 195 |
}
|
| 196 |
}), 201
|
| 197 |
+
except auth.EmailAlreadyExistsError: # Specific Firebase Auth error
|
| 198 |
+
logging.warning(f"Signup attempt with existing email: {email}")
|
| 199 |
+
return jsonify({'error': 'Email already in use.'}), 409
|
| 200 |
+
except Exception as e: # General catch-all
|
| 201 |
+
logging.error(f"General signup error: {e}")
|
| 202 |
+
logging.error(traceback.format_exc())
|
| 203 |
return jsonify({'error': str(e)}), 400
|
| 204 |
|
| 205 |
@app.route('/api/user/profile', methods=['GET'])
|
|
|
|
| 249 |
decoded_token = auth.verify_id_token(token)
|
| 250 |
uid = decoded_token['uid']
|
| 251 |
email = decoded_token.get('email')
|
| 252 |
+
logging.info(f"Google Sign-In attempt for UID: {uid}, Email: {email}")
|
| 253 |
|
| 254 |
user_ref = db.reference(f'users/{uid}')
|
| 255 |
+
user_data_from_db = user_ref.get()
|
| 256 |
+
user_data_for_response = None
|
| 257 |
|
| 258 |
+
if not user_data_from_db:
|
| 259 |
+
logging.info(f"Google user {uid} (Email: {email}) not found in DB, creating new profile.")
|
| 260 |
+
new_user_data_to_set = {
|
| 261 |
'email': email,
|
| 262 |
'credits': 10,
|
| 263 |
'is_admin': False,
|
| 264 |
'created_at': datetime.utcnow().isoformat(),
|
| 265 |
'suspended': False
|
| 266 |
}
|
| 267 |
+
logging.info(f"Attempting to write Google user profile to DB for UID: {uid}. Data: {new_user_data_to_set}")
|
| 268 |
+
try:
|
| 269 |
+
user_ref.set(new_user_data_to_set)
|
| 270 |
+
logging.info(f"DB WRITE: user_ref.set() CALLED for Google user UID: {uid}.")
|
| 271 |
+
|
| 272 |
+
# VERIFICATION STEP
|
| 273 |
+
time.sleep(0.5)
|
| 274 |
+
retrieved_data = user_ref.get()
|
| 275 |
+
if retrieved_data and retrieved_data.get('email') == email:
|
| 276 |
+
logging.info(f"DB VERIFICATION SUCCESS: Data for Google user UID {uid} read back successfully: {retrieved_data}")
|
| 277 |
+
user_data_for_response = new_user_data_to_set
|
| 278 |
+
else:
|
| 279 |
+
logging.error(f"DB VERIFICATION FAILED: Data for Google user UID {uid} NOT found or mismatched after set. Retrieved: {retrieved_data}")
|
| 280 |
+
# For Google Sign-In, the Auth user already exists, so we don't delete it.
|
| 281 |
+
# The main issue is the DB profile creation.
|
| 282 |
+
return jsonify({'error': 'Failed to reliably save Google user profile to database.'}), 500
|
| 283 |
+
|
| 284 |
+
except Exception as db_error:
|
| 285 |
+
logging.error(f"DATABASE WRITE EXCEPTION during user_ref.set() for new Google user UID {uid}: {db_error}")
|
| 286 |
+
logging.error(traceback.format_exc())
|
| 287 |
+
return jsonify({'error': f'User signed in with Google, but failed to save profile to database: {str(db_error)}'}), 500
|
| 288 |
else:
|
| 289 |
+
logging.info(f"Existing Google user {uid} logged in. DB data: {user_data_from_db}")
|
| 290 |
+
user_data_for_response = user_data_from_db
|
| 291 |
|
| 292 |
return jsonify({
|
| 293 |
'success': True,
|
| 294 |
'user': {
|
| 295 |
'uid': uid,
|
| 296 |
+
**user_data_for_response
|
| 297 |
}
|
| 298 |
}), 200
|
| 299 |
|
| 300 |
+
except Exception as e: # General catch-all for token verification or other issues
|
| 301 |
logging.error(f"Google sign-in error: {e}")
|
| 302 |
+
logging.error(traceback.format_exc())
|
| 303 |
+
return jsonify({'error': str(e)}), 400
|
| 304 |
|
| 305 |
@app.route('/api/user/request-credits', methods=['POST'])
|
| 306 |
@credit_required(cost=0)
|