Allow updating mailbox addresses
This commit is contained in:
parent
a0808896b4
commit
ddd8ecf634
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in a new issue