Compare commits

...

7 commits

Author SHA1 Message Date
22945f72bf Prepare release
- update changelog
- update dependencies
- bump version
2023-07-22 20:12:00 +02:00
d0fe915612 Update german translation 2023-07-22 20:07:01 +02:00
cb62bd63e2 Add disk usage statistics
- add model CustomerPackageDiskUsage for hosting package disk usage
  statistics
- add REST API endpoint for submittings statistics for disk, mysql and
  pgsql usage
- add disk usage information to hosting package detail view
- add separate hosting package disk usage statistic view
2023-07-22 19:43:10 +02:00
affb49a971 Update to Django 4.2
- fix deprecation warnings
- update dependencies
2023-07-08 19:21:02 +02:00
8aadae1c83 Fix Django4 deprecation warnings 2023-07-08 18:34:12 +02:00
30ffdf1751 Update dependencies 2023-07-08 17:01:49 +02:00
aed8e97dbc Fix Poetry deprecation warning 2023-07-08 16:59:04 +02:00
29 changed files with 1513 additions and 1170 deletions

View file

@ -1,6 +1,9 @@
Changelog Changelog
========= =========
* :release:`0.14.0 <2023-07-22>`
* :feature:`-` add disk space statistics
* :release:`0.13.0 <2023-05-08>` * :release:`0.13.0 <2023-05-08>`
* :feature:`-` add REST API to retrieve and set user information as admin * :feature:`-` add REST API to retrieve and set user information as admin
* :feature:`-` add support model for offline account reset codes in new help * :feature:`-` add support model for offline account reset codes in new help

View file

@ -20,46 +20,49 @@ import django
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath(os.path.join('..', 'gnuviechadmin'))) sys.path.insert(0, os.path.abspath(os.path.join("..", "gnuviechadmin")))
os.environ['DJANGO_SETTINGS_MODULE'] = 'gnuviechadmin.settings' os.environ["DJANGO_SETTINGS_MODULE"] = "gnuviechadmin.settings"
os.environ['GVA_SITE_ADMINMAIL'] = 'admin@gva.example.org' os.environ["GVA_SITE_ADMINMAIL"] = "admin@gva.example.org"
django.setup() django.setup()
# -- General configuration ----------------------------------------------------- # -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here. # If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0' # needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [ extensions = [
'releases', 'sphinx.ext.autodoc', 'celery.contrib.sphinx', "releases",
'sphinxcontrib.blockdiag'] "sphinx.ext.autodoc",
"celery.contrib.sphinx",
"sphinxcontrib.blockdiag",
]
# configuration for releases extension # configuration for releases extension
releases_issue_uri = 'https://git.dittberner.info/gnuviech/gva/issues/%s' releases_issue_uri = "https://git.dittberner.info/gnuviech/gva/issues/%s"
releases_release_uri = 'https://git.dittberner.info/gnuviech/gva/src/tag/%s' releases_release_uri = "https://git.dittberner.info/gnuviech/gva/src/tag/%s"
# configuration for blockdiag extension # configuration for blockdiag extension
blockdiag_fontpath = '/usr/share/fonts/truetype/dejavu/' blockdiag_fontpath = "/usr/share/fonts/truetype/dejavu/"
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ["_templates"]
# The suffix of source filenames. # The suffix of source filenames.
source_suffix = '.rst' source_suffix = ".rst"
# The encoding of source files. # The encoding of source files.
#source_encoding = 'utf-8-sig' # source_encoding = 'utf-8-sig'
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = "index"
# General information about the project. # General information about the project.
project = u'gnuviechadmin' project = "gnuviechadmin"
copyright = u'2014-2020, Jan Dittberner' copyright = "2014-2023, Jan Dittberner"
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -69,121 +72,121 @@ copyright = u'2014-2020, Jan Dittberner'
from gnuviechadmin import __version__ as release from gnuviechadmin import __version__ as release
# The short X.Y version. # The short X.Y version.
version = ".".join(release.split('.')[:2]) version = ".".join(release.split(".")[:2])
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
#language = None # language = None
# There are two options for replacing |today|: either, you set today to some # There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used: # non-false value, then it is used:
#today = '' # today = ''
# Else, today_fmt is used as the format for a strftime call. # Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y' # today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
exclude_patterns = ['_build'] exclude_patterns = ["_build"]
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None # default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text. # If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True # add_function_parentheses = True
# If true, the current module name will be prepended to all description # If true, the current module name will be prepended to all description
# unit titles (such as .. function::). # unit titles (such as .. function::).
#add_module_names = True # add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the # If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default. # output. They are ignored by default.
#show_authors = False # show_authors = False
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting. # A list of ignored prefixes for module index sorting.
#modindex_common_prefix = [] # modindex_common_prefix = []
# -- Options for HTML output --------------------------------------------------- # -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'alabaster' html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme # Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the # further. For a list of options available for each theme, see the
# documentation. # documentation.
#html_theme_options = {} # html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory. # Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = [] # html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
#html_title = None # html_title = None
# A shorter title for the navigation bar. Default is the same as html_title. # A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None # html_short_title = None
# The name of an image file (relative to this directory) to place at the top # The name of an image file (relative to this directory) to place at the top
# of the sidebar. # of the sidebar.
#html_logo = None # html_logo = None
# The name of an image file (within the static path) to use as favicon of the # The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large. # pixels large.
#html_favicon = None # html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ["_static"]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format. # using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y' # html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to # If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities. # typographically correct entities.
#html_use_smartypants = True # html_use_smartypants = True
# Custom sidebar templates, maps document names to template names. # Custom sidebar templates, maps document names to template names.
#html_sidebars = {} # html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to # Additional templates that should be rendered to pages, maps page names to
# template names. # template names.
#html_additional_pages = {} # html_additional_pages = {}
# If false, no module index is generated. # If false, no module index is generated.
#html_domain_indices = True # html_domain_indices = True
# If false, no index is generated. # If false, no index is generated.
#html_use_index = True # html_use_index = True
# If true, the index is split into individual pages for each letter. # If true, the index is split into individual pages for each letter.
#html_split_index = False # html_split_index = False
# If true, links to the reST sources are added to the pages. # If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True # html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True # html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True # html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will # If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the # contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served. # base URL from which the finished HTML is served.
#html_use_opensearch = '' # html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml"). # This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None # html_file_suffix = None
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'gnuviechadmindoc' htmlhelp_basename = "gnuviechadmindoc"
# -- Options for LaTeX output -------------------------------------------------- # -- Options for LaTeX output --------------------------------------------------
@ -191,10 +194,8 @@ htmlhelp_basename = 'gnuviechadmindoc'
latex_elements = { latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper', #'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt'). # The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt', #'pointsize': '10pt',
# Additional stuff for the LaTeX preamble. # Additional stuff for the LaTeX preamble.
#'preamble': '', #'preamble': '',
} }
@ -202,29 +203,34 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'gnuviechadmin.tex', u'gnuviechadmin Documentation', (
u'Jan Dittberner', 'manual'), "index",
"gnuviechadmin.tex",
"gnuviechadmin Documentation",
"Jan Dittberner",
"manual",
),
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
# the title page. # the title page.
#latex_logo = None # latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts, # For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters. # not chapters.
#latex_use_parts = False # latex_use_parts = False
# If true, show page references after internal links. # If true, show page references after internal links.
#latex_show_pagerefs = False # latex_show_pagerefs = False
# If true, show URL addresses after external links. # If true, show URL addresses after external links.
#latex_show_urls = False # latex_show_urls = False
# Documents to append as an appendix to all manuals. # Documents to append as an appendix to all manuals.
#latex_appendices = [] # latex_appendices = []
# If false, no module index is generated. # If false, no module index is generated.
#latex_domain_indices = True # latex_domain_indices = True
# -- Options for manual page output -------------------------------------------- # -- Options for manual page output --------------------------------------------
@ -232,12 +238,11 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'gnuviechadmin', u'gnuviechadmin Documentation', ("index", "gnuviechadmin", "gnuviechadmin Documentation", ["Jan Dittberner"], 1)
[u'Jan Dittberner'], 1)
] ]
# If true, show URL addresses after external links. # If true, show URL addresses after external links.
#man_show_urls = False # man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------ # -- Options for Texinfo output ------------------------------------------------
@ -246,16 +251,22 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
('index', 'gnuviechadmin', u'gnuviechadmin Documentation', (
u'Jan Dittberner', 'gnuviechadmin', 'Customer center for gnuviech servers.', "index",
'Miscellaneous'), "gnuviechadmin",
"gnuviechadmin Documentation",
"Jan Dittberner",
"gnuviechadmin",
"Customer center for gnuviech servers.",
"Miscellaneous",
),
] ]
# Documents to append as an appendix to all manuals. # Documents to append as an appendix to all manuals.
#texinfo_appendices = [] # texinfo_appendices = []
# If false, no module index is generated. # If false, no module index is generated.
#texinfo_domain_indices = True # texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'. # How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote' # texinfo_show_urls = 'footnote'

View file

@ -7,6 +7,7 @@ from __future__ import absolute_import, unicode_literals
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit from crispy_forms.layout import Submit
from django import forms from django import forms
from django.apps import apps
from django.conf import settings from django.conf import settings
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.contrib.sites.requests import RequestSite from django.contrib.sites.requests import RequestSite
@ -41,7 +42,7 @@ class ContactForm(forms.Form):
def get_context(self): def get_context(self):
if not self.is_valid(): if not self.is_valid():
raise ValueError("Cannot generate context from invalid contact form") raise ValueError("Cannot generate context from invalid contact form")
if Site._meta.installed: if apps.is_installed("django.contrib.sites"):
site = Site.objects.get_current() site = Site.objects.get_current()
else: else:
site = RequestSite(self.request) site = RequestSite(self.request)

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: contact_form\n" "Project-Id-Version: contact_form\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-22 13:01+0200\n" "POT-Creation-Date: 2023-07-22 19:45+0200\n"
"PO-Revision-Date: 2023-04-22 13:01+0200\n" "PO-Revision-Date: 2023-04-22 13:01+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
@ -19,19 +19,19 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n" "X-Generator: Poedit 3.2.2\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
#: contact_form/forms.py:25 #: contact_form/forms.py:26
msgid "Your name" msgid "Your name"
msgstr "Ihr Name" msgstr "Ihr Name"
#: contact_form/forms.py:26 #: contact_form/forms.py:27
msgid "Your email address" msgid "Your email address"
msgstr "Ihre E-Mail-Adresse" msgstr "Ihre E-Mail-Adresse"
#: contact_form/forms.py:27 #: contact_form/forms.py:28
msgid "Your message" msgid "Your message"
msgstr "Ihre Nachricht" msgstr "Ihre Nachricht"
#: contact_form/forms.py:39 #: contact_form/forms.py:40
msgid "Send message" msgid "Send message"
msgstr "Nachricht senden" msgstr "Nachricht senden"

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnuviechadmin dashboard\n" "Project-Id-Version: gnuviechadmin dashboard\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-16 22:07+0200\n" "POT-Creation-Date: 2023-07-22 19:45+0200\n"
"PO-Revision-Date: 2023-04-16 18:31+0200\n" "PO-Revision-Date: 2023-07-22 19:46+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -19,25 +19,6 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n" "X-Generator: Poedit 3.2.2\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
#: dashboard/templates/dashboard/index.html:3
msgid "Welcome"
msgstr "Willkommen"
#: dashboard/templates/dashboard/index.html:4
msgid "Welcome to our customer self service"
msgstr "Willkommen in unserem Selbstservice-System"
#: dashboard/templates/dashboard/index.html:7
#, python-format
msgid ""
"Hello %(full_name)s,<br/> You can visit your <a "
"href=\"%(dashboard_url)s\">Dashboard</a> to view and modify your hosting "
"options."
msgstr ""
"Hallo %(full_name)s,<br /> Sie können Ihre <a "
"href=\"%(dashboard_url)s\">Startseite</a> besuchen, um Ihre "
"Hostingeinstellungen anzusehen und zu bearbeiten."
#: dashboard/templates/dashboard/user_dashboard.html:3 #: dashboard/templates/dashboard/user_dashboard.html:3
#: dashboard/templates/dashboard/user_dashboard.html:6 #: dashboard/templates/dashboard/user_dashboard.html:6
#, python-format #, python-format
@ -53,46 +34,26 @@ msgid "Name"
msgstr "Name" msgstr "Name"
#: dashboard/templates/dashboard/user_dashboard.html:18 #: dashboard/templates/dashboard/user_dashboard.html:18
msgid "Disk space" msgid "Setup date"
msgstr "Speicherplatz" msgstr "Einrichtungsdatum"
#: dashboard/templates/dashboard/user_dashboard.html:19 #: dashboard/templates/dashboard/user_dashboard.html:19
msgid "Mailboxes"
msgstr "Postfächer"
#: dashboard/templates/dashboard/user_dashboard.html:20
msgid "Databases"
msgstr "Datenbanken"
#: dashboard/templates/dashboard/user_dashboard.html:21
msgid "Actions" msgid "Actions"
msgstr "Aktionen" msgstr "Aktionen"
#: dashboard/templates/dashboard/user_dashboard.html:28 #: dashboard/templates/dashboard/user_dashboard.html:26
#, python-format #, python-format
msgid "Show details for %(packagename)s" msgid "Show details for %(packagename)s"
msgstr "Details für %(packagename)s anzeigen" msgstr "Details für %(packagename)s anzeigen"
#: dashboard/templates/dashboard/user_dashboard.html:34 #: dashboard/templates/dashboard/user_dashboard.html:38
#, python-format
msgid ""
"The reserved disk space for your hosting package is %(diskspace)s bytes."
msgstr ""
"Der für Ihr Hostingpaket reservierte Speicherplatz sind %(diskspace)s Bytes."
#: dashboard/templates/dashboard/user_dashboard.html:40
#, python-format
msgid "used %(num)s of %(total)s"
msgstr "%(num)s von %(total)s genutzt"
#: dashboard/templates/dashboard/user_dashboard.html:55
msgid "You have no hosting packages yet." msgid "You have no hosting packages yet."
msgstr "Sie haben noch keine Hostingpakete." msgstr "Sie haben noch keine Hostingpakete."
#: dashboard/templates/dashboard/user_dashboard.html:56 #: dashboard/templates/dashboard/user_dashboard.html:39
msgid "This user has no hosting packages assigned yet." msgid "This user has no hosting packages assigned yet."
msgstr "Diesem Benutzer sind noch keine Hostingpakete zugewiesen." msgstr "Diesem Benutzer sind noch keine Hostingpakete zugewiesen."
#: dashboard/templates/dashboard/user_dashboard.html:60 #: dashboard/templates/dashboard/user_dashboard.html:43
msgid "Add hosting package" msgid "Add hosting package"
msgstr "Hostingpaket anlegen" msgstr "Hostingpaket anlegen"

View file

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

View file

@ -76,9 +76,6 @@ SITES_SITE_NAME = get_env_variable("GVA_SITE_NAME")
# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n # See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True USE_I18N = True
# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True
# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz # See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True USE_TZ = True
# ######### END GENERAL CONFIGURATION # ######### END GENERAL CONFIGURATION

View file

@ -1,7 +1,7 @@
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from help.models import HelpUser from help.models import HelpUser

View file

@ -2,7 +2,7 @@ import uuid
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
class HelpUser(models.Model): class HelpUser(models.Model):

View file

@ -12,6 +12,7 @@ from .models import (
CustomerHostingPackage, CustomerHostingPackage,
CustomerHostingPackageDomain, CustomerHostingPackageDomain,
CustomerMailboxOption, CustomerMailboxOption,
CustomerPackageDiskUsage,
CustomerUserDatabaseOption, CustomerUserDatabaseOption,
DiskSpaceOption, DiskSpaceOption,
HostingPackageTemplate, HostingPackageTemplate,
@ -95,6 +96,18 @@ class CustomerHostingPackageDomainInline(admin.TabularInline):
extra = 0 extra = 0
class CustomerPackageDiskUsageInline(admin.TabularInline):
model = CustomerPackageDiskUsage
ordering = ["-used_kb", "source", "item"]
fields = ["source", "item", "used_kb"]
readonly_fields = ["source", "item", "used_kb"]
extra = 0
can_delete = False
def has_add_permission(self, request, obj):
return False
class CustomerHostingPackageAdmin(admin.ModelAdmin): class CustomerHostingPackageAdmin(admin.ModelAdmin):
""" """
This class implements the admin interface for This class implements the admin interface for
@ -110,6 +123,7 @@ class CustomerHostingPackageAdmin(admin.ModelAdmin):
CustomerMailboxOptionInline, CustomerMailboxOptionInline,
CustomerUserDatabaseOptionInline, CustomerUserDatabaseOptionInline,
CustomerHostingPackageDomainInline, CustomerHostingPackageDomainInline,
CustomerPackageDiskUsageInline,
] ]
list_display = ["name", "customer", "osuser"] list_display = ["name", "customer", "osuser"]

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnuviechadmin hostingpackages\n" "Project-Id-Version: gnuviechadmin hostingpackages\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-22 13:14+0200\n" "POT-Creation-Date: 2023-07-22 20:06+0200\n"
"PO-Revision-Date: 2023-04-22 13:15+0200\n" "PO-Revision-Date: 2023-07-22 20:06+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -39,177 +39,206 @@ msgstr "Postfachoption hinzufügen"
msgid "Add database option" msgid "Add database option"
msgstr "Datenbankoption hinzufügen" msgstr "Datenbankoption hinzufügen"
#: hostingpackages/models.py:21 #: hostingpackages/models.py:22
msgid "MiB" msgid "MiB"
msgstr "MiB" msgstr "MiB"
#: hostingpackages/models.py:21 #: hostingpackages/models.py:22
msgid "GiB" msgid "GiB"
msgstr "GiB" msgstr "GiB"
#: hostingpackages/models.py:21 #: hostingpackages/models.py:22
msgid "TiB" msgid "TiB"
msgstr "TiB" msgstr "TiB"
#: hostingpackages/models.py:27 #: hostingpackages/models.py:28
msgid "description" msgid "description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: hostingpackages/models.py:28 #: hostingpackages/models.py:29
msgid "mailbox count" msgid "mailbox count"
msgstr "Anzahl Postfächer" msgstr "Anzahl Postfächer"
#: hostingpackages/models.py:30 hostingpackages/models.py:59 #: hostingpackages/models.py:31 hostingpackages/models.py:60
msgid "disk space" msgid "disk space"
msgstr "Speicherplatz" msgstr "Speicherplatz"
#: hostingpackages/models.py:30 #: hostingpackages/models.py:31
msgid "disk space for the hosting package" msgid "disk space for the hosting package"
msgstr "Speicherplatz für das Hostingpaket" msgstr "Speicherplatz für das Hostingpaket"
#: hostingpackages/models.py:33 hostingpackages/models.py:61 #: hostingpackages/models.py:34 hostingpackages/models.py:62
msgid "unit of disk space" msgid "unit of disk space"
msgstr "Maßeinheit für den Speicherplatz" msgstr "Maßeinheit für den Speicherplatz"
#: hostingpackages/models.py:44 hostingpackages/models.py:192 #: hostingpackages/models.py:45 hostingpackages/models.py:193
msgid "name" msgid "name"
msgstr "Name" msgstr "Name"
#: hostingpackages/models.py:47 #: hostingpackages/models.py:48
msgid "Hosting package" msgid "Hosting package"
msgstr "Hostingpaket" msgstr "Hostingpaket"
#: hostingpackages/models.py:48 #: hostingpackages/models.py:49
msgid "Hosting packages" msgid "Hosting packages"
msgstr "Hostingpakete" msgstr "Hostingpakete"
#: hostingpackages/models.py:67 #: hostingpackages/models.py:68
msgid "Disk space option" msgid "Disk space option"
msgstr "Speicherplatzoption" msgstr "Speicherplatzoption"
#: hostingpackages/models.py:68 #: hostingpackages/models.py:69
msgid "Disk space options" msgid "Disk space options"
msgstr "Speicherplatzoptionen" msgstr "Speicherplatzoptionen"
#: hostingpackages/models.py:71 #: hostingpackages/models.py:72
#, python-brace-format #, python-brace-format
msgid "Additional disk space {space} {unit}" msgid "Additional disk space {space} {unit}"
msgstr "Zusätzlicher Speicherplatz {space} {unit}" msgstr "Zusätzlicher Speicherplatz {space} {unit}"
#: hostingpackages/models.py:88 #: hostingpackages/models.py:89
msgid "number of databases" msgid "number of databases"
msgstr "Anzahl von Datenbanken" msgstr "Anzahl von Datenbanken"
#: hostingpackages/models.py:89 #: hostingpackages/models.py:90
msgid "database type" msgid "database type"
msgstr "Datenbanktyp" msgstr "Datenbanktyp"
#: hostingpackages/models.py:94 #: hostingpackages/models.py:95
msgid "Database option" msgid "Database option"
msgstr "Datenbankoption" msgstr "Datenbankoption"
#: hostingpackages/models.py:95 #: hostingpackages/models.py:96
msgid "Database options" msgid "Database options"
msgstr "Datenbankoptionen" msgstr "Datenbankoptionen"
#: hostingpackages/models.py:99 #: hostingpackages/models.py:100
#, python-brace-format #, python-brace-format
msgid "{type} database" msgid "{type} database"
msgid_plural "{count} {type} databases" msgid_plural "{count} {type} databases"
msgstr[0] "{type}-Datenbank" msgstr[0] "{type}-Datenbank"
msgstr[1] "{count} {type}-Datenbanken" msgstr[1] "{count} {type}-Datenbanken"
#: hostingpackages/models.py:120 #: hostingpackages/models.py:121
msgid "number of mailboxes" msgid "number of mailboxes"
msgstr "Anzahl von Postfächern" msgstr "Anzahl von Postfächern"
#: hostingpackages/models.py:125 #: hostingpackages/models.py:126
msgid "Mailbox option" msgid "Mailbox option"
msgstr "Postfachoption" msgstr "Postfachoption"
#: hostingpackages/models.py:126 #: hostingpackages/models.py:127
msgid "Mailbox options" msgid "Mailbox options"
msgstr "Postfachoptionen" msgstr "Postfachoptionen"
#: hostingpackages/models.py:130 #: hostingpackages/models.py:131
#, python-brace-format #, python-brace-format
msgid "{count} additional mailbox" msgid "{count} additional mailbox"
msgid_plural "{count} additional mailboxes" msgid_plural "{count} additional mailboxes"
msgstr[0] "{count} zusätzliches Postfach" msgstr[0] "{count} zusätzliches Postfach"
msgstr[1] "{count} zusätzliche Postfächer" msgstr[1] "{count} zusätzliche Postfächer"
#: hostingpackages/models.py:182 #: hostingpackages/models.py:183
msgid "customer" msgid "customer"
msgstr "Kunde" msgstr "Kunde"
#: hostingpackages/models.py:186 #: hostingpackages/models.py:187
msgid "hosting package template" msgid "hosting package template"
msgstr "Hostingpaketvorlage" msgstr "Hostingpaketvorlage"
#: hostingpackages/models.py:188 #: hostingpackages/models.py:189
msgid "The hosting package template that this hosting package is based on" msgid "The hosting package template that this hosting package is based on"
msgstr "Die Hostingpaketvorlage, auf der dieses Hostingpaket aufgebaut ist" msgstr "Die Hostingpaketvorlage, auf der dieses Hostingpaket aufgebaut ist"
#: hostingpackages/models.py:195 #: hostingpackages/models.py:196
msgid "Operating system user" msgid "Operating system user"
msgstr "Betriebssystemnutzer" msgstr "Betriebssystemnutzer"
#: hostingpackages/models.py:205 #: hostingpackages/models.py:206
msgid "customer hosting package" msgid "customer hosting package"
msgstr "Kundenhostingpaket" msgstr "Kundenhostingpaket"
#: hostingpackages/models.py:206 #: hostingpackages/models.py:207
msgid "customer hosting packages" msgid "customer hosting packages"
msgstr "Kundenhostingpakete" msgstr "Kundenhostingpakete"
#: hostingpackages/models.py:209 #: hostingpackages/models.py:210
#, python-brace-format #, python-brace-format
msgid "{name} for {customer}" msgid "{name} for {customer}"
msgstr "{name} für {customer}" msgstr "{name} für {customer}"
#: hostingpackages/models.py:388 hostingpackages/models.py:415 #: hostingpackages/models.py:419 hostingpackages/models.py:446
#: hostingpackages/models.py:511
msgid "hosting package" msgid "hosting package"
msgstr "Hostingpaket" msgstr "Hostingpaket"
#: hostingpackages/models.py:393 #: hostingpackages/models.py:424
msgid "hosting domain" msgid "hosting domain"
msgstr "Hostingdomain" msgstr "Hostingdomain"
#: hostingpackages/models.py:420 #: hostingpackages/models.py:451
msgid "customer hosting option" msgid "customer hosting option"
msgstr "kundenspezifische Hostingoption" msgstr "kundenspezifische Hostingoption"
#: hostingpackages/models.py:421 #: hostingpackages/models.py:452
msgid "customer hosting options" msgid "customer hosting options"
msgstr "kundenspezifische Hostingoptionen" msgstr "kundenspezifische Hostingoptionen"
#: hostingpackages/models.py:433 #: hostingpackages/models.py:464
msgid "disk space option template" msgid "disk space option template"
msgstr "Speicherplatzoptionsvorlage" msgstr "Speicherplatzoptionsvorlage"
#: hostingpackages/models.py:435 #: hostingpackages/models.py:466
msgid "The disk space option template that this disk space option is based on" msgid "The disk space option template that this disk space option is based on"
msgstr "" msgstr ""
"Die Speicherplatzoptionsvorlage auf der diese Speicherplatzoption aufgebaut " "Die Speicherplatzoptionsvorlage auf der diese Speicherplatzoption aufgebaut "
"ist" "ist"
#: hostingpackages/models.py:450 #: hostingpackages/models.py:481
msgid "user database option template" msgid "user database option template"
msgstr "Nutzerdatenbankoptionsvorlage" msgstr "Nutzerdatenbankoptionsvorlage"
#: hostingpackages/models.py:452 #: hostingpackages/models.py:483
msgid "The user database option template that this database option is based on" msgid "The user database option template that this database option is based on"
msgstr "" msgstr ""
"Die Nutzerdatenbankoptionsvorlage auf der diese Datenbankoption aufgebaut ist" "Die Nutzerdatenbankoptionsvorlage auf der diese Datenbankoption aufgebaut ist"
#: hostingpackages/models.py:467 #: hostingpackages/models.py:498
msgid "mailbox option template" msgid "mailbox option template"
msgstr "Postfachoptionsvorlage" msgstr "Postfachoptionsvorlage"
#: hostingpackages/models.py:468 #: hostingpackages/models.py:499
msgid "The mailbox option template that this mailbox option is based on" msgid "The mailbox option template that this mailbox option is based on"
msgstr "Die Postfachoptionsvorlage auf der diese Postfachoption aufgebaut ist" msgstr "Die Postfachoptionsvorlage auf der diese Postfachoption aufgebaut ist"
#: hostingpackages/models.py:512
msgid "The hosting package"
msgstr "Das Hostingpaket"
#: hostingpackages/models.py:516
msgid "data source"
msgstr "Datenquelle"
#: hostingpackages/models.py:517
msgid "disk"
msgstr "Festplatte"
#: hostingpackages/models.py:517
msgid "mysql"
msgstr "MySQL"
#: hostingpackages/models.py:517
msgid "pgsql"
msgstr "PostgreSQL"
#: hostingpackages/models.py:519
msgid "data item"
msgstr "Dateneinheit"
#: hostingpackages/models.py:521
msgid "space used in KiB"
msgstr "genutzter Platz in KiB"
#: hostingpackages/templates/hostingpackages/add_hosting_option.html:4 #: hostingpackages/templates/hostingpackages/add_hosting_option.html:4
#: hostingpackages/templates/hostingpackages/add_hosting_option.html:7 #: hostingpackages/templates/hostingpackages/add_hosting_option.html:7
#, python-format #, python-format
@ -224,7 +253,6 @@ msgstr "Alle Hostingpakete"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:11 #: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:11
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:36 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:36
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:26
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@ -237,16 +265,46 @@ msgid "OS User"
msgstr "OS-Nutzer" msgstr "OS-Nutzer"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:14 #: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:14
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:27 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:40
#: hostingpackages/views.py:183
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
msgid "Mailboxes"
msgstr "Postfächer"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:16
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:239
#: hostingpackages/views.py:197
msgid "Databases"
msgstr "Datenbanken"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:17
msgid "Setup date" msgid "Setup date"
msgstr "Einrichtungsdatum" msgstr "Einrichtungsdatum"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:31 #: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:28
#, python-format
msgid ""
"The reserved disk space for your hosting package is %(diskspace)s bytes."
msgstr ""
"Der für Ihr Hostingpaket reservierte Speicherplatz beträgt %(diskspace)s "
"Bytes."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:34
#, python-format
msgid "used %(num)s of %(total)s"
msgstr "used %(num)s of %(total)s"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:48
msgid "No hosting packages have been setup yet." msgid "No hosting packages have been setup yet."
msgstr "Es wurden noch keine Hostingpakete eingerichtet." msgstr "Es wurden noch keine Hostingpakete eingerichtet."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:34 #: hostingpackages/templates/hostingpackages/customerhostingpackage_admin_list.html:51
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:46
msgid "Add hosting package" msgid "Add hosting package"
msgstr "Hostingpaket anlegen" msgstr "Hostingpaket anlegen"
@ -287,38 +345,45 @@ msgstr "Informationen zum Hostingpaket ändern"
msgid "Description" msgid "Description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:40
#: hostingpackages/views.py:199
msgid "Disk space"
msgstr "Speicherplatz"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:43 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:43
#, python-format #, python-format
msgid "The reserved disk space for your hosting package is %(diskspace)s bytes" msgid ""
"You use %(used_space)s of the reserved disk space of %(disk_space)s for your "
"hosting package"
msgstr "" msgstr ""
"Der für Ihr Hostingpaket reservierte Speicherplatz beträgt %(diskspace)s " "Sie nutzen aktuell %(used_space)s des reservierten Speicherplatzes von "
"Bytes" "%(disk_space)s für Ihr Hostingpaket"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:45
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:27
#, 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%%)"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:47 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:47
msgid "Disk usage details"
msgstr "Details zur Speicherplatznutzung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:47
msgid "Details"
msgstr "Details"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:49
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:31
#, python-format #, python-format
msgid "" msgid ""
"The package contributes %(humanbytes)s (%(packagespace)s bytes) the " "The package contributes %(package_space)s the difference comes from disk "
"difference comes from disk space options" "space options"
msgstr "" msgstr ""
"Das Paket trägt %(humanbytes)s (%(packagespace)s Bytes) zur Gesamtgröße bei, " "Das Paket trägt %(package_space)s zur Gesamtgröße bei, der Unterschied "
"der Unterschied ergibt sich aus Speicherplatzoptionen" "ergibt sich aus Speicherplatzoptionen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:52 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:56
#: hostingpackages/views.py:206
msgid "Mailboxes"
msgstr "Postfächer"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:54
#, python-format #, python-format
msgid "%(num)s of %(total)s in use" msgid "%(num)s of %(total)s in use"
msgstr "%(num)s von %(total)s genutzt" msgstr "%(num)s von %(total)s genutzt"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:57 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:59
#, python-format #, python-format
msgid "" msgid ""
"The package provides %(mailboxcount)s mailboxes the difference comes from " "The package provides %(mailboxcount)s mailboxes the difference comes from "
@ -327,234 +392,272 @@ msgstr ""
"Das Paket bietet %(mailboxcount)s Postfächer, der Unterschied ergibt sich " "Das Paket bietet %(mailboxcount)s Postfächer, der Unterschied ergibt sich "
"durch die Postfachoptionen." "durch die Postfachoptionen."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:59 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:61
msgid "SFTP username" msgid "SFTP username"
msgstr "SFTP-Benutzername" msgstr "SFTP-Benutzername"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:60 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:62
msgid "SSH/SFTP username" msgid "SSH/SFTP username"
msgstr "SSH/SFTP-Benutzername" msgstr "SSH/SFTP-Benutzername"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:63 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:65
#, python-format #, python-format
msgid "There is an SSH public key set for this user." msgid "There is an SSH public key set for this user."
msgid_plural "There are %(counter)s SSH public keys set for this user." msgid_plural "There are %(counter)s SSH public keys set for this user."
msgstr[0] "Es wurde ein SSH-Schlüssel für diesen Nutzer hinterlegt." msgstr[0] "Es wurde ein SSH-Schlüssel für diesen Nutzer hinterlegt."
msgstr[1] "Es wurden %(counter)s SSH-Schlüssel für diesen Nutzer hinterlegt." msgstr[1] "Es wurden %(counter)s SSH-Schlüssel für diesen Nutzer hinterlegt."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:65 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:67
msgid "Upload server" msgid "Upload server"
msgstr "Uploadserver" msgstr "Uploadserver"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:73 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:75
msgid "Hosting Package Options" msgid "Hosting Package Options"
msgstr "Hostingpaketoptionen" msgstr "Hostingpaketoptionen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:81 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:83
msgid "No options booked" msgid "No options booked"
msgstr "Keine Optionen gebucht" msgstr "Keine Optionen gebucht"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:87 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:89
msgid "Add another hosting option" msgid "Add another hosting option"
msgstr "Eine weitere Hostingoption hinzufügen" msgstr "Eine weitere Hostingoption hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:87 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:89
msgid "Add option" msgid "Add option"
msgstr "Option hinzufügen" msgstr "Option hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:94 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:96
msgid "Hosting Package Actions" msgid "Hosting Package Actions"
msgstr "Aktionen zum Hostingpaket" msgstr "Aktionen zum Hostingpaket"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:98 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:100
msgid "Edit Hosting Package Description" msgid "Edit Hosting Package Description"
msgstr "Beschreibung des Hostingpakets bearbeiten" msgstr "Beschreibung des Hostingpakets bearbeiten"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:98 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:100
msgid "Edit description" msgid "Edit description"
msgstr "Beschreibung bearbeiten" msgstr "Beschreibung bearbeiten"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:101 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:103
msgid "Set SFTP password" msgid "Set SFTP password"
msgstr "SFTP-Passwort setzen" msgstr "SFTP-Passwort setzen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:102 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:104
msgid "Set SSH/SFTP password" msgid "Set SSH/SFTP password"
msgstr "SSH/SFTP-Passwort setzen" msgstr "SSH/SFTP-Passwort setzen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:105 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:107
msgid "Add an SSH public key that can be used as an alternative for password" msgid "Add an SSH public key that can be used as an alternative for password"
msgstr "" msgstr ""
"Einen SSH-Schlüssel, der als Alternative zum Passwort genutzt werden kann, " "Einen SSH-Schlüssel, der als Alternative zum Passwort genutzt werden kann, "
"hinzufügen" "hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:107 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:109
msgid "Add SSH public key" msgid "Add SSH public key"
msgstr "SSH-Schlüssel hinzufügen" msgstr "SSH-Schlüssel hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:116 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:118
msgid "Domains" msgid "Domains"
msgstr "Domains" msgstr "Domains"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:121 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:123
msgid "Domain name" msgid "Domain name"
msgstr "Domainname" msgstr "Domainname"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:122 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:124
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:201 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:203
msgid "Mail addresses" msgid "Mail addresses"
msgstr "E-Mailadressen" msgstr "E-Mailadressen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:123 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:125
msgid "Websites" msgid "Websites"
msgstr "Webauftritte" msgstr "Webauftritte"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:124 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:126
msgid "Domain actions" msgid "Domain actions"
msgstr "Domainaktionen" msgstr "Domainaktionen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:125 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:127
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:204 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:206
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:247 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:249
msgid "Actions" msgid "Actions"
msgstr "Aktionen" msgstr "Aktionen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:137 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:139
msgid "Edit mail address targets" msgid "Edit mail address targets"
msgstr "E-Mailadressziele bearbeiten" msgstr "E-Mailadressziele bearbeiten"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:139
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:141 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:141
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:143
msgid "Delete mail address" msgid "Delete mail address"
msgstr "E-Mailadresse löschen" msgstr "E-Mailadresse löschen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:146 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:148
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:161 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:163
msgid "None" msgid "None"
msgstr "Keine" msgstr "Keine"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:154
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:156 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:156
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:158
msgid "Delete website" msgid "Delete website"
msgstr "Webauftritt löschen" msgstr "Webauftritt löschen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:167
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:169 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:169
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:171
msgid "Add mail address" msgid "Add mail address"
msgstr "E-Mailadresse hinzufügen" msgstr "E-Mailadresse hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:174 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:176
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:175 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:177
msgid "Add website" msgid "Add website"
msgstr "Webauftritt anlegen" msgstr "Webauftritt anlegen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:183 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:185
msgid "There are no domains assigned to this hosting package yet." msgid "There are no domains assigned to this hosting package yet."
msgstr "Diesem Paket sind noch keine Domains zugeordnet." msgstr "Diesem Paket sind noch keine Domains zugeordnet."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:187 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:189
msgid "Add domain" msgid "Add domain"
msgstr "Domain hinzufügen" msgstr "Domain hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:195 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:197
msgid "E-Mail-Accounts" msgid "E-Mail-Accounts"
msgstr "E-Mail-Konten" msgstr "E-Mail-Konten"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:200 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:202
msgid "Mailbox" msgid "Mailbox"
msgstr "Postfach" msgstr "Postfach"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:202 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:204
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:214 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:216
msgid "Active" msgid "Active"
msgstr "Aktiv" msgstr "Aktiv"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:203 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:205
msgid "Mailbox actions" msgid "Mailbox actions"
msgstr "Postfachaktionen" msgstr "Postfachaktionen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:215 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:217
msgid "inactive" msgid "inactive"
msgstr "inaktiv" msgstr "inaktiv"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:218 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:220
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:219 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:221
msgid "Set mailbox password" msgid "Set mailbox password"
msgstr "Postfachpasswort setzen" msgstr "Postfachpasswort setzen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:225 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:227
msgid "There are no mailboxes assigned to this hosting package yet." msgid "There are no mailboxes assigned to this hosting package yet."
msgstr "Diesem Hostingpaket sind noch keine Postfächer zugeordnet." msgstr "Diesem Hostingpaket sind noch keine Postfächer zugeordnet."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:230 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:232
msgid "Add mailbox" msgid "Add mailbox"
msgstr "Postfach hinzufügen" msgstr "Postfach hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:237 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:244
#: hostingpackages/views.py:213
msgid "Databases"
msgstr "Datenbanken"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:242
msgid "Database name" msgid "Database name"
msgstr "Datenbankname" msgstr "Datenbankname"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:243 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:245
msgid "Database user" msgid "Database user"
msgstr "Datenbanknutzer" msgstr "Datenbanknutzer"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:244 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:246
msgid "Database type" msgid "Database type"
msgstr "Datenbanktyp" msgstr "Datenbanktyp"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:245 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:247
msgid "Type" msgid "Type"
msgstr "Typ" msgstr "Typ"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:246 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:248
msgid "Database actions" msgid "Database actions"
msgstr "Datenbankaktionen" msgstr "Datenbankaktionen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:258
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:260 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:260
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:262
msgid "Set database user password" msgid "Set database user password"
msgstr "Datenbanknutzerpasswort setzen" msgstr "Datenbanknutzerpasswort setzen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:262 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:264
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:263 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:265
msgid "Delete database" msgid "Delete database"
msgstr "Datenbank löschen" msgstr "Datenbank löschen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:270 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:272
msgid "There are no databases assigned to this hosting package yet." msgid "There are no databases assigned to this hosting package yet."
msgstr "Diesem Hostingpaket sind noch keine Datenbanken zugeordnet." msgstr "Diesem Hostingpaket sind noch keine Datenbanken zugeordnet."
#: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:275 #: hostingpackages/templates/hostingpackages/customerhostingpackage_detail.html:277
msgid "Add database" msgid "Add database"
msgstr "Datenbank hinzufügen" msgstr "Datenbank hinzufügen"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:5 #: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:6
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:14
msgid "Your hosting packages"
msgstr "Ihre Hostingpakete"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:7
#, python-format #, python-format
msgid "Hosting Packages of %(customer)s" msgid "Disk usage of your Hosting Package %(package)s"
msgstr "Hostingpakete des Kunden %(customer)s" msgstr "Speicherplatznutzung Ihres Hostingpakets %(package)s"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:16 #: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:10
#, python-format #, python-format
msgid "Hosting Packages <small>of %(customer)s</small>" msgid "Disk usage of Hosting Package %(package)s of %(full_name)s"
msgstr "Hostingpakete <small>des Kunden %(customer)s</small>" msgstr "Speicherplatznutzung des Hostingpakets %(package)s von %(full_name)s"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:41 #: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:16
msgid "You have no hosting packages setup yet." #, python-format
msgstr "Es wurden noch keine Hostingpakete für Sie eingerichtet." msgid ""
"Disk usage of Hosting Package <a href=\"%(package_url)s\">%(package)s</a>"
msgstr ""
"Speicherplatznutzung des Hostingpakets <a "
"href=\"%(package_url)s\">%(package)s</a>"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_list.html:42 #: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:22
msgid "There are no hosting packages setup for this customer yet." #, python-format
msgstr "Es wurden noch keine Hostingpakete für diesen Kunden eingerichtet." msgid ""
"You use %(used_space)s of the reserved disk space of %(disk_space)s for your "
"hosting package."
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
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:41
msgid "Origin"
msgstr "Quelle"
#: 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
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:48
msgid "Other"
msgstr "Sonstiges"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:56
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
msgid "Database"
msgstr "Datenbank"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_disk_usage_details.html:73
msgid "PostgreSQL database usage"
msgstr "PostgreSQL-Datenbanknutzung"
#: hostingpackages/templates/hostingpackages/customerhostingpackage_option_choices.html:5 #: hostingpackages/templates/hostingpackages/customerhostingpackage_option_choices.html:5
#: hostingpackages/templates/hostingpackages/customerhostingpackage_option_choices.html:8 #: hostingpackages/templates/hostingpackages/customerhostingpackage_option_choices.html:8
@ -565,12 +668,12 @@ msgstr ""
"Wählen Sie eine neue Option für das Hostingpaket %(package)s des Kunden " "Wählen Sie eine neue Option für das Hostingpaket %(package)s des Kunden "
"%(full_name)s" "%(full_name)s"
#: hostingpackages/views.py:49 hostingpackages/views.py:83 #: hostingpackages/views.py:62 hostingpackages/views.py:96
#, python-brace-format #, python-brace-format
msgid "Started setup of new hosting package {name}." msgid "Started setup of new hosting package {name}."
msgstr "Einrichtung des Hostingpakets {name} wurde gestartet." msgstr "Einrichtung des Hostingpakets {name} wurde gestartet."
#: hostingpackages/views.py:287 #: hostingpackages/views.py:271
#, python-brace-format #, python-brace-format
msgid "Successfully added option {option} to hosting package {package}." msgid "Successfully added option {option} to hosting package {package}."
msgstr "Option {option} erfolgreich zum Hostingpaket {package} hinzugefügt." msgstr "Option {option} erfolgreich zum Hostingpaket {package} hinzugefügt."

View file

@ -0,0 +1,79 @@
# Generated by Django 4.2.3 on 2023-07-22 17:31
import django.utils.timezone
import model_utils.fields
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"),
]
operations = [
migrations.CreateModel(
name="CustomerPackageDiskUsage",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
editable=False,
verbose_name="created",
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
editable=False,
verbose_name="modified",
),
),
(
"source",
models.CharField(
choices=[
("disk", "disk"),
("mysql", "mysql"),
("pgsql", "pgsql"),
],
verbose_name="data source",
),
),
("item", models.CharField(verbose_name="data item")),
(
"used_kb",
models.PositiveBigIntegerField(
default=0, verbose_name="space used in KiB"
),
),
(
"package",
models.ForeignKey(
help_text="The hosting package",
on_delete=django.db.models.deletion.CASCADE,
to="hostingpackages.customerhostingpackage",
verbose_name="hosting package",
),
),
],
options={
"unique_together": {("package", "source", "item")},
},
),
]

View file

@ -269,6 +269,31 @@ class CustomerHostingPackage(HostingPackageBase):
return DISK_SPACE_FACTORS[unit][min_unit] * diskspace return DISK_SPACE_FACTORS[unit][min_unit] * diskspace
return DISK_SPACE_FACTORS[min_unit][unit] * diskspace return DISK_SPACE_FACTORS[min_unit][unit] * diskspace
disk_space = property(get_disk_space)
def get_used_disk_space_sum(self, unit=None):
"""
Get the used disk space of this hosting package from submitted disk space statistics.
:param unit: value from :py:data:`DISK_SPACE_UNITS` or :py:const:`None`
:return: disk space in unit or bytes (if parameter unit is :py:const:`None`)
:rtype: int
"""
sum = 0
for usage in self.customerpackagediskusage_set.all():
sum += usage.size_in_bytes
if unit is None:
return sum
return DISK_SPACE_FACTORS[0][unit] * sum
used_disk_space_sum = property(get_used_disk_space_sum)
def get_space_level(self):
return self.used_disk_space_sum / self.disk_space * 100.0
space_level = property(get_space_level)
def get_package_space(self, unit=None): def get_package_space(self, unit=None):
""" """
Get the total disk space reserved for this package without looking at Get the total disk space reserved for this package without looking at
@ -474,3 +499,34 @@ class CustomerMailboxOption(MailboxOptionBase, CustomerHostingPackageOption):
help_text=_("The mailbox option template that this mailbox option is based on"), help_text=_("The mailbox option template that this mailbox option is based on"),
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
class CustomerPackageDiskUsage(TimeStampedModel):
"""
This class represents disk usage statistics for a customer hosting package.
"""
package = models.ForeignKey(
CustomerHostingPackage,
verbose_name=_("hosting package"),
help_text=_("The hosting package"),
on_delete=models.CASCADE,
)
source = models.CharField(
verbose_name=_("data source"),
choices=(("disk", _("disk")), ("mysql", _("mysql")), ("pgsql", _("pgsql"))),
)
item = models.CharField(verbose_name=_("data item"))
used_kb = models.PositiveBigIntegerField(
verbose_name=_("space used in KiB"), default=0
)
class Meta:
unique_together = ("package", "source", "item")
def __str__(self):
return "%s %s = %d KiB" % (self.source, self.item, self.used_kb)
@property
def size_in_bytes(self):
return self.used_kb * 1024

View file

@ -0,0 +1,7 @@
from rest_framework import serializers
from hostingpackages.models import CustomerPackageDiskUsage
class DiskUsageSerializer(serializers.Serializer):
user = serializers.CharField()

View file

@ -38,14 +38,16 @@
<dt>{% translate "Description" %}</dt> <dt>{% translate "Description" %}</dt>
<dd>{{ hostingpackage.description|default:"-" }}</dd> <dd>{{ hostingpackage.description|default:"-" }}</dd>
<dt>{% translate "Disk space" %}</dt> <dt>{% translate "Disk space" %}</dt>
{% with diskspace=hostingpackage.get_disk_space packagespace=hostingpackage.get_package_space %} {% 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 %}
<dd> <dd>
<span title="{% blocktranslate trimmed %} <span title="{% blocktranslate trimmed %}
The reserved disk space for your hosting package is {{ diskspace }} bytes You use {{ used_space }} of the reserved disk space of {{ disk_space }} for your hosting package
{% endblocktranslate %}">{{ diskspace|filesizeformat }}</span> {% 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>
<i class="bi-info-circle" <i class="bi-info-circle"
title="{% blocktranslate with humanbytes=packagespace|filesizeformat trimmed %} title="{% blocktranslate trimmed %}
The package contributes {{ humanbytes }} ({{ packagespace }} bytes) the difference comes from disk space options The package contributes {{ package_space }} the difference comes from disk space options
{% endblocktranslate %}"></i> {% endblocktranslate %}"></i>
</dd> </dd>
{% endwith %} {% endwith %}

View file

@ -0,0 +1,91 @@
{% extends "hostingpackages/base.html" %}
{% load i18n %}
{% block title %}{{ block.super }} - {% spaceless %}
{% if user == customer %}
{% blocktranslate with package=hostingpackage.name trimmed %}
Disk usage of your Hosting Package {{ package }}
{% endblocktranslate %}
{% else %}
{% blocktranslate with package=hostingpackage.name full_name=customer.get_full_name trimmed %}
Disk usage of Hosting Package {{ package }} of {{ full_name }}
{% endblocktranslate %}
{% 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 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 %}
<p>{% blocktranslate trimmed %}
You use {{ used_space }} of the reserved disk space of {{ disk_space }} for your hosting package.
{% endblocktranslate %}</p>
<p class="lead"><span
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 %}</span>
<i class="bi-info-circle"
title="{% blocktranslate trimmed %}
The package contributes {{ package_space }} the difference comes from disk space options
{% endblocktranslate %}"></i>
</p>
<h2>{% trans "Breakdown by usage" %}</h2>
{% if disk_usage %}
<h3>{% trans "Regular file system usage" %}</h3>
<table class="table table-condensed">
<thead>
<tr>
<th>{% translate "Origin" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
{% for line in disk_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 class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if mysql_usage %}
<h3>{% trans "MySQL/MariaDB database usage" %}</h3>
<table class="table table-condensed">
<thead>
<tr>
<th>{% translate "Database" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
{% for line in mysql_usage %}
<tr>
<td>{{ line.item }}</td>
<td class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if pgsql_usage %}
<h3>{% trans "PostgreSQL database usage" %}</h3>
<table class="table table-condensed">
<thead>
<tr>
<th>{% translate "Database" %}</th>
<th class="text-end">{% translate "Used space" %}</th>
</tr>
</thead>
{% for line in pgsql_usage %}
<tr>
<td>{{ line.item }}</td>
<td class="text-end">{{ line.size_in_bytes|filesizeformat }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endwith %}
{% endblock content %}

View file

@ -16,37 +16,54 @@ User = get_user_model()
class CustomerHostingPackageTest(TestCase): class CustomerHostingPackageTest(TestCase):
def test_get_disk_space_bytes(self): def setUp(self) -> None:
package = CustomerHostingPackage( self.user = User.objects.create(username="test")
diskspace=10, diskspace_unit=DISK_SPACE_UNITS.G self.template = HostingPackageTemplate.objects.create(
mailboxcount=10,
diskspace=100,
diskspace_unit=DISK_SPACE_UNITS.M,
description="Test package 1 - Description",
name="Test package 1",
) )
self.assertEqual(package.get_disk_space(), 10 * 1024**3)
def test_get_disk_space_mib(self): @override_settings(OSUSER_DEFAULT_GROUPS=[])
package = CustomerHostingPackage( def test_get_disk_space_bytes(self):
diskspace=10, diskspace_unit=DISK_SPACE_UNITS.G self.template.diskspace = 10
self.template.diskspace_unit = DISK_SPACE_UNITS.G
self.template.save()
package = CustomerHostingPackage.objects.create_from_template(
customer=self.user, template=self.template, name="customer",
) )
package.save()
self.assertEqual(package.get_disk_space(), 10 * 1024 ** 3)
@override_settings(OSUSER_DEFAULT_GROUPS=[])
def test_get_disk_space_mib(self):
self.template.diskspace = 10
self.template.diskspace_unit = DISK_SPACE_UNITS.G
self.template.save()
package = CustomerHostingPackage.objects.create_from_template(
customer=self.user, template=self.template, name="customer",
)
package.save()
self.assertEqual(package.get_disk_space(DISK_SPACE_UNITS.M), 10 * 1024) self.assertEqual(package.get_disk_space(DISK_SPACE_UNITS.M), 10 * 1024)
@override_settings(OSUSER_DEFAULT_GROUPS=[])
def test_get_quota(self): def test_get_quota(self):
package = CustomerHostingPackage( self.template.diskspace = 256
diskspace=256, diskspace_unit=DISK_SPACE_UNITS.M self.template.diskspace_unit = DISK_SPACE_UNITS.M
self.template.save()
package = CustomerHostingPackage.objects.create_from_template(
customer=self.user, template=self.template, name="customer",
) )
package.save()
self.assertEqual(package.get_quota(), (262144, 275251)) self.assertEqual(package.get_quota(), (262144, 275251))
@override_settings(OSUSER_DEFAULT_GROUPS=["testgroup"]) @override_settings(OSUSER_DEFAULT_GROUPS=["testgroup"])
def test_additional_group_not_defined(self): def test_additional_group_not_defined(self):
user = User.objects.create(username="test")
template = HostingPackageTemplate.objects.create(
description="Test package 1 - Description",
mailboxcount=10,
diskspace=100,
diskspace_unit=DISK_SPACE_UNITS.M,
name="Test package 1",
)
with self.assertRaises(ImproperlyConfigured) as ctx: with self.assertRaises(ImproperlyConfigured) as ctx:
package = CustomerHostingPackage.objects.create_from_template( package = CustomerHostingPackage.objects.create_from_template(
customer=user, template=template, name="Test customer package" customer=self.user, template=self.template, name="Test customer package",
) )
package.save() package.save()
self.assertIn("testgroup", str(ctx.exception)) self.assertIn("testgroup", str(ctx.exception))

View file

@ -4,7 +4,7 @@ This module defines the URL patterns for hosting package related views.
""" """
from __future__ import absolute_import from __future__ import absolute_import
from django.urls import re_path from django.urls import path, re_path
from .views import ( from .views import (
AddHostingOption, AddHostingOption,
@ -12,7 +12,9 @@ from .views import (
CreateCustomerHostingPackage, CreateCustomerHostingPackage,
CreateHostingPackage, CreateHostingPackage,
CustomerHostingPackageDetails, CustomerHostingPackageDetails,
CustomerHostingPackageDiskUsageDetails,
HostingOptionChoices, HostingOptionChoices,
UploadCustomerPackageDiskUsage,
) )
urlpatterns = [ urlpatterns = [
@ -42,4 +44,14 @@ urlpatterns = [
AddHostingOption.as_view(), AddHostingOption.as_view(),
name="add_hosting_option", name="add_hosting_option",
), ),
path(
"<int:package>/disk-usage/",
CustomerHostingPackageDiskUsageDetails.as_view(),
name="disk_usage_details",
),
path(
"upload-disk-usage/",
UploadCustomerPackageDiskUsage.as_view(),
name="upload_disk_usage",
),
] ]

View file

@ -4,6 +4,9 @@ This module defines views related to hosting packages.
""" """
from __future__ import absolute_import from __future__ import absolute_import
import http
import logging
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -13,6 +16,12 @@ from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
from django.views.generic.edit import CreateView, FormView from django.views.generic.edit import CreateView, FormView
import rest_framework.request
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework.views import APIView
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
from .forms import ( from .forms import (
@ -24,10 +33,14 @@ from .forms import (
) )
from .models import ( from .models import (
CustomerHostingPackage, CustomerHostingPackage,
CustomerPackageDiskUsage,
DiskSpaceOption, DiskSpaceOption,
MailboxOption, MailboxOption,
UserDatabaseOption, UserDatabaseOption,
) )
from .serializers import DiskUsageSerializer
logger = logging.getLogger("gnuviechadmin.hostingpackages")
class CreateHostingPackage(PermissionRequiredMixin, CreateView): class CreateHostingPackage(PermissionRequiredMixin, CreateView):
@ -259,3 +272,85 @@ class AddHostingOption(StaffUserRequiredMixin, FormView):
).format(option=option, package=hosting_package.name), ).format(option=option, package=hosting_package.name),
) )
return redirect(hosting_package) return redirect(hosting_package)
class HasDiskUsageUploadPermission(BasePermission):
def has_permission(self, request, view):
return (
request.user.has_perm("hostingpackages.add_customerpackagediskusage")
and request.method == "POST"
)
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)
for row in request.data:
user = row["user"]
for key in row:
if key == "user":
continue
else:
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
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)
return Response("Accepted", status=http.HTTPStatus.ACCEPTED)
class CustomerHostingPackageDiskUsageDetails(DetailView):
template_name_suffix = "_disk_usage_details"
model = CustomerHostingPackage
pk_url_kwarg = "package"
context_object_name = "hostingpackage"
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 = [], [], []
for usage in self.get_object().customerpackagediskusage_set.order_by(
"-used_kb"
):
if usage.source == "disk":
disk_usage.append(usage)
elif usage.source == "mysql":
mysql_usage.append(usage)
elif usage.source == "pgsql":
pgsql_usage.append(usage)
context_data.update(
{
"disk_usage": disk_usage,
"mysql_usage": mysql_usage,
"pgsql_usage": pgsql_usage,
}
)
return context_data

View file

@ -1,5 +1,5 @@
from django.apps import AppConfig from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
class InvoiceConfig(AppConfig): class InvoiceConfig(AppConfig):

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnuviechadmin invoice\n" "Project-Id-Version: gnuviechadmin invoice\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-23 14:35+0200\n" "POT-Creation-Date: 2023-07-22 19:45+0200\n"
"PO-Revision-Date: 2023-04-23 14:35+0200\n" "PO-Revision-Date: 2023-04-23 14:35+0200\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
@ -19,51 +19,51 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n" "X-Generator: Poedit 3.2.2\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
#: invoice/apps.py:8 #: invoices/apps.py:8
msgid "Invoices" msgid "Invoices"
msgstr "Rechnungen" msgstr "Rechnungen"
#: invoice/models.py:26 #: invoices/models.py:26
msgid "customer" msgid "customer"
msgstr "Kunde" msgstr "Kunde"
#: invoice/models.py:33 #: invoices/models.py:33
msgid "invoice number" msgid "invoice number"
msgstr "Rechnungsnummer" msgstr "Rechnungsnummer"
#: invoice/models.py:35 #: invoices/models.py:35
msgid "invoice date" msgid "invoice date"
msgstr "Rechnungsdatum" msgstr "Rechnungsdatum"
#: invoice/models.py:37 #: invoices/models.py:37
msgid "amount" msgid "amount"
msgstr "Betrag" msgstr "Betrag"
#: invoice/models.py:40 #: invoices/models.py:40
msgid "currency" msgid "currency"
msgstr "Währung" msgstr "Währung"
#: invoice/models.py:42 #: invoices/models.py:42
msgid "due date" msgid "due date"
msgstr "Fälligkeit" msgstr "Fälligkeit"
#: invoice/models.py:44 #: invoices/models.py:44
msgid "payment date" msgid "payment date"
msgstr "Zahlungsdatum" msgstr "Zahlungsdatum"
#: invoice/models.py:47 #: invoices/models.py:47
msgid "payment variant" msgid "payment variant"
msgstr "Zahlungsart" msgstr "Zahlungsart"
#: invoice/models.py:51 #: invoices/models.py:51
msgid "invoice" msgid "invoice"
msgstr "Rechnung" msgstr "Rechnung"
#: invoice/models.py:52 #: invoices/models.py:52
msgid "invoices" msgid "invoices"
msgstr "Rechnungen" msgstr "Rechnungen"
#: invoice/models.py:56 #: invoices/models.py:56
#, python-brace-format #, python-brace-format
msgid "Invoice {0}" msgid "Invoice {0}"
msgstr "Rechnung {0}" msgstr "Rechnung {0}"

View file

@ -3,7 +3,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import FileExtensionValidator from django.core.validators import FileExtensionValidator
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
CURRENCIES = [(1, "EUR")] CURRENCIES = [(1, "EUR")]

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnuviechadmin\n" "Project-Id-Version: gnuviechadmin\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-22 13:01+0200\n" "POT-Creation-Date: 2023-07-22 19:45+0200\n"
"PO-Revision-Date: 2023-04-22 12:58+0200\n" "PO-Revision-Date: 2023-07-22 19:56+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -44,7 +44,7 @@ msgstr "Die folgenden E-Mailadressen sind Ihrem Konto zugeordnet:"
msgid "Email address" msgid "Email address"
msgstr "E-Mailadresse" msgstr "E-Mailadresse"
#: templates/account/email.html:15 templates/account/email.html:25 #: templates/account/email.html:15 templates/account/email.html:26
msgid "Verified" msgid "Verified"
msgstr "Geprüft" msgstr "Geprüft"
@ -52,31 +52,40 @@ msgstr "Geprüft"
msgid "Primary" msgid "Primary"
msgstr "Primär" msgstr "Primär"
#: templates/account/email.html:27 #: templates/account/email.html:17
msgid "Selection"
msgstr "Auswahl"
#: templates/account/email.html:28
msgid "Unverified" msgid "Unverified"
msgstr "Unbestätigt" msgstr "Unbestätigt"
#: templates/account/email.html:32 #: templates/account/email.html:33
msgid "This is the current primary Email address" msgid "This is the current primary Email address"
msgstr "Dies ist die aktuelle primäre E-Mailadresse" msgstr "Dies ist die aktuelle primäre E-Mailadresse"
#: templates/account/email.html:43 #: templates/account/email.html:43
#, python-format
msgid "Select %(address)s"
msgstr "%(address)s auswählen"
#: templates/account/email.html:54
msgid "Make Primary" msgid "Make Primary"
msgstr "Als primär definieren" msgstr "Als primär definieren"
#: templates/account/email.html:44 #: templates/account/email.html:57
msgid "Re-send Verification" msgid "Re-send Verification"
msgstr "Prüf-E-Mail noch einmal verschicken" msgstr "Prüf-E-Mail noch einmal verschicken"
#: templates/account/email.html:45 templates/socialaccount/connections.html:42 #: templates/account/email.html:58 templates/socialaccount/connections.html:42
msgid "Remove" msgid "Remove"
msgstr "Entfernen" msgstr "Entfernen"
#: templates/account/email.html:49 #: templates/account/email.html:63
msgid "Warning:" msgid "Warning:"
msgstr "Warnung:" msgstr "Warnung:"
#: templates/account/email.html:49 #: templates/account/email.html:63
msgid "" msgid ""
"You currently do not have any e-mail address set up. You should really add " "You currently do not have any e-mail address set up. You should really add "
"an e-mail address so you can receive notifications, reset your password, etc." "an e-mail address so you can receive notifications, reset your password, etc."
@ -85,15 +94,15 @@ msgstr ""
"Mailadresse, um Benachrichtigungen zu erhalten, Ihr Passwort zurückzusetzen, " "Mailadresse, um Benachrichtigungen zu erhalten, Ihr Passwort zurückzusetzen, "
"etc." "etc."
#: templates/account/email.html:52 #: templates/account/email.html:67
msgid "Add E-mail Address" msgid "Add E-mail Address"
msgstr "E-Mailadresse hinzufügen" msgstr "E-Mailadresse hinzufügen"
#: templates/account/email.html:57 #: templates/account/email.html:72
msgid "Add E-mail" msgid "Add E-mail"
msgstr "E-Mail hinzufügen" msgstr "E-Mail hinzufügen"
#: templates/account/email.html:64 #: templates/account/email.html:79
msgid "Do you really want to remove the selected e-mail address?" msgid "Do you really want to remove the selected e-mail address?"
msgstr "Wollen Sie die augewählte E-Mailadresse wirklich entfernen?" msgstr "Wollen Sie die augewählte E-Mailadresse wirklich entfernen?"
@ -181,7 +190,7 @@ msgstr ""
"Mailadresse des Benutzers %(user_display)s ist." "Mailadresse des Benutzers %(user_display)s ist."
#: templates/account/login.html:4 templates/account/login.html:5 #: templates/account/login.html:4 templates/account/login.html:5
#: templates/account/login.html:18 templates/base.html:124 #: templates/account/login.html:18 templates/base.html:112
#: templates/registration/login.html:4 templates/socialaccount/login.html:4 #: templates/registration/login.html:4 templates/socialaccount/login.html:4
msgid "Sign In" msgid "Sign In"
msgstr "Anmelden" msgstr "Anmelden"
@ -399,67 +408,59 @@ msgstr ""
"<strong>Hinweis:</strong> Sie können Ihre <a href=\"%(email_url)s\">E-" "<strong>Hinweis:</strong> Sie können Ihre <a href=\"%(email_url)s\">E-"
"Mailadresse noch ändern</a>." "Mailadresse noch ändern</a>."
#: templates/base.html:32 #: templates/base.html:26
msgid "Dashboard" msgid "Dashboard"
msgstr "Dashboard" msgstr "Dashboard"
#: templates/base.html:34 #: templates/base.html:28
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "Navigation umschalten" msgstr "Navigation umschalten"
#: templates/base.html:42 templates/base.html:53 #: templates/base.html:36
msgid "Hosting" msgid "Hosting"
msgstr "Hosting" msgstr "Hosting"
#: templates/base.html:45 #: templates/base.html:42
msgid "Your hosting packages"
msgstr "Ihre Hostingpakete"
#: templates/base.html:47
msgid "All hosting packages"
msgstr "Alle Hostingpakete"
#: templates/base.html:57
msgid "Links" msgid "Links"
msgstr "Links" msgstr "Links"
#: templates/base.html:60 #: templates/base.html:45
msgid "Web based mail system" msgid "Web based mail system"
msgstr "Webbasiertes E-Mailsystem" msgstr "Webbasiertes E-Mailsystem"
#: templates/base.html:61 #: templates/base.html:46
msgid "Webmail" msgid "Webmail"
msgstr "Webmail" msgstr "Webmail"
#: templates/base.html:63 #: templates/base.html:48
msgid "phpMyAdmin - MySQL database administration tool" msgid "phpMyAdmin - MySQL database administration tool"
msgstr "phpMyAdmin - MySQL-Datenbankverwaltungswerkzeug" msgstr "phpMyAdmin - MySQL-Datenbankverwaltungswerkzeug"
#: templates/base.html:64 #: templates/base.html:49
msgid "phpMyAdmin" msgid "phpMyAdmin"
msgstr "phpMyAdmin" msgstr "phpMyAdmin"
#: templates/base.html:66 #: templates/base.html:51
msgid "phpPgAdmin - PostgreSQL database administration tool" msgid "phpPgAdmin - PostgreSQL database administration tool"
msgstr "phpPgAdmin - PostgreSQL-Datenbankverwaltungswerkzeug" msgstr "phpPgAdmin - PostgreSQL-Datenbankverwaltungswerkzeug"
#: templates/base.html:67 #: templates/base.html:52
msgid "phpPgAdmin" msgid "phpPgAdmin"
msgstr "phpPgAdmin" msgstr "phpPgAdmin"
#: templates/base.html:71 #: templates/base.html:57
msgid "Imprint" msgid "Imprint"
msgstr "Impressum" msgstr "Impressum"
#: templates/base.html:74 #: templates/base.html:61
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Datenschutz" msgstr "Datenschutz"
#: templates/base.html:78 #: templates/base.html:65
msgid "Contact" msgid "Contact"
msgstr "Kontakt" msgstr "Kontakt"
#: templates/base.html:86 #: templates/base.html:73
#, python-format #, python-format
msgid "" msgid ""
"Signed in as <a href=\"%(profile_url)s\" class=\"navbar-link\" title=\"My " "Signed in as <a href=\"%(profile_url)s\" class=\"navbar-link\" title=\"My "
@ -474,7 +475,7 @@ msgstr ""
"class=\"navbar-link\"><i class=\"bi-sign-stop\" title=\"Übernahme " "class=\"navbar-link\"><i class=\"bi-sign-stop\" title=\"Übernahme "
"beenden\"></i></a>" "beenden\"></i></a>"
#: templates/base.html:93 #: templates/base.html:81
#, python-format #, python-format
msgid "" msgid ""
"Signed in as <a href=\"%(profile_url)s\" class=\"navbar-link\" title=\"My " "Signed in as <a href=\"%(profile_url)s\" class=\"navbar-link\" title=\"My "
@ -483,31 +484,31 @@ msgstr ""
"Angemeldet als <a href=\"%(profile_url)s\" class=\"navbar-link\" " "Angemeldet als <a href=\"%(profile_url)s\" class=\"navbar-link\" "
"title=\"Mein Profil\">%(user_display)s</a>" "title=\"Mein Profil\">%(user_display)s</a>"
#: templates/base.html:103 #: templates/base.html:91
msgid "My Account" msgid "My Account"
msgstr "Mein Konto" msgstr "Mein Konto"
#: templates/base.html:107 #: templates/base.html:95
msgid "Impersonate user" msgid "Impersonate user"
msgstr "Als Nutzer agieren" msgstr "Als Nutzer agieren"
#: templates/base.html:111 #: templates/base.html:99
msgid "Admin site" msgid "Admin site"
msgstr "Adminsite" msgstr "Adminsite"
#: templates/base.html:113 #: templates/base.html:101
msgid "Change Email" msgid "Change Email"
msgstr "E-Mail ändern" msgstr "E-Mail ändern"
#: templates/base.html:116 #: templates/base.html:104
msgid "Social Accounts" msgid "Social Accounts"
msgstr "Konten in sozialen Netzwerken" msgstr "Konten in sozialen Netzwerken"
#: templates/base.html:118 #: templates/base.html:106
msgid "Logout" msgid "Logout"
msgstr "Abmelden" msgstr "Abmelden"
#: templates/base.html:139 #: templates/base.html:127
msgid "Close" msgid "Close"
msgstr "Schließen" msgstr "Schließen"
@ -527,6 +528,12 @@ msgstr "Django Impersonate - Nutzerliste"
msgid "User List - Page %(page_number)s" msgid "User List - Page %(page_number)s"
msgstr "Nutzerliste - Seite %(page_number)s" msgstr "Nutzerliste - Seite %(page_number)s"
#: templates/impersonate/list_users.html:14
#: templates/impersonate/search_users.html:24
#, python-format
msgid "Impersonate %(user)s"
msgstr "Als Nutzer %(user)s agieren"
#: templates/impersonate/list_users.html:21 #: templates/impersonate/list_users.html:21
msgid "Search users" msgid "Search users"
msgstr "Nutzer suchen" msgstr "Nutzer suchen"

View file

@ -140,7 +140,7 @@ class MailAddressTest(TestCaseWithCeleryTasks):
def get_target(maf): def get_target(maf):
return maf.target return maf.target
self.assertQuerysetEqual( self.assertQuerySetEqual(
ma.mailaddressforward_set.all(), ["test2@example.org"], get_target ma.mailaddressforward_set.all(), ["test2@example.org"], get_target
) )
@ -152,7 +152,7 @@ class MailAddressTest(TestCaseWithCeleryTasks):
def get_target(maf): def get_target(maf):
return maf.target return maf.target
self.assertQuerysetEqual( self.assertQuerySetEqual(
ma.mailaddressforward_set.all(), ["test2@example.org"], get_target ma.mailaddressforward_set.all(), ["test2@example.org"], get_target
) )
@ -165,7 +165,7 @@ class MailAddressTest(TestCaseWithCeleryTasks):
def get_target(maf): def get_target(maf):
return maf.target return maf.target
self.assertQuerysetEqual( self.assertQuerySetEqual(
ma.mailaddressforward_set.all(), ["test3@example.org"], get_target ma.mailaddressforward_set.all(), ["test3@example.org"], get_target
) )
@ -178,7 +178,7 @@ class MailAddressTest(TestCaseWithCeleryTasks):
def get_target(maf): def get_target(maf):
return maf.target return maf.target
self.assertQuerysetEqual( self.assertQuerySetEqual(
ma.mailaddressforward_set.all(), ma.mailaddressforward_set.all(),
["test2@example.org", "test3@example.org"], ["test2@example.org", "test3@example.org"],
get_target, get_target,
@ -198,7 +198,7 @@ class MailAddressTest(TestCaseWithCeleryTasks):
def get_target(maf): def get_target(maf):
return maf.target return maf.target
self.assertQuerysetEqual( self.assertQuerySetEqual(
ma.mailaddressforward_set.all(), ["test2@example.org"], get_target ma.mailaddressforward_set.all(), ["test2@example.org"], get_target
) )
@ -213,7 +213,6 @@ class MailAddressTest(TestCaseWithCeleryTasks):
md = MailDomain.objects.create(domain="example.org") md = MailDomain.objects.create(domain="example.org")
ma = MailAddress(localpart="test", domain=md) ma = MailAddress(localpart="test", domain=md)
mafwds = ma.set_forward_addresses(["test2@example.org"], commit=False) mafwds = ma.set_forward_addresses(["test2@example.org"], commit=False)
self.assertEqual(ma.mailaddressforward_set.count(), 0)
self.assertEqual(mafwds[0].target, "test2@example.org") self.assertEqual(mafwds[0].target, "test2@example.org")
@ -242,14 +241,14 @@ class MailboxManagerTest(TestCaseWithCeleryTasks):
md = MailDomain.objects.create(domain="example.org") md = MailDomain.objects.create(domain="example.org")
address = MailAddress.objects.create(localpart="test", domain=md) address = MailAddress.objects.create(localpart="test", domain=md)
mailboxes = Mailbox.objects.unused_or_own(address, self.user) mailboxes = Mailbox.objects.unused_or_own(address, self.user)
self.assertQuerysetEqual(mailboxes, []) self.assertQuerySetEqual(mailboxes, [])
def test_unused_or_own_unassigned(self): def test_unused_or_own_unassigned(self):
md = MailDomain.objects.create(domain="example.org") md = MailDomain.objects.create(domain="example.org")
address = MailAddress.objects.create(localpart="test", domain=md) address = MailAddress.objects.create(localpart="test", domain=md)
mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)] mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)]
assignable = Mailbox.objects.unused_or_own(address, self.user) assignable = Mailbox.objects.unused_or_own(address, self.user)
self.assertQuerysetEqual( self.assertQuerySetEqual(
assignable, [repr(mb) for mb in mailboxes], transform=repr assignable, [repr(mb) for mb in mailboxes], transform=repr
) )
@ -259,7 +258,7 @@ class MailboxManagerTest(TestCaseWithCeleryTasks):
mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)] mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)]
address.set_mailbox(mailboxes[0]) address.set_mailbox(mailboxes[0])
assignable = Mailbox.objects.unused_or_own(address, self.user) assignable = Mailbox.objects.unused_or_own(address, self.user)
self.assertQuerysetEqual( self.assertQuerySetEqual(
assignable, [repr(mb) for mb in mailboxes], transform=repr assignable, [repr(mb) for mb in mailboxes], transform=repr
) )
@ -270,16 +269,16 @@ class MailboxManagerTest(TestCaseWithCeleryTasks):
mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)] mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)]
address2.set_mailbox(mailboxes[0]) address2.set_mailbox(mailboxes[0])
assignable = Mailbox.objects.unused_or_own(address, self.user) assignable = Mailbox.objects.unused_or_own(address, self.user)
self.assertQuerysetEqual(assignable, [repr(mailboxes[1])], transform=repr) self.assertQuerySetEqual(assignable, [repr(mailboxes[1])], transform=repr)
def test_unused_fresh(self): def test_unused_fresh(self):
mailboxes = Mailbox.objects.unused(self.user) mailboxes = Mailbox.objects.unused(self.user)
self.assertQuerysetEqual(mailboxes, []) self.assertQuerySetEqual(mailboxes, [])
def test_unused_unassigned(self): def test_unused_unassigned(self):
mailbox = Mailbox.objects.create_mailbox(self.user) mailbox = Mailbox.objects.create_mailbox(self.user)
mailboxes = Mailbox.objects.unused(self.user) mailboxes = Mailbox.objects.unused(self.user)
self.assertQuerysetEqual(mailboxes, [repr(mailbox)], transform=repr) self.assertQuerySetEqual(mailboxes, [repr(mailbox)], transform=repr)
def test_unused_assigned(self): def test_unused_assigned(self):
md = MailDomain.objects.create(domain="example.org") md = MailDomain.objects.create(domain="example.org")
@ -287,7 +286,7 @@ class MailboxManagerTest(TestCaseWithCeleryTasks):
mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)] mailboxes = [Mailbox.objects.create_mailbox(self.user) for _ in range(2)]
address.set_mailbox(mailboxes[0]) address.set_mailbox(mailboxes[0])
assignable = Mailbox.objects.unused(self.user) assignable = Mailbox.objects.unused(self.user)
self.assertQuerysetEqual(assignable, [repr(mailboxes[1])], transform=repr) self.assertQuerySetEqual(assignable, [repr(mailboxes[1])], transform=repr)
def test_create_mailbox_no_password(self): def test_create_mailbox_no_password(self):
mailbox = Mailbox.objects.create_mailbox(self.user) mailbox = Mailbox.objects.create_mailbox(self.user)

View file

@ -166,7 +166,7 @@ class DeleteSshPublicKeyTest(HostingPackageAwareTestMixin, TestCase):
kwargs={"package": str(self.package.pk), "pk": str(self.sshkey.pk)}, kwargs={"package": str(self.package.pk), "pk": str(self.sshkey.pk)},
) )
queryset = view.get_queryset() queryset = view.get_queryset()
self.assertQuerysetEqual(queryset, [repr(self.sshkey)], transform=repr) self.assertQuerySetEqual(queryset, [repr(self.sshkey)], transform=repr)
def test_get_context_data(self): def test_get_context_data(self):
self.client.login(username=TEST_USER, password=TEST_PASSWORD) self.client.login(username=TEST_USER, password=TEST_PASSWORD)
@ -234,7 +234,7 @@ class EditSshPublicKeyCommentTest(HostingPackageAwareTestMixin, TransactionTestC
kwargs={"package": str(self.package.pk), "pk": str(self.sshkey.pk)}, kwargs={"package": str(self.package.pk), "pk": str(self.sshkey.pk)},
) )
queryset = view.get_queryset() queryset = view.get_queryset()
self.assertQuerysetEqual(queryset, [repr(self.sshkey)], transform=repr) self.assertQuerySetEqual(queryset, [repr(self.sshkey)], transform=repr)
def test_get_form_kwargs(self): def test_get_form_kwargs(self):
self.client.login(username=TEST_USER, password=TEST_PASSWORD) self.client.login(username=TEST_USER, password=TEST_PASSWORD)

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnuviechadmin taskresults\n" "Project-Id-Version: gnuviechadmin taskresults\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-16 22:07+0200\n" "POT-Creation-Date: 2023-07-22 19:45+0200\n"
"PO-Revision-Date: 2023-04-16 18:21+0200\n" "PO-Revision-Date: 2023-07-22 19:57+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -19,38 +19,38 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n" "X-Generator: Poedit 3.2.2\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
#: taskresults/models.py:23 #: taskresults/models.py:24
msgid "Task id" msgid "Task id"
msgstr "Task-Id" msgstr "Task-Id"
#: taskresults/models.py:24 #: taskresults/models.py:25
msgid "Task signature" msgid "Task signature"
msgstr "Tasksignatur" msgstr "Tasksignatur"
#: taskresults/models.py:25 #: taskresults/models.py:26
msgid "Task creator" msgid "Task creator"
msgstr "Taskersteller" msgstr "Taskersteller"
#: taskresults/models.py:26 #: taskresults/models.py:27
msgid "Task notes" msgid "Task notes"
msgstr "Tasknotizen" msgstr "Tasknotizen"
#: taskresults/models.py:27 taskresults/models.py:34 #: taskresults/models.py:28 taskresults/models.py:35
msgid "Task result" msgid "Task result"
msgstr "Taskergebnis" msgstr "Taskergebnis"
#: taskresults/models.py:29 #: taskresults/models.py:30
msgid "Task state" msgid "Task state"
msgstr "Taskstatus" msgstr "Taskstatus"
#: taskresults/models.py:35 #: taskresults/models.py:36
msgid "Task results" msgid "Task results"
msgstr "Taskergebnisse" msgstr "Taskergebnisse"
#: taskresults/models.py:42 #: taskresults/models.py:43
msgid "yes" msgid "yes"
msgstr "ja" msgstr "ja"
#: taskresults/models.py:42 #: taskresults/models.py:43
msgid "no" msgid "no"
msgstr "nein" msgstr "nein"

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: websites gnuviechadmin app\n" "Project-Id-Version: websites gnuviechadmin app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-16 22:07+0200\n" "POT-Creation-Date: 2023-07-22 19:45+0200\n"
"PO-Revision-Date: 2023-04-16 18:21+0200\n" "PO-Revision-Date: 2023-07-22 19:57+0200\n"
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n" "Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
"Language-Team: Jan Dittberner <jan@dittberner.info>\n" "Language-Team: Jan Dittberner <jan@dittberner.info>\n"
"Language: de\n" "Language: de\n"
@ -31,27 +31,27 @@ msgstr "Webauftritt anlegen"
msgid "There is already a website for this subdomain" msgid "There is already a website for this subdomain"
msgstr "Es gibt bereits einen Webauftritt mit dieser Subdomain" msgstr "Es gibt bereits einen Webauftritt mit dieser Subdomain"
#: websites/models.py:32 #: websites/models.py:20
msgid "sub domain" msgid "sub domain"
msgstr "Subdomain" msgstr "Subdomain"
#: websites/models.py:34 #: websites/models.py:22
msgid "operating system user" msgid "operating system user"
msgstr "Betriebssystemnutzer" msgstr "Betriebssystemnutzer"
#: websites/models.py:36 #: websites/models.py:24
msgid "domain" msgid "domain"
msgstr "Domain" msgstr "Domain"
#: websites/models.py:37 #: websites/models.py:25
msgid "wildcard" msgid "wildcard"
msgstr "Wildcard" msgstr "Wildcard"
#: websites/models.py:41 #: websites/models.py:29
msgid "website" msgid "website"
msgstr "Webauftritt" msgstr "Webauftritt"
#: websites/models.py:42 #: websites/models.py:30
msgid "websites" msgid "websites"
msgstr "Webauftritte" msgstr "Webauftritte"

1438
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,21 @@
[tool.poetry] [tool.poetry]
name = "gva" name = "gva"
version = "0.13.0" version = "0.14.0"
description = "gnuviechadmin web interface" description = "gnuviechadmin web interface"
authors = ["Jan Dittberner <jan@dittberner.info>"] authors = ["Jan Dittberner <jan@dittberner.info>"]
license = "AGPL-3+" license = "AGPL-3+"
readme = "README.md" readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.7" python = "^3.8"
django = "<4" django = "^4.2"
psycopg2-binary = "^2.9" psycopg2-binary = "^2.9"
celery = "^5.2.7" celery = "^5.2.7"
django-allauth = "^0.52.0" django-allauth = "^0.52.0"
django-crispy-forms = "^2.0" django-crispy-forms = "^2.0"
django-debug-toolbar = "^3.8" django-debug-toolbar = "^3.8"
django-model-utils = "^4.1" django-model-utils = "^4.1"
gvacommon = {version = "^0.6.0", source = "gnuviech"} gvacommon = {version = "^0.7.0", source = "gnuviech"}
passlib = "^1.7.4" passlib = "^1.7.4"
redis = "^4.5.1" redis = "^4.5.1"
requests-oauthlib = "^1.3.1" requests-oauthlib = "^1.3.1"
@ -25,6 +25,7 @@ markdown = "^3.4.3"
django-filter = "^23.1" django-filter = "^23.1"
crispy-bootstrap5 = "^0.7" crispy-bootstrap5 = "^0.7"
python-magic = "^0.4.27" python-magic = "^0.4.27"
isort = "^5.12.0"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
@ -34,16 +35,21 @@ releases = "^2.0.0"
sphinxcontrib-blockdiag = "^3.0.0" sphinxcontrib-blockdiag = "^3.0.0"
pylama = "^8.4.1" pylama = "^8.4.1"
black = {extras = ["d"], version = "^23.3.0"} black = {extras = ["d"], version = "^23.3.0"}
isort = "<5"
[[tool.poetry.source]] [[tool.poetry.source]]
name = "gnuviech" name = "gnuviech"
url = "https://pypi.gnuviech-server.de/simple" url = "https://pypi.gnuviech-server.de/simple"
default = false priority = "explicit"
secondary = false
[tool.isort]
profile = "black"
known_django = ["django","model_utils"]
known_drf = ["rest_framework"]
known_celery = ["celery"]
sections = ["FUTURE", "STDLIB", "DJANGO", "DRF", "CELERY", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"