from django.shortcuts import redirect from django.views.generic.edit import UpdateView, FormView from django.views.generic.base import TemplateResponseMixin, View from django.core.urlresolvers import reverse from django.contrib import messages from django.contrib.auth.models import User from django.utils.translation import ugettext as _ from django.http import HttpResponseRedirect import django_journal from . import models from . import forms from . import cbv from . import utils class ProfileView(cbv.FormWithPrefixMixin, cbv.FormWithRequestMixin, cbv.FormWithPostTarget, UpdateView): form_class = forms.ProfileForm template_name = 'docbow/profile.html' prefix = 'profile' success_url = '#profile' def get_object(self): try: return models.DocbowProfile.objects.get(user=self.request.user) except models.DocbowProfile.DoesNotExist: return None def is_post_target(self): return 'profile-clear_mobile_phone' in self.request.POST or \ 'profile-validate' in self.request.POST def post(self, request, *args, **kwargs): self.object = self.get_object() if 'profile-clear_mobile_phone' in self.request.POST: if self.object: self.object.mobile_phone = '' self.object.save() return redirect('profile') return super(ProfileView, self).post(request, *args, **kwargs) def form_valid(self, form): self.request.record('update-profile', 'modified its profile', **form.cleaned_data) return super(ProfileView, self).form_valid(form) class DelegateView(cbv.FormWithPrefixMixin, cbv.FormWithPostTarget, FormView): form_class = forms.DelegationForm template_name = 'docbow/delegate.html' success_url = '#delegate' prefix = 'delegate' def __init__(self, *args, **kwargs): super(DelegateView, self).__init__(*args, **kwargs) def add_journal_to_delegations(self, delegations): delegations__to = [ delegation.to for delegation in delegations ] journals = django_journal.Journal.objects \ .for_objects(delegations__to) \ .filter(tag__name='login') \ .order_by('-time')[:len(delegations__to)*5] journal_by_users = dict() for journal in journals: for objectdata in journal.objectdata_set.all(): if objectdata.tag.name == 'delegate': journal_by_users.setdefault(objectdata.object_id, []) \ .append(journal.time) for delegation in delegations: delegation.journals = journal_by_users.get(delegation.to.id, [])[:5] @property def delegations(self): qs = models.Delegation.objects.all() qs = qs.filter(by=self.request.user) qs = qs.select_related() qs = qs.prefetch_related('to__docbowprofile') self.add_journal_to_delegations(qs) return qs def get_form_kwargs(self, **kwargs): kwargs = super(DelegateView, self).get_form_kwargs(**kwargs) kwargs['user'] = self.request.user kwargs['delegatees'] = [ delegation.to for delegation in self.delegations ] return kwargs def delete(self, delegation): request = self.request delegation.delete() delegate_user = delegation.to request.record('delete-delegation', 'deleted delegation ' '{delegation} to user {delegated}', delegation=delegation.id, delegated=delegate_user) user = request.user # notify delegate ctx = { 'user': utils.clean_ldap_user(user), 'delegate': delegate_user, 'to': [delegate_user.email], 'reply_to': user.email, } models.Notification.objects.create(kind='delete-delegation', ctx=ctx) messages.info(request, _('Delegation %s supressed') % delegate_user) messages.info(request, _('%s has been notified.') % delegate_user.email) request.record('notify', 'notified {email} of ' 'the deletion of its delegate user', email=delegate_user.email) # delete guest accounts if delegation.guest_delegate: delegate_user.delete() request.record('delete-delegate', 'deleted delegate ' 'user {username}, {first_name} {last_name}, ' '({email})', username=delegate_user.username, first_name=delegate_user.first_name, last_name=delegate_user.last_name, email=delegate_user.email) return HttpResponseRedirect(self.success_url) def is_post_target(self): if 'delegate-create' in self.request.POST: return True for delegation in self.delegations: username = delegation.to.username if 'delegate-delete-{username}.x'.format(username=username) in \ self.request.POST: return True return False def post(self, request, *args, **kwargs): if 'delegate-create' in request.POST: return super(DelegateView, self).post(request, *args, **kwargs) for delegation in self.delegations: username = delegation.to.username if 'delegate-delete-{username}.x'.format(username=username) in \ self.request.POST: return self.delete(delegation) return self.get(request, *args, **kwargs) def form_valid(self, form): request = self.request is_guest = not form.cleaned_data.get('existing_user') ctx = { 'user': utils.clean_ldap_user(request.user), 'reply_to' :request.user.email, 'is_guest': is_guest, } if is_guest: delegate_username = utils.get_free_delegation_number(request.user) delegate_user = User(username=delegate_username, first_name=form.cleaned_data.get('first_name', ''), last_name=form.cleaned_data.get('last_name', ''), email=form.cleaned_data.get('email', '')) delegate_user.set_unusable_password() delegate_user.save() models.DocbowProfile.objects.create(user=delegate_user, is_guest=True) delegation, created = models.Delegation.objects.get_or_create(by=request.user, to=delegate_user) request.record('create-delegate', 'created delegate with ' 'parameters {first_name} {last_name} <{email}>', **form.cleaned_data) ctx.update({ 'password_reset_link': utils.make_password_reset_url(request, delegate_user), 'to': [form.cleaned_data['email']], 'delegate': delegate_user, 'delegation': delegation, }) messages.info(request, _('New delegation to user %s created.') % delegate_user.username) messages.info(request, _('A notification was sent to %s about this new delegation') % delegate_user.email) else: delegate_user = form.cleaned_data.get('existing_user') delegate_username = delegate_user.username delegation, created = models.Delegation.objects.get_or_create(by=request.user, to=delegate_user) ctx.update({ 'to': models.all_emails(delegate_user), 'delegate': delegate_user, 'delegation': delegation, }) messages.info(request, _('New delegation to user %s created.') % delegate_user.username) messages.info(request, _('A notification was sent to %s about this new delegation') % delegate_user.get_full_name()) models.Notification.objects.create(kind='new-delegation', ctx=ctx) request.record('create-delegation', 'created delegation to ' 'user {delegated}', delegated=delegate_user) return super(DelegateView, self).form_valid(form) def get_context_data(self, **kwargs): ctx = super(DelegateView, self).get_context_data(**kwargs) ctx['delegations'] = self.delegations ctx['received_delegations'] = self.request.user.delegations_by.all() return ctx class PasswordChangeView(cbv.FormWithPrefixMixin, cbv.FormWithPostTarget, FormView): template_name = 'registration/password_change_form.html' form_class = forms.PasswordChangeFormWithLogging prefix = 'password-change' success_url = '#password-change' def is_post_target(self): return 'password-change-validate' in self.request.POST def form_valid(self, form): messages.info(self.request, _('Password changed')) return super(PasswordChangeView, self).form_valid(form) def get_form_kwargs(self, **kwargs): kwargs = super(PasswordChangeView, self).get_form_kwargs(**kwargs) kwargs['user'] = self.request.user return kwargs class FullProfileView(TemplateResponseMixin, View): # multiplex all profile views template_name = 'docbow/full-profile.html' subviews = ( ('profile_form', ProfileView), ('delegate_form', DelegateView), ('password_change_form', PasswordChangeView), ) def dispatch(self, request, *args, **kwargs): if models.is_guest(request.user): self.subviews = filter(lambda s: s[0] != 'delegate_form', self.subviews) print self.subviews return super(FullProfileView, self).dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): ctx = {} for var_name, view_class in self.subviews: res = self.get_view(var_name, view_class) if isinstance(res, dict): ctx.update(res) else: return res return self.render_to_response(ctx) def get_view(self, var_name, view_class): view = view_class() view.request, view.args, view.kwargs = \ self.request, self.args, self.kwargs if hasattr(view, 'get_object'): view.object = view.get_object() if self.request.method == 'POST' and view.is_post_target(): res = view.post(self.request, *self.args, **self.kwargs) if isinstance(res, HttpResponseRedirect): return res else: ctx = res.context_data ctx[var_name] = ctx.pop('form') return ctx else: form_class = view.get_form_class() form = view.get_form(form_class) return view.get_context_data(**{var_name: form}) def get(self, request, *args, **kwargs): ctx = {} for var_name, view_class in self.subviews: ctx.update(self.get_view(var_name, view_class)) return self.render_to_response(ctx)