2015-01-20 00:51:05 +01:00
|
|
|
"""
|
|
|
|
This module defines views related to hosting packages.
|
|
|
|
|
|
|
|
"""
|
2023-02-18 22:46:48 +01:00
|
|
|
from __future__ import absolute_import
|
2015-01-20 00:51:05 +01:00
|
|
|
|
2023-07-22 19:43:10 +02:00
|
|
|
import http
|
|
|
|
import logging
|
2023-07-23 11:24:10 +02:00
|
|
|
from datetime import timedelta
|
2023-07-22 19:43:10 +02:00
|
|
|
|
2015-01-24 16:23:17 +01:00
|
|
|
from django.conf import settings
|
2015-01-22 00:19:30 +01:00
|
|
|
from django.contrib import messages
|
2015-01-24 16:23:17 +01:00
|
|
|
from django.contrib.auth import get_user_model
|
2023-04-14 19:16:58 +02:00
|
|
|
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
|
2023-02-18 22:46:48 +01:00
|
|
|
from django.http import Http404
|
|
|
|
from django.shortcuts import get_object_or_404, redirect
|
2023-07-23 11:24:10 +02:00
|
|
|
from django.utils import timezone
|
2023-02-18 22:46:48 +01:00
|
|
|
from django.utils.translation import gettext as _
|
|
|
|
from django.views.generic import DetailView, ListView
|
|
|
|
from django.views.generic.edit import CreateView, FormView
|
2023-07-22 19:43:10 +02:00
|
|
|
|
|
|
|
import rest_framework.request
|
|
|
|
from rest_framework.permissions import BasePermission
|
|
|
|
from rest_framework.response import Response
|
|
|
|
from rest_framework.views import APIView
|
|
|
|
|
2015-01-24 16:23:17 +01:00
|
|
|
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
|
|
|
|
|
2023-07-23 10:26:43 +02:00
|
|
|
from managemails.models import Mailbox
|
2015-01-24 23:34:15 +01:00
|
|
|
from .forms import (
|
2015-01-25 15:15:39 +01:00
|
|
|
AddDiskspaceOptionForm,
|
|
|
|
AddMailboxOptionForm,
|
|
|
|
AddUserDatabaseOptionForm,
|
2015-01-24 23:34:15 +01:00
|
|
|
CreateCustomerHostingPackageForm,
|
|
|
|
CreateHostingPackageForm,
|
|
|
|
)
|
2015-01-25 14:04:32 +01:00
|
|
|
from .models import (
|
|
|
|
CustomerHostingPackage,
|
2023-07-22 19:43:10 +02:00
|
|
|
CustomerPackageDiskUsage,
|
2015-01-25 14:04:32 +01:00
|
|
|
DiskSpaceOption,
|
|
|
|
MailboxOption,
|
|
|
|
UserDatabaseOption,
|
|
|
|
)
|
2023-07-22 19:43:10 +02:00
|
|
|
from .serializers import DiskUsageSerializer
|
|
|
|
|
2023-07-23 10:26:43 +02:00
|
|
|
logger = logging.getLogger(__name__)
|
2015-01-20 00:51:05 +01:00
|
|
|
|
|
|
|
|
2023-04-14 19:16:58 +02:00
|
|
|
class CreateHostingPackage(PermissionRequiredMixin, CreateView):
|
2015-01-20 00:51:05 +01:00
|
|
|
"""
|
|
|
|
Create a hosting package.
|
|
|
|
|
|
|
|
"""
|
2023-02-18 22:46:48 +01:00
|
|
|
|
2015-01-20 00:51:05 +01:00
|
|
|
model = CustomerHostingPackage
|
|
|
|
raise_exception = True
|
2023-04-22 13:16:13 +02:00
|
|
|
permission_required = "domains.add_customerhostingpackage"
|
2023-02-18 22:46:48 +01:00
|
|
|
template_name_suffix = "_create"
|
2015-01-20 00:51:05 +01:00
|
|
|
form_class = CreateHostingPackageForm
|
|
|
|
|
2015-01-24 23:34:15 +01:00
|
|
|
def form_valid(self, form):
|
2023-04-22 13:16:13 +02:00
|
|
|
hosting_package = form.save()
|
2015-01-24 23:34:15 +01:00
|
|
|
messages.success(
|
|
|
|
self.request,
|
2023-02-18 22:46:48 +01:00
|
|
|
_("Started setup of new hosting package {name}.").format(
|
2023-04-22 13:16:13 +02:00
|
|
|
name=hosting_package.name
|
2023-02-18 22:46:48 +01:00
|
|
|
),
|
2015-01-24 23:34:15 +01:00
|
|
|
)
|
2023-04-22 13:16:13 +02:00
|
|
|
return redirect(hosting_package)
|
2015-01-24 23:34:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
class CreateCustomerHostingPackage(CreateHostingPackage):
|
|
|
|
"""
|
|
|
|
Create a hosting package for a selected customer.
|
|
|
|
|
|
|
|
"""
|
2023-02-18 22:46:48 +01:00
|
|
|
|
2015-01-24 23:34:15 +01:00
|
|
|
form_class = CreateCustomerHostingPackageForm
|
|
|
|
|
2015-01-20 00:51:05 +01:00
|
|
|
def get_form_kwargs(self):
|
2015-01-24 23:34:15 +01:00
|
|
|
kwargs = super(CreateCustomerHostingPackage, self).get_form_kwargs()
|
2015-01-20 00:51:05 +01:00
|
|
|
kwargs.update(self.kwargs)
|
|
|
|
return kwargs
|
|
|
|
|
2015-01-24 16:23:17 +01:00
|
|
|
def get_customer_object(self):
|
2023-02-18 22:46:48 +01:00
|
|
|
return get_object_or_404(get_user_model(), username=self.kwargs["user"])
|
2015-01-22 00:19:30 +01:00
|
|
|
|
2015-01-20 00:51:05 +01:00
|
|
|
def get_context_data(self, **kwargs):
|
2023-02-18 22:46:48 +01:00
|
|
|
context = super(CreateCustomerHostingPackage, self).get_context_data(**kwargs)
|
|
|
|
context["customer"] = self.get_customer_object()
|
2015-01-20 00:51:05 +01:00
|
|
|
return context
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
2023-04-22 13:16:13 +02:00
|
|
|
hosting_package = form.save(commit=False)
|
|
|
|
hosting_package.customer = self.get_customer_object()
|
|
|
|
hosting_package.save()
|
2015-01-22 00:19:30 +01:00
|
|
|
messages.success(
|
|
|
|
self.request,
|
2023-02-18 22:46:48 +01:00
|
|
|
_("Started setup of new hosting package {name}.").format(
|
2023-04-22 13:16:13 +02:00
|
|
|
name=hosting_package.name
|
2023-02-18 22:46:48 +01:00
|
|
|
),
|
2015-01-22 00:19:30 +01:00
|
|
|
)
|
2023-04-22 13:16:13 +02:00
|
|
|
return redirect(hosting_package)
|
2015-01-24 16:23:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
class CustomerHostingPackageDetails(StaffOrSelfLoginRequiredMixin, DetailView):
|
|
|
|
"""
|
|
|
|
This view is for showing details of a customer hosting package.
|
|
|
|
|
|
|
|
"""
|
2023-02-18 22:46:48 +01:00
|
|
|
|
2015-01-24 16:23:17 +01:00
|
|
|
model = CustomerHostingPackage
|
2023-02-18 22:46:48 +01:00
|
|
|
context_object_name = "hostingpackage"
|
2015-02-01 15:00:44 +01:00
|
|
|
customer = None
|
2015-01-24 16:23:17 +01:00
|
|
|
|
|
|
|
def get_customer_object(self):
|
2015-02-01 15:00:44 +01:00
|
|
|
if self.customer is None:
|
|
|
|
self.customer = get_object_or_404(
|
2023-02-18 22:46:48 +01:00
|
|
|
get_user_model(), username=self.kwargs["user"]
|
|
|
|
)
|
2015-02-01 15:00:44 +01:00
|
|
|
return self.customer
|
2015-01-24 16:23:17 +01:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2023-02-18 22:46:48 +01:00
|
|
|
context = super(CustomerHostingPackageDetails, self).get_context_data(**kwargs)
|
|
|
|
context.update(
|
|
|
|
{
|
|
|
|
"customer": self.get_customer_object(),
|
|
|
|
"uploadserver": settings.OSUSER_UPLOAD_SERVER,
|
|
|
|
"databases": context["hostingpackage"].databases,
|
|
|
|
"osuser": context["hostingpackage"].osuser,
|
|
|
|
"hostingoptions": context["hostingpackage"].get_hostingoptions(),
|
|
|
|
"domains": context["hostingpackage"].domains.all(),
|
|
|
|
"mailboxes": context["hostingpackage"].mailboxes,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
context["sshkeys"] = context["osuser"].sshpublickey_set.all()
|
2015-01-24 16:23:17 +01:00
|
|
|
return context
|
2015-01-24 23:34:15 +01:00
|
|
|
|
|
|
|
|
2023-04-14 19:16:58 +02:00
|
|
|
class StaffUserRequiredMixin(UserPassesTestMixin):
|
|
|
|
"""
|
|
|
|
Mixin to make views available to staff members only.
|
|
|
|
|
|
|
|
"""
|
2023-04-22 13:16:13 +02:00
|
|
|
|
2023-04-14 19:16:58 +02:00
|
|
|
def test_func(self):
|
|
|
|
return self.request.user.is_staff
|
|
|
|
|
|
|
|
|
|
|
|
class AllCustomerHostingPackageList(StaffUserRequiredMixin, ListView):
|
2015-02-01 15:00:44 +01:00
|
|
|
"""
|
|
|
|
This view is used for showing a list of all hosting packages.
|
|
|
|
|
|
|
|
"""
|
2023-02-18 22:46:48 +01:00
|
|
|
|
2015-01-24 23:34:15 +01:00
|
|
|
model = CustomerHostingPackage
|
2023-02-18 22:46:48 +01:00
|
|
|
template_name_suffix = "_admin_list"
|
2015-01-25 14:04:32 +01:00
|
|
|
|
2023-04-22 13:16:13 +02:00
|
|
|
def get_queryset(self):
|
|
|
|
return (
|
|
|
|
super()
|
|
|
|
.get_queryset()
|
|
|
|
.select_related("osuser", "customer")
|
|
|
|
.only("name", "pk", "created", "customer__username", "osuser__username")
|
|
|
|
)
|
|
|
|
|
2015-01-25 14:04:32 +01:00
|
|
|
|
2023-04-14 19:16:58 +02:00
|
|
|
class HostingOptionChoices(StaffUserRequiredMixin, DetailView):
|
2015-01-25 14:04:32 +01:00
|
|
|
"""
|
|
|
|
This view displays choices of hosting options for a customer hosting
|
|
|
|
package.
|
|
|
|
|
|
|
|
"""
|
2023-02-18 22:46:48 +01:00
|
|
|
|
2015-01-25 14:04:32 +01:00
|
|
|
model = CustomerHostingPackage
|
2023-02-18 22:46:48 +01:00
|
|
|
context_object_name = "hostingpackage"
|
|
|
|
template_name_suffix = "_option_choices"
|
2015-01-25 14:04:32 +01:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2023-02-18 22:46:48 +01:00
|
|
|
context = super(HostingOptionChoices, self).get_context_data(**kwargs)
|
|
|
|
context.update(
|
|
|
|
{
|
|
|
|
"customer": self.get_object().customer,
|
|
|
|
"hosting_options": (
|
|
|
|
(
|
|
|
|
_("Disk space"),
|
|
|
|
[
|
|
|
|
(option, "diskspace")
|
|
|
|
for option in DiskSpaceOption.objects.all()
|
|
|
|
],
|
|
|
|
),
|
|
|
|
(
|
|
|
|
_("Mailboxes"),
|
|
|
|
[
|
|
|
|
(option, "mailboxes")
|
|
|
|
for option in MailboxOption.objects.all()
|
|
|
|
],
|
|
|
|
),
|
|
|
|
(
|
|
|
|
_("Databases"),
|
|
|
|
[
|
|
|
|
(option, "databases")
|
|
|
|
for option in UserDatabaseOption.objects.all()
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
}
|
|
|
|
)
|
2015-01-25 14:04:32 +01:00
|
|
|
return context
|
2015-01-25 15:15:39 +01:00
|
|
|
|
|
|
|
|
2023-04-14 19:16:58 +02:00
|
|
|
class AddHostingOption(StaffUserRequiredMixin, FormView):
|
2023-02-18 22:46:48 +01:00
|
|
|
template_name = "hostingpackages/add_hosting_option.html"
|
2015-01-25 15:15:39 +01:00
|
|
|
|
|
|
|
def get_form_class(self):
|
2023-02-18 22:46:48 +01:00
|
|
|
optiontype = self.kwargs["type"]
|
|
|
|
if optiontype == "diskspace":
|
2015-01-25 15:15:39 +01:00
|
|
|
return AddDiskspaceOptionForm
|
2023-02-18 22:46:48 +01:00
|
|
|
elif optiontype == "mailboxes":
|
2015-01-25 15:15:39 +01:00
|
|
|
return AddMailboxOptionForm
|
2023-02-18 22:46:48 +01:00
|
|
|
elif optiontype == "databases":
|
2015-01-25 15:15:39 +01:00
|
|
|
return AddUserDatabaseOptionForm
|
|
|
|
raise Http404()
|
|
|
|
|
|
|
|
def get_hosting_package(self):
|
2023-02-18 22:46:48 +01:00
|
|
|
return get_object_or_404(CustomerHostingPackage, pk=int(self.kwargs["package"]))
|
2015-01-25 15:15:39 +01:00
|
|
|
|
|
|
|
def get_option_template(self):
|
2023-02-18 22:46:48 +01:00
|
|
|
optiontype = self.kwargs["type"]
|
|
|
|
optionid = int(self.kwargs["optionid"])
|
|
|
|
if optiontype == "diskspace":
|
2015-01-25 15:15:39 +01:00
|
|
|
return get_object_or_404(DiskSpaceOption, pk=optionid)
|
2023-02-18 22:46:48 +01:00
|
|
|
elif optiontype == "mailboxes":
|
2015-01-25 15:15:39 +01:00
|
|
|
return get_object_or_404(MailboxOption, pk=optionid)
|
2023-02-18 22:46:48 +01:00
|
|
|
elif optiontype == "databases":
|
2015-01-25 15:15:39 +01:00
|
|
|
return get_object_or_404(UserDatabaseOption, pk=optionid)
|
|
|
|
raise Http404()
|
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
|
|
|
kwargs = super(AddHostingOption, self).get_form_kwargs()
|
2023-02-18 22:46:48 +01:00
|
|
|
kwargs["hostingpackage"] = self.get_hosting_package()
|
|
|
|
kwargs["option_template"] = self.get_option_template()
|
2015-01-25 15:15:39 +01:00
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def get_initial(self):
|
|
|
|
initial = super(AddHostingOption, self).get_initial()
|
|
|
|
template = self.get_option_template()
|
|
|
|
if type(template) == DiskSpaceOption:
|
2023-02-18 22:46:48 +01:00
|
|
|
initial.update(
|
|
|
|
{
|
|
|
|
"diskspace": template.diskspace,
|
|
|
|
"diskspace_unit": template.diskspace_unit,
|
|
|
|
}
|
|
|
|
)
|
2015-01-25 15:15:39 +01:00
|
|
|
elif type(template) == MailboxOption:
|
2023-02-18 22:46:48 +01:00
|
|
|
initial["number"] = template.number
|
2015-01-25 15:15:39 +01:00
|
|
|
elif type(template) == UserDatabaseOption:
|
2023-02-18 22:46:48 +01:00
|
|
|
initial["number"] = template.number
|
2015-01-25 15:15:39 +01:00
|
|
|
else:
|
|
|
|
raise Http404()
|
|
|
|
return initial
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super(AddHostingOption, self).get_context_data(**kwargs)
|
2023-02-18 22:46:48 +01:00
|
|
|
context["option_template"] = self.get_option_template()
|
2015-01-25 15:15:39 +01:00
|
|
|
return context
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
option = form.save()
|
|
|
|
hosting_package = self.get_hosting_package()
|
|
|
|
messages.success(
|
|
|
|
self.request,
|
2023-02-18 22:46:48 +01:00
|
|
|
_(
|
|
|
|
"Successfully added option {option} to hosting package " "{package}."
|
|
|
|
).format(option=option, package=hosting_package.name),
|
2015-01-25 15:15:39 +01:00
|
|
|
)
|
|
|
|
return redirect(hosting_package)
|
2023-07-22 19:43:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
class HasDiskUsageUploadPermission(BasePermission):
|
|
|
|
def has_permission(self, request, view):
|
|
|
|
return (
|
2023-07-23 11:24:10 +02:00
|
|
|
request.user.has_perm("hostingpackages.add_customerpackagediskusage")
|
|
|
|
and request.method == "POST"
|
2023-07-22 19:43:10 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class UploadCustomerPackageDiskUsage(APIView):
|
|
|
|
permission_classes = [HasDiskUsageUploadPermission]
|
|
|
|
allowed_methods = ("POST",)
|
|
|
|
serializer = DiskUsageSerializer(many=True)
|
|
|
|
|
|
|
|
def post(self, request: rest_framework.request.Request, format=None):
|
|
|
|
if request.content_type != "application/json":
|
|
|
|
return Response("Unacceptable", status=http.HTTPStatus.BAD_REQUEST)
|
2023-07-23 10:26:43 +02:00
|
|
|
|
2023-07-23 11:24:10 +02:00
|
|
|
submitted_sources = set()
|
|
|
|
|
2023-07-22 19:43:10 +02:00
|
|
|
for row in request.data:
|
|
|
|
user = row["user"]
|
|
|
|
for key in row:
|
|
|
|
if key == "user":
|
|
|
|
continue
|
|
|
|
else:
|
2023-07-23 11:24:10 +02:00
|
|
|
submitted_sources.add(key)
|
2023-07-22 19:43:10 +02:00
|
|
|
for item, size in row[key].items():
|
|
|
|
try:
|
|
|
|
package = CustomerHostingPackage.objects.get(
|
|
|
|
osuser__username=user
|
|
|
|
)
|
|
|
|
(
|
|
|
|
metric,
|
|
|
|
created,
|
|
|
|
) = CustomerPackageDiskUsage.objects.get_or_create(
|
|
|
|
package=package,
|
|
|
|
source=key,
|
|
|
|
item=item,
|
|
|
|
)
|
|
|
|
metric.used_kb = size
|
2023-07-23 10:26:43 +02:00
|
|
|
|
|
|
|
if key == "mail":
|
|
|
|
try:
|
2023-07-23 11:24:10 +02:00
|
|
|
ma_mb = package.mailboxes.get(
|
|
|
|
username=item
|
|
|
|
).mailaddressmailbox_set.first()
|
2023-07-23 10:26:43 +02:00
|
|
|
if ma_mb:
|
|
|
|
metric.email_address_id = ma_mb.mailaddress_id
|
|
|
|
except Mailbox.DoesNotExist:
|
|
|
|
logger.warning("mail box %s does not exist", item)
|
|
|
|
|
2023-07-22 19:43:10 +02:00
|
|
|
metric.save()
|
|
|
|
except CustomerHostingPackage.DoesNotExist:
|
|
|
|
logger.warning(
|
|
|
|
"hosting package for user %s does not exist", user
|
|
|
|
)
|
|
|
|
|
2023-07-23 11:24:10 +02:00
|
|
|
if submitted_sources:
|
|
|
|
CustomerPackageDiskUsage.objects.filter(
|
|
|
|
source__in=submitted_sources,
|
|
|
|
modified__lt=timezone.now() - timedelta(minutes=30),
|
|
|
|
).delete()
|
|
|
|
|
2023-07-23 10:26:43 +02:00
|
|
|
logger.info("usage data submitted by %s", request.user)
|
2023-07-22 19:43:10 +02:00
|
|
|
|
|
|
|
return Response("Accepted", status=http.HTTPStatus.ACCEPTED)
|
|
|
|
|
|
|
|
|
2023-07-22 22:25:08 +02:00
|
|
|
class CustomerHostingPackageDiskUsageDetails(StaffOrSelfLoginRequiredMixin, DetailView):
|
2023-07-22 19:43:10 +02:00
|
|
|
template_name_suffix = "_disk_usage_details"
|
|
|
|
model = CustomerHostingPackage
|
|
|
|
pk_url_kwarg = "package"
|
|
|
|
context_object_name = "hostingpackage"
|
|
|
|
|
2023-07-22 22:34:09 +02:00
|
|
|
customer = None
|
|
|
|
|
|
|
|
def get_customer_object(self):
|
|
|
|
if self.customer is None:
|
|
|
|
self.customer = get_object_or_404(
|
|
|
|
get_user_model(), username=self.kwargs["user"]
|
|
|
|
)
|
|
|
|
return self.customer
|
|
|
|
|
2023-07-22 19:43:10 +02:00
|
|
|
def get_queryset(self, queryset=None):
|
|
|
|
return super().get_queryset().prefetch_related("customerpackagediskusage_set")
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context_data = super().get_context_data(**kwargs)
|
|
|
|
|
2023-07-23 10:26:43 +02:00
|
|
|
mail_usage, web_usage, mysql_usage, pgsql_usage = [], [], [], []
|
2023-07-22 19:43:10 +02:00
|
|
|
|
|
|
|
for usage in self.get_object().customerpackagediskusage_set.order_by(
|
2023-07-23 11:24:10 +02:00
|
|
|
"-used_kb"
|
2023-07-22 19:43:10 +02:00
|
|
|
):
|
2023-07-23 10:26:43 +02:00
|
|
|
if usage.used_kb <= 0:
|
|
|
|
continue
|
|
|
|
if usage.source == "mail":
|
|
|
|
mail_usage.append(usage)
|
|
|
|
elif usage.source == "web":
|
|
|
|
web_usage.append(usage)
|
2023-07-22 19:43:10 +02:00
|
|
|
elif usage.source == "mysql":
|
|
|
|
mysql_usage.append(usage)
|
|
|
|
elif usage.source == "pgsql":
|
|
|
|
pgsql_usage.append(usage)
|
|
|
|
|
|
|
|
context_data.update(
|
|
|
|
{
|
2023-07-22 22:34:09 +02:00
|
|
|
"customer": self.get_customer_object(),
|
2023-07-23 10:26:43 +02:00
|
|
|
"mail_usage": mail_usage,
|
|
|
|
"web_usage": web_usage,
|
2023-07-22 19:43:10 +02:00
|
|
|
"mysql_usage": mysql_usage,
|
|
|
|
"pgsql_usage": pgsql_usage,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
return context_data
|