# Copyright (C) 2017 Semester.ly Technologies, LLC
#
# Semester.ly is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Semester.ly is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
from __future__ import absolute_import, division, print_function
import json
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.shortcuts import render
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
from agreement.models import Agreement
from agreement.serializers import AgreementSerializer
from student.utils import get_student
from student.serializers import get_student_dict
from timetable.models import Semester
from timetable.school_mappers import SCHOOLS_MAP
from parsing.schools.active import ACTIVE_SCHOOLS
from timetable.utils import get_current_semesters
[docs]class ValidateSubdomainMixin:
"""
Mixin which validates subdomain, redirecting user to index if the school
is not in :obj:`ACTIVE_SCHOOLS`.
"""
def dispatch(self, request, *args, **kwargs):
if request.subdomain == "queens":
return render(request, "queens_error.html")
elif request.subdomain not in ACTIVE_SCHOOLS:
return render(request, "index.html")
return super(ValidateSubdomainMixin, self).dispatch(request, *args, **kwargs)
[docs]class FeatureFlowView(ValidateSubdomainMixin, APIView):
"""
Template that handles GET requests by rendering the homepage. Feature_name or get_feature_flow()
can be overridden to launch a feature or action on homepage load.
"""
feature_name = None
allow_unauthenticated = True
[docs] def get_feature_flow(self, request, *args, **kwargs):
"""
Return data needed for the feature flow for this HomeView.
A name value is automatically added in .get() using the feature_name class variable.
A semester value can also be provided, which will change the initial semester state of
the home page.
"""
return {}
def get(self, request, *args, **kwargs):
if not self.allow_unauthenticated and not request.user.is_authenticated:
return HttpResponseRedirect("/")
self.school = request.subdomain
self.student = get_student(request)
feature_flow = self.get_feature_flow(request, *args, **kwargs)
# take semester provided by feature flow if available, otherwise the first available sem
all_semesters = get_current_semesters(self.school)
if "semester" in feature_flow:
sem = feature_flow.pop("semester")
sem_dict = {"name": sem.name, "year": sem.year}
if sem_dict not in all_semesters:
all_semesters.append(sem_dict)
curr_sem_index = all_semesters.index(sem_dict)
else:
curr_sem_index = 0
sem = Semester.objects.get(**all_semesters[curr_sem_index])
integrations = []
if self.student and self.student.user.is_authenticated:
self.student.school = self.school
self.student.save()
for i in self.student.integrations.all():
integrations.append(i.name)
final_exams = []
if SCHOOLS_MAP[self.school].final_exams is None:
final_exams = []
else:
for year, terms in SCHOOLS_MAP[self.school].final_exams.items():
for term in terms:
final_exams.append({"name": term, "year": str(year)})
init_data = {
"school": self.school,
"currentUser": get_student_dict(self.school, self.student, sem),
"currentSemester": curr_sem_index,
"allSemesters": all_semesters,
# 'oldSemesters': get_old_semesters(self.school),
"uses12HrTime": SCHOOLS_MAP[self.school].ampm,
"studentIntegrations": integrations,
"latestAgreement": AgreementSerializer(Agreement.objects.latest()).data,
"registrar": SCHOOLS_MAP[self.school].registrar,
"examSupportedSemesters": list(map(all_semesters.index, final_exams)),
"timeUpdatedTos": Agreement.objects.latest().last_updated.isoformat(),
"featureFlow": dict(feature_flow, name=self.feature_name),
}
return render(request, "timetable.html", {"init_data": json.dumps(init_data)})
[docs]class CsrfExemptSessionAuthentication(SessionAuthentication):
[docs] def enforce_csrf(self, request):
return
class CsrfExemptMixin:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
[docs]class RedirectToSignupMixin(LoginRequiredMixin):
login_url = "/signup/"
redirect_field_name = None