""" routes/user_dashboard.py — Regular user: shift check dashboard. """ import logging import time import requests as _http_req from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify from models import ( get_today_checks, mark_website_checked, unmark_website_checked, update_check_note, get_user_active_shifts, get_website_credentials, get_website_url, log_action, ) from utils.decorators import login_required logger = logging.getLogger("routes.user_dashboard") user_dashboard_bp = Blueprint("user_dashboard", __name__, url_prefix="/dashboard") @user_dashboard_bp.route("/") @login_required def my_shifts(): user_id = session["user"]["id"] try: sites = get_today_checks(user_id) shifts = get_user_active_shifts(user_id) except Exception as e: logger.error(f"my_shifts error: {e}") sites, shifts = [], [] checked = sum(1 for s in sites if s.get("check_id")) total = len(sites) pct = round(checked * 100 / total) if total else 0 return render_template("user/dashboard.html", sites=sites, shifts=shifts, checked=checked, total=total, pct=pct) @user_dashboard_bp.route("/check/", methods=["POST"]) @login_required def check_site(website_id): user_id = session["user"]["id"] user_note = request.form.get("user_note", "").strip() try: mark_website_checked(user_id, website_id, user_note) flash("Site marked as checked.", "success") logger.info(f"User {user_id} checked website {website_id}.") except Exception as e: logger.error(f"check_site error: {e}") flash(f"Error: {e}", "danger") return redirect(url_for("user_dashboard.my_shifts")) @user_dashboard_bp.route("/uncheck/", methods=["POST"]) @login_required def uncheck_site(website_id): user_id = session["user"]["id"] try: unmark_website_checked(user_id, website_id) flash("Check removed.", "info") logger.info(f"User {user_id} unchecked website {website_id}.") except Exception as e: logger.error(f"uncheck_site error: {e}") flash(f"Error: {e}", "danger") return redirect(url_for("user_dashboard.my_shifts")) @user_dashboard_bp.route("/note/", methods=["POST"]) @login_required def update_note(website_id): user_id = session["user"]["id"] user_note = request.form.get("user_note", "").strip() try: update_check_note(user_id, website_id, user_note) flash("Note updated.", "success") except Exception as e: logger.error(f"update_note error: {e}") flash(f"Error: {e}", "danger") return redirect(url_for("user_dashboard.my_shifts")) @user_dashboard_bp.route("/credentials/") @login_required def view_credentials(website_id): """JSON endpoint: return decrypted credentials for a site.""" try: creds = get_website_credentials(website_id) user_id = session["user"]["id"] log_action(user_id, "VIEW_CREDENTIALS", "websites", website_id, f"User viewed credentials for website {website_id}.") return jsonify([{ "label": c.get("label", ""), "username": c.get("username", ""), "password": c.get("password", ""), } for c in creds]) except Exception as e: logger.error(f"view_credentials error: {e}") return jsonify({"error": str(e)}), 500 @user_dashboard_bp.route("/health/") @login_required def health_check(website_id): """Server-side HEAD probe for a website's reachability.""" url = get_website_url(website_id) if not url: return jsonify({"status": "not_found"}), 404 try: t0 = time.time() resp = _http_req.head(url, timeout=6, allow_redirects=True, headers={"User-Agent": "BidChecker/1.0 (health-check)"}) ms = int((time.time() - t0) * 1000) ok = resp.status_code < 400 return jsonify({"status": "ok" if ok else "error", "ms": ms}) except _http_req.exceptions.Timeout: return jsonify({"status": "timeout", "ms": 6000}) except Exception: return jsonify({"status": "unreachable", "ms": None})