(Draft) Add view to create addresses
This commit is contained in:
parent
30bb572589
commit
f635721831
|
@ -62,7 +62,7 @@ class Orchestra(object):
|
||||||
|
|
||||||
return response.json().get("token", None)
|
return response.json().get("token", None)
|
||||||
|
|
||||||
def request(self, verb, resource=None, url=None, render_as="json", querystring=None, raise_exception=True):
|
def request(self, verb, resource=None, url=None, data=None, render_as="json", querystring=None, raise_exception=True):
|
||||||
assert verb in ["HEAD", "GET", "POST", "PATCH", "PUT", "DELETE"]
|
assert verb in ["HEAD", "GET", "POST", "PATCH", "PUT", "DELETE"]
|
||||||
if resource is not None:
|
if resource is not None:
|
||||||
url = self.build_absolute_uri(resource)
|
url = self.build_absolute_uri(resource)
|
||||||
|
@ -73,8 +73,11 @@ class Orchestra(object):
|
||||||
url = "{}?{}".format(url, querystring)
|
url = "{}?{}".format(url, querystring)
|
||||||
|
|
||||||
verb = getattr(self.session, verb.lower())
|
verb = getattr(self.session, verb.lower())
|
||||||
response = verb(url, headers={"Authorization": "Token {}".format(
|
headers = {
|
||||||
self.auth_token)}, allow_redirects=False)
|
"Authorization": "Token {}".format(self.auth_token),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
response = verb(url, json=data, headers=headers, allow_redirects=False)
|
||||||
|
|
||||||
if raise_exception:
|
if raise_exception:
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
@ -109,6 +112,15 @@ class Orchestra(object):
|
||||||
raise Http404(_("No domain found matching the query"))
|
raise Http404(_("No domain found matching the query"))
|
||||||
return bill_pdf
|
return bill_pdf
|
||||||
|
|
||||||
|
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_list(self, querystring=None):
|
def retrieve_mail_address_list(self, querystring=None):
|
||||||
def get_mailbox_id(value):
|
def get_mailbox_id(value):
|
||||||
mailboxes = value.get('mailboxes')
|
mailboxes = value.get('mailboxes')
|
||||||
|
@ -139,7 +151,7 @@ class Orchestra(object):
|
||||||
|
|
||||||
# PATCH to include Pangea addresses not shown by orchestra
|
# PATCH to include Pangea addresses not shown by orchestra
|
||||||
# described on issue #4
|
# described on issue #4
|
||||||
raw_mailboxes = self.retrieve_service_list('mailbox')
|
raw_mailboxes = self.retrieve_mailbox_list()
|
||||||
for mailbox in raw_mailboxes:
|
for mailbox in raw_mailboxes:
|
||||||
if mailbox['addresses'] == []:
|
if mailbox['addresses'] == []:
|
||||||
address_data = {
|
address_data = {
|
||||||
|
@ -155,6 +167,11 @@ class Orchestra(object):
|
||||||
|
|
||||||
return addresses
|
return addresses
|
||||||
|
|
||||||
|
def retrieve_mailbox_list(self):
|
||||||
|
# TODO(@slamora) encapsulate as a Service class
|
||||||
|
raw_mailboxes = self.retrieve_service_list('mailbox')
|
||||||
|
return raw_mailboxes
|
||||||
|
|
||||||
def retrieve_domain(self, pk):
|
def retrieve_domain(self, pk):
|
||||||
path = API_PATHS.get('domain-detail').format_map({'pk': pk})
|
path = API_PATHS.get('domain-detail').format_map({'pk': pk})
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
|
from django import forms
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from . import api
|
from . import api
|
||||||
|
|
||||||
|
@ -20,3 +22,23 @@ class LoginForm(AuthenticationForm):
|
||||||
self.user = orchestra.retrieve_profile()
|
self.user = orchestra.retrieve_profile()
|
||||||
|
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
|
|
||||||
|
class MailForm(forms.Form):
|
||||||
|
name = forms.CharField()
|
||||||
|
domain = forms.ChoiceField()
|
||||||
|
mailboxes = forms.MultipleChoiceField(required=False)
|
||||||
|
forward = forms.EmailField(required=False)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
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]
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super().clean()
|
||||||
|
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
|
||||||
|
|
|
@ -161,7 +161,7 @@ class DatabaseService(OrchestraModel):
|
||||||
return super().new_from_json(data=data, users=users, usage=usage)
|
return super().new_from_json(data=data, users=users, usage=usage)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_usage(self, data):
|
def get_usage(cls, data):
|
||||||
try:
|
try:
|
||||||
resources = data['resources']
|
resources = data['resources']
|
||||||
resource_disk = {}
|
resource_disk = {}
|
||||||
|
@ -201,6 +201,7 @@ class Domain(OrchestraModel):
|
||||||
"mails": [],
|
"mails": [],
|
||||||
"usage": {},
|
"usage": {},
|
||||||
"websites": [],
|
"websites": [],
|
||||||
|
"url": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -41,4 +41,5 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
{% include "musician/components/table_paginator.html" %}
|
{% include "musician/components/table_paginator.html" %}
|
||||||
</table>
|
</table>
|
||||||
|
<a class="btn btn-primary mt-4 mb-4" href="{% url 'musician:mail-create' %}">{% trans "New mail address" %}</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
10
musician/templates/musician/mail_form.html
Normal file
10
musician/templates/musician/mail_form.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% extends "musician/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form }}
|
||||||
|
<button type="submit">OK</button>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -20,6 +20,7 @@ urlpatterns = [
|
||||||
path('bills/<int:pk>/download/', views.BillDownloadView.as_view(), name='bill-download'),
|
path('bills/<int:pk>/download/', views.BillDownloadView.as_view(), name='bill-download'),
|
||||||
path('profile/', views.ProfileView.as_view(), name='profile'),
|
path('profile/', views.ProfileView.as_view(), name='profile'),
|
||||||
path('mails/', views.MailView.as_view(), name='mails'),
|
path('mails/', views.MailView.as_view(), name='mails'),
|
||||||
|
path('mails/new/', views.MailCreateView.as_view(), name='mail-create'),
|
||||||
path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'),
|
path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'),
|
||||||
path('databases/', views.DatabasesView.as_view(), name='databases'),
|
path('databases/', views.DatabasesView.as_view(), name='databases'),
|
||||||
path('software-as-a-service/', views.SaasView.as_view(), name='saas'),
|
path('software-as-a-service/', views.SaasView.as_view(), name='saas'),
|
||||||
|
|
|
@ -11,11 +11,12 @@ from django.views.generic.base import RedirectView, TemplateView
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
from django.views.generic.list import ListView
|
from django.views.generic.list import ListView
|
||||||
|
from requests.exceptions import HTTPError
|
||||||
|
|
||||||
from . import api, get_version
|
from . import api, get_version
|
||||||
from .auth import login as auth_login
|
from .auth import login as auth_login
|
||||||
from .auth import logout as auth_logout
|
from .auth import logout as auth_logout
|
||||||
from .forms import LoginForm
|
from .forms import LoginForm, MailForm
|
||||||
from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
|
from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
|
||||||
UserTokenRequiredMixin)
|
UserTokenRequiredMixin)
|
||||||
from .models import (Bill, DatabaseService, MailinglistService, MailService,
|
from .models import (Bill, DatabaseService, MailinglistService, MailService,
|
||||||
|
@ -201,6 +202,29 @@ class MailView(ServiceListView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class MailCreateView(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()
|
||||||
|
kwargs['domains'] = self.orchestra.retrieve_domain_list()
|
||||||
|
kwargs['mailboxes'] = self.orchestra.retrieve_mailbox_list()
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
# handle request errors e.g. 400 validation
|
||||||
|
try:
|
||||||
|
self.orchestra.create_mail_address(form.cleaned_data)
|
||||||
|
except HTTPError as e:
|
||||||
|
form.add_error(field='__all__', error=e)
|
||||||
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class MailingListsView(ServiceListView):
|
class MailingListsView(ServiceListView):
|
||||||
service_class = MailinglistService
|
service_class = MailinglistService
|
||||||
template_name = "musician/mailinglists.html"
|
template_name = "musician/mailinglists.html"
|
||||||
|
|
Loading…
Reference in a new issue