Source code for intranet.apps.signage.views

import datetime
import logging
from typing import Optional

from django import http
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from django.utils import timezone

from ...utils.date import get_senior_graduation_year
from ...utils.serialization import safe_json
from ..eighth.models import EighthBlock
from ..eighth.serializers import EighthBlockDetailSerializer
from ..schedule.models import Day
from ..schedule.views import schedule_context
from ..users.models import User
from .models import Sign

logger = logging.getLogger(__name__)


[docs]def check_internal_ip(request) -> Optional[HttpResponse]: """ A method to determine if a request is allowed to load a signage page. Denies access by returning None unless the user is authenticated and not restricted, or the request IP address is in ``settings.INTERNAL_IPS``. Returns: a 403 if the request is unauthorized or None if the request is authorized """ remote_addr = request.META["HTTP_X_REAL_IP"] if "HTTP_X_REAL_IP" in request.META else request.META.get("REMOTE_ADDR", "") if (not request.user.is_authenticated or request.user.is_restricted) and remote_addr not in settings.TJ_IPS: return render(request, "error/403.html", {"reason": "You are not authorized to view this page."}, status=403) return None
[docs]def signage_display(request, display_id: str) -> HttpResponse: check_ip = check_internal_ip(request) if check_ip: return check_ip sign = get_object_or_404(Sign, display=display_id) now = timezone.localtime() day = Day.objects.today() if day is not None and day.end_time is not None: end_of_day = day.end_time.date_obj(now.date()) else: end_of_day = datetime.datetime(now.year, now.month, now.day, settings.SCHOOL_END_HOUR, settings.SCHOOL_END_MINUTE) context = schedule_context(request) context["sign"] = sign context["page_args"] = (sign, request) context["end_switch_page_time"] = end_of_day - datetime.timedelta(minutes=sign.day_end_switch_minutes) context["custom_switch_time"] = sign.custom_switch_time context["senior_graduation_year"] = get_senior_graduation_year() return render(request, "signage/base.html", context)
[docs]def eighth(request): """Displays the eighth period signage page. This cannot be a regular signage page because it needs to reload in order to switch blocks or update information..""" internal_ip = check_internal_ip(request) if internal_ip: return internal_ip block_id = request.GET.get("block_id") if block_id is None: block = EighthBlock.objects.get_first_upcoming_block() if block is None: raise http.Http404 else: block = get_object_or_404(EighthBlock.objects.prefetch_related("eighthscheduledactivity_set"), id=block_id) # If block_increment is specified, the eighth period block that is <block_increment> blocks ahead of the current # block (or the block specified with block_id) will be displayed. This is used in the template to skip to A/B # blocks. try: block_increment = int(request.GET.get("block_increment", 0)) except ValueError: block_increment = 0 if block_increment > 0: next_blocks = block.next_blocks() if next_blocks.count() >= block_increment: block = next_blocks[block_increment - 1] elif block_increment < 0: index = -block_increment - 1 prev_blocks = block.previous_blocks() if prev_blocks.count() > index: block = prev_blocks[index] user = User.get_signage_user() serializer_context = {"request": request, "user": user} block_info = EighthBlockDetailSerializer(block, context=serializer_context).data try: reload_mins = float(request.GET.get("reload_mins", 5)) except ValueError: reload_mins = 5 touch_signage = not request.GET.get("no_touch") try: next_block = block.next_blocks(1)[0] if next_block.date != block.date: next_block = None except IndexError: next_block = None try: prev_block = block.previous_blocks(1)[0] if prev_block.date != block.date: prev_block = None except IndexError: prev_block = None use_scroll = not touch_signage and bool(request.GET.get("scroll")) context = { "user": user, "block_info": block_info, "activities_list": safe_json(block_info["activities"]), "active_block": block, "active_block_current_signup": None, "no_title": bool(request.GET.get("no_title")), "no_detail": bool(request.GET.get("no_detail")), "no_rooms": bool(request.GET.get("no_rooms")), "use_scroll": use_scroll, "do_reload": not bool(request.GET.get("no_reload")), "preload_background": True, "reload_mins": reload_mins, "no_user_display": True, "no_fav": True, "touch_signage": touch_signage, "next_block": next_block, "prev_block": prev_block, "signage": True, } return render(request, "signage/pages/eighth.html", context)
[docs]def prometheus_metrics(request): """Prometheus metrics for signage displays. Currently just whether or not they are online.""" remote_addr = request.META["HTTP_X_REAL_IP"] if "HTTP_X_REAL_IP" in request.META else request.META.get("REMOTE_ADDR", "") is_admin = request.user.is_authenticated and not request.user.is_restricted and request.user.is_superuser # If they're not from an IP on the white list and they're not an admin, deny access if remote_addr not in settings.ALLOWED_METRIC_SCRAPE_IPS and not is_admin: return render(request, "error/403.html", {"reason": "You are not authorized to view this page."}, status=403) metrics = {"intranet_signage_num_signs_online": Sign.objects.filter_online().count()} for sign in Sign.objects.all(): metrics[f'intranet_signage_sign_is_online{{display="{sign.display}"}}'] = int(not sign.is_offline) context = {"metrics": metrics} return render(request, "monitoring/prometheus-metrics.txt", context, content_type="text/plain")