Allow updating mailbox addresses

This commit is contained in:
Santiago L 2021-10-07 13:51:31 +02:00
parent a0808896b4
commit ddd8ecf634
7 changed files with 76 additions and 13 deletions

View file

@ -1,5 +1,4 @@
import urllib.parse
from itertools import groupby
import requests
from django.conf import settings
@ -178,6 +177,12 @@ class Orchestra(object):
raise Http404(_("No mailbox found matching the query"))
return Mailbox.new_from_json(data_json)
def update_mailbox(self, pk, data):
path = API_PATHS.get('mailbox-detail').format_map({'pk': pk})
url = urllib.parse.urljoin(self.base_url, path)
status, response = self.request("PATCH", url=url, data=data, raise_exception=False)
return status, response
def retrieve_mailbox_list(self):
mailboxes = self.retrieve_service_list(Mailbox.api_name)
return [Mailbox.new_from_json(mailbox_data) for mailbox_data in mailboxes]

View file

@ -94,3 +94,23 @@ class MailboxCreateForm(forms.Form):
"password": self.cleaned_data["password2"],
}
return serialized_data
class MailboxUpdateForm(forms.Form):
addresses = forms.MultipleChoiceField(required=False)
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop('instance', None)
if self.instance is not None:
kwargs['initial'] = self.instance.deserialize()
addresses = kwargs.pop('addresses')
super().__init__(*args, **kwargs)
self.fields['addresses'].choices = [(addr.url, addr.full_address_name) for addr in addresses]
def serialize(self):
assert self.is_valid()
serialized_data = {
"addresses": self.cleaned_data["addresses"],
}
return serialized_data

View file

@ -241,6 +241,7 @@ class Address(OrchestraModel):
"domain": None,
"mailboxes": [],
"forward": None,
'url': None,
}
FORWARD = 'forward'
@ -324,6 +325,12 @@ class Mailbox(OrchestraModel):
addresses = [Address.new_from_json(addr) for addr in data.get('addresses', [])]
return super().new_from_json(data=data, addresses=addresses)
def deserialize(self):
data = {
'addresses': [addr.url for addr in self.addresses],
}
return data
class MailinglistService(OrchestraModel):
api_name = 'mailinglist'

View file

@ -21,7 +21,7 @@
<button type="submit" class="btn btn-secondary">{% trans "Save" %}</button>
{% if form.instance %}
<div class="float-right">
<a class="btn btn-danger" href="{# TODO url 'musician:mailbox-delete' view.kwargs.pk #}">{% trans "Delete" %}</a>
<a class="btn btn-danger" href="{% url 'musician:mailbox-delete' view.kwargs.pk %}">{% trans "Delete" %}</a>
</div>
{% endif %}
{% endbuttons %}

View file

@ -5,17 +5,15 @@
<div class="tab-pane fade show active" id="mailboxes" role="tabpanel" aria-labelledby="mailboxes-tab">
<table class="table service-list">
<colgroup>
<col span="1" style="width: 20%;">
<col span="1" style="width: 10%;">
<col span="1" style="width: 60%;">
<col span="1" style="width: 25%;">
<col span="1" style="width: 10%;">
<col span="1" style="width: 65%;">
</colgroup>
<thead class="thead-dark">
<tr>
<th scope="col">{% trans "Name" %}</th>
<th scope="col">{% trans "Filtering" %}</th>
<th scope="col">{% trans "Addresses" %}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@ -23,19 +21,15 @@
{# <!-- Exclude (don't render) inactive mailboxes -->#}
{% if mailbox.is_active %}
<tr>
<td>{{ mailbox.name }}</td>
<td><a href="{% url 'musician:mailbox-update' mailbox.id %}">{{ mailbox.name }}</a></td>
<td>{{ mailbox.filtering }}</td>
<td>
{% for addr in mailbox.addresses %}
<a href="{% url 'musician:address-update' addr.data.id %}">
{{ addr.data.name }}@{{ addr.data.domain.name }}
{{ addr.full_address_name }}
</a><br/>
{% endfor %}
</td>
<td>
<a class="btn btn-outline-danger" href="{% url 'musician:mailbox-delete' mailbox.id %}" title="{% trans 'Delete' %}"><i class="fas fa-trash"></i></a>
</td>
</tr>
{% endif %}{# <!-- /is_active --> #}
{% endfor %}

View file

@ -25,6 +25,7 @@ urlpatterns = [
path('address/<int:pk>/delete/', views.AddressDeleteView.as_view(), name='address-delete'),
path('mailboxes/', views.MailboxesView.as_view(), name='mailbox-list'),
path('mailboxes/new/', views.MailboxCreateView.as_view(), name='mailbox-create'),
path('mailboxes/<int:pk>/', views.MailboxUpdateView.as_view(), name='mailbox-update'),
path('mailboxes/<int:pk>/delete/', views.MailboxDeleteView.as_view(), name='mailbox-delete'),
path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'),
path('databases/', views.DatabasesView.as_view(), name='database-list'),

View file

@ -18,7 +18,7 @@ from requests.exceptions import HTTPError
from . import api, get_version
from .auth import login as auth_login
from .auth import logout as auth_logout
from .forms import LoginForm, MailForm, MailboxCreateForm
from .forms import LoginForm, MailForm, MailboxCreateForm, MailboxUpdateForm
from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
UserTokenRequiredMixin)
from .models import (Address, Bill, DatabaseService, Mailbox, MailinglistService,
@ -356,6 +356,42 @@ class MailboxCreateView(CustomContextMixin, UserTokenRequiredMixin, FormView):
return super().form_valid(form)
class MailboxUpdateView(CustomContextMixin, UserTokenRequiredMixin, FormView):
service_class = Mailbox
template_name = "musician/mailbox_form.html"
form_class = MailboxUpdateForm
success_url = reverse_lazy("musician:mailbox-list")
extra_context = {'service': service_class}
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
instance = self.orchestra.retrieve_mailbox(self.kwargs['pk'])
kwargs.update({
'instance': instance,
'addresses': self.orchestra.retrieve_mail_address_list(),
})
return kwargs
def form_valid(self, form):
serialized_data = form.serialize()
status, response = self.orchestra.update_mailbox(self.kwargs['pk'], serialized_data)
if status >= 400:
if status == 400:
# handle errors & add to form (they will be rendered)
form.add_error(field=None, error=response)
else:
logger.error("{}: {}".format(status, response[:120]))
msg = "Sorry, an error occurred while processing your request ({})".format(status)
form.add_error(field='__all__', error=msg)
return self.form_invalid(form)
return super().form_valid(form)
class MailboxDeleteView(CustomContextMixin, UserTokenRequiredMixin, DeleteView):
template_name = "musician/mailbox_check_delete.html"
success_url = reverse_lazy("musician:mailbox-list")