import json from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.core.mail import send_mail from django.db.models import Q from django.http import Http404, HttpResponse from django.urls import reverse from django.urls import reverse_lazy from django.utils.translation import get_language from django.views import View from django.views.generic import DetailView from django.views.generic.base import TemplateView from django.views.generic.edit import CreateView, UpdateView from dal import autocomplete from apps.files.models import File from .models import CaseStudy, CaseStudyDraft, SpatialRefSys, PointOfInterest from .forms import ShortCaseStudyForm, LongCaseStudyForm, PointOfInterest NOTIFY_MESSAGE = """ Hello, Someone has submitted a new case study to the Ojuso website. Please follow the below link to look over and approve it: %s%s – Case Study Robot """ class Map(TemplateView): template_name = "map/index.html" class CreateCaseStudySelector(LoginRequiredMixin, TemplateView): template_name = "map/form-selector.html" class CreatePointOfInterest(LoginRequiredMixin, CreateView): """View for base case study form.""" template_name = 'map/form-poi.html' success_url = '/case-study/create/success/' model = PointOfInterest form_class = PointOfInterest def send_email(study_id): """Sends email to moderator to approve case study.""" try: send_mail( 'New case study submitted', NOTIFY_MESSAGE % ( settings.SITE_URL, reverse('admin:map_casestudy_change', args=[study_id]) ), 'noreply@ojuso.org', [settings.DATABASE_EMAIL], fail_silently=False, ) except: # XXX This is bad. We should do something more useful with the error # than this. pass def delete_user_draft(user_id): """ Delete the draft of a given user """ try: draft = CaseStudyDraft.objects.get(author=user_id) draft.delete() except CaseStudyDraft.DoesNotExist: pass class FilesHandlerMixin: def remove_bad_fields(self, form): form.cleaned_data.pop('official_project_documents', None) form.cleaned_data.pop('other_documents', None) form.cleaned_data.pop('shapefiles', None) form.cleaned_data.pop('images', None) def add_file_refs(self, form): self.object.official_project_documents.set(form.cleaned_data.get( 'official_project_documents_files', [] )) self.object.other_documents.set(form.cleaned_data.get( 'other_documents_files', [] )) self.object.shapefiles.set(form.cleaned_data.get( 'shapefiles_files', [] )) self.object.images.set(form.cleaned_data.get( 'images_files', [] )) def handle_files(self, form): self.remove_bad_fields(form) self.object = form.save() self.add_file_refs(form) self.object.save() class BaseCreateForm(LoginRequiredMixin, FilesHandlerMixin, CreateView): """View for base case study form.""" template_name = 'map/form-case_study.html' success_url = reverse_lazy('form-success') model = CaseStudy def form_valid(self, form): self.handle_files(form) self.object.author = self.request.user self.object.language = get_language() self.object.form_type = self.form_type self.object.save() send_email(self.object.id) delete_user_draft(self.request.user) return super().form_valid(form) class CreateShortCaseStudy(BaseCreateForm): """View for short version of case study form.""" form_class = ShortCaseStudyForm form_type = "short" class CreateLongCaseStudy(BaseCreateForm): """View for long version of case study form.""" form_class = LongCaseStudyForm form_type = "long" class CreateCaseStudySuccess(TemplateView): template_name = 'map/form-success.html' class ViewCaseStudyDetail(DetailView): template_name = "map/detail.html" model = CaseStudy context_object_name = "case_study" class BaseEditForm(LoginRequiredMixin, FilesHandlerMixin, UpdateView): """View for base case study form.""" template_name = 'map/form-case_study.html' success_url = reverse_lazy('form-success') model = CaseStudy def form_valid(self, form): self.handle_files(form) return super().form_valid(form) class EditCaseStudy(UserPassesTestMixin, BaseEditForm): form_class = ShortCaseStudyForm def test_func(self): if settings.FFCAN_EDIT is False: return False object = self.get_object() if object.author: author = object.author.id else: author = -1 return self.request.user.is_authenticated and ( author is self.request.user.id ) class SpatialRefSysAutocomplete(autocomplete.Select2QuerySetView): def get_queryset(self): qs = SpatialRefSys.objects.all() if self.q: qs = qs.filter( Q(auth_name__icontains=self.q) | Q(auth_srid__icontains=self.q) ) return qs class DraftsAPI(LoginRequiredMixin, View): """ Retrieve or save a draft. XXX This should be refactored to use csrf protection. """ def get_object(self, request): try: return CaseStudyDraft.objects.get(author=request.user) except: return None def get(self, request): draft = self.get_object(request) if draft == None: return HttpResponse(status=404) # Not Found else: return HttpResponse(draft.data, content_type="application/json") def put(self, request): # Find an existing object is there is one draft = self.get_object(request) if draft == None: # If there isn't, create a new draft... draft = CaseStudyDraft(author=request.user, data=request.body.decode()) draft.save() return HttpResponse(status=201) # Created else: draft.data = request.body.decode() draft.save() return HttpResponse(status=200) # OK def delete(self, request): draft = self.get_object(request) if draft != None: data = json.loads(draft.data) for k in [ 'official_project_documents', 'other_documents', 'shapefiles', 'images' ]: try: keyname = k + '_files' field = data['data']['form'][keyname] # Ignore empty fields if field['value'] == '': continue file_list = json.loads(field['value']) # Delete those items for item in file_list: try: f = File.objects.get(id=item['id']) if f.user != self.request.user: continue f.delete() except File.DoesNotExist: continue except: continue draft.delete() return HttpResponse(status=204)