Commit 18dea3b8 by Bach Dániel

dashboard: add base class for delete views

parent a6c7dcf3
......@@ -27,7 +27,7 @@ from django.contrib.auth import authenticate
from dashboard.views import VmAddInterfaceView
from vm.models import Instance, InstanceTemplate, Lease, Node, Trait
from vm.operations import (WakeUpOperation, AddInterfaceOperation,
AddPortOperation)
AddPortOperation, RemoveInterfaceOperation)
from ..models import Profile
from firewall.models import Vlan, Host, VlanGroup
from mock import Mock, patch
......
......@@ -41,7 +41,8 @@ from ..forms import (
from ..models import FutureMember, GroupProfile
from vm.models import Instance, InstanceTemplate
from ..tables import GroupListTable
from .util import CheckedDetailView, AclUpdateView, search_user, saml_available
from .util import (CheckedDetailView, AclUpdateView, search_user,
saml_available, DeleteViewBase)
logger = logging.getLogger(__name__)
......@@ -224,15 +225,18 @@ class GroupList(LoginRequiredMixin, SingleTableView):
return groups
class GroupRemoveUserView(CheckedDetailView, DeleteView):
class GroupRemoveUserView(DeleteViewBase):
model = Group
slug_field = 'pk'
slug_url_kwarg = 'group_pk'
read_level = 'operator'
level = 'operator'
member_key = 'member_pk'
success_message = _("Member successfully removed from group.")
def get_has_level(self):
return self.object.profile.has_level
def check_auth(self):
if not self.get_object().profile.has_level(
self.request.user, self.level):
raise PermissionDenied()
def get_context_data(self, **kwargs):
context = super(GroupRemoveUserView, self).get_context_data(**kwargs)
......@@ -243,50 +247,24 @@ class GroupRemoveUserView(CheckedDetailView, DeleteView):
return context
def get_success_url(self):
next = self.request.POST.get('next')
if next:
return next
else:
return reverse_lazy("dashboard.views.group-detail",
kwargs={'pk': self.get_object().pk})
return reverse_lazy("dashboard.views.group-detail",
kwargs={'pk': self.get_object().pk})
def get(self, request, member_pk, *args, **kwargs):
self.member_pk = member_pk
return super(GroupRemoveUserView, self).get(request, *args, **kwargs)
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-remove.html']
else:
return ['dashboard/confirm/base-remove.html']
def remove_member(self, pk):
container = self.get_object()
container.user_set.remove(User.objects.get(pk=pk))
def get_success_message(self):
return _("Member successfully removed from group.")
def delete(self, request, *args, **kwargs):
object = self.get_object()
if not object.profile.has_level(request.user, 'operator'):
raise PermissionDenied()
def delete_obj(self, request, *args, **kwargs):
self.remove_member(kwargs[self.member_key])
success_url = self.get_success_url()
success_message = self.get_success_message()
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return redirect(success_url)
class GroupRemoveFutureUserView(GroupRemoveUserView):
member_key = 'member_org_id'
success_message = _("Future user successfully removed from group.")
def get(self, request, member_org_id, *args, **kwargs):
self.member_org_id = member_org_id
......@@ -305,53 +283,17 @@ class GroupRemoveFutureUserView(GroupRemoveUserView):
FutureMember.objects.filter(org_id=org_id,
group=self.get_object()).delete()
def get_success_message(self):
return _("Future user successfully removed from group.")
class GroupDelete(CheckedDetailView, DeleteView):
"""This stuff deletes the group.
"""
class GroupDelete(DeleteViewBase):
model = Group
template_name = "dashboard/confirm/base-delete.html"
read_level = 'operator'
def get_has_level(self):
return self.object.profile.has_level
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
success_message = _("Group successfully deleted.")
# github.com/django/django/blob/master/django/views/generic/edit.py#L245
def delete(self, request, *args, **kwargs):
object = self.get_object()
if not object.profile.has_level(request.user, 'owner'):
def check_auth(self):
if not self.get_object().profile.has_level(self.request.user, 'owner'):
raise PermissionDenied()
object.delete()
success_url = self.get_success_url()
success_message = _("Group successfully deleted.")
if request.is_ajax():
if request.POST.get('redirect').lower() == "true":
messages.success(request, success_message)
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return redirect(success_url)
def get_success_url(self):
next = self.request.POST.get('next')
if next:
return next
else:
return reverse_lazy('dashboard.index')
return reverse_lazy('dashboard.views.group-list')
class GroupCreate(GroupCodeMixin, LoginRequiredMixin, TemplateView):
......
......@@ -28,7 +28,7 @@ from django.forms.models import inlineformset_factory
from django.http import HttpResponse
from django.shortcuts import redirect
from django.utils.translation import ugettext as _
from django.views.generic import DetailView, TemplateView, DeleteView
from django.views.generic import DetailView, TemplateView
from braces.views import LoginRequiredMixin, SuperuserRequiredMixin
from django_tables2 import SingleTableView
......@@ -38,7 +38,7 @@ from vm.models import Node, NodeActivity, Trait
from ..forms import TraitForm, HostForm, NodeForm
from ..tables import NodeListTable
from .util import AjaxOperationMixin, OperationView, GraphMixin
from .util import AjaxOperationMixin, OperationView, GraphMixin, DeleteViewBase
def get_operations(instance, user):
......@@ -203,7 +203,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
context = self.get_context_data(**kwargs)
context.update({
'template': 'dashboard/node-create.html',
'box_title': 'Create a Node',
'box_title': _('Create a node'),
'hostform': hostform,
'formset': formset,
......@@ -236,44 +236,16 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
return redirect(path)
class NodeDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
"""This stuff deletes the node.
"""
class NodeDelete(SuperuserRequiredMixin, DeleteViewBase):
model = Node
template_name = "dashboard/confirm/base-delete.html"
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
success_message = _("Node successfully deleted.")
# github.com/django/django/blob/master/django/views/generic/edit.py#L245
def delete(self, request, *args, **kwargs):
object = self.get_object()
object.delete()
success_url = self.get_success_url()
success_message = _("Node successfully deleted.")
if request.is_ajax():
if request.POST.get('redirect').lower() == "true":
messages.success(request, success_message)
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return redirect(success_url)
def check_auth(self):
if not self.request.user.is_superuser:
raise PermissionDenied()
def get_success_url(self):
next = self.request.POST.get('next')
if next:
return next
else:
return reverse_lazy('dashboard.index')
return reverse_lazy('dashboard.views.node-list')
class NodeAddTraitView(SuperuserRequiredMixin, DetailView):
......
......@@ -28,7 +28,7 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, get_object_or_404
from django.utils.translation import ugettext as _, ugettext_noop
from django.views.generic import (
TemplateView, CreateView, DeleteView, UpdateView,
TemplateView, CreateView, UpdateView,
)
from braces.views import (
......@@ -47,6 +47,7 @@ from ..tables import TemplateListTable, LeaseListTable
from .util import (
AclUpdateView, FilterMixin,
TransferOwnershipConfirmView, TransferOwnershipView,
DeleteViewBase
)
logger = logging.getLogger(__name__)
......@@ -231,46 +232,17 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
return qs.select_related("lease", "owner", "owner__profile")
class TemplateDelete(LoginRequiredMixin, DeleteView):
class TemplateDelete(DeleteViewBase):
model = InstanceTemplate
success_message = _("Template successfully deleted.")
def get_success_url(self):
return reverse("dashboard.views.template-list")
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def get(self, request, *args, **kwargs):
if not self.get_object().has_level(request.user, "owner"):
message = _("Only the owners can delete the selected template.")
if request.is_ajax():
raise PermissionDenied()
else:
messages.warning(request, message)
return redirect(self.get_success_url())
return super(TemplateDelete, self).get(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
def delete_obj(self, request, *args, **kwargs):
object = self.get_object()
if not object.has_level(request.user, 'owner'):
raise PermissionDenied()
object.destroy_disks()
object.delete()
success_url = self.get_success_url()
success_message = _("Template successfully deleted.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect(success_url)
class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
......@@ -333,25 +305,24 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return kwargs
class DiskRemoveView(DeleteView):
class DiskRemoveView(DeleteViewBase):
model = Disk
success_message = _("Disk successfully removed.")
def get_queryset(self):
qs = super(DiskRemoveView, self).get_queryset()
return qs.exclude(template_set=None)
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def get_context_data(self, **kwargs):
context = super(DiskRemoveView, self).get_context_data(**kwargs)
def check_auth(self):
disk = self.get_object()
template = disk.template_set.get()
if not template.has_level(self.request.user, 'owner'):
raise PermissionDenied()
def get_context_data(self, **kwargs):
disk = self.get_object()
template = disk.template_set.get()
context = super(DiskRemoveView, self).get_context_data(**kwargs)
context['title'] = _("Disk remove confirmation")
context['text'] = _("Are you sure you want to remove "
"<strong>%(disk)s</strong> from "
......@@ -360,29 +331,12 @@ class DiskRemoveView(DeleteView):
)
return context
def delete(self, request, *args, **kwargs):
def delete_obj(self, request, *args, **kwargs):
disk = self.get_object()
template = disk.template_set.get()
if not template.has_level(request.user, 'owner'):
raise PermissionDenied()
template.remove_disk(disk=disk, user=request.user)
template.remove_disk(disk)
disk.destroy()
next_url = request.POST.get("next")
success_url = next_url if next_url else template.get_absolute_url()
success_message = _("Disk successfully removed.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect("%s#resources" % success_url)
class LeaseCreate(LoginRequiredMixin, PermissionRequiredMixin,
SuccessMessageMixin, CreateView):
......@@ -435,18 +389,13 @@ class LeaseDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return super(LeaseDetail, self).post(request, *args, **kwargs)
class LeaseDelete(LoginRequiredMixin, DeleteView):
class LeaseDelete(DeleteViewBase):
model = Lease
success_message = _("Lease successfully deleted.")
def get_success_url(self):
return reverse("dashboard.views.template-list")
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def get_context_data(self, *args, **kwargs):
c = super(LeaseDelete, self).get_context_data(*args, **kwargs)
lease = self.get_object()
......@@ -461,36 +410,11 @@ class LeaseDelete(LoginRequiredMixin, DeleteView):
c['disable_submit'] = True
return c
def get(self, request, *args, **kwargs):
if not self.get_object().has_level(request.user, "owner"):
message = _("Only the owners can delete the selected lease.")
if request.is_ajax():
raise PermissionDenied()
else:
messages.warning(request, message)
return redirect(self.get_success_url())
return super(LeaseDelete, self).get(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
def delete_obj(self, request, *args, **kwargs):
object = self.get_object()
if not object.has_level(request.user, "owner"):
raise PermissionDenied()
if object.instancetemplate_set.count() > 0:
raise SuspiciousOperation()
object.delete()
success_url = self.get_success_url()
success_message = _("Lease successfully deleted.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect(success_url)
class TransferTemplateOwnershipConfirmView(TransferOwnershipConfirmView):
......
......@@ -35,7 +35,7 @@ from django.shortcuts import redirect, get_object_or_404
from django.utils.translation import ugettext as _
from django.views.decorators.http import require_POST
from django.views.generic import (
TemplateView, DetailView, View, DeleteView, UpdateView, CreateView,
TemplateView, DetailView, View, UpdateView, CreateView,
)
from django_sshkey.models import UserKey
......@@ -50,7 +50,7 @@ from ..forms import (
from ..models import Profile, GroupProfile, ConnectCommand, create_profile
from ..tables import UserKeyListTable, ConnectCommandListTable
from .util import saml_available
from .util import saml_available, DeleteViewBase
logger = logging.getLogger(__name__)
......@@ -385,36 +385,17 @@ class UserKeyDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return super(UserKeyDetail, self).post(self, request, args, kwargs)
class UserKeyDelete(LoginRequiredMixin, DeleteView):
class UserKeyDelete(DeleteViewBase):
model = UserKey
success_message = _("SSH key successfully deleted.")
def get_success_url(self):
return reverse("dashboard.views.profile-preferences")
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def delete(self, request, *args, **kwargs):
object = self.get_object()
if object.user != request.user:
def check_auth(self):
if self.get_object().user != self.request.user:
raise PermissionDenied()
object.delete()
success_url = self.get_success_url()
success_message = _("SSH key successfully deleted.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect(success_url)
class UserKeyCreate(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = UserKey
......@@ -460,36 +441,17 @@ class ConnectCommandDetail(LoginRequiredMixin, SuccessMessageMixin,
return kwargs
class ConnectCommandDelete(LoginRequiredMixin, DeleteView):
class ConnectCommandDelete(DeleteViewBase):
model = ConnectCommand
success_message = _("Command template successfully deleted.")
def get_success_url(self):
return reverse("dashboard.views.profile-preferences")
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def delete(self, request, *args, **kwargs):
object = self.get_object()
if object.user != request.user:
def check_auth(self):
if self.get_object().user != self.request.user:
raise PermissionDenied()
object.delete()
success_url = self.get_success_url()
success_message = _("Command template successfully deleted.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect(success_url)
class ConnectCommandCreate(LoginRequiredMixin, SuccessMessageMixin,
CreateView):
......
......@@ -33,7 +33,7 @@ from django.db.models import Q
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import redirect, render
from django.utils.translation import ugettext_lazy as _, ugettext_noop
from django.views.generic import DetailView, View
from django.views.generic import DetailView, View, DeleteView
from django.views.generic.detail import SingleObjectMixin
from braces.views import LoginRequiredMixin
......@@ -694,3 +694,45 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
unicode(user), user.pk, new_owner, key)
raise PermissionDenied()
return (instance, new_owner)
class DeleteViewBase(LoginRequiredMixin, DeleteView):
level = 'owner'
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def check_auth(self):
if not self.get_object().has_level(self.request.user, self.level):
raise PermissionDenied()
def get(self, request, *args, **kwargs):
try:
self.check_auth()
except PermissionDenied:
message = _("Only the owners can delete the selected object.")
if request.is_ajax():
raise PermissionDenied()
else:
messages.warning(request, message)
return redirect(self.get_success_url())
return super(DeleteViewBase, self).get(request, *args, **kwargs)
def delete_obj(self, request, *args, **kwargs):
self.get_object().delete()
def delete(self, request, *args, **kwargs):
self.check_auth()
self.delete_obj(request, *args, **kwargs)
if request.is_ajax():
return HttpResponse(
json.dumps({'message': self.success_message}),
content_type="application/json",
)
else:
messages.success(request, self.success_message)
return HttpResponseRedirect(self.get_success_url())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment