351 lines
14 KiB
Python
351 lines
14 KiB
Python
from __future__ import print_function
|
|
import urllib.parse
|
|
|
|
from django.shortcuts import redirect
|
|
from django.views.generic.edit import UpdateView, FormView
|
|
from django.views.generic.base import TemplateResponseMixin, View
|
|
from django.contrib import messages
|
|
from django.contrib.auth.models import User
|
|
from django.core.exceptions import ImproperlyConfigured
|
|
from django.utils.translation import ugettext as _
|
|
from django.http import HttpResponseRedirect
|
|
from django.db.transaction import atomic
|
|
|
|
from django_journal.models import Journal
|
|
import requests
|
|
|
|
|
|
from docbow_project.docbow import models
|
|
from docbow_project.docbow import forms
|
|
from docbow_project.docbow import cbv
|
|
from docbow_project.docbow import utils
|
|
from docbow_project.docbow import app_settings
|
|
|
|
|
|
class ProfileView(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-validate' in self.request.POST
|
|
|
|
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.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 = (
|
|
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]
|
|
kwargs['request'] = self.request
|
|
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:
|
|
|
|
if 'mellon' in app_settings.settings.INSTALLED_APPS and delegate_user.saml_identifiers.count():
|
|
err, json_data, err_desc = utils.a2_wscall(
|
|
urllib.parse.urljoin(
|
|
app_settings.settings.AUTHENTIC_URL,
|
|
'api/users/%s' % delegate_user.saml_identifiers.first().name_id,
|
|
),
|
|
'delete',
|
|
)
|
|
|
|
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
|
|
|
|
@atomic
|
|
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,
|
|
accept_notifications=app_settings.DEFAULT_ACCEPT_NOTIFICATIONS_FOR_GUEST,
|
|
)
|
|
delegation, created = models.Delegation.objects.get_or_create(by=request.user, to=delegate_user)
|
|
if 'mellon' in app_settings.settings.INSTALLED_APPS:
|
|
import mellon
|
|
|
|
ctx['sso'] = True
|
|
issuer = mellon.models.Issuer.objects.filter(
|
|
entity_id__startswith=app_settings.settings.AUTHENTIC_URL
|
|
).first()
|
|
if not issuer:
|
|
raise ImproperlyConfigured('Mellon issuer not found')
|
|
|
|
mellon.models.UserSAMLIdentifier.objects.create(
|
|
name_id=form.cleaned_data['name_id'],
|
|
issuer=issuer,
|
|
user=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()
|
|
ctx['delegate_to_existing_user'] = app_settings.DELEGATE_TO_EXISTING_USER
|
|
return ctx
|
|
|
|
|
|
class PasswordChangeView(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'))
|
|
form.save()
|
|
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 EmailView(cbv.FormWithPostTarget, UpdateView):
|
|
form_class = forms.EmailForm
|
|
template_name = 'docbow/email.html'
|
|
prefix = 'email'
|
|
success_url = '#email'
|
|
|
|
def get_object(self):
|
|
return self.request.user
|
|
|
|
def form_valid(self, form):
|
|
messages.info(self.request, _('Email changed'))
|
|
self.request.record('update-email', 'modified its email', **form.cleaned_data)
|
|
return super(EmailView, self).form_valid(form)
|
|
|
|
|
|
class NotificationPreferenceView(cbv.FormWithPostTarget, cbv.FormWithRequestMixin, FormView):
|
|
form_class = forms.NotificationPreferencesForm
|
|
template_name = 'docbow/notifications.html'
|
|
success_url = '#notifications'
|
|
prefix = 'notifications'
|
|
|
|
def form_valid(self, form):
|
|
form.save()
|
|
messages.info(self.request, _('Notification preferences saved'))
|
|
return super(NotificationPreferenceView, self).form_valid(form)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super(NotificationPreferenceView, self).get_context_data(**kwargs)
|
|
ctx['mobile_phone'] = app_settings.MOBILE_PHONE
|
|
ctx['mobile_phone_paragraph'] = _(
|
|
u'If You would like to receive a SMS alert each '
|
|
u'time your inbox receives a document, provide your '
|
|
u'mobile phone number. If you do not fill this field '
|
|
u'you won\'t receive any SMS alert'
|
|
)
|
|
return ctx
|
|
|
|
|
|
class FullProfileView(TemplateResponseMixin, View):
|
|
# multiplex all profile views
|
|
template_name = 'docbow/full-profile.html'
|
|
subviews = (
|
|
('notifications_form', NotificationPreferenceView),
|
|
('delegate_form', DelegateView),
|
|
)
|
|
if 'mellon' not in app_settings.settings.INSTALLED_APPS:
|
|
subviews = subviews + (('password_change_form', PasswordChangeView),)
|
|
if app_settings.MOBILE_PHONE or app_settings.PERSONAL_EMAIL:
|
|
subviews = (('profile_form', ProfileView),) + subviews
|
|
if app_settings.EDIT_EMAIL and 'mellon' not in app_settings.settings.INSTALLED_APPS:
|
|
subviews += (('email_form', EmailView),)
|
|
|
|
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)
|