Spaces:
Sleeping
Sleeping
Fix session management and login redirect issues
Browse files
app.py
CHANGED
|
@@ -41,7 +41,19 @@ load_dotenv()
|
|
| 41 |
|
| 42 |
# Initialize Flask app
|
| 43 |
app = Flask(__name__, static_folder='app/static', template_folder='app/templates')
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
# MongoDB Connection
|
| 47 |
try:
|
|
@@ -669,16 +681,29 @@ def register():
|
|
| 669 |
def login():
|
| 670 |
student_id = request.form.get('student_id')
|
| 671 |
password = request.form.get('password')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 672 |
student = students_collection.find_one({'student_id': student_id})
|
| 673 |
|
| 674 |
-
if student and student
|
|
|
|
|
|
|
|
|
|
|
|
|
| 675 |
session['logged_in'] = True
|
| 676 |
session['user_type'] = 'student'
|
| 677 |
session['student_id'] = student_id
|
| 678 |
session['name'] = student.get('name')
|
|
|
|
|
|
|
|
|
|
| 679 |
flash('Login successful!', 'success')
|
| 680 |
return redirect(url_for('dashboard'))
|
| 681 |
else:
|
|
|
|
| 682 |
flash('Invalid credentials. Please try again.', 'danger')
|
| 683 |
return redirect(url_for('login_page'))
|
| 684 |
|
|
@@ -729,11 +754,16 @@ def face_login():
|
|
| 729 |
similarity = cosine_similarity([test_features], [ref_features])[0][0]
|
| 730 |
distance = 1 - similarity
|
| 731 |
|
| 732 |
-
if distance < 0.4:
|
|
|
|
|
|
|
| 733 |
session['logged_in'] = True
|
| 734 |
session['user_type'] = face_role
|
| 735 |
session[id_field] = user[id_field]
|
| 736 |
session['name'] = user.get('name')
|
|
|
|
|
|
|
|
|
|
| 737 |
flash('Face login successful!', 'success')
|
| 738 |
return redirect(url_for(dashboard_route))
|
| 739 |
|
|
@@ -741,6 +771,7 @@ def face_login():
|
|
| 741 |
print(f"Error processing user {user.get(id_field)}: {e}")
|
| 742 |
continue
|
| 743 |
|
|
|
|
| 744 |
flash('Face not recognized. Please try again or contact admin.', 'danger')
|
| 745 |
return redirect(url_for('login_page'))
|
| 746 |
|
|
@@ -784,10 +815,14 @@ def auto_face_login():
|
|
| 784 |
distance = 1 - similarity
|
| 785 |
|
| 786 |
if distance < 0.4: # FIXED: removed HTML entity
|
|
|
|
|
|
|
| 787 |
session['logged_in'] = True
|
| 788 |
session['user_type'] = face_role
|
| 789 |
session[id_field] = user[id_field]
|
| 790 |
session['name'] = user.get('name')
|
|
|
|
|
|
|
| 791 |
return jsonify({
|
| 792 |
'success': True,
|
| 793 |
'message': f'Welcome {user["name"]}! Redirecting...',
|
|
@@ -813,15 +848,35 @@ def attendance_page():
|
|
| 813 |
|
| 814 |
@app.route('/dashboard')
|
| 815 |
def dashboard():
|
| 816 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 817 |
return redirect(url_for('login_page'))
|
|
|
|
| 818 |
student_id = session.get('student_id')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 819 |
student = students_collection.find_one({'student_id': student_id})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 820 |
if student and 'face_image' in student and student['face_image']:
|
| 821 |
face_image_base64 = base64.b64encode(student['face_image']).decode('utf-8')
|
| 822 |
mime_type = student.get('face_image_type', 'image/jpeg')
|
| 823 |
student['face_image_url'] = f"data:{mime_type};base64,{face_image_base64}"
|
|
|
|
| 824 |
attendance_records = list(attendance_collection.find({'student_id': student_id}).sort('date', -1))
|
|
|
|
|
|
|
| 825 |
return render_template('dashboard.html', student=student, attendance_records=attendance_records)
|
| 826 |
|
| 827 |
@app.route('/mark-attendance', methods=['POST'])
|
|
@@ -1116,28 +1171,56 @@ def teacher_register():
|
|
| 1116 |
def teacher_login():
|
| 1117 |
teacher_id = request.form.get('teacher_id')
|
| 1118 |
password = request.form.get('password')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1119 |
teacher = teachers_collection.find_one({'teacher_id': teacher_id})
|
| 1120 |
-
if teacher and teacher
|
|
|
|
|
|
|
|
|
|
| 1121 |
session['logged_in'] = True
|
| 1122 |
session['user_type'] = 'teacher'
|
| 1123 |
session['teacher_id'] = teacher_id
|
| 1124 |
session['name'] = teacher.get('name')
|
|
|
|
|
|
|
|
|
|
| 1125 |
flash('Login successful!', 'success')
|
| 1126 |
return redirect(url_for('teacher_dashboard'))
|
| 1127 |
else:
|
|
|
|
| 1128 |
flash('Invalid credentials. Please try again.', 'danger')
|
| 1129 |
return redirect(url_for('teacher_login_page'))
|
| 1130 |
|
| 1131 |
@app.route('/teacher_dashboard')
|
| 1132 |
def teacher_dashboard():
|
| 1133 |
-
|
|
|
|
|
|
|
|
|
|
| 1134 |
return redirect(url_for('teacher_login_page'))
|
|
|
|
| 1135 |
teacher_id = session.get('teacher_id')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1136 |
teacher = teachers_collection.find_one({'teacher_id': teacher_id})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1137 |
if teacher and 'face_image' in teacher and teacher['face_image']:
|
| 1138 |
face_image_base64 = base64.b64encode(teacher['face_image']).decode('utf-8')
|
| 1139 |
mime_type = teacher.get('face_image_type', 'image/jpeg')
|
| 1140 |
teacher['face_image_url'] = f"data:{mime_type};base64,{face_image_base64}"
|
|
|
|
|
|
|
| 1141 |
return render_template('teacher_dashboard.html', teacher=teacher)
|
| 1142 |
|
| 1143 |
@app.route('/teacher_logout')
|
|
|
|
| 41 |
|
| 42 |
# Initialize Flask app
|
| 43 |
app = Flask(__name__, static_folder='app/static', template_folder='app/templates')
|
| 44 |
+
|
| 45 |
+
# FIX: Proper session configuration for HuggingFace Spaces
|
| 46 |
+
app.secret_key = os.environ.get('SECRET_KEY', 'your-secret-key-here-change-this-in-production')
|
| 47 |
+
app.config['SESSION_TYPE'] = 'filesystem'
|
| 48 |
+
app.config['SESSION_PERMANENT'] = False
|
| 49 |
+
app.config['SESSION_USE_SIGNER'] = True
|
| 50 |
+
app.config['SESSION_KEY_PREFIX'] = 'face_attendance:'
|
| 51 |
+
app.config['PERMANENT_SESSION_LIFETIME'] = 1800 # 30 minutes
|
| 52 |
+
|
| 53 |
+
# Additional session security for container environments
|
| 54 |
+
app.config['SESSION_COOKIE_SECURE'] = False # Set to True in production with HTTPS
|
| 55 |
+
app.config['SESSION_COOKIE_HTTPONLY'] = True
|
| 56 |
+
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
|
| 57 |
|
| 58 |
# MongoDB Connection
|
| 59 |
try:
|
|
|
|
| 681 |
def login():
|
| 682 |
student_id = request.form.get('student_id')
|
| 683 |
password = request.form.get('password')
|
| 684 |
+
|
| 685 |
+
if not student_id or not password:
|
| 686 |
+
flash('Please enter both student ID and password.', 'danger')
|
| 687 |
+
return redirect(url_for('login_page'))
|
| 688 |
+
|
| 689 |
student = students_collection.find_one({'student_id': student_id})
|
| 690 |
|
| 691 |
+
if student and student.get('password') == password:
|
| 692 |
+
# FIX: Clear any existing session data first
|
| 693 |
+
session.clear()
|
| 694 |
+
|
| 695 |
+
# Set session data
|
| 696 |
session['logged_in'] = True
|
| 697 |
session['user_type'] = 'student'
|
| 698 |
session['student_id'] = student_id
|
| 699 |
session['name'] = student.get('name')
|
| 700 |
+
session.permanent = True # Make session permanent
|
| 701 |
+
|
| 702 |
+
print(f"Login successful for student: {student_id}") # Debug log
|
| 703 |
flash('Login successful!', 'success')
|
| 704 |
return redirect(url_for('dashboard'))
|
| 705 |
else:
|
| 706 |
+
print(f"Login failed for student: {student_id}") # Debug log
|
| 707 |
flash('Invalid credentials. Please try again.', 'danger')
|
| 708 |
return redirect(url_for('login_page'))
|
| 709 |
|
|
|
|
| 754 |
similarity = cosine_similarity([test_features], [ref_features])[0][0]
|
| 755 |
distance = 1 - similarity
|
| 756 |
|
| 757 |
+
if distance < 0.4:
|
| 758 |
+
# FIX: Clear existing session and set new session data
|
| 759 |
+
session.clear()
|
| 760 |
session['logged_in'] = True
|
| 761 |
session['user_type'] = face_role
|
| 762 |
session[id_field] = user[id_field]
|
| 763 |
session['name'] = user.get('name')
|
| 764 |
+
session.permanent = True # Make session permanent
|
| 765 |
+
|
| 766 |
+
print(f"Face login successful for {face_role}: {user[id_field]}") # Debug log
|
| 767 |
flash('Face login successful!', 'success')
|
| 768 |
return redirect(url_for(dashboard_route))
|
| 769 |
|
|
|
|
| 771 |
print(f"Error processing user {user.get(id_field)}: {e}")
|
| 772 |
continue
|
| 773 |
|
| 774 |
+
print("Face login failed - face not recognized") # Debug log
|
| 775 |
flash('Face not recognized. Please try again or contact admin.', 'danger')
|
| 776 |
return redirect(url_for('login_page'))
|
| 777 |
|
|
|
|
| 815 |
distance = 1 - similarity
|
| 816 |
|
| 817 |
if distance < 0.4: # FIXED: removed HTML entity
|
| 818 |
+
# FIX: Clear existing session and set new session data
|
| 819 |
+
session.clear()
|
| 820 |
session['logged_in'] = True
|
| 821 |
session['user_type'] = face_role
|
| 822 |
session[id_field] = user[id_field]
|
| 823 |
session['name'] = user.get('name')
|
| 824 |
+
session.permanent = True # Make session permanent
|
| 825 |
+
|
| 826 |
return jsonify({
|
| 827 |
'success': True,
|
| 828 |
'message': f'Welcome {user["name"]}! Redirecting...',
|
|
|
|
| 848 |
|
| 849 |
@app.route('/dashboard')
|
| 850 |
def dashboard():
|
| 851 |
+
print(f"Dashboard access - Session data: {dict(session)}") # Debug log
|
| 852 |
+
|
| 853 |
+
# Check if user is logged in
|
| 854 |
+
if not session.get('logged_in') or session.get('user_type') != 'student':
|
| 855 |
+
print("Dashboard access denied - redirecting to login") # Debug log
|
| 856 |
+
flash('Please log in to access the dashboard.', 'warning')
|
| 857 |
return redirect(url_for('login_page'))
|
| 858 |
+
|
| 859 |
student_id = session.get('student_id')
|
| 860 |
+
if not student_id:
|
| 861 |
+
print("Dashboard access denied - no student_id in session") # Debug log
|
| 862 |
+
session.clear()
|
| 863 |
+
return redirect(url_for('login_page'))
|
| 864 |
+
|
| 865 |
student = students_collection.find_one({'student_id': student_id})
|
| 866 |
+
if not student:
|
| 867 |
+
print(f"Dashboard access denied - student not found: {student_id}") # Debug log
|
| 868 |
+
session.clear()
|
| 869 |
+
return redirect(url_for('login_page'))
|
| 870 |
+
|
| 871 |
+
# Process face image for display
|
| 872 |
if student and 'face_image' in student and student['face_image']:
|
| 873 |
face_image_base64 = base64.b64encode(student['face_image']).decode('utf-8')
|
| 874 |
mime_type = student.get('face_image_type', 'image/jpeg')
|
| 875 |
student['face_image_url'] = f"data:{mime_type};base64,{face_image_base64}"
|
| 876 |
+
|
| 877 |
attendance_records = list(attendance_collection.find({'student_id': student_id}).sort('date', -1))
|
| 878 |
+
|
| 879 |
+
print(f"Dashboard loaded successfully for student: {student_id}") # Debug log
|
| 880 |
return render_template('dashboard.html', student=student, attendance_records=attendance_records)
|
| 881 |
|
| 882 |
@app.route('/mark-attendance', methods=['POST'])
|
|
|
|
| 1171 |
def teacher_login():
|
| 1172 |
teacher_id = request.form.get('teacher_id')
|
| 1173 |
password = request.form.get('password')
|
| 1174 |
+
|
| 1175 |
+
if not teacher_id or not password:
|
| 1176 |
+
flash('Please enter both teacher ID and password.', 'danger')
|
| 1177 |
+
return redirect(url_for('teacher_login_page'))
|
| 1178 |
+
|
| 1179 |
teacher = teachers_collection.find_one({'teacher_id': teacher_id})
|
| 1180 |
+
if teacher and teacher.get('password') == password:
|
| 1181 |
+
# FIX: Clear any existing session data first
|
| 1182 |
+
session.clear()
|
| 1183 |
+
|
| 1184 |
session['logged_in'] = True
|
| 1185 |
session['user_type'] = 'teacher'
|
| 1186 |
session['teacher_id'] = teacher_id
|
| 1187 |
session['name'] = teacher.get('name')
|
| 1188 |
+
session.permanent = True # Make session permanent
|
| 1189 |
+
|
| 1190 |
+
print(f"Teacher login successful for: {teacher_id}") # Debug log
|
| 1191 |
flash('Login successful!', 'success')
|
| 1192 |
return redirect(url_for('teacher_dashboard'))
|
| 1193 |
else:
|
| 1194 |
+
print(f"Teacher login failed for: {teacher_id}") # Debug log
|
| 1195 |
flash('Invalid credentials. Please try again.', 'danger')
|
| 1196 |
return redirect(url_for('teacher_login_page'))
|
| 1197 |
|
| 1198 |
@app.route('/teacher_dashboard')
|
| 1199 |
def teacher_dashboard():
|
| 1200 |
+
print(f"Teacher Dashboard access - Session data: {dict(session)}") # Debug log
|
| 1201 |
+
|
| 1202 |
+
if not session.get('logged_in') or session.get('user_type') != 'teacher':
|
| 1203 |
+
print("Teacher dashboard access denied - redirecting to login") # Debug log
|
| 1204 |
return redirect(url_for('teacher_login_page'))
|
| 1205 |
+
|
| 1206 |
teacher_id = session.get('teacher_id')
|
| 1207 |
+
if not teacher_id:
|
| 1208 |
+
print("Teacher dashboard access denied - no teacher_id in session") # Debug log
|
| 1209 |
+
session.clear()
|
| 1210 |
+
return redirect(url_for('teacher_login_page'))
|
| 1211 |
+
|
| 1212 |
teacher = teachers_collection.find_one({'teacher_id': teacher_id})
|
| 1213 |
+
if not teacher:
|
| 1214 |
+
print(f"Teacher dashboard access denied - teacher not found: {teacher_id}") # Debug log
|
| 1215 |
+
session.clear()
|
| 1216 |
+
return redirect(url_for('teacher_login_page'))
|
| 1217 |
+
|
| 1218 |
if teacher and 'face_image' in teacher and teacher['face_image']:
|
| 1219 |
face_image_base64 = base64.b64encode(teacher['face_image']).decode('utf-8')
|
| 1220 |
mime_type = teacher.get('face_image_type', 'image/jpeg')
|
| 1221 |
teacher['face_image_url'] = f"data:{mime_type};base64,{face_image_base64}"
|
| 1222 |
+
|
| 1223 |
+
print(f"Teacher dashboard loaded successfully for: {teacher_id}") # Debug log
|
| 1224 |
return render_template('teacher_dashboard.html', teacher=teacher)
|
| 1225 |
|
| 1226 |
@app.route('/teacher_logout')
|