Spaces:
Runtime error
Runtime error
| from flask import Flask, request, jsonify, session, redirect, url_for, render_template, flash | |
| from simple_salesforce import Salesforce, SalesforceAuthenticationFailed, SalesforceError | |
| import os | |
| from dotenv import load_dotenv | |
| import logging | |
| import bcrypt | |
| from urllib.parse import quote | |
| from datetime import timedelta | |
| # Load environment variables | |
| load_dotenv() | |
| # Configure logging | |
| logging.basicConfig( | |
| level=logging.DEBUG, | |
| format='%(asctime)s - %(levelname)s - %(message)s', | |
| handlers=[ | |
| logging.FileHandler('app.log'), | |
| logging.StreamHandler() | |
| ] | |
| ) | |
| logger = logging.getLogger(__name__) | |
| app = Flask(__name__) | |
| app.secret_key = os.getenv('FLASK_SECRET_KEY', 'tPhZ8oXGBoadFBQXgUkSR2kDH') | |
| app.permanent_session_lifetime = timedelta(minutes=30) # Session expires after 30 minutes | |
| # Salesforce mock data for guest users | |
| MOCK_DATA = { | |
| "supervisor_id": "GUEST", | |
| "project_id": "PROJ_001", | |
| "last_login": "Guest Mode" | |
| } | |
| def get_salesforce_connection(): | |
| """Establish a Salesforce connection with detailed error handling.""" | |
| try: | |
| sf = Salesforce( | |
| username=os.getenv('SALESFORCE_USERNAME'), | |
| password=os.getenv('SALESFORCE_PASSWORD'), | |
| security_token=os.getenv('SALESFORCE_SECURITY_TOKEN'), | |
| domain=os.getenv('SALESFORCE_DOMAIN', 'login'), | |
| version='60.0' | |
| ) | |
| logger.info("Successfully connected to Salesforce") | |
| sf.query("SELECT Id FROM Supervisor__c LIMIT 1") | |
| logger.debug("Salesforce connection test query successful") | |
| return sf | |
| except SalesforceAuthenticationFailed as e: | |
| logger.error(f"Salesforce authentication failed: {str(e)}") | |
| raise Exception(f"Salesforce authentication failed: {str(e)}. Check your credentials.") | |
| except SalesforceError as e: | |
| logger.error(f"Salesforce error during connection: {str(e)}") | |
| raise Exception(f"Salesforce error: {str(e)}. Check object permissions and API access.") | |
| except Exception as e: | |
| logger.error(f"Unexpected error connecting to Salesforce: {str(e)}") | |
| raise Exception(f"Unable to connect to Salesforce: {str(e)}. Please check your configuration.") | |
| def hash_password(password): | |
| """Hash a password using bcrypt.""" | |
| try: | |
| return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') | |
| except Exception as e: | |
| logger.error(f"Password hashing failed: {str(e)}") | |
| raise | |
| def verify_password(password, hashed_password): | |
| """Verify a password against its hash.""" | |
| try: | |
| return bcrypt.checkpw(password.encode('utf-8'), hashed_password.encode('utf-8')) | |
| except Exception as e: | |
| logger.error(f"Password verification failed: {str(e)}") | |
| return False | |
| def index(): | |
| if 'supervisor_id' not in session: | |
| logger.info("User not logged in, redirecting to login page") | |
| flash("Please log in to access the dashboard.", "warning") | |
| return redirect(url_for('login_page')) | |
| logger.info(f"Redirecting user {session['supervisor_id']} to index") | |
| return render_template('index.html') | |
| def login_page(): | |
| return render_template('login.html') | |
| def signup_page(): | |
| return render_template('signup.html') | |
| def login(): | |
| if 'supervisor_id' in session: | |
| logger.info(f"User {session['supervisor_id']} already logged in, redirecting to index") | |
| return jsonify({"status": "success", "message": "Already logged in", "redirect": "/"}), 200 | |
| data = request.get_json() | |
| supervisor_id = data.get('supervisor_id') | |
| password = data.get('password') | |
| if not supervisor_id or not password: | |
| logger.warning("Login failed: Supervisor ID and password are required") | |
| return jsonify({"status": "error", "message": "Supervisor ID and password are required"}), 400 | |
| if supervisor_id == 'GUEST': | |
| session['supervisor_id'] = 'GUEST' | |
| logger.info("Guest login successful") | |
| return jsonify({"status": "success", "message": "Logged in as guest", "redirect": "/"}) | |
| try: | |
| sf = get_salesforce_connection() | |
| logger.debug(f"Querying Salesforce for Supervisor_ID__c: {supervisor_id}") | |
| supervisor_id_escaped = quote(supervisor_id, safe='') | |
| query = f"SELECT Id, Name, Password__c FROM Supervisor__c WHERE Name = '{supervisor_id_escaped}' LIMIT 1" | |
| result = sf.query(query) | |
| logger.debug(f"Salesforce query result: {result}") | |
| if not result['records']: | |
| logger.warning(f"Invalid Supervisor ID: {supervisor_id}") | |
| return jsonify({"status": "error", "message": "Invalid Supervisor ID"}), 401 | |
| record = result['records'][0] | |
| stored_password = record['Password__c'] | |
| if not stored_password: | |
| logger.warning(f"No password set for Supervisor ID: {supervisor_id}") | |
| return jsonify({"status": "error", "message": "No password set for this Supervisor ID"}), 401 | |
| if not verify_password(password, stored_password): | |
| logger.warning(f"Invalid password for Supervisor ID: {supervisor_id}") | |
| return jsonify({"status": "error", "message": "Invalid password"}), 401 | |
| session['supervisor_id'] = supervisor_id | |
| logger.info(f"Login successful for {supervisor_id}") | |
| return jsonify({"status": "success", "message": "Login successful", "redirect": "/"}) | |
| except Exception as e: | |
| logger.error(f"Login error: {str(e)}") | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def signup(): | |
| data = request.get_json() | |
| supervisor_id = data.get('supervisor_id') | |
| password = data.get('password') | |
| if not supervisor_id or not password: | |
| logger.warning("Signup failed: Supervisor ID and password are required") | |
| return jsonify({"status": "error", "message": "Supervisor ID and password are required"}), 400 | |
| try: | |
| sf = get_salesforce_connection() | |
| logger.debug(f"Checking if Supervisor_ID__c {supervisor_id} already exists") | |
| supervisor_id_escaped = quote(supervisor_id, safe='') | |
| query = f"SELECT Id FROM Supervisor__c WHERE Name = '{supervisor_id_escaped}' LIMIT 1" | |
| result = sf.query(query) | |
| if result['records']: | |
| logger.warning(f"Signup failed: Supervisor ID {supervisor_id} already exists") | |
| return jsonify({"status": "error", "message": "Supervisor ID already exists"}), 400 | |
| hashed_password = hash_password(password) | |
| logger.debug(f"Creating new Supervisor__c record for {supervisor_id}") | |
| new_record = { | |
| 'Name': supervisor_id, | |
| 'Password__c': hashed_password | |
| } | |
| response = sf.Supervisor__c.create(new_record) | |
| logger.debug(f"Salesforce create response: {response}") | |
| if not response.get('success'): | |
| logger.error(f"Failed to create Supervisor record: {response.get('errors')}") | |
| return jsonify({"status": "error", "message": f"Failed to create record in Salesforce: {response.get('errors')}"}), 500 | |
| session['supervisor_id'] = supervisor_id | |
| logger.info(f"Signup successful for {supervisor_id}") | |
| return jsonify({"status": "success", "message": "Signup successful, you are now logged in", "redirect": "/"}) | |
| except Exception as e: | |
| logger.error(f"Signup error: {str(e)}") | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| def logout(): | |
| supervisor_id = session.get('supervisor_id', 'Unknown') | |
| session.pop('supervisor_id', None) | |
| logger.info(f"User {supervisor_id} logged out") | |
| return jsonify({"status": "success", "message": "Logged out successfully"}) | |
| def get_supervisor_data(): | |
| supervisor_id = session.get('supervisor_id', 'GUEST') | |
| if supervisor_id == 'GUEST': | |
| logger.info("Returning mock data for guest user") | |
| return jsonify({"status": "success", "data": MOCK_DATA}) | |
| try: | |
| sf = get_salesforce_connection() | |
| supervisor_id_escaped = quote(supervisor_id, safe='') | |
| query = f""" | |
| SELECT Supervisor_ID__c, Project_ID__c | |
| FROM Supervisor__c | |
| WHERE Supervisor_ID__c = '{supervisor_id_escaped}' | |
| LIMIT 1 | |
| """ | |
| result = sf.query(query) | |
| if result['records']: | |
| record = result['records'][0] | |
| data = { | |
| "supervisor_id": record['Supervisor_ID__c'], | |
| "project_id": record['Project_ID__c'], | |
| "last_login": str(datetime.now()) | |
| } | |
| logger.info(f"Fetched data for supervisor {supervisor_id}") | |
| return jsonify({"status": "success", "data": data}) | |
| else: | |
| logger.warning(f"No data found for supervisor {supervisor_id}") | |
| return jsonify({"status": "error", "message": "No data found for this supervisor"}), 404 | |
| except Exception as e: | |
| logger.error(f"Error fetching supervisor data: {str(e)}") | |
| return jsonify({"status": "error", "message": str(e)}), 500 | |
| if __name__ == '__main__': | |
| port = int(os.getenv('PORT', 5000)) | |
| app.run(host='0.0.0.0', port=port, debug=True) |