Spaces:
Runtime error
Runtime error
File size: 9,368 Bytes
c4e396b 948f4e4 fc0b5d3 a77f014 948f4e4 b8d9468 c4e396b 38c73fc a77f014 948f4e4 c4e396b 948f4e4 332329c b8d9468 c4e396b 332329c fc0b5d3 89dbcd5 fc0b5d3 b8d9468 f7c7abf 948f4e4 a77f014 948f4e4 a77f014 c4e396b 948f4e4 c4e396b fec02ce b8d9468 948f4e4 b8d9468 faa4b34 b8d9468 948f4e4 b8d9468 faa4b34 b8d9468 faa4b34 b8d9468 faa4b34 b8d9468 faa4b34 948f4e4 f7c7abf fc0b5d3 89dbcd5 948f4e4 c4e396b fc0b5d3 c4e396b fc0b5d3 f7c7abf fc0b5d3 332329c a497fa8 fc0b5d3 c4e396b 332329c c4e396b 332329c 0816899 faa4b34 0816899 948f4e4 c4e396b 332329c fc0b5d3 948f4e4 fec02ce 0816899 fec02ce a990a67 b8d9468 a497fa8 0816899 a497fa8 b8d9468 0816899 b8d9468 0816899 a497fa8 0816899 c4e396b fc0b5d3 948f4e4 fc0b5d3 332329c a497fa8 c4e396b faa4b34 a497fa8 0816899 d6f7d22 a497fa8 fec02ce 0816899 fec02ce a990a67 a497fa8 0816899 a497fa8 b8d9468 fec02ce a497fa8 0816899 c4e396b a497fa8 fec02ce b8d9468 a497fa8 b8d9468 0816899 c4e396b a497fa8 332329c 89dbcd5 fc0b5d3 332329c fc0b5d3 332329c 89dbcd5 948f4e4 fc0b5d3 332329c 948f4e4 89dbcd5 a990a67 c4e396b fec02ce fc0b5d3 a990a67 f7c7abf fc0b5d3 fec02ce fc0b5d3 89dbcd5 fc0b5d3 89dbcd5 faa4b34 9368f71 948f4e4 fc0b5d3 332329c f7c7abf fec02ce 948f4e4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | 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
@app.route('/')
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')
@app.route('/login', methods=['GET'])
def login_page():
return render_template('login.html')
@app.route('/signup', methods=['GET'])
def signup_page():
return render_template('signup.html')
@app.route('/login', methods=['POST'])
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
@app.route('/signup', methods=['POST'])
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
@app.route('/logout', methods=['POST'])
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"})
@app.route('/get_supervisor_data')
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) |