2020-03-05 11:31:11 +00:00
|
|
|
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
|
2021-07-19 13:06:10 +00:00
|
|
|
|
|
|
|
from camps.mixins import CampViewMixin
|
2020-03-05 11:31:11 +00:00
|
|
|
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)
|
2020-06-03 19:31:01 +00:00
|
|
|
writer.writerow(
|
|
|
|
[
|
|
|
|
"number",
|
|
|
|
"letters",
|
|
|
|
"description",
|
|
|
|
"activation_code",
|
|
|
|
"publish_in_phonebook",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
for dect in DectRegistration.objects.filter(camp=self.camp):
|
2020-03-05 11:31:11 +00:00
|
|
|
writer.writerow(
|
2020-06-03 19:31:01 +00:00
|
|
|
[
|
|
|
|
dect.number,
|
|
|
|
dect.letters,
|
|
|
|
dect.description,
|
|
|
|
dect.activation_code,
|
|
|
|
dect.publish_in_phonebook,
|
|
|
|
]
|
2020-03-05 11:31:11 +00:00
|
|
|
)
|
|
|
|
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)
|
|
|
|
|
2020-03-10 18:45:23 +00:00
|
|
|
# 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)
|
|
|
|
|
2020-03-05 11:31:11 +00:00
|
|
|
# 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}
|
|
|
|
)
|