Spaces:
Running
Running
| import os | |
| import logging | |
| from flask import jsonify | |
| from sendgrid import SendGridAPIClient | |
| from sendgrid.helpers.mail import Mail | |
| from database import generate_reset_code, verify_reset_code, update_user_password | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| logger = logging.getLogger(__name__) | |
| # Email configuration using environment variables | |
| EMAIL_ADDRESS = os.environ.get('EMAIL_ADDRESS') | |
| SENDGRID_API_KEY = os.environ.get('SENDGRID_API_KEY') | |
| SENDER_NAME = os.environ.get('SENDER_NAME', 'BeeGuardian Team') | |
| COMPANY_ADDRESS = os.environ.get('COMPANY_ADDRESS', 'Namal University') | |
| COMPANY_CITY = os.environ.get('COMPANY_CITY', 'Mianwali') | |
| COMPANY_STATE = os.environ.get('COMPANY_STATE', 'Punjab') | |
| COMPANY_ZIP = os.environ.get('COMPANY_ZIP', '42200') | |
| COMPANY_COUNTRY = os.environ.get('COMPANY_COUNTRY', 'Pakistan') | |
| # Send email with reset code using SendGrid | |
| def send_reset_email(email, code): | |
| if not EMAIL_ADDRESS or not SENDGRID_API_KEY: | |
| logger.error("Email configuration missing") | |
| return False, "Email configuration missing" | |
| # Email content with BeeGuardian intro and CAN-SPAM compliant footer | |
| footer = ( | |
| f"\n\n--\n" | |
| f"{SENDER_NAME}\n" | |
| f"{COMPANY_ADDRESS}\n" | |
| f"{COMPANY_CITY}, {COMPANY_STATE} {COMPANY_ZIP}\n" | |
| f"{COMPANY_COUNTRY}" | |
| ) | |
| content = ( | |
| f"Welcome to BeeGuardian! We are a team of students from Namal University Mianwali who created an innovative app to help beekeepers monitor bee health using mobile phone recordings. Our mission is to protect bees and support biodiversity.\n\n" | |
| f"To reset your password, please use this code: {code}\n" | |
| f"This code is valid for 15 minutes.{footer}" | |
| ) | |
| message = Mail( | |
| from_email=(EMAIL_ADDRESS, SENDER_NAME), | |
| to_emails=email, | |
| subject='Password Reset Code for BeeGuardian', | |
| plain_text_content=content | |
| ) | |
| try: | |
| sg = SendGridAPIClient(SENDGRID_API_KEY) | |
| response = sg.send(message) | |
| return True, None | |
| except Exception as e: | |
| logger.error(f"Failed to send email to {email}: {str(e)}") | |
| return False, str(e) | |
| # Forgot password logic | |
| def forgot_password(request): | |
| data = request.json | |
| if 'email' not in data: | |
| logger.warning("Forgot password request missing email") | |
| return jsonify({"error": "Email is required"}), 400 | |
| try: | |
| code = generate_reset_code(data['email']) | |
| if not code: | |
| return jsonify({"error": "Email not found"}), 404 | |
| success, error_msg = send_reset_email(data['email'], code) | |
| if success: | |
| return jsonify({"success": True, "message": "Reset code sent to email"}), 200 | |
| logger.error(f"Failed to send reset email: {error_msg}") | |
| return jsonify({"error": f"Failed to send email: {error_msg}"}), 500 | |
| except Exception as e: | |
| logger.error(f"Error in forgot_password for {data['email']}: {str(e)}") | |
| return jsonify({"error": str(e)}), 500 | |
| # Verify reset code logic | |
| def verify_reset_code_endpoint(request): | |
| data = request.json | |
| if not all(key in data for key in ['email', 'code']): | |
| logger.warning("Verify reset code request missing email or code") | |
| return jsonify({"error": "Email and code are required"}), 400 | |
| try: | |
| valid = verify_reset_code(data['email'], data['code']) | |
| if valid: | |
| return jsonify({"success": True, "message": "Code verified"}), 200 | |
| return jsonify({"error": "Invalid or expired code"}), 400 | |
| except Exception as e: | |
| logger.error(f"Error in verify_reset_code for {data['email']}: {str(e)}") | |
| return jsonify({"error": str(e)}), 500 | |
| # Reset password logic | |
| def reset_password(request): | |
| data = request.json | |
| if not all(key in data for key in ['email', 'new_password']): | |
| logger.warning("Reset password request missing required fields") | |
| return jsonify({"error": "Email and new password are required"}), 400 | |
| try: | |
| updated = update_user_password(data['email'], data['new_password']) | |
| if updated: | |
| return jsonify({"success": True, "message": "Password reset successfully"}), 200 | |
| logger.error(f"Failed to update password for {data['email']}") | |
| return jsonify({"error": "Failed to update password"}), 500 | |
| except Exception as e: | |
| logger.error(f"Error in reset_password for {data['email']}: {str(e)}") | |
| return jsonify({"error": str(e)}), 500 |