Merge branch 'release/0.8.0' into production
* release/0.8.0: add release version in changelog, update conf.py add german translation for new strings implement user database deletion improve table layout on hosting package detail page implement database user password change link from hostingpackages details to add_userdatabase implement setup of new user databases add combined method for creating databases with users performance optimizations for hosting package detail view move HostingPackageAndCustomerMixin to gvawebcore.views
This commit is contained in:
commit
3b248f650c
20 changed files with 619 additions and 68 deletions
|
@ -1,6 +1,14 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
* :release:`0.8.0 <2015-01-26>`
|
||||
* :feature:`-` implement deletion of user database and database users
|
||||
* :feature:`-` implement password changes for database users
|
||||
* :feature:`-` implement setup of user databases
|
||||
* :support:`-` performance improvement for hosting package detail view
|
||||
* :support:`-` move HostingPackageAndCustomerMixin from managemails.views to
|
||||
gvawebcore.views
|
||||
|
||||
* :release:`0.7.0 <2015-01-25>`
|
||||
* :feature:`-` implement mail address target editing
|
||||
* :feature:`-` implement mail address deletion
|
||||
|
|
|
@ -9,3 +9,10 @@
|
|||
|
||||
.. automodule:: gvawebcore.forms
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`views <gvawebcore.views>`
|
||||
----------------------------------
|
||||
|
||||
.. automodule:: gvawebcore.views
|
||||
:members:
|
||||
|
|
|
@ -17,6 +17,13 @@
|
|||
.. automodule:: userdbs.apps
|
||||
|
||||
|
||||
:py:mod:`forms <userdbs.forms>`
|
||||
-------------------------------
|
||||
|
||||
.. automodule:: userdbs.forms
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`models <userdbs.models>`
|
||||
---------------------------------
|
||||
|
||||
|
@ -34,3 +41,17 @@
|
|||
|
||||
.. automodule:: userdbs.templatetags.userdb
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`urls <userdbs.urls>`
|
||||
-----------------------------
|
||||
|
||||
.. automodule:: userdbs.urls
|
||||
:members:
|
||||
|
||||
|
||||
:py:mod:`views <userdbs.views>`
|
||||
-------------------------------
|
||||
|
||||
.. automodule:: userdbs.views
|
||||
:members:
|
||||
|
|
|
@ -60,9 +60,9 @@ copyright = u'2014, 2015 Jan Dittberner'
|
|||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.7'
|
||||
version = '0.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.7.0'
|
||||
release = '0.8.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -10,6 +10,7 @@ urlpatterns = patterns(
|
|||
'',
|
||||
url(r'', include('dashboard.urls')),
|
||||
url(r'^accounts/', include('allauth.urls')),
|
||||
url(r'^database/', include('userdbs.urls')),
|
||||
url(r'^domains/', include('domains.urls')),
|
||||
url(r'^hosting/', include('hostingpackages.urls')),
|
||||
url(r'^mail/', include('managemails.urls')),
|
||||
|
|
26
gnuviechadmin/gvawebcore/views.py
Normal file
26
gnuviechadmin/gvawebcore/views.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
"""
|
||||
This module defines common view code to be used by multiple gnuviechadmin apps.
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from hostingpackages.models import CustomerHostingPackage
|
||||
|
||||
|
||||
class HostingPackageAndCustomerMixin(object):
|
||||
"""
|
||||
Mixin for views that gets the hosting package instance from the URL
|
||||
keyword argument 'package'.
|
||||
|
||||
"""
|
||||
hosting_package_kwarg = 'package'
|
||||
"""Keyword argument used to find the hosting package in the URL."""
|
||||
|
||||
def get_hosting_package(self):
|
||||
return get_object_or_404(
|
||||
CustomerHostingPackage,
|
||||
pk=int(self.kwargs[self.hosting_package_kwarg]))
|
||||
|
||||
def get_customer_object(self):
|
||||
return self.get_hosting_package().customer
|
|
@ -114,6 +114,12 @@ class CustomerHostingPackageDetails(StaffOrSelfLoginRequiredMixin, DetailView):
|
|||
context.update({
|
||||
'customer': self.get_customer_object(),
|
||||
'uploadserver': settings.OSUSER_UPLOAD_SERVER,
|
||||
'databases': context['hostingpackage'].databases,
|
||||
'osuser': context['hostingpackage'].osuser,
|
||||
'hostingoptions':
|
||||
context['hostingpackage'].get_hostingoptions(),
|
||||
'domains': context['hostingpackage'].domains.all(),
|
||||
'mailboxes': context['hostingpackage'].mailboxes,
|
||||
})
|
||||
return context
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: gnuviechadmin\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-01-25 22:13+0100\n"
|
||||
"PO-Revision-Date: 2015-01-25 22:20+0100\n"
|
||||
"POT-Creation-Date: 2015-01-26 13:42+0100\n"
|
||||
"PO-Revision-Date: 2015-01-26 13:51+0100\n"
|
||||
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
|
||||
"Language-Team: Jan Dittberner <jan@dittberner.info>\n"
|
||||
"Language: de\n"
|
||||
|
@ -785,30 +785,38 @@ msgid "Add mailbox"
|
|||
msgstr "Postfach hinzufügen"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:168
|
||||
msgid "Database type"
|
||||
msgstr "Datenbanktyp"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:168
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:169
|
||||
msgid "Database name"
|
||||
msgstr "Datenbankname"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:170
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:169
|
||||
msgid "Database user"
|
||||
msgstr "Datenbanknutzer"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:170
|
||||
msgid "Database type"
|
||||
msgstr "Datenbanktyp"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:170
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:171
|
||||
msgid "Database actions"
|
||||
msgstr "Datenbankaktionen"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:186
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:181
|
||||
msgid "Set database user password"
|
||||
msgstr "Datenbanknutzerpasswort setzen"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:182
|
||||
msgid "Delete database"
|
||||
msgstr "Datenbank löschen"
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:189
|
||||
msgid "There are no databases assigned to this hosting package yet."
|
||||
msgstr "Diesem Hostingpaket sind noch keine Datenbanken zugeordnet."
|
||||
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:189
|
||||
#: templates/hostingpackages/customerhostingpackage_detail.html:192
|
||||
msgid "Add database"
|
||||
msgstr "Datenbank hinzufügen"
|
||||
|
||||
|
@ -839,10 +847,12 @@ msgid "Do you really want to delete the mail address %(mailaddress)s?"
|
|||
msgstr "Wollen Sie die E-Mailadresse %(mailaddress)s wirklich löschen?"
|
||||
|
||||
#: templates/managemails/mailaddress_confirm_delete.html:28
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:29
|
||||
msgid "Yes, do it!"
|
||||
msgstr "Ja, so soll es sein!"
|
||||
|
||||
#: templates/managemails/mailaddress_confirm_delete.html:29
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:30
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
|
@ -1021,6 +1031,93 @@ msgstr ""
|
|||
"%(site_name)s zu nutzen. Als letzten Schritt füllen Sie bitte folgendes "
|
||||
"Formular aus:"
|
||||
|
||||
#: templates/userdbs/databaseuser_setpassword.html:6
|
||||
#, python-format
|
||||
msgid "Set Database User Password for %(dbuser)s"
|
||||
msgstr "Neues Datenbanknutzerpasswort für %(dbuser)s setzen"
|
||||
|
||||
#: templates/userdbs/databaseuser_setpassword.html:8
|
||||
#, python-format
|
||||
msgid "Set Database User Password for %(dbuser)s of Customer %(full_name)s"
|
||||
msgstr ""
|
||||
"Neues Datenbanknutzerpasswort für %(dbuser)s des Kunden %(full_name)s setzen."
|
||||
|
||||
#: templates/userdbs/databaseuser_setpassword.html:14
|
||||
#, python-format
|
||||
msgid "Set Database User Password <small>for %(dbuser)s</small>"
|
||||
msgstr "Datenbanknutzerpasswort setzen <small>für %(dbuser)s</small>"
|
||||
|
||||
#: templates/userdbs/databaseuser_setpassword.html:16
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Set Database User Password <small>for %(dbuser)s of Customer %(full_name)s</"
|
||||
"small>"
|
||||
msgstr ""
|
||||
"Neues Datenbanknutzerpasswort setzen <small>für %(dbuser)s des Kunden "
|
||||
"%(full_name)s</small>"
|
||||
|
||||
#: templates/userdbs/databaseuser_setpassword.html:21
|
||||
msgid "Please specify the new password for your database user."
|
||||
msgstr "Bitte geben Sie das neue Passwort für Ihren Datenbanknutzer ein."
|
||||
|
||||
#: templates/userdbs/databaseuser_setpassword.html:21
|
||||
msgid "Please specify the new password of the database user."
|
||||
msgstr "Bitte geben Sie das neue Passwort für den Datenbanknutzer ein."
|
||||
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:6
|
||||
#, python-format
|
||||
msgid "Delete Database %(database)s"
|
||||
msgstr "Datenbank %(database)s löschen"
|
||||
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:8
|
||||
#, python-format
|
||||
msgid "Delete Database %(database)s of customer %(full_name)s"
|
||||
msgstr "Datenbank %(database)s des Kunden %(full_name)s löschen"
|
||||
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:14
|
||||
#, python-format
|
||||
msgid "Delete Database <small>%(database)s</small>"
|
||||
msgstr "Datenbank löschen <small>%(database)s</small>"
|
||||
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:16
|
||||
#, python-format
|
||||
msgid "Delete Database <small>%(database)s of customer %(full_name)s</small>"
|
||||
msgstr "Datenbank löschen <small>%(database)s des Kunden %(full_name)s</small>"
|
||||
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:23
|
||||
#, python-format
|
||||
msgid "Do you really want to delete the database %(database)s?"
|
||||
msgstr "Wollen Sie die Datenbank %(database)s wirklich löschen?"
|
||||
|
||||
#: templates/userdbs/userdatabase_confirm_delete.html:26
|
||||
msgid ""
|
||||
"When you confirm the deletion the database will be removed from the database "
|
||||
"server. <strong>All data in the database will be lost!</strong> If the "
|
||||
"database user assigned to that database has no other databases assigned it "
|
||||
"will be deleted too."
|
||||
msgstr ""
|
||||
"Wenn Sie die Löschung bestätigen, wird die Datenbank vom Datenbankserver "
|
||||
"entfernt. <strong>Alle Daten in der Datenbank gehen verloren!</strong> Wenn "
|
||||
"dem zu dieser Datenbank gehörigen Datenbanknutzer keine weiteren Datenbanken "
|
||||
"zugeordnet sind, wird er ebenfalls gelöscht."
|
||||
|
||||
#: templates/userdbs/userdatabase_create.html:6
|
||||
#: templates/userdbs/userdatabase_create.html:14
|
||||
msgid "Add new Database"
|
||||
msgstr "Neue Datenbank hinzufügen"
|
||||
|
||||
#: templates/userdbs/userdatabase_create.html:8
|
||||
#: templates/userdbs/userdatabase_create.html:16
|
||||
#, python-format
|
||||
msgid "Add new Database for Customer %(full_name)s"
|
||||
msgstr "Neue Datenbank für Kunde %(full_name)s anlegen"
|
||||
|
||||
#: templates/userdbs/userdatabase_create.html:21
|
||||
msgid "Please enter a password for a new database user for your database."
|
||||
msgstr ""
|
||||
"Bitte geben Sie ein Passwort für den neuen Datenbanknutzer für Ihre "
|
||||
"Datenbank ein."
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Password Reset"
|
||||
#~ msgid "Password (again)"
|
||||
|
|
|
@ -15,8 +15,7 @@ from django.views.generic.edit import (
|
|||
from django.contrib import messages
|
||||
|
||||
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
|
||||
|
||||
from hostingpackages.models import CustomerHostingPackage
|
||||
from gvawebcore.views import HostingPackageAndCustomerMixin
|
||||
|
||||
from domains.models import MailDomain
|
||||
from .forms import (
|
||||
|
@ -33,25 +32,6 @@ from .models import (
|
|||
)
|
||||
|
||||
|
||||
class HostingPackageAndCustomerMixin(object):
|
||||
"""
|
||||
Mixin for views that gets the hosting package instance from the URL
|
||||
keyword argument 'package'.
|
||||
|
||||
"""
|
||||
hosting_package_kwarg = 'package'
|
||||
"""Keyword argument used to find the hosting package in the URL."""
|
||||
|
||||
def get_hosting_package(self):
|
||||
return get_object_or_404(
|
||||
CustomerHostingPackage,
|
||||
pk=int(self.kwargs[self.hosting_package_kwarg]))
|
||||
|
||||
def get_customer_object(self):
|
||||
return self.get_hosting_package().customer
|
||||
|
||||
|
||||
|
||||
class CreateMailbox(
|
||||
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, CreateView
|
||||
):
|
||||
|
|
|
@ -1 +1,10 @@
|
|||
/*! project specific CSS goes here. */
|
||||
table thead th.actions-column {
|
||||
width: 5em;
|
||||
}
|
||||
table thead th.status-column {
|
||||
width: 5em;
|
||||
}
|
||||
table thead th.name-column {
|
||||
width: 15em;
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
<dt>{% trans "Mailboxes" %}</dt>
|
||||
<dd>{% blocktrans with num=hostingpackage.used_mailbox_count total=hostingpackage.mailbox_count %}{{ num }} of {{ total }} in use{% endblocktrans %} <span class="glyphicon
|
||||
glyphicon-info-sign" title="{% blocktrans with mailboxes=hostingpackage.mailboxcount %}The package provides {{ mailboxcount }} mailboxes the difference comes from mailbox options.{% endblocktrans %}"></span></dd>
|
||||
<dt>{% if hostingpackage.osuser.is_sftp_user %}{% trans "SFTP username" %}{% else %}{% trans "SSH/SFTP username" %}{% endif %}</dt>
|
||||
<dd>{{ hostingpackage.osuser.username }}</dd>
|
||||
<dt>{% if osuser.is_sftp_user %}{% trans "SFTP username" %}{% else %}{% trans "SSH/SFTP username" %}{% endif %}</dt>
|
||||
<dd>{{ osuser.username }}</dd>
|
||||
<dt>{% trans "Upload server" %}</dt>
|
||||
<dd>{{ uploadserver }}</dd>
|
||||
</dl>
|
||||
|
@ -48,9 +48,9 @@
|
|||
<div class="col-lg-4 col-md-6 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{% trans "Hosting Package Options" %}</div>
|
||||
{% if hostingpackage.customerhostingpackageoption_set.exists %}
|
||||
{% if hostingoptions %}
|
||||
<ul class="list-group">
|
||||
{% for opt in hostingpackage.get_hostingoptions %}
|
||||
{% for opt in hostingoptions %}
|
||||
<li class="list-group-item">{{ opt }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -67,7 +67,7 @@
|
|||
<div class="panel-heading">{% trans "Hosting Package Actions" %}</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><a href="#" title="{% trans "Edit Hosting Package Description" %}">{% trans "Edit description" %}</a></li>
|
||||
<li class="list-group-item"><a href="{% url "set_osuser_password" slug=hostingpackage.osuser.username %}">{% if hostingpackage.osuser.is_sftp %}{% trans "Set SFTP password" %}{% else %}{% trans "Set SSH/SFTP password" %}{% endif %}</a></li>
|
||||
<li class="list-group-item"><a href="{% url "set_osuser_password" slug=osuser.username %}">{% if osuser.is_sftp %}{% trans "Set SFTP password" %}{% else %}{% trans "Set SSH/SFTP password" %}{% endif %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -76,18 +76,18 @@
|
|||
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{% trans "Domains" %}</div>
|
||||
{% if hostingpackage.domains %}
|
||||
{% if domains %}
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Domain name" %}</th>
|
||||
<th class="name-column">{% trans "Domain name" %}</th>
|
||||
<th>{% trans "Mail addresses" %}</th>
|
||||
<th>{% trans "Websites" %}</th>
|
||||
<th title="{% trans "Domain actions" %}"><span class="sr-only">{% trans "Actions" %}</span></th>
|
||||
<th title="{% trans "Domain actions" %}" class="actions-column"><span class="sr-only">{% trans "Actions" %}</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for domain in hostingpackage.domains.all %}
|
||||
{% for domain in domains %}
|
||||
<tr>
|
||||
<td>{{ domain.domain }}</td>
|
||||
{% if domain.domain.maildomain %}
|
||||
|
@ -126,18 +126,18 @@
|
|||
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{% trans "E-Mail-Accounts" %}</div>
|
||||
{% if hostingpackage.mailboxes %}
|
||||
{% if mailboxes %}
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Mailbox" %}</th>
|
||||
<th class="name-column">{% trans "Mailbox" %}</th>
|
||||
<th>{% trans "Mail addresses" %}</th>
|
||||
<th>{% trans "Active" %}</th>
|
||||
<th title="{% trans "Mailbox actions" %}"><span class="sr-only">{% trans "Actions" %}</span></th>
|
||||
<th class="status-column">{% trans "Active" %}</th>
|
||||
<th title="{% trans "Mailbox actions" %}" class="actions-column"><span class="sr-only">{% trans "Actions" %}</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for mailbox in hostingpackage.mailboxes %}
|
||||
{% for mailbox in mailboxes %}
|
||||
<tr>
|
||||
<td>{{ mailbox.username }}</td>
|
||||
<td>{{ mailbox.mailaddresses|join:", " }}</td>
|
||||
|
@ -161,23 +161,26 @@
|
|||
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{% trans "Databases" %}</div>
|
||||
{% if hostingpackage.databases %}
|
||||
{% if databases %}
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="name-column">{% trans "Database name" %}</th>
|
||||
<th class="name-column">{% trans "Database user" %}</th>
|
||||
<th title="{% trans "Database type" %}"><span class="sr-only">{% trans "Type" %}</span></th>
|
||||
<th>{% trans "Database name" %}</th>
|
||||
<th>{% trans "Database user" %}</th>
|
||||
<th title="{% trans "Database actions" %}"><span class="sr-only">{% trans "Actions" %}</span></th>
|
||||
<th title="{% trans "Database actions" %}" class="actions-column"><span class="sr-only">{% trans "Actions" %}</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for database in hostingpackage.databases %}
|
||||
{% for database in databases %}
|
||||
<tr>
|
||||
<td>{% include "userdbs/snippets/db_type.html" with db_type=database.db_user.db_type %}</td>
|
||||
<td>{{ database.db_name }}</td>
|
||||
<td>{{ database.db_user.username }}</td>
|
||||
<td></td>
|
||||
<td>{{ database.db_user.name }}</td>
|
||||
<td>{% include "userdbs/snippets/db_type.html" with db_type=database.db_user.db_type %}</td>
|
||||
<td>
|
||||
<a href="{% url 'change_dbuser_password' package=hostingpackage.id slug=database.db_user.name %}" title="{% trans "Set database user password" %}"><i class="fa fa-user-secret"></i><span class="sr-only"> {% trans "Set database user password" %}</span></a>
|
||||
<a href="{% url 'delete_userdatabase' package=hostingpackage.id slug=database.db_name %}" title="{% trans "Delete database" %}"><i class="glyphicon glyphicon-trash"></i><span class="sr-only">{% trans "Delete database" %}</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -186,7 +189,7 @@
|
|||
<p class="panel-body text-info">{% trans "There are no databases assigned to this hosting package yet." %}</p>
|
||||
{% endif %}
|
||||
{% if hostingpackage.may_add_database %}
|
||||
<p class="panel-body"><a href="#" class="btn btn-primary">{% trans "Add database" %}</a></p>
|
||||
<p class="panel-body"><a href="{% url 'add_userdatabase' package=hostingpackage.id %}" class="btn btn-primary">{% trans "Add database" %}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
1
gnuviechadmin/templates/userdbs/base.html
Normal file
1
gnuviechadmin/templates/userdbs/base.html
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends "base.html" %}
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "userdbs/base.html" %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
|
||||
{% block title %}{{ block.super }} - {% spaceless %}
|
||||
{% if customer == user %}
|
||||
{% blocktrans with dbuser=dbuser.name %}Set Database User Password for {{ dbuser }}{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with dbuser=dbuser.name full_name=customer.get_full_name %}Set Database User Password for {{ dbuser }} of Customer {{ full_name }}{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock title %}
|
||||
|
||||
{% block page_title %}{% spaceless %}
|
||||
{% if customer == user %}
|
||||
{% blocktrans with dbuser=dbuser.name %}Set Database User Password <small>for {{ dbuser }}</small>{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with dbuser=dbuser.name full_name=customer.get_full_name %}Set Database User Password <small>for {{ dbuser }} of Customer {{ full_name }}</small>{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock page_title %}
|
||||
|
||||
{% block content %}
|
||||
<p>{% if customer == user %}{% trans "Please specify the new password for your database user." %}{% else %}{% trans "Please specify the new password of the database user." %}{% endif %}
|
||||
{% crispy form %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('input[type=password]').val('').first().focus();
|
||||
});
|
||||
</script>
|
||||
{% endblock extra_js %}
|
|
@ -0,0 +1,34 @@
|
|||
{% extends "userdbs/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{{ block.super }} - {% spaceless %}
|
||||
{% if user == customer %}
|
||||
{% blocktrans with database=database.db_name %}Delete Database {{ database }}{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with database=database.db_name full_name=customer.get_full_name %}Delete Database {{ database }} of customer {{ full_name }}{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock title %}
|
||||
|
||||
{% block page_title %}{% spaceless %}
|
||||
{% if user == customer %}
|
||||
{% blocktrans with database=database.db_name %}Delete Database <small>{{ database }}</small>{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with database=database.db_name full_name=customer.get_full_name %}Delete Database <small>{{ database }} of customer {{ full_name }}</small>{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock page_title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
{% blocktrans with database=database.db_name %}Do you really want to delete the database {{ database }}?{% endblocktrans %}
|
||||
</div>
|
||||
<div class="panel-body form">
|
||||
<p>{% blocktrans %}When you confirm the deletion the database will be removed from the database server. <strong>All data in the database will be lost!</strong> If the database user assigned to that database has no other databases assigned it will be deleted too.{% endblocktrans %}</p>
|
||||
<form action="{% url 'delete_userdatabase' package=hostingpackage.id slug=database.db_name %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input class="btn btn-warning" type="submit" value="{% trans "Yes, do it!" %}" />
|
||||
<a class="btn btn-default" href="{{ hostingpackage.get_absolute_url }}">{% trans "Cancel" %}</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
31
gnuviechadmin/templates/userdbs/userdatabase_create.html
Normal file
31
gnuviechadmin/templates/userdbs/userdatabase_create.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% extends "userdbs/base.html" %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
|
||||
{% block title %}{{ block.super }} - {% spaceless %}
|
||||
{% if user == customer %}
|
||||
{% blocktrans %}Add new Database{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with full_name=customer.get_full_name %}Add new Database for Customer {{ full_name }}{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock title %}
|
||||
|
||||
{% block page_title %}{% spaceless %}
|
||||
{% if user == customer %}
|
||||
{% blocktrans %}Add new Database{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with full_name=customer.get_full_name %}Add new Database for Customer {{ full_name }}{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endspaceless %}{% endblock page_title %}
|
||||
|
||||
{% block content %}
|
||||
<p>{% blocktrans %}Please enter a password for a new database user for your database.{% endblocktrans %}</p>
|
||||
{% crispy form %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('input[type=password]').val('').first().focus();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
92
gnuviechadmin/userdbs/forms.py
Normal file
92
gnuviechadmin/userdbs/forms.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
"""
|
||||
This module defines form classes for user database editing.
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import (
|
||||
Submit,
|
||||
)
|
||||
|
||||
from .models import (
|
||||
DB_TYPES,
|
||||
DatabaseUser,
|
||||
UserDatabase,
|
||||
)
|
||||
from gvawebcore.forms import PasswordModelFormMixin
|
||||
|
||||
|
||||
class AddUserDatabaseForm(forms.ModelForm, PasswordModelFormMixin):
|
||||
"""
|
||||
This form is used to create new user database instances.
|
||||
|
||||
"""
|
||||
db_type = forms.TypedChoiceField(
|
||||
label=_('Database type'),
|
||||
choices=DB_TYPES,
|
||||
widget=forms.RadioSelect,
|
||||
coerce=int,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = UserDatabase
|
||||
fields = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.hosting_package = kwargs.pop('hostingpackage')
|
||||
self.available_dbtypes = kwargs.pop('dbtypes')
|
||||
super(AddUserDatabaseForm, self).__init__(*args, **kwargs)
|
||||
self.fields['db_type'].choices = self.available_dbtypes
|
||||
if len(self.available_dbtypes) == 1:
|
||||
self.fields['db_type'].initial = self.available_dbtypes[0][0]
|
||||
self.fields['db_type'].widget = forms.HiddenInput()
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_action = reverse(
|
||||
'add_userdatabase', kwargs={'package': self.hosting_package.id})
|
||||
self.helper.add_input(Submit('submit', _('Create database')))
|
||||
|
||||
def save(self, commit=True):
|
||||
"""
|
||||
Setup a new database with a new database user with the specified
|
||||
password.
|
||||
|
||||
:param boolean commit: whether to save the created database
|
||||
:return: database instance
|
||||
:rtype: :py:class:`userdbs.models.UserDatabase`
|
||||
|
||||
"""
|
||||
data = self.cleaned_data
|
||||
self.instance = UserDatabase.objects.create_userdatabase_with_user(
|
||||
data['db_type'], self.hosting_package.osuser,
|
||||
password=data['password1'], commit=commit)
|
||||
return super(AddUserDatabaseForm, self).save(commit)
|
||||
|
||||
|
||||
class ChangeDatabaseUserPasswordForm(forms.ModelForm, PasswordModelFormMixin):
|
||||
"""
|
||||
This form is used to change the password of a database user.
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
model = DatabaseUser
|
||||
fields = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.hosting_package = kwargs.pop('hostingpackage')
|
||||
super(ChangeDatabaseUserPasswordForm, self).__init__(*args, **kwargs)
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_action = reverse(
|
||||
'change_dbuser_password', kwargs={
|
||||
'slug': self.instance.name,
|
||||
'package': self.hosting_package.id,
|
||||
})
|
||||
self.helper.add_input(Submit('submit', _('Set password')))
|
||||
|
||||
def save(self, commit=True):
|
||||
self.instance.set_password(self.cleaned_data['password1'])
|
||||
return super(ChangeDatabaseUserPasswordForm, self).save()
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: gnuviechadmin userdbs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-01-17 15:59+0100\n"
|
||||
"PO-Revision-Date: 2015-01-17 16:00+0100\n"
|
||||
"POT-Creation-Date: 2015-01-26 13:42+0100\n"
|
||||
"PO-Revision-Date: 2015-01-26 13:44+0100\n"
|
||||
"Last-Translator: Jan Dittberner <jan@dittberner.info>\n"
|
||||
"Language-Team: Jan Dittberner <jan@dittberner.info>\n"
|
||||
"Language: de\n"
|
||||
|
@ -31,6 +31,18 @@ msgstr "Ausgewählte Nutzerdatenbanken löschen"
|
|||
msgid "Database Users and their Databases"
|
||||
msgstr "Datenbanknutzer und ihre Datenbanken"
|
||||
|
||||
#: userdbs/forms.py:30
|
||||
msgid "Database type"
|
||||
msgstr "Datenbanktyp"
|
||||
|
||||
#: userdbs/forms.py:51
|
||||
msgid "Create database"
|
||||
msgstr "Datenbank anlegen"
|
||||
|
||||
#: userdbs/forms.py:88
|
||||
msgid "Set password"
|
||||
msgstr "Passwort setzen"
|
||||
|
||||
#: userdbs/models.py:32
|
||||
msgid "PostgreSQL"
|
||||
msgstr "PostgreSQL"
|
||||
|
@ -47,7 +59,7 @@ msgstr "Benutzername"
|
|||
msgid "database type"
|
||||
msgstr "Datenbanktyp"
|
||||
|
||||
#: userdbs/models.py:114 userdbs/models.py:230
|
||||
#: userdbs/models.py:114 userdbs/models.py:250
|
||||
msgid "database user"
|
||||
msgstr "Datenbanknutzer"
|
||||
|
||||
|
@ -55,14 +67,29 @@ msgstr "Datenbanknutzer"
|
|||
msgid "database users"
|
||||
msgstr "Datenbanknutzer"
|
||||
|
||||
#: userdbs/models.py:229
|
||||
#: userdbs/models.py:249
|
||||
msgid "database name"
|
||||
msgstr "Datenbankname"
|
||||
|
||||
#: userdbs/models.py:236
|
||||
#: userdbs/models.py:256
|
||||
msgid "user database"
|
||||
msgstr "Nutzerdatenbank"
|
||||
|
||||
#: userdbs/models.py:237
|
||||
#: userdbs/models.py:257
|
||||
msgid "user specific database"
|
||||
msgstr "nutzerspezifische Datenbank"
|
||||
|
||||
#: userdbs/views.py:63
|
||||
#, python-brace-format
|
||||
msgid "Successfully create new {type} database {dbname} for user {dbuser}"
|
||||
msgstr ""
|
||||
"Neue {type}-Datenbank {dbname} für Benutzer {dbuser} erfolgreich angelegt"
|
||||
|
||||
#: userdbs/views.py:100
|
||||
#, python-brace-format
|
||||
msgid "Successfully changed password of database user {dbuser}"
|
||||
msgstr "Passwort des Datenbanknutzers {dbuser} wurde erfolgreich geändert."
|
||||
|
||||
#: userdbs/views.py:129
|
||||
msgid "Database deleted"
|
||||
msgstr "Datenbank gelöscht"
|
||||
|
|
|
@ -202,6 +202,26 @@ class UserDatabaseManager(models.Manager):
|
|||
break
|
||||
return nextname
|
||||
|
||||
@transaction.atomic
|
||||
def create_userdatabase_with_user(
|
||||
self, db_type, osuser, password=None, commit=True):
|
||||
"""
|
||||
Creates a new user database with a new user.
|
||||
|
||||
:param db_type: database type from :py:data:`DB_TYPES`
|
||||
:param osuser: :py:class:`osusers.models.OsUser` instance
|
||||
:param str password: the password of the new database user
|
||||
:param boolean commit: whether the user and the database should be
|
||||
persisted
|
||||
:return: database instance
|
||||
:rtype: :py:class:`UserDatabase`
|
||||
|
||||
"""
|
||||
dbuser = DatabaseUser.objects.create_database_user(
|
||||
osuser, db_type, password=password, commit=commit)
|
||||
database = self.create_userdatabase(dbuser, commit=commit)
|
||||
return database
|
||||
|
||||
@transaction.atomic
|
||||
def create_userdatabase(self, db_user, db_name=None, commit=True):
|
||||
"""
|
||||
|
@ -267,10 +287,13 @@ class UserDatabase(TimeStampedModel, models.Model):
|
|||
:py:meth:`django.db.models.Model.delete`
|
||||
|
||||
"""
|
||||
if self.db_user.db_type == DB_TYPES.pgsql:
|
||||
db_user = self.db_user
|
||||
if db_user.db_type == DB_TYPES.pgsql:
|
||||
delete_pgsql_database.delay(self.db_name).get()
|
||||
elif self.db_user.db_type == DB_TYPES.mysql:
|
||||
delete_mysql_database.delay(self.db_name, self.db_user.name).get()
|
||||
elif db_user.db_type == DB_TYPES.mysql:
|
||||
delete_mysql_database.delay(self.db_name, db_user.name).get()
|
||||
else:
|
||||
raise ValueError('Unknown database type %d' % self.db_type)
|
||||
super(UserDatabase, self).delete(*args, **kwargs)
|
||||
if not db_user.userdatabase_set.exists():
|
||||
db_user.delete()
|
||||
|
|
23
gnuviechadmin/userdbs/urls.py
Normal file
23
gnuviechadmin/userdbs/urls.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
This module defines the URL patterns for user database views.
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .views import (
|
||||
AddUserDatabase,
|
||||
ChangeDatabaseUserPassword,
|
||||
DeleteUserDatabase,
|
||||
)
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^(?P<package>\d+)/create$',
|
||||
AddUserDatabase.as_view(), name='add_userdatabase'),
|
||||
url(r'^(?P<package>\d+)/(?P<slug>[\w0-9]+)/setpassword',
|
||||
ChangeDatabaseUserPassword.as_view(), name='change_dbuser_password'),
|
||||
url(r'^(?P<package>\d+)/(?P<slug>[\w0-9]+)/delete',
|
||||
DeleteUserDatabase.as_view(), name='delete_userdatabase'),
|
||||
)
|
131
gnuviechadmin/userdbs/views.py
Normal file
131
gnuviechadmin/userdbs/views.py
Normal file
|
@ -0,0 +1,131 @@
|
|||
"""
|
||||
This module defines views for user database handling.
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic.edit import (
|
||||
CreateView,
|
||||
DeleteView,
|
||||
UpdateView,
|
||||
)
|
||||
from django.contrib import messages
|
||||
|
||||
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
|
||||
from gvawebcore.views import HostingPackageAndCustomerMixin
|
||||
|
||||
from .forms import (
|
||||
AddUserDatabaseForm,
|
||||
ChangeDatabaseUserPasswordForm,
|
||||
)
|
||||
from .models import (
|
||||
DB_TYPES,
|
||||
DatabaseUser,
|
||||
UserDatabase,
|
||||
)
|
||||
|
||||
|
||||
class AddUserDatabase(
|
||||
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, CreateView
|
||||
):
|
||||
"""
|
||||
This view is used to setup new user databases.
|
||||
|
||||
"""
|
||||
model = UserDatabase
|
||||
context_object_name = 'database'
|
||||
template_name_suffix = '_create'
|
||||
form_class = AddUserDatabaseForm
|
||||
|
||||
def _get_dbtypes(self, hostingpackage):
|
||||
retval = []
|
||||
db_options = hostingpackage.get_databases()
|
||||
for opt in db_options:
|
||||
dbs_of_type = UserDatabase.objects.filter(
|
||||
db_user__osuser=hostingpackage.osuser,
|
||||
db_user__db_type=opt['db_type']).count()
|
||||
if dbs_of_type < opt['number']:
|
||||
retval.append((opt['db_type'], DB_TYPES[opt['db_type']]))
|
||||
return retval
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(AddUserDatabase, self).get_form_kwargs()
|
||||
kwargs['hostingpackage'] = self.get_hosting_package()
|
||||
kwargs['dbtypes'] = self._get_dbtypes(kwargs['hostingpackage'])
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
userdatabase = form.save()
|
||||
messages.success(
|
||||
self.request,
|
||||
_('Successfully create new {type} database {dbname} for user '
|
||||
'{dbuser}').format(
|
||||
type=userdatabase.db_user.db_type,
|
||||
dbname=userdatabase.db_name, dbuser=userdatabase.db_user)
|
||||
)
|
||||
return redirect(self.get_hosting_package())
|
||||
|
||||
|
||||
class ChangeDatabaseUserPassword(
|
||||
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, UpdateView
|
||||
):
|
||||
"""
|
||||
This view is used to change a database user's password.
|
||||
|
||||
"""
|
||||
model = DatabaseUser
|
||||
slug_field = 'name'
|
||||
context_object_name = 'dbuser'
|
||||
template_name_suffix = '_setpassword'
|
||||
form_class = ChangeDatabaseUserPasswordForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(ChangeDatabaseUserPassword, self).get_form_kwargs()
|
||||
kwargs['hostingpackage'] = self.get_hosting_package()
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ChangeDatabaseUserPassword, self).get_context_data(
|
||||
**kwargs)
|
||||
context['hostingpackage'] = self.get_hosting_package()
|
||||
context['customer'] = self.get_customer_object()
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
db_user = form.save()
|
||||
messages.success(
|
||||
self.request,
|
||||
_('Successfully changed password of database user {dbuser}'
|
||||
).format(dbuser=db_user.name)
|
||||
)
|
||||
return redirect(self.get_hosting_package())
|
||||
|
||||
|
||||
class DeleteUserDatabase(
|
||||
HostingPackageAndCustomerMixin, StaffOrSelfLoginRequiredMixin, DeleteView
|
||||
):
|
||||
"""
|
||||
This view is used to delete user databases and databases users if they have
|
||||
no more databases assigned.
|
||||
|
||||
"""
|
||||
model = UserDatabase
|
||||
slug_field = 'db_name'
|
||||
context_object_name = 'database'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DeleteUserDatabase, self).get_context_data(**kwargs)
|
||||
context.update({
|
||||
'hostingpackage': self.get_hosting_package(),
|
||||
'customer': self.get_customer_object(),
|
||||
})
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(
|
||||
self.request,
|
||||
_('Database deleted'),
|
||||
)
|
||||
return self.get_hosting_package().get_absolute_url()
|
Loading…
Reference in a new issue