Compare commits

...

17 commits
0.14.0 ... main

Author SHA1 Message Date
Jan Dittberner 11c04df074 Add flatpage URL for /issues/
Jira has been decommissioned and replaced with a flatpage
2024-02-11 13:12:54 +01:00
Jan Dittberner 7c57b4cc94 Update docker setup 2024-02-11 13:12:26 +01:00
Jan Dittberner 78e06dd2b9 Update dependencies
- updated minimum version of several dependencies in pyproject.toml
- update of django-allauth required to add
  allauth.account.middleware.AccountMiddleware to MIDDLEWARE setting
2024-01-13 13:38:03 +01:00
Jan Dittberner 90795375e7 Update dependencies 2024-01-13 13:22:50 +01:00
Jan Dittberner c1b226e5a1 Update dependency versions 2023-08-03 09:24:42 +02:00
Jan Dittberner 5e527ef10d Release 0.15.1 2023-07-23 11:24:46 +02:00
Jan Dittberner 3b6d50a62a Remove stale disk usage stats 2023-07-23 11:24:10 +02:00
Jan Dittberner 4b74f5d04b Release 0.15.0 2023-07-23 10:28:00 +02:00
Jan Dittberner ec6a9a7cc1 Add disk usage details for mail and web
Addresses #10
2023-07-23 10:26:43 +02:00
Jan Dittberner f21987158b Release 0.14.4 2023-07-22 22:35:49 +02:00
Jan Dittberner 2e7dca529a Add customer to disk space detail view 2023-07-22 22:34:44 +02:00
Jan Dittberner 1d4f070867 Release 0.14.3 2023-07-22 22:25:36 +02:00
Jan Dittberner d1494af0a1 Fix permission check on disk space detail view 2023-07-22 22:25:08 +02:00
Jan Dittberner 69638b6b6d Release 0.14.2 2023-07-22 21:57:40 +02:00
Jan Dittberner ee561a5127 Fix division by zero 2023-07-22 21:56:53 +02:00
Jan Dittberner b69ecbfa2d Prepare release 0.14.1 2023-07-22 20:46:47 +02:00
Jan Dittberner bf7b02d5b5 Fix squashed migration 2023-07-22 20:46:03 +02:00
16 changed files with 1087 additions and 863 deletions

View file

@ -1,8 +1,8 @@
ARG DEBIAN_RELEASE=buster
ARG DEBIAN_RELEASE=bookworm
FROM debian:$DEBIAN_RELEASE AS builder
ARG GVAAPP=gva
ARG POETRY_VERSION=1.3.1
ARG POETRY_VERSION=1.7.1
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
@ -26,7 +26,7 @@ WORKDIR /srv/$GVAAPP
COPY poetry.lock pyproject.toml /srv/$GVAAPP/
RUN /root/.local/bin/poetry install --only=main
RUN /root/.local/bin/poetry install --only=main --no-root
FROM debian:$DEBIAN_RELEASE
LABEL maintainer="Jan Dittberner <jan@dittberner.info>"

View file

@ -19,7 +19,7 @@ services:
volumes:
- "redis_data:/var/lib/redis"
gva:
image: gnuviech/gva:buster
image: gnuviech/gva:bookworm
build:
context: .
args:
@ -67,7 +67,7 @@ services:
volumes:
- "../gvaldap/gvaldap:/srv/gvaldap/gvaldap"
file:
image: gnuviech/gvafile:buster
image: gnuviech/gvafile:bookworm
build:
context: ../gvafile
args:

View file

@ -1,6 +1,24 @@
Changelog
=========
* :release:`0.15.1 <2023-07-23>
* :bug:`-` remove stale disk usage stats older than 30 minutes
* :release:`0.15.0 <2023-07-23>
* :feature:`10` add disk usage details for mail and web
* :release:`0.14.4 <2023-07-22>`
* :bug:`-` add customer to disk space detail view
* :release:`0.14.3 <2023-07-22>`
* :bug:`-` fix missing permission check on disk space detail view
* :release:`0.14.2 <2023-07-22>`
* :bug:`-` fix division by zero for hosting packages without disk space allocation
* :release:`0.14.1 <2023-07-22>`
* :bug:`-` fix squashed migration for disk space statistics
* :release:`0.14.0 <2023-07-22>`
* :feature:`-` add disk space statistics

View file

@ -1,4 +1,4 @@
# import celery_app to initialize it
from gnuviechadmin.celery import app as celery_app # NOQA
__version__ = "0.14.0"
__version__ = "0.15.1"

View file

@ -161,6 +161,7 @@ MIDDLEWARE = [
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"allauth.account.middleware.AccountMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
# uncomment next line to enable translation to browser locale

View file

@ -38,6 +38,7 @@ urlpatterns = [
path("contact/", include("contact_form.urls")),
path("impressum/", views.flatpage, {"url": "/impressum/"}, name="imprint"),
path("datenschutz/", views.flatpage, {"url": "/datenschutz/"}, name="privacy"),
path("issues/", views.flatpage, {"url": "/issues/"}, name="support"),
]
# Uncomment the next line to serve media files in dev.

View file

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnuviechadmin hostingpackages\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-07-22 20:06+0200\n"
"PO-Revision-Date: 2023-07-22 20:06+0200\n"
"POT-Creation-Date: 2023-07-23 10:23+0200\n"
"PO-Revision-Date: 2023-07-23 10:24+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n"
@ -167,78 +167,100 @@ msgstr "Kundenhostingpakete"
msgid "{name} for {customer}"
msgstr "{name} für {customer}"
#: hostingpackages/models.py:419 hostingpackages/models.py:446
#: hostingpackages/models.py:511
#: hostingpackages/models.py:421 hostingpackages/models.py:448
#: hostingpackages/models.py:513
msgid "hosting package"
msgstr "Hostingpaket"
#: hostingpackages/models.py:424
#: hostingpackages/models.py:426
msgid "hosting domain"
msgstr "Hostingdomain"
#: hostingpackages/models.py:451
#: hostingpackages/models.py:453
msgid "customer hosting option"
msgstr "kundenspezifische Hostingoption"
#: hostingpackages/models.py:452
#: hostingpackages/models.py:454
msgid "customer hosting options"
msgstr "kundenspezifische Hostingoptionen"
#: hostingpackages/models.py:464
#: hostingpackages/models.py:466
msgid "disk space option template"
msgstr "Speicherplatzoptionsvorlage"
#: hostingpackages/models.py:466
#: hostingpackages/models.py:468
msgid "The disk space option template that this disk space option is based on"
msgstr ""
"Die Speicherplatzoptionsvorlage auf der diese Speicherplatzoption aufgebaut "
"ist"
#: hostingpackages/models.py:481
#: hostingpackages/models.py:483
msgid "user database option template"
msgstr "Nutzerdatenbankoptionsvorlage"
#: hostingpackages/models.py:483
#: hostingpackages/models.py:485
msgid "The user database option template that this database option is based on"
msgstr ""
"Die Nutzerdatenbankoptionsvorlage auf der diese Datenbankoption aufgebaut ist"
#: hostingpackages/models.py:498
#: hostingpackages/models.py:500
msgid "mailbox option template"
msgstr "Postfachoptionsvorlage"
#: hostingpackages/models.py:499
#: hostingpackages/models.py:501
msgid "The mailbox option template that this mailbox option is based on"
msgstr "Die Postfachoptionsvorlage auf der diese Postfachoption aufgebaut ist"
#: hostingpackages/models.py:512
#: hostingpackages/models.py:514
msgid "The hosting package"
msgstr "Das Hostingpaket"
#: hostingpackages/models.py:516
#: hostingpackages/models.py:518
msgid "data source"
msgstr "Datenquelle"
#: hostingpackages/models.py:517
msgid "disk"
msgstr "Festplatte"
#: hostingpackages/models.py:520
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:202
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:42
msgid "Mailbox"
msgstr "Postfach"
#: hostingpackages/models.py:517
msgid "mysql"
msgstr "MySQL"
#: hostingpackages/models.py:521
msgid "Website"
msgstr "Webauftritt"
#: hostingpackages/models.py:517
msgid "pgsql"
msgstr "PostgreSQL"
#: hostingpackages/models.py:522
msgid "MariaDB database"
msgstr "MariaDB-Datenbank"
#: hostingpackages/models.py:519
#: hostingpackages/models.py:523
msgid "PostgreSQL database"
msgstr "PostgreSQL-Datenbank"
#: hostingpackages/models.py:526
msgid "data item"
msgstr "Dateneinheit"
#: hostingpackages/models.py:521
#: hostingpackages/models.py:528
msgid "space used in KiB"
msgstr "genutzter Platz in KiB"
#: hostingpackages/models.py:532
msgid "mail address"
msgstr "E-Mailadresse"
#: hostingpackages/models.py:533
msgid "Assigned mail address"
msgstr "Zugeordnete E-Mailadresse"
#: hostingpackages/models.py:539
msgid "website"
msgstr "Webauftritt"
#: hostingpackages/models.py:540
msgid "Assigned web site"
msgstr "Zugeordneter Webauftritt"
#: hostingpackages/templates/hostingpackages/add_hosting_option.html:4
#: hostingpackages/templates/hostingpackages/add_hosting_option.html:7
#, python-format
@ -266,20 +288,19 @@ msgstr "OS-Nutzer"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:14
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:40
#: hostingpackages/views.py:183
#: hostingpackages/views.py:184
msgid "Disk space"
msgstr "Speicherplatz"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:15
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:54
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:48
#: hostingpackages/views.py:190
#: hostingpackages/views.py:191
msgid "Mailboxes"
msgstr "Postfächer"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:16
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:239
#: hostingpackages/views.py:197
#: hostingpackages/views.py:198
msgid "Databases"
msgstr "Datenbanken"
@ -355,7 +376,7 @@ msgstr ""
"%(disk_space)s für Ihr Hostingpaket"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:45
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:27
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:28
#, python-format
msgid "%(used_space)s of %(disk_space)s (%(space_level_percent)s%%)"
msgstr "%(used_space)s von %(disk_space)s (%(space_level_percent)s%%)"
@ -369,7 +390,7 @@ msgid "Details"
msgstr "Details"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:49
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:31
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:32
#, python-format
msgid ""
"The package contributes %(package_space)s the difference comes from disk "
@ -525,10 +546,6 @@ msgstr "Domain hinzufügen"
msgid "E-Mail-Accounts"
msgstr "E-Mail-Konten"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:202
msgid "Mailbox"
msgstr "Postfach"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:204
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:216
msgid "Active"
@ -603,7 +620,7 @@ msgstr "Speicherplatznutzung Ihres Hostingpakets %(package)s"
msgid "Disk usage of Hosting Package %(package)s of %(full_name)s"
msgstr "Speicherplatznutzung des Hostingpakets %(package)s von %(full_name)s"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:16
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:17
#, python-format
msgid ""
"Disk usage of Hosting Package <a href=\"%(package_url)s\">%(package)s</a>"
@ -611,7 +628,7 @@ msgstr ""
"Speicherplatznutzung des Hostingpakets <a "
"href=\"%(package_url)s\">%(package)s</a>"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:22
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:23
#, python-format
msgid ""
"You use %(used_space)s of the reserved disk space of %(disk_space)s for your "
@ -620,42 +637,43 @@ msgstr ""
"Sie nutzen %(used_space)s des reservierten Speicherplatzes von "
"%(disk_space)s für Ihr Hostingpaket."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:35
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:36
msgid "Breakdown by usage"
msgstr "Aufgliederung nach Nutzung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:37
msgid "Regular file system usage"
msgstr "Reguläre Dateisystemnutzung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:38
msgid "Mailbox usage"
msgstr "Postfachnutzung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:41
msgid "Origin"
msgstr "Quelle"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:43
msgid "Primary email address"
msgstr "Primäre E-Mailadresse"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:42
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:61
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:78
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:44
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:64
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:83
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:102
msgid "Used space"
msgstr "Genutzter Speicherplatz"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:47
msgid "Website data"
msgstr "Webseiten-Daten"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:59
msgid "Website usage"
msgstr "Nutzung für Webauftritte"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:48
msgid "Other"
msgstr "Sonstiges"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:63
msgid "Website / Directory"
msgstr "Webauftritt / Verzeichnis"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:56
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:78
msgid "MySQL/MariaDB database usage"
msgstr "MySQL/MariaDB-Datenbanknutzung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:60
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:77
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:82
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:101
msgid "Database"
msgstr "Datenbank"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:73
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:97
msgid "PostgreSQL database usage"
msgstr "PostgreSQL-Datenbanknutzung"
@ -668,12 +686,12 @@ msgstr ""
"Wählen Sie eine neue Option für das Hostingpaket %(package)s des Kunden "
"%(full_name)s"
#: hostingpackages/views.py:62 hostingpackages/views.py:96
#: hostingpackages/views.py:63 hostingpackages/views.py:97
#, python-brace-format
msgid "Started setup of new hosting package {name}."
msgstr "Einrichtung des Hostingpakets {name} wurde gestartet."
#: hostingpackages/views.py:271
#: hostingpackages/views.py:272
#, python-brace-format
msgid "Successfully added option {option} to hosting package {package}."
msgstr "Option {option} erfolgreich zum Hostingpaket {package} hinzugefügt."

View file

@ -6,11 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
replaces = [
("hostingpackages", "0007_add_disk_usage_table"),
("hostingpackages", "0008_add_default_for_used_kb_change_uniqueness"),
]
dependencies = [
("hostingpackages", "0006_auto_20150125_1510"),
]

View file

@ -0,0 +1,53 @@
# Generated by Django 4.2.3 on 2023-07-23 07:24
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("managemails", "0004_auto_20150125_1825"),
("websites", "0001_initial"),
("hostingpackages", "0007_add_disk_usage_table"),
]
operations = [
migrations.AddField(
model_name="customerpackagediskusage",
name="email_address",
field=models.ForeignKey(
help_text="Assigned mail address",
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="managemails.mailaddress",
verbose_name="mail address",
),
),
migrations.AddField(
model_name="customerpackagediskusage",
name="website",
field=models.ForeignKey(
help_text="Assigned web site",
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="websites.website",
verbose_name="website",
),
),
migrations.RunSQL(
"DELETE FROM hostingpackages_customerpackagediskusage WHERE source='disk'"
),
migrations.AlterField(
model_name="customerpackagediskusage",
name="source",
field=models.CharField(
choices=[
("mail", "Mailbox"),
("web", "Website"),
("mysql", "MariaDB database"),
("pgsql", "PostgreSQL database"),
],
verbose_name="data source",
),
),
]

View file

@ -290,6 +290,8 @@ class CustomerHostingPackage(HostingPackageBase):
used_disk_space_sum = property(get_used_disk_space_sum)
def get_space_level(self):
if not self.diskspace:
return 100.0
return self.used_disk_space_sum / self.disk_space * 100.0
space_level = property(get_space_level)
@ -514,12 +516,31 @@ class CustomerPackageDiskUsage(TimeStampedModel):
)
source = models.CharField(
verbose_name=_("data source"),
choices=(("disk", _("disk")), ("mysql", _("mysql")), ("pgsql", _("pgsql"))),
choices=(
("mail", _("Mailbox")),
("web", _("Website")),
("mysql", _("MariaDB database")),
("pgsql", _("PostgreSQL database")),
),
)
item = models.CharField(verbose_name=_("data item"))
used_kb = models.PositiveBigIntegerField(
verbose_name=_("space used in KiB"), default=0
)
email_address = models.ForeignKey(
"managemails.MailAddress",
verbose_name=_("mail address"),
help_text=_("Assigned mail address"),
on_delete=models.CASCADE,
null=True,
)
website = models.ForeignKey(
"websites.Website",
verbose_name=_("website"),
help_text=_("Assigned web site"),
on_delete=models.CASCADE,
null=True,
)
class Meta:
unique_together = ("package", "source", "item")

View file

@ -44,7 +44,7 @@
You use {{ used_space }} of the reserved disk space of {{ disk_space }} for your hosting package
{% endblocktranslate %}" class="text-{% if space_level > 90.0 %}danger{% elif space_level > 80.0 %}warning{% else %}success{% endif %}">{% blocktranslate with space_level_percent=space_level|floatformat:1 trimmed%}
{{ used_space }} of {{ disk_space }} ({{ space_level_percent }}%)
{% endblocktranslate %} <a title="{% translate "Disk usage details" %}" href="{% url "disk_usage_details" package=hostingpackage.id %}">{% translate "Details" %}</a></span>
{% endblocktranslate %} <a title="{% translate "Disk usage details" %}" href="{% url "disk_usage_details" user=hostingpackage.customer.username package=hostingpackage.id %}">{% translate "Details" %}</a></span>
<i class="bi-info-circle"
title="{% blocktranslate trimmed %}
The package contributes {{ package_space }} the difference comes from disk space options

View file

@ -13,9 +13,10 @@
{% endif %}
{% endspaceless %}{% endblock title %}
{% block page_title %}{% blocktranslate with package=hostingpackage.name package_url=hostingpackage.get_absolute_url trimmed %}
Disk usage of Hosting Package <a href="{{ package_url }}">{{ package }}</a>
{% endblocktranslate %}{% endblock page_title %}
{% block page_title %}
{% blocktranslate with package=hostingpackage.name package_url=hostingpackage.get_absolute_url trimmed %}
Disk usage of Hosting Package <a href="{{ package_url }}">{{ package }}</a>
{% endblocktranslate %}{% endblock page_title %}
{% block content %}
{% with used_space=hostingpackage.get_used_disk_space_sum|filesizeformat disk_space=hostingpackage.get_disk_space|filesizeformat package_space=hostingpackage.get_package_space|filesizeformat space_level=hostingpackage.space_level %}
@ -33,57 +34,82 @@ The package contributes {{ package_space }} the difference comes from disk space
{% endblocktranslate %}"></i>
</p>
<h2>{% trans "Breakdown by usage" %}</h2>
{% if disk_usage %}
<h3>{% trans "Regular file system usage" %}</h3>
<table class="table table-condensed">
{% if mail_usage %}
<h3>{% trans "Mailbox usage" %}</h3>
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>{% translate "Origin" %}</th>
<th>{% translate "Mailbox" %}</th>
<th>{% translate "Primary email address" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
{% for line in disk_usage %}
<tbody>
{% for line in mail_usage %}
<tr>
<td>{% if line.item == "web" %}{% translate "Website data" %}{% elif line.item == "mail" %}
{% translate "Mailboxes" %}{% elif line.item == "other" %}{% translate "Other" %}{% else %}
{{ line.item }}{% endif %}</td>
<td>{{ line.item }}</td>
<td>{% if line.email_address %}{{ line.email_address }}{% else %}-{% endif %}</td>
<td class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if web_usage %}
<h3>{% trans "Website usage" %}</h3>
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>{% translate "Website / Directory" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
<tbody>
{% for line in web_usage %}
<tr>
<td>{{ line.item }}</td>
<td class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if mysql_usage %}
<h3>{% trans "MySQL/MariaDB database usage" %}</h3>
<table class="table table-condensed">
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>{% translate "Database" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
<tbody>
{% for line in mysql_usage %}
<tr>
<td>{{ line.item }}</td>
<td class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if pgsql_usage %}
<h3>{% trans "PostgreSQL database usage" %}</h3>
<table class="table table-condensed">
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>{% translate "Database" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
<tbody>
{% for line in pgsql_usage %}
<tr>
<td>{{ line.item }}</td>
<td class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endwith %}

View file

@ -45,7 +45,7 @@ urlpatterns = [
name="add_hosting_option",
),
path(
"<int:package>/disk-usage/",
"<str:user>/<int:package>/disk-usage/",
CustomerHostingPackageDiskUsageDetails.as_view(),
name="disk_usage_details",
),

View file

@ -6,6 +6,7 @@ from __future__ import absolute_import
import http
import logging
from datetime import timedelta
from django.conf import settings
from django.contrib import messages
@ -13,6 +14,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.utils import timezone
from django.utils.translation import gettext as _
from django.views.generic import DetailView, ListView
from django.views.generic.edit import CreateView, FormView
@ -24,6 +26,7 @@ from rest_framework.views import APIView
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
from managemails.models import Mailbox
from .forms import (
AddDiskspaceOptionForm,
AddMailboxOptionForm,
@ -40,7 +43,7 @@ from .models import (
)
from .serializers import DiskUsageSerializer
logger = logging.getLogger("gnuviechadmin.hostingpackages")
logger = logging.getLogger(__name__)
class CreateHostingPackage(PermissionRequiredMixin, CreateView):
@ -277,8 +280,8 @@ class AddHostingOption(StaffUserRequiredMixin, FormView):
class HasDiskUsageUploadPermission(BasePermission):
def has_permission(self, request, view):
return (
request.user.has_perm("hostingpackages.add_customerpackagediskusage")
and request.method == "POST"
request.user.has_perm("hostingpackages.add_customerpackagediskusage")
and request.method == "POST"
)
@ -290,12 +293,16 @@ class UploadCustomerPackageDiskUsage(APIView):
def post(self, request: rest_framework.request.Request, format=None):
if request.content_type != "application/json":
return Response("Unacceptable", status=http.HTTPStatus.BAD_REQUEST)
submitted_sources = set()
for row in request.data:
user = row["user"]
for key in row:
if key == "user":
continue
else:
submitted_sources.add(key)
for item, size in row[key].items():
try:
package = CustomerHostingPackage.objects.get(
@ -310,36 +317,66 @@ class UploadCustomerPackageDiskUsage(APIView):
item=item,
)
metric.used_kb = size
if key == "mail":
try:
ma_mb = package.mailboxes.get(
username=item
).mailaddressmailbox_set.first()
if ma_mb:
metric.email_address_id = ma_mb.mailaddress_id
except Mailbox.DoesNotExist:
logger.warning("mail box %s does not exist", item)
metric.save()
except CustomerHostingPackage.DoesNotExist:
logger.warning(
"hosting package for user %s does not exist", user
)
logger.info("usage date submitted by %s", request.user)
if submitted_sources:
CustomerPackageDiskUsage.objects.filter(
source__in=submitted_sources,
modified__lt=timezone.now() - timedelta(minutes=30),
).delete()
logger.info("usage data submitted by %s", request.user)
return Response("Accepted", status=http.HTTPStatus.ACCEPTED)
class CustomerHostingPackageDiskUsageDetails(DetailView):
class CustomerHostingPackageDiskUsageDetails(StaffOrSelfLoginRequiredMixin, DetailView):
template_name_suffix = "_disk_usage_details"
model = CustomerHostingPackage
pk_url_kwarg = "package"
context_object_name = "hostingpackage"
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
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)
disk_usage, mysql_usage, pgsql_usage = [], [], []
mail_usage, web_usage, mysql_usage, pgsql_usage = [], [], [], []
for usage in self.get_object().customerpackagediskusage_set.order_by(
"-used_kb"
"-used_kb"
):
if usage.source == "disk":
disk_usage.append(usage)
if usage.used_kb <= 0:
continue
if usage.source == "mail":
mail_usage.append(usage)
elif usage.source == "web":
web_usage.append(usage)
elif usage.source == "mysql":
mysql_usage.append(usage)
elif usage.source == "pgsql":
@ -347,7 +384,9 @@ class CustomerHostingPackageDiskUsageDetails(DetailView):
context_data.update(
{
"disk_usage": disk_usage,
"customer": self.get_customer_object(),
"mail_usage": mail_usage,
"web_usage": web_usage,
"mysql_usage": mysql_usage,
"pgsql_usage": pgsql_usage,
}

1572
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,29 @@
[tool.poetry]
name = "gva"
version = "0.14.0"
version = "0.15.1"
description = "gnuviechadmin web interface"
authors = ["Jan Dittberner <jan@dittberner.info>"]
license = "AGPL-3+"
readme = "README.md"
readme = "README.rst"
[tool.poetry.dependencies]
python = "^3.8"
django = "^4.2"
psycopg2-binary = "^2.9"
celery = "^5.2.7"
django-allauth = "^0.52.0"
django-allauth = "^0.60.0"
django-crispy-forms = "^2.0"
django-debug-toolbar = "^3.8"
django-debug-toolbar = "^4.2"
django-model-utils = "^4.1"
gvacommon = {version = "^0.7.0", source = "gnuviech"}
passlib = "^1.7.4"
redis = "^4.5.1"
redis = "^5.0.1"
requests-oauthlib = "^1.3.1"
django-impersonate = "^1.9.1"
djangorestframework = "^3.14.0"
markdown = "^3.4.3"
django-filter = "^23.1"
crispy-bootstrap5 = "^0.7"
crispy-bootstrap5 = "^2023.10"
python-magic = "^0.4.27"
isort = "^5.12.0"