geethareddy commited on
Commit
eba0723
·
verified ·
1 Parent(s): 02615cd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +227 -38
app.py CHANGED
@@ -1,43 +1,193 @@
1
- import requests
2
- import json
3
  import os
4
- import logging
5
- from datetime import datetime
6
  from dotenv import load_dotenv
7
- from simple_salesforce import Salesforce
8
- from flask import Flask, jsonify, request, render_template, redirect, url_for
9
-
10
- # Configure logging
11
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
12
- logger = logging.getLogger(__name__)
13
 
14
  # Load environment variables
15
  load_dotenv()
16
 
17
- # Hugging Face API configuration
18
- HUGGING_FACE_API_URL = os.getenv("HUGGING_FACE_API_URL", "https://api-inference.huggingface.co/models/distilgpt2")
19
- HUGGING_FACE_API_TOKEN = os.getenv("HUGGING_FACE_API_TOKEN")
20
-
21
- # Salesforce configuration
22
- SALESFORCE_USERNAME = os.getenv("SALESFORCE_USERNAME")
23
- SALESFORCE_PASSWORD = os.getenv("SALESFORCE_PASSWORD")
24
- SALESFORCE_SECURITY_TOKEN = os.getenv("SALESFORCE_SECURITY_TOKEN")
25
- SALESFORCE_DOMAIN = os.getenv("SALESFORCE_DOMAIN", "login")
26
-
27
- # Validate environment variables
28
- if not HUGGING_FACE_API_TOKEN:
29
- logger.error("HUGGING_FACE_API_TOKEN is not set")
30
- raise ValueError("HUGGING_FACE_API_TOKEN environment variable is not set")
31
- if not HUGGING_FACE_API_URL.startswith("https://api-inference.huggingface.co/models/"):
32
- logger.error("Invalid HUGGING_FACE_API_URL: %s", HUGGING_FACE_API_URL)
33
- raise ValueError("HUGGING_FACE_API_URL must point to a valid Hugging Face model")
34
- if not all([SALESFORCE_USERNAME, SALESFORCE_PASSWORD, SALESFORCE_SECURITY_TOKEN]):
35
- logger.error("Salesforce credentials are incomplete")
36
- raise ValueError("Salesforce credentials must be set")
37
-
38
- # Initialize Flask app
39
  app = Flask(__name__)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  def generate_coaching_output(data):
42
  """
43
  Generate daily checklist and tips using Hugging Face LLM.
@@ -46,12 +196,10 @@ def generate_coaching_output(data):
46
  milestones_json = json.dumps(data['milestones'], indent=2)
47
  prompt = f"""
48
  You are an AI Coach for construction site supervisors. Based on the following data, generate a daily checklist, three focus tips, and a motivational quote. Ensure outputs are concise, actionable, and tailored to the supervisor's role, project status, and reflection log.
49
-
50
  Supervisor Role: {data['role']}
51
  Project Milestones: {milestones_json}
52
  Reflection Log: {data['reflection_log']}
53
  Weather: {data['weather']}
54
-
55
  Format the response as JSON:
56
  {{
57
  "checklist": ["item1", "item2", ...],
@@ -99,7 +247,6 @@ Format the response as JSON:
99
  except Exception as e:
100
  logger.error("Unexpected error in Hugging Face API call: %s", e)
101
  return None
102
-
103
  def save_to_salesforce(output, supervisor_id, project_id):
104
  """
105
  Save coaching output to Salesforce Supervisor_AI_Coaching__c object.
@@ -149,7 +296,7 @@ def ui():
149
  """
150
  Serve the HTML user interface.
151
  """
152
- return render_template('index.html')
153
 
154
  @app.route('/generate', methods=['POST'])
155
  def generate_endpoint():
@@ -181,5 +328,47 @@ def health_check():
181
  """
182
  return jsonify({"status": "healthy", "message": "Application is running"}), 200
183
 
184
- if __name__ == "__main__":
185
- app.run(host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, session, redirect, url_for, render_template
2
+ from simple_salesforce import Salesforce, SalesforceAuthenticationFailed, SalesforceError
3
  import os
 
 
4
  from dotenv import load_dotenv
5
+ import logging
6
+ import bcrypt
7
+ from urllib.parse import quote
 
 
 
8
 
9
  # Load environment variables
10
  load_dotenv()
11
 
12
+ # Configure logging
13
+ logging.basicConfig(
14
+ level=logging.DEBUG, # Set to DEBUG for detailed logs
15
+ format='%(asctime)s - %(levelname)s - %(message)s',
16
+ handlers=[
17
+ logging.FileHandler('app.log'),
18
+ logging.StreamHandler()
19
+ ]
20
+ )
21
+ logger = logging.getLogger(__name__)
22
+
 
 
 
 
 
 
 
 
 
 
 
23
  app = Flask(__name__)
24
+ app.secret_key = os.getenv('FLASK_SECRET_KEY', 'tPhZ8oXGBoadFBQXgUkSR2kDH')
25
+
26
+ # Salesforce mock data for guest users
27
+ MOCK_DATA = {
28
+ "supervisor_id": "GUEST",
29
+ "project_id": "PROJ_001",
30
+ "last_login": "Guest Mode"
31
+ }
32
+
33
+ def get_salesforce_connection():
34
+ """Establish a Salesforce connection with detailed error handling."""
35
+ try:
36
+ # Ensure you are passing the correct environment variables
37
+ sf = Salesforce(
38
+ username=os.getenv('SALESFORCE_USERNAME'),
39
+ password=os.getenv('SALESFORCE_PASSWORD'),
40
+ security_token=os.getenv('SALESFORCE_SECURITY_TOKEN'),
41
+ domain=os.getenv('SALESFORCE_DOMAIN', 'login'), # 'test' is for sandbox, 'login' is for production
42
+ version='60.0' # Specify Salesforce API version
43
+ )
44
+ logger.info("Successfully connected to Salesforce")
45
+
46
+ # Test connection
47
+ sf.query("SELECT Id FROM Supervisor__c LIMIT 1")
48
+ logger.debug("Salesforce connection test query successful")
49
+ return sf
50
+ except SalesforceAuthenticationFailed as e:
51
+ logger.error(f"Salesforce authentication failed: {str(e)}")
52
+ raise Exception(f"Salesforce authentication failed: {str(e)}. Check your credentials.")
53
+ except SalesforceError as e:
54
+ logger.error(f"Salesforce error during connection: {str(e)}")
55
+ raise Exception(f"Salesforce error: {str(e)}. Check object permissions and API access.")
56
+ except Exception as e:
57
+ logger.error(f"Unexpected error connecting to Salesforce: {str(e)}")
58
+ raise Exception(f"Unable to connect to Salesforce: {str(e)}. Please check your configuration.")
59
+
60
+
61
+ def hash_password(password):
62
+ """Hash a password using bcrypt."""
63
+ try:
64
+ return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
65
+ except Exception as e:
66
+ logger.error(f"Password hashing failed: {str(e)}")
67
+ raise
68
+
69
+ def verify_password(password, hashed_password):
70
+ """Verify a password against its hash."""
71
+ try:
72
+ return bcrypt.checkpw(password.encode('utf-8'), hashed_password.encode('utf-8'))
73
+ except Exception as e:
74
+ logger.error(f"Password verification failed: {str(e)}")
75
+ return False
76
+
77
+ @app.route('/')
78
+ def index():
79
+ if 'supervisor_id' not in session:
80
+ logger.info("User not logged in, redirecting to login page")
81
+ return redirect(url_for('login_page'))
82
+ return render_template('index.html')
83
+
84
+ @app.route('/login', methods=['GET'])
85
+ def login_page():
86
+ return render_template('login.html')
87
+
88
+ @app.route('/signup', methods=['GET'])
89
+ def signup_page():
90
+ return render_template('signup.html')
91
+
92
+ from flask import redirect, url_for
93
+
94
+ from flask import Flask, request, session, redirect, render_template, url_for, jsonify
95
+ from urllib.parse import quote
96
+
97
+ @app.route('/login', methods=['POST'])
98
+ def login():
99
+ data = request.get_json()
100
+ supervisor_id = data.get('supervisor_id')
101
+ password = data.get('password')
102
+
103
+ if not supervisor_id or not password:
104
+ logger.warning("Login failed: Supervisor ID and password are required")
105
+ return jsonify({"status": "error", "message": "Supervisor ID and password are required"}), 400
106
+
107
+ if supervisor_id == 'GUEST':
108
+ session['supervisor_id'] = 'GUEST'
109
+ logger.info("Guest login successful")
110
+ return jsonify({"status": "success", "message": "Logged in as guest", "redirect": "/dashboard"})
111
 
112
+ try:
113
+ sf = get_salesforce_connection()
114
+ logger.debug(f"Querying Salesforce for Supervisor_ID__c: {supervisor_id}")
115
+ supervisor_id_escaped = quote(supervisor_id, safe='')
116
+ query = f"SELECT Id, Name, Password__c FROM Supervisor__c WHERE Name = '{supervisor_id_escaped}' LIMIT 1"
117
+ result = sf.query(query)
118
+ logger.debug(f"Salesforce query result: {result}")
119
+
120
+ if not result['records']:
121
+ logger.warning(f"Invalid Supervisor ID: {supervisor_id}")
122
+ return jsonify({"status": "error", "message": "Invalid Supervisor ID"}), 401
123
+
124
+ record = result['records'][0]
125
+ stored_password = record['Password__c']
126
+ if not stored_password:
127
+ logger.warning(f"No password set for Supervisor ID: {supervisor_id}")
128
+ return jsonify({"status": "error", "message": "No password set for this Supervisor ID"}), 401
129
+
130
+ if not verify_password(password, stored_password):
131
+ logger.warning(f"Invalid password for Supervisor ID: {supervisor_id}")
132
+ return jsonify({"status": "error", "message": "Invalid password"}), 401
133
+
134
+ session['supervisor_id'] = supervisor_id
135
+ logger.info(f"Login successful for {supervisor_id}")
136
+ return jsonify({"status": "success", "message": "Logged in as guest", "redirect": "/dashboard"})
137
+
138
+ except Exception as e:
139
+ logger.error(f"Login error: {str(e)}")
140
+ return jsonify({"status": "error", "message": str(e)}), 500
141
+ @app.route('/dashboard', methods=['GET'])
142
+ def dashboard():
143
+ """
144
+ Serve the dashboard page after successful login.
145
+ """
146
+ return render_template('dashboard.html')
147
+ @app.route('/home')
148
+ def home():
149
+ return render_template('home.html')
150
+
151
+ @app.route('/signup', methods=['POST'])
152
+ def signup():
153
+ data = request.get_json()
154
+ supervisor_id = data.get('supervisor_id')
155
+ password = data.get('password')
156
+
157
+ if not supervisor_id or not password:
158
+ logger.warning("Signup failed: Supervisor ID and password are required")
159
+ return jsonify({"status": "error", "message": "Supervisor ID and password are required"}), 400
160
+
161
+ try:
162
+ sf = get_salesforce_connection()
163
+ logger.debug(f"Checking if Supervisor_ID__c {supervisor_id} already exists")
164
+ supervisor_id_escaped = quote(supervisor_id, safe='')
165
+ query = f"SELECT Id FROM Supervisor__c WHERE Name = '{supervisor_id_escaped}' LIMIT 1"
166
+ result = sf.query(query)
167
+ if result['records']:
168
+ logger.warning(f"Signup failed: Supervisor ID {supervisor_id} already exists")
169
+ return jsonify({"status": "error", "message": "Supervisor ID already exists"}), 400
170
+
171
+ hashed_password = hash_password(password)
172
+ logger.debug(f"Creating new Supervisor__c record for {supervisor_id}")
173
+ new_record = {
174
+ 'Name': supervisor_id,
175
+ 'Password__c': hashed_password
176
+
177
+ }
178
+ response = sf.Supervisor__c.create(new_record)
179
+ logger.debug(f"Salesforce create response: {response}")
180
+
181
+ if not response.get('success'):
182
+ logger.error(f"Failed to create Supervisor record: {response.get('errors')}")
183
+ return jsonify({"status": "error", "message": f"Failed to create record in Salesforce: {response.get('errors')}"}), 500
184
+
185
+ session['supervisor_id'] = supervisor_id
186
+ logger.info(f"Signup successful for {supervisor_id}")
187
+ return jsonify({"status": "success", "message": "Signup successful, you are now logged in"})
188
+ except Exception as e:
189
+ logger.error(f"Signup error: {str(e)}")
190
+ return jsonify({"status": "error", "message": str(e)}), 500
191
  def generate_coaching_output(data):
192
  """
193
  Generate daily checklist and tips using Hugging Face LLM.
 
196
  milestones_json = json.dumps(data['milestones'], indent=2)
197
  prompt = f"""
198
  You are an AI Coach for construction site supervisors. Based on the following data, generate a daily checklist, three focus tips, and a motivational quote. Ensure outputs are concise, actionable, and tailored to the supervisor's role, project status, and reflection log.
 
199
  Supervisor Role: {data['role']}
200
  Project Milestones: {milestones_json}
201
  Reflection Log: {data['reflection_log']}
202
  Weather: {data['weather']}
 
203
  Format the response as JSON:
204
  {{
205
  "checklist": ["item1", "item2", ...],
 
247
  except Exception as e:
248
  logger.error("Unexpected error in Hugging Face API call: %s", e)
249
  return None
 
250
  def save_to_salesforce(output, supervisor_id, project_id):
251
  """
252
  Save coaching output to Salesforce Supervisor_AI_Coaching__c object.
 
296
  """
297
  Serve the HTML user interface.
298
  """
299
+ return render_template('home.html')
300
 
301
  @app.route('/generate', methods=['POST'])
302
  def generate_endpoint():
 
328
  """
329
  return jsonify({"status": "healthy", "message": "Application is running"}), 200
330
 
331
+ @app.route('/logout', methods=['POST'])
332
+ def logout():
333
+ supervisor_id = session.get('supervisor_id', 'Unknown')
334
+ session.pop('supervisor_id', None)
335
+ logger.info(f"User {supervisor_id} logged out")
336
+ return jsonify({"status": "success", "message": "Logged out successfully"})
337
+
338
+ @app.route('/get_supervisor_data')
339
+ def get_supervisor_data():
340
+ supervisor_id = session.get('supervisor_id', 'GUEST')
341
+ if supervisor_id == 'GUEST':
342
+ logger.info("Returning mock data for guest user")
343
+ return jsonify({"status": "success", "data": MOCK_DATA})
344
+
345
+ try:
346
+ sf = get_salesforce_connection()
347
+ supervisor_id_escaped = quote(supervisor_id, safe='')
348
+ query = f"""
349
+ SELECT Supervisor_ID__c, Project_ID__c
350
+ FROM Supervisor__c
351
+ WHERE Supervisor_ID__c = '{supervisor_id_escaped}'
352
+ LIMIT 1
353
+ """
354
+ result = sf.query(query)
355
+
356
+ if result['records']:
357
+ record = result['records'][0]
358
+ data = {
359
+ "supervisor_id": record['Supervisor_ID__c'],
360
+ "project_id": record['Project_ID__c'],
361
+ "last_login": str(datetime.now())
362
+ }
363
+ logger.info(f"Fetched data for supervisor {supervisor_id}")
364
+ return jsonify({"status": "success", "data": data})
365
+ else:
366
+ logger.warning(f"No data found for supervisor {supervisor_id}")
367
+ return jsonify({"status": "error", "message": "No data found for this supervisor"}), 404
368
+ except Exception as e:
369
+ logger.error(f"Error fetching supervisor data: {str(e)}")
370
+ return jsonify({"status": "error", "message": str(e)}), 500
371
+
372
+ if __name__ == '__main__':
373
+ port = int(os.getenv('PORT', 5000))
374
+ app.run(host='0.0.0.0', port=port, debug=True)