File size: 9,057 Bytes
d85f039
 
5a6aa4a
 
d85f039
 
 
a65ab2b
5a6aa4a
 
 
d85f039
 
 
 
 
 
 
 
 
 
 
a65ab2b
d85f039
a65ab2b
d85f039
 
 
 
 
 
5a6aa4a
d85f039
 
5a6aa4a
d85f039
 
 
 
 
 
 
 
 
5a6aa4a
d85f039
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5a6aa4a
d85f039
 
 
 
 
 
 
 
 
5a6aa4a
 
d85f039
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5a6aa4a
d85f039
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5a6aa4a
d85f039
 
5a6aa4a
d85f039
 
 
5a6aa4a
d85f039
 
 
5a6aa4a
d85f039
 
5a6aa4a
d85f039
 
 
 
 
 
 
 
 
 
 
 
 
5a6aa4a
 
d85f039
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5a6aa4a
d85f039
 
5a6aa4a
d85f039
5a6aa4a
a65ab2b
d85f039
 
55c32dc
 
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
from flask import Flask, request, jsonify, session, redirect, url_for, render_template
from simple_salesforce import Salesforce, SalesforceAuthenticationFailed, SalesforceError
import os
from dotenv import load_dotenv
import logging
import bcrypt
from urllib.parse import quote

# Load environment variables
load_dotenv()

# Configure logging
logging.basicConfig(
    level=logging.DEBUG,  # Set to DEBUG for detailed logs
    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')

# 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:
        # Ensure you are passing the correct environment variables
        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'),  # 'test' is for sandbox, 'login' is for production
            version='60.0'  # Specify Salesforce API version
        )
        logger.info("Successfully connected to Salesforce")
        
        # Test connection
        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")
        return redirect(url_for('login_page'))
    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():
    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"})

    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"})
    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"})
    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)