# import calendar # import locale import json from datetime import datetime from itertools import chain from django.conf import settings from django.db import models from django.http import HttpResponseRedirect, JsonResponse from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.utils import timezone from django.views.decorators.http import require_POST from django_downloadview import ObjectDownloadView from django_http_exceptions import HTTPExceptions from guardian.shortcuts import get_objects_for_user from .models import Lecture, LectureGroup, LectureMaterial class LectureMaterialFileDownloadView(ObjectDownloadView): model = LectureMaterial file_field = "file" attachment = False def get_queryset(self, *args, **kwargs): queryset = ( super() .get_queryset(*args, **kwargs) .filter( lecture__groups__in=( get_objects_for_user( self.current_user, "lectures.view_lecturegroup" ).filter( models.Q(user_groups__in=self.current_user.groups.all()) | models.Q(user_groups=None) ) ) ) ) return queryset def get(self, request, *args, **kwargs): self.current_user = request.user return super().get(request, *args, **kwargs) def get_base_context(request) -> dict: return { "site_url": settings.SITE_URL, } def generate_auth_redirect(request) -> HttpResponseRedirect: return HttpResponseRedirect( request.build_absolute_uri(reverse("oidc_authentication_init")) + "?next=" + request.path ) def get_lecture(request, id: int) -> tuple: lecture = ( get_objects_for_user(request.user, "lectures.view_lecture") .filter(id=id) .first() ) if lecture is None: raise HTTPExceptions.NOT_FOUND if not ( get_objects_for_user(request.user, "lectures.view_lecturegroup") .filter( models.Q(id__in=lecture.groups.all()) & ( ( models.Q(user_groups__in=request.user.groups.all()) | models.Q(user_groups=None) ) if not request.user.is_superuser else models.Q(id__isnull=False) # Always True ) ) .distinct() .exists() ): # User does not have access to related groups if request.user.is_authenticated: # The user can log in raise HTTPExceptions.NOT_FOUND else: # They can log in return False, generate_auth_redirect(request) return True, lecture def view_groups(request): lecture_groups = ( get_objects_for_user(request.user, "lectures.view_lecturegroup") .filter( ( models.Q(user_groups__in=request.user.groups.all()) | models.Q(user_groups=None) ) if not request.user.is_superuser else models.Q(id__isnull=False) # Always True ) .distinct() .all() ) return render( request, "lectures/view_groups.html", { **get_base_context(request), "title": "Výukové skupiny", "description": "Kurzy a školení zaměřené na politickou práci a organizaci kampaní.", "header_name": "Pirátský e-Learning", "lecture_groups": lecture_groups, "settings": Lecture.settings, }, ) def view_group_lectures(request, group_id: int): group = get_objects_for_user(request.user, "lectures.view_lecturegroup").filter( id=group_id ) group_id_exists = group.exists() if not request.user.is_superuser: group = group.filter( models.Q(user_groups__in=request.user.groups.all()) | models.Q(user_groups=None) ) if not group.exists(): if not group_id_exists: # Doesn't exist at all raise HTTPExceptions.NOT_FOUND elif group_id_exists: # Exists without permissions checks if request.user_is_authenticated: # The user is logged in raise HTTPExceptions.NOT_FOUND else: # The user can log in return generate_auth_redirect(request) group = group.first() timestamp_starting_separator = timezone.now() - Lecture.is_current_starting_treshold timestamp_ending_separator = timezone.now() + Lecture.is_current_ending_treshold past_lectures = ( get_objects_for_user(request.user, "lectures.view_lecture") .filter( groups=group, timestamp__lt=timestamp_starting_separator, ) .all() ) current_lectures = ( get_objects_for_user(request.user, "lectures.view_lecture") .filter( groups=group, timestamp__gte=timestamp_starting_separator, timestamp__lte=timestamp_ending_separator, ) .all() ) calendar_data = [] all_lectures = list( chain( past_lectures, current_lectures, ( get_objects_for_user(request.user, "lectures.view_lecture") .filter(groups=group, timestamp__gte=timestamp_ending_separator) .all() ), ) ) per_month_lectures = {} MONTH_NAMES = { 0: "", 1: "Leden", 2: "Únor", 3: "Březen", 4: "Duben", 5: "Květen", 6: "Červen", 7: "Červenec", 8: "Srpen", 9: "Září", 10: "Říjen", 11: "Listopad", 12: "Prosinec", } # locale.setlocale( # locale.LC_ALL, # "cs_CZ.UTF-8" # ) current_year = datetime.today().year has_previous_timeline_years = False has_next_timeline_years = False for lecture in all_lectures: if not has_previous_timeline_years and lecture.timestamp.year < current_year: has_previous_timeline_years = True if not has_next_timeline_years and lecture.timestamp.year > current_year: has_next_timeline_years = True if lecture.timestamp.year not in per_month_lectures: per_month_lectures[lecture.timestamp.year] = { MONTH_NAMES[month]: [] for month in range(1, 12 + 1) } if current_year not in per_month_lectures: per_month_lectures[current_year] = { MONTH_NAMES[month]: [] for month in range(1, 12 + 1) } per_month_lectures[lecture.timestamp.year][ MONTH_NAMES[lecture.timestamp.month] ].append(lecture) # locale.setlocale( # locale.LC_ALL, # "" # ) return render( request, "lectures/view_group_lectures.html", { **get_base_context(request), "title": f"Výuka pro {group.name}", "description": f"e-Learningová výuka pro skupinu {group.name}.", "header_name": group.name, "group": group, "current_lectures": current_lectures, "past_lectures": past_lectures, "per_month_lectures": per_month_lectures, "current_year": current_year, "has_previous_timeline_years": has_previous_timeline_years, "has_next_timeline_years": has_next_timeline_years, }, ) def view_lecture(request, lecture_id: int): is_successful, lecture = get_lecture(request, lecture_id) if not is_successful: return lecture related_group_id = request.GET.get("related_group_id") if related_group_id is not None and not ( get_objects_for_user(request.user, "lectures.view_lecture") .filter(id=related_group_id) .exists() ): # Ignore the wrong part of the URL and move on, don't raise exceptions # just because of the related_group_id being wrong. related_group_id = None return render( request, "lectures/view_lecture.html", { **get_base_context(request), "title": f"{lecture.name}", "description": f"e-Learningové školení {lecture.name}.", "header_name": lecture.name, "lecture": lecture, "related_group_id": related_group_id, }, ) @require_POST def rsvp_lecture(request, lecture_id: int): is_successful, lecture = get_lecture(request, lecture_id) if not is_successful: return lecture is_registered = request.POST.get("register", "false") == "true" if is_registered is request.user.get_lecture_registered( lecture ): # The RSVP state is the same return JsonResponse({"success": False}) if is_registered: request.user.rsvp_lectures.add(lecture) else: request.user.rsvp_lectures.remove(lecture) request.user.save() return JsonResponse({"success": True})