2019-10-30 13:06:55 +00:00
|
|
|
|
2019-11-13 10:08:19 +00:00
|
|
|
from itertools import groupby
|
2019-11-13 11:26:35 +00:00
|
|
|
|
|
|
|
from django.core.exceptions import ImproperlyConfigured
|
2019-10-30 12:05:46 +00:00
|
|
|
from django.http import HttpResponseRedirect
|
2019-10-10 07:18:34 +00:00
|
|
|
from django.shortcuts import render
|
2019-10-29 09:58:54 +00:00
|
|
|
from django.urls import reverse_lazy
|
2019-10-31 09:46:54 +00:00
|
|
|
from django.utils.http import is_safe_url
|
2019-12-10 13:02:26 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2019-10-30 12:05:46 +00:00
|
|
|
from django.views.generic.base import RedirectView, TemplateView
|
2019-12-06 09:28:34 +00:00
|
|
|
from django.views.generic.detail import DetailView
|
2019-10-29 09:58:54 +00:00
|
|
|
from django.views.generic.edit import FormView
|
2019-10-31 13:08:49 +00:00
|
|
|
from django.views.generic.list import ListView
|
2019-10-10 07:18:34 +00:00
|
|
|
|
2019-10-29 09:58:54 +00:00
|
|
|
from . import api, get_version
|
2019-10-30 13:06:55 +00:00
|
|
|
from .auth import login as auth_login
|
|
|
|
from .auth import logout as auth_logout
|
2019-10-29 09:58:54 +00:00
|
|
|
from .forms import LoginForm
|
2019-12-06 09:28:34 +00:00
|
|
|
from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
|
|
|
|
UserTokenRequiredMixin)
|
|
|
|
from .models import (DatabaseService, MailinglistService, MailService,
|
|
|
|
PaymentSource, SaasService, UserAccount)
|
2019-10-25 11:33:37 +00:00
|
|
|
|
|
|
|
|
2019-10-30 13:06:55 +00:00
|
|
|
class DashboardView(CustomContextMixin, UserTokenRequiredMixin, TemplateView):
|
2019-10-25 11:33:37 +00:00
|
|
|
template_name = "musician/dashboard.html"
|
2019-10-29 09:58:54 +00:00
|
|
|
|
2019-10-30 13:08:14 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
2019-12-12 13:19:39 +00:00
|
|
|
domains = self.orchestra.retrieve_domain_list()
|
2019-10-30 13:08:14 +00:00
|
|
|
|
2019-12-10 13:02:26 +00:00
|
|
|
# TODO(@slamora) update when backend provides resource usage data
|
|
|
|
resource_usage = {
|
|
|
|
'disk': {
|
|
|
|
'verbose_name': _('Disk usage'),
|
|
|
|
'usage': 534,
|
|
|
|
'total': 1024,
|
|
|
|
'unit': 'MB',
|
|
|
|
'percent': 50,
|
|
|
|
},
|
|
|
|
'traffic': {
|
|
|
|
'verbose_name': _('Traffic'),
|
|
|
|
'usage': 300,
|
|
|
|
'total': 2048,
|
|
|
|
'unit': 'MB/month',
|
|
|
|
'percent': 25,
|
|
|
|
},
|
|
|
|
'mailbox': {
|
|
|
|
'verbose_name': _('Mailbox usage'),
|
|
|
|
'usage': 1,
|
|
|
|
'total': 2,
|
|
|
|
'unit': 'accounts',
|
|
|
|
'percent': 50,
|
|
|
|
},
|
|
|
|
}
|
2019-12-12 09:48:40 +00:00
|
|
|
|
2019-12-10 13:02:26 +00:00
|
|
|
# TODO(@slamora) update when backend supports notifications
|
|
|
|
notifications = []
|
|
|
|
|
2019-10-30 13:08:14 +00:00
|
|
|
context.update({
|
2019-12-12 13:19:39 +00:00
|
|
|
'domains': domains,
|
2019-12-10 13:02:26 +00:00
|
|
|
'resource_usage': resource_usage,
|
|
|
|
'notifications': notifications,
|
2019-10-30 13:08:14 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return context
|
|
|
|
|
2019-10-29 09:58:54 +00:00
|
|
|
|
2019-12-06 09:00:11 +00:00
|
|
|
class BillingView(CustomContextMixin, ExtendedPaginationMixin, UserTokenRequiredMixin, ListView):
|
|
|
|
template_name = "musician/billing.html"
|
|
|
|
|
|
|
|
def get_queryset(self):
|
|
|
|
# TODO (@slamora) retrieve user bills
|
|
|
|
from django.utils import timezone
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
'number': 24,
|
|
|
|
'date': timezone.now(),
|
|
|
|
'type': 'subscription',
|
|
|
|
'total_amount': '25,00 €',
|
|
|
|
'status': 'paid',
|
|
|
|
'pdf_url': 'https://example.org/bill.pdf'
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2019-11-20 19:07:35 +00:00
|
|
|
class ProfileView(CustomContextMixin, UserTokenRequiredMixin, TemplateView):
|
|
|
|
template_name = "musician/profile.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
try:
|
|
|
|
pay_source = self.orchestra.retrieve_service_list(
|
|
|
|
PaymentSource.api_name)[0]
|
|
|
|
except IndexError:
|
|
|
|
pay_source = {}
|
|
|
|
context.update({
|
|
|
|
'payment': PaymentSource.new_from_json(pay_source)
|
|
|
|
})
|
|
|
|
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
2019-10-31 16:16:51 +00:00
|
|
|
class ServiceListView(CustomContextMixin, ExtendedPaginationMixin, UserTokenRequiredMixin, ListView):
|
|
|
|
"""Base list view to all services"""
|
2019-11-13 11:26:35 +00:00
|
|
|
service_class = None
|
2019-11-13 10:08:19 +00:00
|
|
|
template_name = "musician/service_list.html" # TODO move to ServiceListView
|
2019-10-31 16:16:51 +00:00
|
|
|
|
2019-11-13 10:08:19 +00:00
|
|
|
def get_queryset(self):
|
2019-11-13 11:26:35 +00:00
|
|
|
if self.service_class is None or self.service_class.api_name is None:
|
2019-11-13 10:08:19 +00:00
|
|
|
raise ImproperlyConfigured(
|
|
|
|
"ServiceListView requires a definiton of 'service'")
|
|
|
|
|
2019-11-20 19:07:35 +00:00
|
|
|
json_qs = self.orchestra.retrieve_service_list(
|
|
|
|
self.service_class.api_name)
|
2019-11-20 09:29:39 +00:00
|
|
|
return [self.service_class.new_from_json(data) for data in json_qs]
|
2019-11-13 10:08:19 +00:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context.update({
|
|
|
|
'service': self.service_class,
|
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
|
|
class MailView(ServiceListView):
|
|
|
|
service_class = MailService
|
2019-11-20 16:25:32 +00:00
|
|
|
template_name = "musician/mail.html"
|
2019-11-13 10:08:19 +00:00
|
|
|
|
|
|
|
def get_queryset(self):
|
|
|
|
def retrieve_mailbox(value):
|
|
|
|
mailboxes = value.get('mailboxes')
|
|
|
|
|
|
|
|
if len(mailboxes) == 0:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
return mailboxes[0]['id']
|
|
|
|
|
|
|
|
# group addresses with the same mailbox
|
|
|
|
raw_data = self.orchestra.retrieve_service_list(
|
2019-11-13 11:26:35 +00:00
|
|
|
self.service_class.api_name)
|
2019-11-13 10:08:19 +00:00
|
|
|
addresses = []
|
|
|
|
for key, group in groupby(raw_data, retrieve_mailbox):
|
|
|
|
aliases = []
|
|
|
|
data = {}
|
|
|
|
for thing in group:
|
|
|
|
aliases.append(thing.pop('name'))
|
|
|
|
data = thing
|
|
|
|
|
|
|
|
data['names'] = aliases
|
2019-11-20 16:25:32 +00:00
|
|
|
addresses.append(self.service_class.new_from_json(data))
|
2019-10-31 16:16:51 +00:00
|
|
|
|
2019-11-13 10:08:19 +00:00
|
|
|
return addresses
|
2019-10-30 13:23:46 +00:00
|
|
|
|
|
|
|
|
2019-10-31 16:16:51 +00:00
|
|
|
class MailingListsView(ServiceListView):
|
2019-11-13 10:42:23 +00:00
|
|
|
service_class = MailinglistService
|
2019-12-04 11:37:35 +00:00
|
|
|
template_name = "musician/mailinglists.html"
|
2019-10-31 13:09:49 +00:00
|
|
|
|
2019-10-30 13:23:46 +00:00
|
|
|
|
2019-11-13 11:27:25 +00:00
|
|
|
class DatabasesView(ServiceListView):
|
2019-11-20 09:29:39 +00:00
|
|
|
template_name = "musician/databases.html"
|
2019-11-13 11:27:25 +00:00
|
|
|
service_class = DatabaseService
|
2019-10-30 13:23:46 +00:00
|
|
|
|
|
|
|
|
2019-12-06 09:28:34 +00:00
|
|
|
class SaasView(ServiceListView):
|
|
|
|
service_class = SaasService
|
2019-10-30 13:23:46 +00:00
|
|
|
template_name = "musician/saas.html"
|
|
|
|
|
|
|
|
|
2019-10-29 09:58:54 +00:00
|
|
|
class LoginView(FormView):
|
|
|
|
template_name = 'auth/login.html'
|
|
|
|
form_class = LoginForm
|
|
|
|
success_url = reverse_lazy('musician:dashboard')
|
2019-10-31 09:46:54 +00:00
|
|
|
redirect_field_name = 'next'
|
2019-10-29 09:58:54 +00:00
|
|
|
extra_context = {'version': get_version()}
|
2019-10-30 12:05:46 +00:00
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
|
|
|
kwargs = super().get_form_kwargs()
|
|
|
|
kwargs['request'] = self.request
|
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
"""Security check complete. Log the user in."""
|
|
|
|
auth_login(self.request, form.username, form.token)
|
|
|
|
return HttpResponseRedirect(self.get_success_url())
|
|
|
|
|
2019-10-31 09:46:54 +00:00
|
|
|
def get_success_url(self):
|
|
|
|
url = self.get_redirect_url()
|
|
|
|
return url or self.success_url
|
|
|
|
|
|
|
|
def get_redirect_url(self):
|
|
|
|
"""Return the user-originating redirect URL if it's safe."""
|
|
|
|
redirect_to = self.request.POST.get(
|
|
|
|
self.redirect_field_name,
|
|
|
|
self.request.GET.get(self.redirect_field_name, '')
|
|
|
|
)
|
|
|
|
url_is_safe = is_safe_url(
|
|
|
|
url=redirect_to,
|
|
|
|
allowed_hosts={self.request.get_host()},
|
|
|
|
require_https=self.request.is_secure(),
|
|
|
|
)
|
|
|
|
return redirect_to if url_is_safe else ''
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context.update({
|
|
|
|
self.redirect_field_name: self.get_redirect_url(),
|
|
|
|
**(self.extra_context or {})
|
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
2019-10-30 12:05:46 +00:00
|
|
|
|
|
|
|
class LogoutView(RedirectView):
|
|
|
|
"""
|
|
|
|
Log out the user.
|
|
|
|
"""
|
|
|
|
permanent = False
|
|
|
|
pattern_name = 'musician:login'
|
|
|
|
|
|
|
|
def get_redirect_url(self, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
Logs out the user.
|
|
|
|
"""
|
|
|
|
auth_logout(self.request)
|
|
|
|
return super().get_redirect_url(*args, **kwargs)
|
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
"""Logout may be done via POST."""
|
|
|
|
return self.get(request, *args, **kwargs)
|