From 64e3f973305dd638c53c9ef87b38eebcf7e5ac15 Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan@dittberner.info>
Date: Mon, 26 Jan 2015 13:39:35 +0100
Subject: [PATCH] implement user database deletion

- modify userdbs.models.UserDatabase.delete to perform deletion of database
  user if it has no other databases assigned
- implement userdbs.views.DeleteUserDatabase
- add URL pattern 'delete_userdatabase' to userdbs.urls
- add template userdbs/userdatabase_confirm_delete.html
- add link to 'delete_userdatabase' on hosting package detail page
- add changelog entry
---
 docs/changelog.rst                            |  1 +
 .../customerhostingpackage_detail.html        |  1 +
 .../userdbs/userdatabase_confirm_delete.html  | 34 +++++++++++++++++++
 gnuviechadmin/userdbs/models.py               |  9 +++--
 gnuviechadmin/userdbs/urls.py                 |  3 ++
 gnuviechadmin/userdbs/views.py                | 31 ++++++++++++++++-
 6 files changed, 75 insertions(+), 4 deletions(-)
 create mode 100644 gnuviechadmin/templates/userdbs/userdatabase_confirm_delete.html

diff --git a/docs/changelog.rst b/docs/changelog.rst
index 41cc64b..66a6188 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,6 +1,7 @@
 Changelog
 =========
 
+* :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
diff --git a/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html b/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html
index ed95f4b..0f13250 100644
--- a/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html
+++ b/gnuviechadmin/templates/hostingpackages/customerhostingpackage_detail.html
@@ -179,6 +179,7 @@
             <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 %}
diff --git a/gnuviechadmin/templates/userdbs/userdatabase_confirm_delete.html b/gnuviechadmin/templates/userdbs/userdatabase_confirm_delete.html
new file mode 100644
index 0000000..4c71342
--- /dev/null
+++ b/gnuviechadmin/templates/userdbs/userdatabase_confirm_delete.html
@@ -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 %}
diff --git a/gnuviechadmin/userdbs/models.py b/gnuviechadmin/userdbs/models.py
index cf09969..4cc2b76 100644
--- a/gnuviechadmin/userdbs/models.py
+++ b/gnuviechadmin/userdbs/models.py
@@ -287,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()
diff --git a/gnuviechadmin/userdbs/urls.py b/gnuviechadmin/userdbs/urls.py
index 7f21f35..c31cf4d 100644
--- a/gnuviechadmin/userdbs/urls.py
+++ b/gnuviechadmin/userdbs/urls.py
@@ -9,6 +9,7 @@ from django.conf.urls import patterns, url
 from .views import (
     AddUserDatabase,
     ChangeDatabaseUserPassword,
+    DeleteUserDatabase,
 )
 
 urlpatterns = patterns(
@@ -17,4 +18,6 @@ urlpatterns = patterns(
         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'),
 )
diff --git a/gnuviechadmin/userdbs/views.py b/gnuviechadmin/userdbs/views.py
index c11caf6..e8794d6 100644
--- a/gnuviechadmin/userdbs/views.py
+++ b/gnuviechadmin/userdbs/views.py
@@ -8,6 +8,7 @@ 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
@@ -62,7 +63,7 @@ class AddUserDatabase(
             _('Successfully create new {type} database {dbname} for user '
               '{dbuser}').format(
                   type=userdatabase.db_user.db_type,
-                  dbname=userdatabase.db_name, db_user=userdatabase.db_user)
+                  dbname=userdatabase.db_name, dbuser=userdatabase.db_user)
         )
         return redirect(self.get_hosting_package())
 
@@ -100,3 +101,31 @@ class ChangeDatabaseUserPassword(
               ).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()