bornhack-website/src/phonebook/views.py

183 lines
5.7 KiB
Python

import csv
import logging
import secrets
import string
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import ValidationError
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils import timezone
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from oauth2_provider.views.generic import ProtectedResourceView
from camps.mixins import CampViewMixin
from utils.mixins import RaisePermissionRequiredMixin, UserIsObjectOwnerMixin
from .mixins import DectRegistrationViewMixin
from .models import DectRegistration
logger = logging.getLogger("bornhack.%s" % __name__)
class DectExportView(
CampViewMixin, RaisePermissionRequiredMixin, ProtectedResourceView
):
"""
CSV export for the POC team / DECT system
"""
permission_required = "camps.pocteam_permission"
def get(self, request, *args, **kwargs):
response = HttpResponse(content_type="text/csv")
response[
"Content-Disposition"
] = f'attachment; filename="{self.camp.slug}-dect-export-{timezone.now()}.csv"'
writer = csv.writer(response)
writer.writerow(
[
"number",
"letters",
"description",
"activation_code",
"publish_in_phonebook",
]
)
for dect in DectRegistration.objects.filter(camp=self.camp):
writer.writerow(
[
dect.number,
dect.letters,
dect.description,
dect.activation_code,
dect.publish_in_phonebook,
]
)
return response
class PhonebookListView(CampViewMixin, ListView):
"""
Our phonebook view currently only shows DectRegistration entries,
but could later be extended to show maybe GSM or other kinds of
phone numbers.
"""
model = DectRegistration
template_name = "phonebook.html"
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
return qs.filter(publish_in_phonebook=True)
class DectRegistrationListView(LoginRequiredMixin, CampViewMixin, ListView):
model = DectRegistration
template_name = "dectregistration_list.html"
def get_queryset(self, *args, **kwargs):
"""
Show only DectRegistration entries belonging to the current user
"""
qs = super().get_queryset(*args, **kwargs)
return qs.filter(user=self.request.user)
class DectRegistrationCreateView(LoginRequiredMixin, CampViewMixin, CreateView):
model = DectRegistration
fields = ["number", "letters", "description", "publish_in_phonebook"]
template_name = "dectregistration_form.html"
def form_valid(self, form):
dect = form.save(commit=False)
dect.camp = self.camp
dect.user = self.request.user
try:
dect.clean_number()
except ValidationError as E:
form.add_error("number", E)
return super().form_invalid(form)
try:
dect.clean_letters()
except ValidationError as E:
form.add_error("letters", E)
return super().form_invalid(form)
# this check needs to be in this form, but not in model.save(), because then we cant save service numbers from the admin
if len(dect.number) < 4:
form.add_error(
"number",
ValidationError(
"Numbers with fewer than 4 digits are reserved for special use"
),
)
return super().form_invalid(form)
# generate a 10 digit activation code for this dect registration?
if not dect.activation_code:
dect.activation_code = "".join(
secrets.choice(string.digits) for i in range(10)
)
# all good, save and return to list
dect.save()
messages.success(
self.request,
"New DECT registration created successfully. Call the activation number from your handset to activate it!",
)
return redirect(
reverse(
"phonebook:dectregistration_list", kwargs={"camp_slug": self.camp.slug}
)
)
class DectRegistrationUpdateView(
LoginRequiredMixin, DectRegistrationViewMixin, UserIsObjectOwnerMixin, UpdateView
):
model = DectRegistration
fields = ["letters", "description", "publish_in_phonebook"]
template_name = "dectregistration_form.html"
def form_valid(self, form):
dect = form.save(commit=False)
# check if the letters match the DECT number
try:
dect.clean_letters()
except ValidationError as E:
form.add_error("letters", E)
return super().form_invalid(form)
# save and return
dect.save()
messages.success(
self.request, "Your DECT registration has been updated successfully"
)
return redirect(
reverse(
"phonebook:dectregistration_list", kwargs={"camp_slug": self.camp.slug}
)
)
class DectRegistrationDeleteView(
LoginRequiredMixin, DectRegistrationViewMixin, UserIsObjectOwnerMixin, DeleteView
):
model = DectRegistration
template_name = "dectregistration_delete.html"
def get_success_url(self):
messages.success(
self.request,
f"Your DECT registration for number {self.get_object().number} has been deleted successfully",
)
return reverse(
"phonebook:dectregistration_list", kwargs={"camp_slug": self.camp.slug}
)