Files
django-dav-events/dav_events/views/events.py

328 lines
13 KiB
Python

# -*- coding: utf-8 -*-
import datetime
import logging
import os
from django.apps import apps
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.views import generic
from .. import choices
from .. import forms
from .. import models
from ..utils import has_role
app_config = apps.get_containing_app_config(__package__)
logger = logging.getLogger(__name__)
class EventListView(generic.ListView):
model = models.Event
def get_queryset(self):
user = self.request.user
if user.is_superuser:
qs = self.model.objects.all()
elif has_role(user, 'manage_all'):
qs = self.model.objects.all()
else:
filter = Q(owner=user)
user_sports_list = list()
for k in ('W', 'S', 'M', 'K', 'B'):
role = 'manage_{}'.format(k.lower())
if has_role(user, role):
user_sports_list.append(k)
filter |= Q(sport__in=user_sports_list)
if has_role(user, 'publish') or has_role(user, 'publish_incremental'):
filter |= Q(accepted=True)
qs = self.model.objects.filter(filter)
return qs
def get_context_data(self, **kwargs):
context = super(EventListView, self).get_context_data(**kwargs)
user = self.request.user
context['has_permission_export'] = user.is_superuser or has_role(user, 'publish')
return context
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(EventListView, self).dispatch(request, *args, **kwargs)
class EventListExportView(generic.FormView):
form_class = forms.events.EventListExportForm
template_name = 'dav_events/event_list_export_form.html'
def form_valid(self, form):
filename = _(u'Veranstaltungen')
filter_kwargs = {
'accepted': True,
}
if form.cleaned_data['sport']:
sport = form.cleaned_data['sport']
filter_kwargs['sport'] = sport
filename += u'--%s' % choices.SPORT_CHOICES.get_label(sport)
if form.cleaned_data['begin']:
date = form.cleaned_data['begin']
filter_kwargs['first_day__gte'] = date
filename += u'--%s' % date.strftime('%Y-%m-%d')
if form.cleaned_data['end']:
date = form.cleaned_data['end']
filter_kwargs['first_day__lte'] = date
filename += u'--%s' % date.strftime('%Y-%m-%d')
exclude_expired = not form.cleaned_data.get('expired', False)
txt = u''
event_qs = models.Event.objects.filter(**filter_kwargs).order_by('sport', 'first_day')
for event in event_qs:
if exclude_expired and event.get_status() == 'expired':
continue
txt += event.render_as_text(format='ka-alpin')
if event.internal_note:
txt += u'\n> Bearbeitungshinweis:\n> ' + event.internal_note.replace('\n', '\n> ') + u'\n'
txt += u'\n' + (u'-' * 72) + '\n\n'
filename += u'.txt'
response = HttpResponse(txt, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename="{filename}"'.format(filename=filename)
return response
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
user = request.user
if not user.is_superuser and not has_role(user, 'publish'):
raise PermissionDenied('publish')
return super(EventListExportView, self).dispatch(request, *args, **kwargs)
class EventPermissionMixin(object):
permission = 'view'
def has_permission(self, permission, obj):
user = self.request.user
if user.is_superuser:
return True
if permission == 'view':
if obj.owner == user:
return True
if has_role(user, 'manage_all'):
return True
if has_role(user, 'manage_{}'.format(obj.sport.lower())):
return True
if obj.accepted and (has_role(user, 'publish') or has_role(user, 'publish_incremental')):
return True
elif permission == 'accept':
if has_role(user, 'manage_all'):
return True
if has_role(user, 'manage_{}'.format(obj.sport.lower())):
return True
elif permission == 'update':
if not obj.accepted and not obj.publication_confirmed:
if has_role(user, 'manage_all'):
return True
if has_role(user, 'manage_{}'.format(obj.sport.lower())):
return True
elif has_role(user, 'publish') or has_role(user, 'publish_incremental'):
return True
elif permission == 'publish':
if has_role(user, 'publish') or has_role(user, 'publish_incremental'):
return True
return False
def enforce_permission(self, obj):
permission = self.permission
if not self.has_permission(permission, obj):
raise PermissionDenied(permission)
class EventDetailView(EventPermissionMixin, generic.DetailView):
model = models.Event
def get_object(self, queryset=None):
obj = super(EventDetailView, self).get_object(queryset=queryset)
self.enforce_permission(obj)
return obj
def get_context_data(self, **kwargs):
context = super(EventDetailView, self).get_context_data(**kwargs)
obj = context.get('event')
context['has_permission_accept'] = self.has_permission('accept', obj)
context['has_permission_update'] = self.has_permission('update', obj)
context['has_permission_publish'] = self.has_permission('publish', obj)
return context
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(EventDetailView, self).dispatch(request, *args, **kwargs)
class EventAcceptView(EventDetailView):
permission = 'accept'
def get(self, request, *args, **kwargs):
event = self.get_object()
event.accept(request.user)
messages.success(request, _(u'Veranstaltung freigegeben.'))
return HttpResponseRedirect(event.get_absolute_url())
class EventConfirmPublicationView(EventDetailView):
permission = 'publish'
def get(self, request, *args, **kwargs):
event = self.get_object()
if event.accepted:
event.confirm_publication(request.user)
messages.success(request, _(u'Veröffentlichung registriert.'))
else:
messages.error(request, _(u'Veranstaltung ist noch nicht freigegeben.'))
return HttpResponseRedirect(event.get_absolute_url())
class EventUpdateView(EventPermissionMixin, generic.UpdateView):
permission = 'update'
model = models.Event
form_class = forms.events.EventUpdateForm
template_name_suffix = '_update_form'
def get_object(self, queryset=None):
obj = super(EventUpdateView, self).get_object(queryset=queryset)
self.enforce_permission(obj)
return obj
def get_context_data(self, **kwargs):
context = super(EventUpdateView, self).get_context_data(**kwargs)
obj = context.get('event')
context['has_permission_accept'] = self.has_permission('accept', obj)
context['has_permission_update'] = self.has_permission('update', obj)
context['has_permission_publish'] = self.has_permission('publish', obj)
return context
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(EventUpdateView, self).dispatch(request, *args, **kwargs)
class EventCreateView(EventPermissionMixin, generic.FormView):
form_class = forms.events.EventCreateForm
template_dir = os.path.join('dav_events', 'event_create')
default_template_name = 'default.html'
abort_url = reverse_lazy('dav_events:home')
def get_template_names(self):
form = self.get_form()
form_name = form.form_name
template = os.path.join(self.template_dir, '{}.html'.format(form_name))
default_template = os.path.join(self.template_dir, self.default_template_name)
return [
template, default_template
]
def get_form_class(self, form_name=None):
if form_name is not None:
form_class = getattr(forms.events, form_name)
elif 'dav_events_event_create_next_form_name' in self.request.session:
form_name = self.request.session['dav_events_event_create_next_form_name']
form_class = getattr(forms.events, form_name)
if not issubclass(form_class, self.form_class):
raise SuspiciousOperation('Invalid next form: {}'.format(form_name))
else:
base_form_class = self.form_class
initial_form_name = base_form_class.get_initial_form_name()
form_class = getattr(forms.events, initial_form_name)
return form_class
def get_form_kwargs(self):
kwargs = super(EventCreateView, self).get_form_kwargs()
if 'request' not in kwargs:
kwargs['request'] = self.request
return kwargs
def get_context_data(self, **kwargs):
context = super(EventCreateView, self).get_context_data(**kwargs)
context['abort_url'] = self.abort_url
return context
def form_valid(self, form):
event = form.get_instance()
next_form_name = form.next_form_name
if next_form_name:
self.request.session['dav_events_event_create_next_form_name'] = next_form_name
next_form_class = self.get_form_class(next_form_name)
next_form = next_form_class(request=self.request)
return self.render_to_response(self.get_context_data(form=next_form, event=event))
else:
event.save()
form.flush_session_data()
messages.success(self.request, _(u'Veranstaltung angelegt.'))
owner = event.owner
self.clean_session_data()
if self.request.user.is_authenticated:
next_url = reverse('dav_events:event_list')
elif owner.has_usable_password():
next_url = reverse('dav_events:event_list')
else:
login(self.request, owner)
next_url = reverse('dav_events:set_password')
messages.success(self.request,
_(u'Neuen Benutzer angemeldet: %(username)s') % {'username': owner.username})
messages.warning(self.request, _(u'Bitte neues Passwort setzen!'))
return HttpResponseRedirect(next_url)
def clean_session_data(self, session=None):
if session is None:
session = self.request.session
if 'dav_events_event_create_next_form_name' in session:
del session['dav_events_event_create_next_form_name']
def get(self, request, *args, **kwargs):
self.clean_session_data(request.session)
if 'abort' in request.GET:
form = self.get_form()
form.flush_session_data()
return HttpResponseRedirect(self.abort_url)
elif 'copy' in request.GET:
event = get_object_or_404(models.Event, pk=request.GET.get('copy'))
if not self.has_permission('view', event):
raise PermissionDenied('copy')
for field in ('id',
'owner', 'created_at',
'accepted_at', 'accepted_by',
'publication_confirmed_at', 'publication_confirmed_by',
'number',
'planned_publication_date', 'internal_note',):
if hasattr(event, field):
setattr(event, field, None)
for field in ('accepted', 'publication_confirmed'):
if hasattr(event, field):
setattr(event, field, False)
initial_form_name = self.form_class.get_initial_form_name()
form_class = getattr(forms.events, initial_form_name)
form = form_class(request=self.request, instance=event)
form.save_session_data()
return super(EventCreateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return super(EventCreateView, self).post(request, *args, **kwargs)