From 7ff01d60ef75d8fe34987a0f9a996617060faa78 Mon Sep 17 00:00:00 2001 From: Santiago Lamora Date: Thu, 24 Jun 2021 13:08:16 +0200 Subject: [PATCH] (Draft) Add view to update existing addresses --- musician/api.py | 20 ++++++++++++---- musician/forms.py | 15 ++++++++++++ musician/models.py | 12 +++++++++- musician/templates/musician/mail.html | 2 +- musician/urls.py | 1 + musician/views.py | 33 ++++++++++++++++++++++++++- 6 files changed, 75 insertions(+), 8 deletions(-) diff --git a/musician/api.py b/musician/api.py index 4913a23..9a38e01 100644 --- a/musician/api.py +++ b/musician/api.py @@ -23,6 +23,7 @@ API_PATHS = { 'domain-list': 'domains/', 'domain-detail': 'domains/{pk}/', 'address-list': 'addresses/', + 'address-detail': 'addresses/{pk}/', 'mailbox-list': 'mailboxes/', 'mailinglist-list': 'lists/', 'saas-list': 'saas/', @@ -114,13 +115,22 @@ class Orchestra(object): def create_mail_address(self, data): resource = '{}-list'.format(MailService.api_name) - - # transform form data to expected format - data["domain"] = {"url": data["domain"]} - data["mailboxes"] = [{"url": mbox} for mbox in data["mailboxes"]] - return self.request("POST", resource=resource, data=data) + def retrieve_mail_address(self, pk): + path = API_PATHS.get('address-detail').format_map({'pk': pk}) + url = urllib.parse.urljoin(self.base_url, path) + status, data = self.request("GET", url=url, raise_exception=False) + if status == 404: + raise Http404(_("No object found matching the query")) + + return MailService.new_from_json(data) + + def update_mail_address(self, pk, data): + path = API_PATHS.get('address-detail').format_map({'pk': pk}) + url = urllib.parse.urljoin(self.base_url, path) + return self.request("PUT", url=url, data=data) + def retrieve_mail_address_list(self, querystring=None): def get_mailbox_id(value): mailboxes = value.get('mailboxes') diff --git a/musician/forms.py b/musician/forms.py index bbfd2de..1302fb2 100644 --- a/musician/forms.py +++ b/musician/forms.py @@ -31,8 +31,13 @@ class MailForm(forms.Form): forward = forms.EmailField(required=False) def __init__(self, *args, **kwargs): + instance = kwargs.pop('instance', None) + if instance is not None: + kwargs['initial'] = instance.deserialize() + domains = kwargs.pop('domains') mailboxes = kwargs.pop('mailboxes') + super().__init__(*args, **kwargs) self.fields['domain'].choices = [(d.url, d.name) for d in domains] self.fields['mailboxes'].choices = [(m['url'], m['name']) for m in mailboxes] @@ -42,3 +47,13 @@ class MailForm(forms.Form): if not cleaned_data.get('mailboxes') and not cleaned_data.get('forward'): raise ValidationError("A mailbox or forward address should be provided.") return cleaned_data + + def serialize(self): + assert hasattr(self, 'cleaned_data') + serialized_data = { + "name": self.cleaned_data["name"], + "domain": {"url": self.cleaned_data["domain"]}, + "mailboxes": [{"url": mbox} for mbox in self.cleaned_data["mailboxes"]], + "forward": self.cleaned_data["forward"], + } + return serialized_data diff --git a/musician/models.py b/musician/models.py index 978a0c8..7ac681f 100644 --- a/musician/models.py +++ b/musician/models.py @@ -225,12 +225,13 @@ class DomainRecord(OrchestraModel): return '<%s: %s>' % (self.type, self.value) +# TODO(@slamora) rename to Address class MailService(OrchestraModel): api_name = 'address' verbose_name = _('Mail addresses') description = _('Description details for mail addresses page.') fields = ('mail_address', 'aliases', 'type', 'type_detail') - param_defaults = {} + param_defaults = {"id": None,} FORWARD = 'forward' MAILBOX = 'mailbox' @@ -239,6 +240,15 @@ class MailService(OrchestraModel): self.data = kwargs super().__init__(**kwargs) + def deserialize(self): + data = { + 'name': self.data['name'], + 'domain': self.data['domain']['url'], + 'mailboxes': [mbox['url'] for mbox in self.data['mailboxes']], + 'forward': self.data['forward'], + } + return data + @property def aliases(self): return [ diff --git a/musician/templates/musician/mail.html b/musician/templates/musician/mail.html index f1fcf14..38f0fe3 100644 --- a/musician/templates/musician/mail.html +++ b/musician/templates/musician/mail.html @@ -26,7 +26,7 @@ {% for obj in object_list %} - {{ obj.mail_address }} + {{ obj.mail_address }} {{ obj.aliases|join:" , " }} {{ obj.type|capfirst }} diff --git a/musician/urls.py b/musician/urls.py index f1f3c40..ae2676b 100644 --- a/musician/urls.py +++ b/musician/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ path('profile/', views.ProfileView.as_view(), name='profile'), path('mails/', views.MailView.as_view(), name='mails'), path('mails/new/', views.MailCreateView.as_view(), name='mail-create'), + path('mails//', views.MailUpdateView.as_view(), name='mail-update'), path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'), path('databases/', views.DatabasesView.as_view(), name='databases'), path('software-as-a-service/', views.SaasView.as_view(), name='saas'), diff --git a/musician/views.py b/musician/views.py index b039b26..387c4e6 100644 --- a/musician/views.py +++ b/musician/views.py @@ -217,7 +217,38 @@ class MailCreateView(CustomContextMixin, UserTokenRequiredMixin, FormView): def form_valid(self, form): # handle request errors e.g. 400 validation try: - self.orchestra.create_mail_address(form.cleaned_data) + serialized_data = form.serialize() + self.orchestra.create_mail_address(serialized_data) + except HTTPError as e: + form.add_error(field='__all__', error=e) + return self.form_invalid(form) + + return super().form_valid(form) + + +class MailUpdateView(CustomContextMixin, UserTokenRequiredMixin, FormView): + service_class = MailService + template_name = "musician/mail_form.html" + form_class = MailForm + success_url = reverse_lazy("musician:mails") + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + instance = self.orchestra.retrieve_mail_address(self.kwargs['pk']) + + kwargs.update({ + 'instance': instance, + 'domains': self.orchestra.retrieve_domain_list(), + 'mailboxes': self.orchestra.retrieve_mailbox_list(), + }) + + return kwargs + + def form_valid(self, form): + # handle request errors e.g. 400 validation + try: + serialized_data = form.serialize() + self.orchestra.update_mail_address(self.kwargs['pk'], serialized_data) except HTTPError as e: form.add_error(field='__all__', error=e) return self.form_invalid(form)