2 from django.conf import settings
3 from django.contrib.admin.views.decorators import staff_member_required
4 from django.contrib.auth.decorators import login_required
5 from django.contrib.auth.models import Group, Permission
6 from django.core.exceptions import PermissionDenied
7 from django.db.models import Q, Sum
8 from django.http import HttpResponse, HttpResponseRedirect
9 from django.urls import reverse_lazy
10 from django.utils.timezone import now
11 from django.utils.translation import ugettext_lazy as _
12 from django.views.decorators.http import require_POST
13 from django.views.generic.base import RedirectView, TemplateView, View
14 from django.views.generic.detail import DetailView
15 from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
16 from django.views.generic.list import ListView
18 from .forms import MemberCreateForm, MemberEditForm, MemberEmissionForm, MembershipForm
19 from .models import Membership, User
21 RELEVANT_PERMISSIONS = [
22 ('nonstop.add_track', _('Add tracks to nonstop')),
23 ('emissions.change_nonstop', _('Adjust nonstop schedule')),
24 ('emissions.change_schedule', _('Adjust emissions schedules')),
25 ('emissions.add_diffusion', _('Add a diffusion out of regular schedules')),
26 ('emissions.add_emission', _('Add a new emission')),
27 ('emissions.delete_emission', _('Delete an emission (careful!)')),
28 ('nonstop.add_scheduleddiffusion', _('Define a stream in an episode')),
29 ('nonstop.change_stream', _('Manage available streams')),
30 ('service_messages.change_message', _('Manage service messages')),
31 ('agendas.add_booking', _('Manage agendas')),
32 ('aa.add_user', _('Manage users and goups')),
36 class ProfileView(TemplateView):
37 template_name = 'aa/profile.html'
40 profile_view = login_required(ProfileView.as_view())
43 class ProfileContactEditView(UpdateView):
45 fields = ['phone', 'mobile', 'share_contact_details']
46 success_url = reverse_lazy('profile-view')
47 template_name = 'aa/profile_form.html'
50 return self.request.user
53 profile_contact_edit = login_required(ProfileContactEditView.as_view())
56 class MembersListView(ListView):
59 def get_queryset(self):
60 qs = User.objects.all().prefetch_related('emissions').prefetch_related('groups')
61 if not (self.request.user.is_staff and self.request.GET.get('q')):
62 # filter on active users unless a search term is given
63 qs = qs.filter(is_active=True)
64 if self.request.GET.get('q'):
65 for part in self.request.GET.get('q').split():
69 if part.lower() in ('ca', 'cp'):
70 qs = qs.filter(groups__name=part.upper())
73 Q(first_name__icontains=part)
74 | Q(last_name__icontains=part)
75 | Q(emissions__title__icontains=part)
76 | Q(emissions__slug__icontains=part)
78 current_year = now().year
79 if self.request.GET.get('membership') == 'ok':
80 qs = qs.filter(membership__year=current_year)
81 if self.request.GET.get('membership') == 'renew':
82 qs = qs.filter(membership__year=current_year - 1).exclude(membership__year=current_year)
86 def get_context_data(self, **kwargs):
87 context = super().get_context_data(**kwargs)
88 if self.request.GET.get('membership') == 'ok':
89 context['total_membership'] = True
90 context['total_money'] = (
92 .aggregate(Sum('membership__payment_amount'))
93 .get('membership__payment_amount__sum')
98 members_list_view = login_required(MembersListView.as_view())
101 class MembersVCardView(MembersListView):
102 def get_queryset(self):
103 qs = super().get_queryset()
104 if not self.request.user.is_staff:
105 qs = qs.filter(share_contact_details=True)
106 qs = qs.exclude(email='')
109 def render_to_response(self, context, **response_kwargs):
111 for member in self.get_queryset():
112 card = vobject.vCard()
114 card.n.value = vobject.vcard.Name(family=member.last_name, given=member.first_name)
116 card.fn.value = str(member)
118 card.email.value = member.email
119 card.email.type_param = 'INTERNET'
123 note_parts.append('CA')
125 note_parts.append('CP')
126 note_parts.extend([str(x) for x in member.active_emissions()])
127 card.note.value = ', '.join(note_parts)
130 card.tel.value = member.phone
131 card.tel.type_param = 'HOME'
134 card.tel.value = member.mobile
135 card.tel.type_param = 'CELL'
136 members.append(card.serialize())
137 content = ''.join(members)
138 return HttpResponse(content, content_type='text/vcard')
141 members_vcard = login_required(MembersVCardView.as_view())
144 class MemberView(DetailView):
147 def get_queryset(self):
148 return User.objects.all().prefetch_related('emissions').prefetch_related('groups')
150 def get_context_data(self, **kwargs):
151 context = super().get_context_data(**kwargs)
152 current_year = now().year
153 user = self.get_object()
154 memberships = user.membership_set.all().order_by('-year')
156 context['current_membership'] = [x for x in memberships if x.year == current_year][0]
159 context['past_memberships'] = [x for x in memberships if x.year != current_year]
163 member_view = login_required(MemberView.as_view())
166 class MemberEditView(UpdateView):
168 form_class = MemberEditForm
170 def get_object(self):
171 if not self.request.user.has_perm('aa.add_user'):
172 raise PermissionDenied()
173 return super().get_object()
175 def form_valid(self, form):
176 response = super().form_valid(form)
177 if Group.objects.filter(name__iexact='admin').exists():
178 self.object.is_superuser = bool(self.object.groups.filter(name__iexact='admin').exists())
182 def get_success_url(self):
183 return reverse_lazy('member-view', kwargs={'pk': self.get_object().id})
186 member_edit = login_required(MemberEditView.as_view())
189 class MemberCreateView(CreateView):
191 form_class = MemberCreateForm
193 def get_object(self):
194 if not self.request.user.has_perm('aa.add_user'):
195 raise PermissionDenied()
196 return super().get_object()
198 def form_valid(self, form):
199 form.instance.username = form.instance.email
200 response = super().form_valid(form)
201 self.object.set_password(form.cleaned_data['password'])
205 def get_success_url(self):
206 return reverse_lazy('member-view', kwargs={'pk': self.object.id})
209 member_new = login_required(MemberCreateView.as_view())
212 class MemberEmissionsView(FormView):
213 form_class = MemberEmissionForm
214 template_name = 'aa/member_emissions.html'
216 def get_context_data(self, **kwargs):
217 context = super().get_context_data(**kwargs)
218 context['member'] = User.objects.get(id=self.kwargs['pk'])
221 def form_valid(self, form):
222 response = super().form_valid(form)
223 member = User.objects.get(id=self.kwargs['pk'])
224 member.emissions.add(form.cleaned_data['emission'])
227 def get_success_url(self):
228 return reverse_lazy('member-view', kwargs={'pk': self.kwargs['pk']})
231 member_emissions = login_required(MemberEmissionsView.as_view())
234 class MemberEmissionRemoveView(RedirectView):
235 def get_redirect_url(self, *args, **kwargs):
236 if not self.request.user.has_perm('aa.add_user'):
237 raise PermissionDenied()
238 member = User.objects.get(id=kwargs['pk'])
239 member.emissions.remove(kwargs['em_pk'])
240 return reverse_lazy('member-view', kwargs={'pk': member.id})
243 member_emission_remove = login_required(MemberEmissionRemoveView.as_view())
246 @staff_member_required
247 def mark_as_active(request, pk):
248 User.objects.filter(pk=pk).update(is_active=True)
249 return HttpResponseRedirect(reverse_lazy('member-view', kwargs={'pk': pk}))
252 @staff_member_required
253 def mark_as_inactive(request, pk):
254 User.objects.filter(pk=pk).update(is_active=False)
255 return HttpResponseRedirect(reverse_lazy('member-view', kwargs={'pk': pk}))
258 class RegisterMembershipView(FormView):
259 form_class = MembershipForm
260 template_name = 'aa/register_membership.html'
262 def get_context_data(self, **kwargs):
263 if not self.request.user.has_perm('aa.add_membership'):
264 raise PermissionDenied()
265 context = super().get_context_data(**kwargs)
266 context['member'] = User.objects.get(id=self.kwargs['pk'])
269 def get_initial(self):
270 initial = super().get_initial()
271 initial['year'] = now().year
272 initial['payment_date'] = now().date()
273 initial['payment_amount'] = settings.MEMBERSHIP_DEFAULT_AMOUNT or ''
276 def form_valid(self, form):
277 member = User.objects.get(id=self.kwargs['pk'])
278 membership, created = Membership.objects.get_or_create(member=member, year=form.cleaned_data['year'])
279 membership.payment_date = form.cleaned_data['payment_date']
280 membership.payment_amount = form.cleaned_data['payment_amount']
281 membership.notes = form.cleaned_data['notes']
283 return super().form_valid(form)
285 def get_success_url(self):
286 return reverse_lazy('member-view', kwargs={'pk': self.kwargs['pk']})
289 register_membership = login_required(RegisterMembershipView.as_view())
292 class GroupsList(ListView):
294 template_name = 'aa/groups_list.html'
296 def dispatch(self, request, *args, **kwargs):
297 if not self.request.user.has_perm('aa.add_user'):
298 raise PermissionDenied()
299 return super().dispatch(request, *args, **kwargs)
301 def get_queryset(self):
302 return Group.objects.order_by('name')
305 groups_list = login_required(GroupsList.as_view())
308 class GroupCreateView(CreateView):
311 template_name = 'aa/group_new.html'
312 success_url = reverse_lazy('groups-list')
314 def get_object(self):
315 if not self.request.user.has_perm('aa.add_user'):
316 raise PermissionDenied()
317 return super().get_object()
320 group_new = login_required(GroupCreateView.as_view())
323 class GroupDetailView(DetailView):
325 template_name = 'aa/group_detail.html'
327 def get_object(self):
328 if not self.request.user.has_perm('aa.add_user'):
329 raise PermissionDenied()
330 return super().get_object()
332 def get_context_data(self, **kwargs):
333 context = super().get_context_data(**kwargs)
334 group = self.get_object()
336 f'{x.content_type.app_label}.{x.codename}' for x in group.permissions.all().select_related()
339 {'code': x[0], 'label': x[1], 'enabled': x[0] in has_perms} for x in RELEVANT_PERMISSIONS
344 group_view = login_required(GroupDetailView.as_view())
347 class GroupUpdatePerms(View):
348 def post(self, request, *args, **kwargs):
349 if not request.user.has_perm('aa.add_user'):
350 raise PermissionDenied()
351 group = Group.objects.get(**kwargs)
352 set_permissions = set()
353 unset_permissions = set()
354 for perm in RELEVANT_PERMISSIONS:
355 app_label, codename = perm[0].split('.')
356 perm_obj = Permission.objects.filter(content_type__app_label=app_label, codename=codename).first()
359 if perm[0] in request.POST.getlist('perms'):
360 group.permissions.add(perm_obj)
362 group.permissions.remove(perm_obj)
363 return HttpResponseRedirect(reverse_lazy('groups-list'))
366 group_update_perms = login_required(require_POST(GroupUpdatePerms.as_view()))
369 class GroupDeleteView(DeleteView):
371 template_name = 'aa/group_confirm_delete.html'
372 success_url = reverse_lazy('groups-list')
374 def get_object(self):
375 if not self.request.user.has_perm('aa.add_user'):
376 raise PermissionDenied()
377 return super().get_object()
380 group_delete = login_required(GroupDeleteView.as_view())