implement password change for mailboxes

- implement managemails.forms.ChangeMailboxPasswordForm
- extract code for determining hosting package and customer from URL into
  HostingPackageAndCustomerMixin
- implement managemails.views.ChangeMailboxPassword
- add new URL pattern 'change_mailbox_password' to managemails.urls
- add template managemails/mailbox_setpassword.html
- link from template hostingpackages/customerhostingpackage_detail.html to
  change_mailbox_password
- add german translation for new strings
- document new feature in changelog
This commit is contained in:
Jan Dittberner 2015-01-25 12:49:31 +01:00
parent d1119331d8
commit 2e4efe7839
8 changed files with 178 additions and 21 deletions

View file

@ -1,6 +1,7 @@
Changelog Changelog
========= =========
* :feature:`-` implement password change functionality for mailboxes
* :feature:`-` implement creation of new mailboxes for hosting packages * :feature:`-` implement creation of new mailboxes for hosting packages
* :support:`-` move common form code to new module gvawebcore.forms * :support:`-` move common form code to new module gvawebcore.forms
* :feature:`-` make it possible to assign domains to a customer * :feature:`-` make it possible to assign domains to a customer

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnuviechadmin\n" "Project-Id-Version: gnuviechadmin\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-01-25 12:04+0100\n" "POT-Creation-Date: 2015-01-25 12:46+0100\n"
"PO-Revision-Date: 2015-01-25 12:06+0100\n" "PO-Revision-Date: 2015-01-25 12:49+0100\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -814,6 +814,26 @@ msgstr "Bitte geben Sie das Passwort für Ihr neues Postfach ein."
msgid "Please specify the password for the new mailbox." msgid "Please specify the password for the new mailbox."
msgstr "Bitte geben Sie das Passwort für das neue Postfach ein." msgstr "Bitte geben Sie das Passwort für das neue Postfach ein."
#: templates/managemails/mailbox_setpassword.html:6
#: templates/managemails/mailbox_setpassword.html:15
#, python-format
msgid "Set Password for Mailbox %(mailbox)s"
msgstr "Passwort für Postfach %(mailbox)s setzen"
#: templates/managemails/mailbox_setpassword.html:8
#: templates/managemails/mailbox_setpassword.html:17
#, python-format
msgid "Set Password for Mailbox %(mailbox)s of Customer %(full_name)s"
msgstr "Passwort für Postfach %(mailbox)s des Kunden %(full_name)s setzen"
#: templates/managemails/mailbox_setpassword.html:23
msgid "Please specify the new password for your mailbox."
msgstr "Bitte geben Sie das neue Passwort für Ihr Postfach ein."
#: templates/managemails/mailbox_setpassword.html:23
msgid "Please specify the new password for the mailbox."
msgstr "Bitte geben Sie das neue Passwort für das Postfach ein."
#: templates/osusers/user_setpassword.html:5 #: templates/osusers/user_setpassword.html:5
#: templates/osusers/user_setpassword.html:13 #: templates/osusers/user_setpassword.html:13
#, python-format #, python-format

View file

@ -46,3 +46,36 @@ class CreateMailboxForm(PasswordModelFormMixin, forms.ModelForm):
self.instance.username = Mailbox.objects.get_next_mailbox_name(osuser) self.instance.username = Mailbox.objects.get_next_mailbox_name(osuser)
self.instance.set_password(self.cleaned_data['password1']) self.instance.set_password(self.cleaned_data['password1'])
return super(CreateMailboxForm, self).save(commit=commit) return super(CreateMailboxForm, self).save(commit=commit)
class ChangeMailboxPasswordForm(PasswordModelFormMixin, forms.ModelForm):
"""
This form is used to set a new password for an existing mailbox.
"""
class Meta:
model = Mailbox
fields = []
def __init__(self, *args, **kwargs):
self.hosting_package = kwargs.pop('hostingpackage')
super(ChangeMailboxPasswordForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_action = reverse(
'change_mailbox_password', kwargs={
'package': self.hosting_package.id,
'slug': self.instance.username,
})
self.helper.add_input(Submit('submit', _('Set password')))
def save(self, commit=True):
"""
Set the mailbox password.
:param boolean commit: whether to save the mailbox instance
:return: mailbox instance
:rtype: :py:class:`managemails.models.Mailbox`
"""
self.instance.set_password(self.cleaned_data['password1'])
return super(ChangeMailboxPasswordForm, self).save(commit=commit)

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: managemails\n" "Project-Id-Version: managemails\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-01-25 12:04+0100\n" "POT-Creation-Date: 2015-01-25 12:46+0100\n"
"PO-Revision-Date: 2015-01-25 12:07+0100\n" "PO-Revision-Date: 2015-01-25 12:47+0100\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -51,6 +51,10 @@ msgstr "Postfächer und E-Mailadressen"
msgid "Create mailbox" msgid "Create mailbox"
msgstr "Postfach anlegen" msgstr "Postfach anlegen"
#: managemails/forms.py:69
msgid "Set password"
msgstr "Passwort setzen"
#: managemails/models.py:79 #: managemails/models.py:79
msgid "Mailbox" msgid "Mailbox"
msgstr "Postfach" msgstr "Postfach"
@ -75,11 +79,17 @@ msgstr "E-Mailadresse"
msgid "mailbox" msgid "mailbox"
msgstr "Postfach" msgstr "Postfach"
#: managemails/views.py:35 #: managemails/views.py:63
msgid "You are not allowed to add more mailboxes to this hosting package" msgid "You are not allowed to add more mailboxes to this hosting package"
msgstr "Sie können keine weiteren Postfächer zu diesem Hostingpaket hinzufügen" msgstr "Sie können keine weiteren Postfächer zu diesem Hostingpaket hinzufügen"
#: managemails/views.py:61 #: managemails/views.py:82
#, python-brace-format #, python-brace-format
msgid "Mailbox {mailbox} created successfully." msgid "Mailbox {mailbox} created successfully."
msgstr "Postfach {mailbox} erfolgreich angelegt." msgstr "Postfach {mailbox} erfolgreich angelegt."
#: managemails/views.py:117
#, python-brace-format
msgid "Successfully set new password for mailbox {mailbox}."
msgstr ""
"Für das Postfach {mailbox} wurde erfolgreich ein neues Passwort gesetzt."

View file

@ -8,6 +8,7 @@ from __future__ import absolute_import, unicode_literals
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from .views import ( from .views import (
ChangeMailboxPassword,
CreateMailbox, CreateMailbox,
) )
@ -15,4 +16,6 @@ urlpatterns = patterns(
'', '',
url(r'^(?P<package>\d+)/mailbox/create$', url(r'^(?P<package>\d+)/mailbox/create$',
CreateMailbox.as_view(), name='create_mailbox'), CreateMailbox.as_view(), name='create_mailbox'),
url(r'^(?P<package>\d+)/mailbox/(?P<slug>[\w0-9]+)/setpassword$',
ChangeMailboxPassword.as_view(), name='change_mailbox_password'),
) )

View file

@ -7,18 +7,46 @@ from __future__ import absolute_import, unicode_literals
from django.http import HttpResponseForbidden from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic.edit import CreateView from django.views.generic.edit import (
CreateView,
UpdateView,
)
from django.contrib import messages from django.contrib import messages
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
from hostingpackages.models import CustomerHostingPackage from hostingpackages.models import CustomerHostingPackage
from .forms import CreateMailboxForm from .forms import (
CreateMailboxForm,
ChangeMailboxPasswordForm,
)
from .models import Mailbox from .models import Mailbox
class CreateMailbox(StaffOrSelfLoginRequiredMixin, CreateView):
class HostingPackageAndCustomerMixin(object):
"""
Mixin for views that gets the hosting package instance from the URL
keyword argument 'package'.
"""
hosting_package_kwarg = 'package'
"""Keyword argument used to find the hosting package in the URL."""
def get_hosting_package(self):
return get_object_or_404(
CustomerHostingPackage,
pk=int(self.kwargs[self.hosting_package_kwarg]))
def get_customer_object(self):
return self.get_hosting_package().customer
class CreateMailbox(
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, CreateView
):
""" """
This view is used to setup new mailboxes for a customer hosting package. This view is used to setup new mailboxes for a customer hosting package.
@ -30,28 +58,21 @@ class CreateMailbox(StaffOrSelfLoginRequiredMixin, CreateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
resp = super(CreateMailbox, self).dispatch(request, *args, **kwargs) resp = super(CreateMailbox, self).dispatch(request, *args, **kwargs)
if not self._get_hosting_package().may_add_mailbox(): if not self.get_hosting_package().may_add_mailbox():
resp = HttpResponseForbidden( resp = HttpResponseForbidden(
_('You are not allowed to add more mailboxes to this' _('You are not allowed to add more mailboxes to this'
' hosting package')) ' hosting package'))
return resp return resp
def _get_hosting_package(self):
return get_object_or_404(
CustomerHostingPackage, pk=int(self.kwargs['package']))
def get_customer_object(self):
return self._get_hosting_package().customer
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(CreateMailbox, self).get_context_data(**kwargs) context = super(CreateMailbox, self).get_context_data(**kwargs)
context['hostingpackage'] = self._get_hosting_package() context['hostingpackage'] = self.get_hosting_package()
context['customer'] = self.get_customer_object() context['customer'] = self.get_customer_object()
return context return context
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(CreateMailbox, self).get_form_kwargs() kwargs = super(CreateMailbox, self).get_form_kwargs()
kwargs['hostingpackage'] = self._get_hosting_package() kwargs['hostingpackage'] = self.get_hosting_package()
return kwargs return kwargs
def form_valid(self, form): def form_valid(self, form):
@ -62,4 +83,39 @@ class CreateMailbox(StaffOrSelfLoginRequiredMixin, CreateView):
mailbox=mailbox.username mailbox=mailbox.username
) )
) )
return redirect(self._get_hosting_package().get_absolute_url()) return redirect(self.get_hosting_package())
class ChangeMailboxPassword(
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, UpdateView
):
"""
This view is used to set a new password for an existing mailbox.
"""
context_object_name = 'mailbox'
form_class = ChangeMailboxPasswordForm
model = Mailbox
slug_field = 'username'
template_name_suffix = '_setpassword'
def get_context_data(self, **kwargs):
context = super(ChangeMailboxPassword, self).get_context_data(**kwargs)
context['hostingpackage'] = self.get_hosting_package()
context['customer'] = self.get_customer_object()
return context
def get_form_kwargs(self):
kwargs = super(ChangeMailboxPassword, self).get_form_kwargs()
kwargs['hostingpackage'] = self.get_hosting_package()
return kwargs
def form_valid(self, form):
mailbox = form.save()
messages.success(
self.request,
_('Successfully set new password for mailbox {mailbox}.').format(
mailbox=mailbox.username
)
)
return redirect(self.get_hosting_package())

View file

@ -131,7 +131,7 @@
<td>{{ mailbox.mailaddresses|join:", " }}</td> <td>{{ mailbox.mailaddresses|join:", " }}</td>
<td><i class="glyphicon glyphicon-{% if mailbox.active %}ok-circle{% else %}minus-sign{% endif %}"></i><span class="sr-only"> {% if mailbox.active %}{% trans "Active" %}{% else %}{% trans "inactive" %}{% endif %}</span></td> <td><i class="glyphicon glyphicon-{% if mailbox.active %}ok-circle{% else %}minus-sign{% endif %}"></i><span class="sr-only"> {% if mailbox.active %}{% trans "Active" %}{% else %}{% trans "inactive" %}{% endif %}</span></td>
<td> <td>
<a href="#"><i class="fa fa-user-secret" title="{% trans "Set mailbox password" %}"></i><span class="sr-only"> {% trans "Set mailbox password" %}</span></a> <a href="{% url 'change_mailbox_password' package=hostingpackage.id slug=mailbox.username %}"><i class="fa fa-user-secret" title="{% trans "Set mailbox password" %}"></i><span class="sr-only"> {% trans "Set mailbox password" %}</span></a>
</td> </td>
{% endfor %} {% endfor %}
</tbody> </tbody>

View file

@ -0,0 +1,34 @@
{% extends "managemails/base.html" %}
{% load i18n crispy_forms_tags %}
{% block title %}{{ block.user }} - {% spaceless %}
{% with full_name=customer.get_full_name mailbox=mailbox.username %}
{% if customer == user %}
{% blocktrans %}Set Password for Mailbox {{ mailbox }}{% endblocktrans %}
{% else %}
{% blocktrans %}Set Password for Mailbox {{ mailbox }} of Customer {{ full_name }}{% endblocktrans %}
{% endif %}
{% endwith %}
{% endspaceless %}{% endblock title %}
{% block page_title %}{% spaceless %}
{% with full_name=customer.get_full_name mailbox=mailbox.username %}
{% if customer == user %}
{% blocktrans %}Set Password for Mailbox {{ mailbox }}{% endblocktrans %}
{% else %}
{% blocktrans %}Set Password for Mailbox {{ mailbox }} of Customer {{ full_name }}{% endblocktrans %}
{% endif %}
{% endwith %}
{% endspaceless %}{% endblock page_title %}
{% block content %}
<p>{% if customer == user %}{% trans "Please specify the new password for your mailbox." %}{% else %}{% trans "Please specify the new password for the mailbox." %}{% endif %}</p>
{% crispy form %}
{% endblock content %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$('input[type=password]').val('');
$('input[type=password]').first().focus();
});
</script>
{% endblock extra_js %}