"""Webapp views.""" import jwt import json from django.utils import timezone from dealer.git import git from django.conf import settings from django.contrib.auth import authenticate from django.http import HttpResponseBadRequest, HttpResponse from django.shortcuts import redirect, render from django.views.decorators.http import require_http_methods from django_filters import rest_framework as filters from rest_framework import permissions, routers, viewsets from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAuthenticatedOrReadOnly, AllowAny from rest_framework.response import Response from rest_framework.reverse import reverse from jsonschema import validate import logging from webapp.models import Event, SignupForm, Signup, TemplateQuestion, Feed, Committee, Occupation, Tag from webapp.serializers import (EventSerializer, SignupFormSerializer, SignupSerializer, SavedQuestionsSerializer, FeedSerializer, CommitteeSerializer, OccupationSerializer, TagSerializer) class IsPostOrIsAuthenticated(permissions.BasePermission): def has_permission(self, request, view): if request.method == 'POST': return True return request.user and request.user.is_authenticated # -- REST API -- # class RootView(routers.APIRootView): permission_classes = [IsAuthenticatedOrReadOnly] class EventViewSet(viewsets.ModelViewSet): queryset = Event.objects.all() ordering = ["start_time"] serializer_class = EventSerializer permission_classes = [IsAuthenticatedOrReadOnly] filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) filter_fields = '__all__' search_fields = '__all__' def get_queryset(self): if self.request.user.is_authenticated: return Event.objects.all() since = self.request.query_params.get('since', None) if since: return Event.objects.filter(visible=True, end_time__gt=since).order_by('start_time') return Event.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time') class SignupFormViewSet(viewsets.ModelViewSet): queryset = SignupForm.objects.all() serializer_class = SignupFormSerializer permission_classes = [IsAuthenticatedOrReadOnly] # Throws errors with JSONFIeld. Modify __all__ to not use JSONField if filters are enadbled # filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) # filter_fields = '__all__' # search_fields = '__all__' def get_queryset(self): if self.request.user.is_authenticated: return SignupForm.objects.all().order_by('start_time') return SignupForm.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time') class SignupViewSet(viewsets.ModelViewSet): queryset = Signup.objects.all() serializer_class = SignupSerializer permission_classes = [AllowAny] # permission_classes = [IsPostOrIsAuthenticated] # filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) # filter_fields = '__all__' # search_fields = '__all__' def create(self, request, *args, **kwargs): try: form = SignupForm.objects.get(id=request.data["signupForm_id"]) if (form.visible): signup = json.loads(request.data["answer"]) # Throws error if not valid print(form.schema) validate(instance=signup, schema=form.schema) return super().create(request, *args, **kwargs) except Exception as inst: print(inst) return HttpResponseBadRequest() else: return HttpResponseBadRequest() def update(self, request, *args, **kwargs): return super().update(request, *args, **kwargs) class SavedQuestionsViewSet(viewsets.ModelViewSet): queryset = TemplateQuestion.objects.all() serializer_class = SavedQuestionsSerializer permission_classes = [IsAuthenticatedOrReadOnly] class FeedViewSet(viewsets.ModelViewSet): queryset = Feed.objects.all() serializer_class = FeedSerializer permission_classes = [IsAuthenticatedOrReadOnly] filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) filter_fields = '__all__' search_fields = '__all__' def get_queryset(self): if self.request.user.is_authenticated: return Feed.objects.all().order_by('publish_time') else: objs = Feed.objects.filter(visible=True).order_by('publish_time') result_ids = [] for obj in objs: if obj.autohide_enabled: if obj.autohide > timezone.now(): result_ids.append(obj.id) else: result_ids.append(obj.id) return Feed.objects.filter(id__in=result_ids) class ContactsViewSet(viewsets.ReadOnlyModelViewSet): queryset = Occupation.objects.all() serializer_class = OccupationSerializer permission_classes = [IsAuthenticatedOrReadOnly] def get_queryset(self): year = self.request.query_params.get('year') if not year: return Occupation.by_year(timezone.now().year) return Occupation.by_year(int(year)) class CommitteeViewSet(viewsets.ReadOnlyModelViewSet): queryset = Committee.objects.all() serializer_class = CommitteeSerializer permission_classes = [IsAuthenticatedOrReadOnly] class TagsViewSet(viewsets.ReadOnlyModelViewSet): queryset = Tag.objects.all() serializer_class = TagSerializer permission_classes = [IsAuthenticatedOrReadOnly] @require_http_methods(["GET"]) def about_view(request, *args, **kwargs): """Render about page.""" latest_commit = "Not found" latest_date = "Not found" latest_tag = "Not found" try: repo = git.init_repo() latest_commit = repo.git("rev-parse HEAD").decode('utf-8') latest_date = repo.git("show -s --format=%ci " + latest_commit).decode('utf-8') latest_tag = repo.git("describe --tags " + repo.git("rev-list --tags --max-count=1").decode('utf-8')).decode('utf-8') except Exception as e: print(f"Git failed:\n{e}") context = { 'commit': latest_commit, 'date': latest_date, 'tag': latest_tag } return render(request, "about.html", context) @require_http_methods(["GET"]) def nginx_jwt_resp(request, *args, **kwargs): cookie = request.COOKIES.get("jwt", None) if not cookie: return HttpResponse("", status=401) try: token = jwt.decode(cookie, settings.SECRET_KEY) except jwt.exceptions.InvalidSignatureError: return HttpResponse("", status=403) user = 'admin' if token.get('username', '') == 'admin' else 'moderator' resp = HttpResponse("", status=200) resp['X-FBrowser-User'] = user return resp