from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify from flask_login import login_user, logout_user, login_required, current_user from werkzeug.utils import secure_filename import os import json from datetime import datetime from backend.form.AuthForms import LoginForm, SignupForm from backend.models.user import User from backend.models.database import db auth_bp = Blueprint('auth', __name__) def handle_resume_upload(file): """ Handle a resume upload by saving the file to a temporary location and returning an empty feature dictionary. This function no longer attempts to parse the resume contents; it simply stores the file so that it can be referenced later (e.g. for downloading or inspection) and returns a placeholder features object. A tuple of (features_dict, error_message, filepath) is returned. If an error occurs, ``features_dict`` will be ``None`` and ``error_message`` will contain a description of the error. """ # Validate that a file was provided if not file or file.filename == '': return None, "No file uploaded", None try: # Generate a safe filename and determine the target directory. Use # ``/tmp/resumes`` so that the directory is writable within Hugging # Face Spaces. Creating the directory with ``exist_ok=True`` ensures # that it is available without raising an error if it already exists. filename = secure_filename(file.filename) temp_dir = os.path.join('/tmp', 'resumes') os.makedirs(temp_dir, exist_ok=True) filepath = os.path.join(temp_dir, filename) # Save the uploaded file to the temporary location. If this fails # (e.g. due to permissions issues) the exception will be caught below. file.save(filepath) # Resume parsing has been removed from this project. To maintain # compatibility with the rest of the application, return an empty # dictionary of features. Downstream code will interpret an empty # dictionary as "no extracted features", which still allows the # interview flow to proceed. features = {} return features, None, filepath except Exception as e: # Log the error and propagate it to the caller. Returning None for # ``features`` signals that the upload failed. print(f"Error in handle_resume_upload: {e}") return None, str(e), None @auth_bp.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() # When the form is submitted and passes validation, attempt to authenticate # the user. If the email/password pair is valid, log them in and provide # a success flash message so the user has feedback. Without this message # the application silently redirects to the home page, which can be # confusing. If authentication fails, flash an error message. if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() if user and user.check_password(form.password.data): login_user(user) # ✅ Provide a success message so users know the login worked flash('You have been logged in successfully!', 'success') return redirect(url_for('index')) else: flash('Invalid credentials', 'danger') return render_template('login.html', form=form) @auth_bp.route('/signup', methods=['GET', 'POST']) def signup(): form = SignupForm() if form.validate_on_submit(): existing_user = User.query.filter_by(email=form.email.data).first() if existing_user: flash('Email already registered.', 'warning') else: user = User( username=form.username.data, email=form.email.data, role=form.role.data ) user.set_password(form.password.data) db.session.add(user) db.session.commit() # Log the user in and redirect to profile completion login_user(user) flash('Account created successfully! Welcome to Codingo.', 'success') return redirect(url_for('index')) return render_template('signup.html', form=form) @auth_bp.route('/logout') @login_required def logout(): logout_user() flash('You have been logged out successfully.', 'info') return redirect(url_for('auth.login'))