campus-connect / utils.py
Bhuwan31's picture
Initial deploy
dc76e71
# utils.py
# Shared helper functions and decorators
from functools import wraps
from flask import session, redirect, url_for, request, jsonify
from datetime import datetime, timezone
import random
import string
# ── AUTH DECORATORS ────────────────────────────────────────
def login_required(f):
"""Redirect to login if user is not in session. Returns 401 for API calls."""
@wraps(f)
def decorated(*args, **kwargs):
if "user_id" not in session:
if request.is_json or request.path.startswith("/api/"):
return jsonify({"success": False, "message": "Login required."}), 401
return redirect(url_for("auth.login_page"))
return f(*args, **kwargs)
return decorated
def admin_required(f):
"""Returns 403 if the current user is not an admin."""
@wraps(f)
def decorated(*args, **kwargs):
if not session.get("is_admin"):
return jsonify({"success": False, "message": "Admin access required."}), 403
return f(*args, **kwargs)
return decorated
# ── TIME HELPERS ───────────────────────────────────────────
def time_ago(dt: datetime) -> str:
"""Convert a datetime to a human-readable 'X ago' string."""
now = datetime.now(timezone.utc)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
seconds = int((now - dt).total_seconds())
if seconds < 60:
return "Just now"
elif seconds < 3600:
m = seconds // 60
return f"{m} minute{'s' if m > 1 else ''} ago"
elif seconds < 86400:
h = seconds // 3600
return f"{h} hour{'s' if h > 1 else ''} ago"
elif seconds < 604800:
d = seconds // 86400
return f"{d} day{'s' if d > 1 else ''} ago"
else:
return dt.strftime("%b %d, %Y")
# ── ID GENERATOR ───────────────────────────────────────────
def generate_student_id() -> str:
"""Generate a unique student ID like STU123456."""
return "STU" + "".join(random.choices(string.digits, k=6))
# ── PAGINATION HELPER ──────────────────────────────────────
def get_pagination_args():
"""Extract page and limit from request args."""
page = max(1, int(request.args.get("page", 1)))
limit = min(50, int(request.args.get("limit", 10)))
return page, limit, (page - 1) * limit