import fitz # PyMuPDF from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity import os import requests from functools import wraps from flask import request, jsonify def extract_text_from_pdf(file_storage): with fitz.open(stream=file_storage.read(), filetype="pdf") as doc: return " ".join([page.get_text() for page in doc]) def rank_resumes_by_similarity(resume_files, job_description): resume_texts = [extract_text_from_pdf(f) for f in resume_files] documents = [job_description] + resume_texts vectorizer = TfidfVectorizer(stop_words='english') tfidf_matrix = vectorizer.fit_transform(documents) job_vector = tfidf_matrix[0] resume_vectors = tfidf_matrix[1:] similarities = cosine_similarity(job_vector, resume_vectors).flatten() ranked = sorted(zip(resume_files, similarities), key=lambda x: x[1], reverse=True) return [ {"filename": file.filename, "score": round(score, 4)} for file, score in ranked ] SUPABASE_URL = os.getenv("SUPABASE_URL") SUPABASE_API_KEY = os.getenv("SUPABASE_API_KEY") def require_api_key(f): @wraps(f) def decorated_function(*args, **kwargs): auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return jsonify({"error": "Missing or invalid Authorization header."}), 401 token = auth_header.split("Bearer ")[1].strip() # Call Supabase REST API to validate token headers = { "apikey": SUPABASE_API_KEY, "Authorization": f"Bearer {SUPABASE_API_KEY}", # service role "Content-Type": "application/json" } url = f"{SUPABASE_URL}/rest/v1/users?api_key=eq.{token}" response = requests.get(url, headers=headers) if response.status_code != 200: return jsonify({"error": "Failed to contact Supabase"}), 500 user_data = response.json() if not user_data: return jsonify({"error": "Invalid or revoked API key."}), 403 # Optionally attach user to request (like before) request.user = user_data[0] return f(*args, **kwargs) return decorated_function