1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00

fix(templates): each delete page says what deleting its object does

The shared delete page asked only whether to delete the object. Each
view now gives its consequence: a deleted compute's VMs keep running
but the panel forgets them and their owners, a deleted user's VMs
stay, a group's members keep their accounts, a VM's owner loses only
the access, a removed VM's record no longer brings its owners back,
an SSH key stays on the VMs that have it, a flavor only goes as a
size template.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
catborise 2026-10-22 11:02:54 +03:00
parent f9c8c36a6b
commit fbe93d9aee
6 changed files with 54 additions and 7 deletions

View file

@ -93,6 +93,7 @@ def ssh_key_delete(request, pk):
{
"object": ssh_key,
"title": _("Delete SSH key"),
"consequence": _("VMs that already have it keep it; VMs created from now on do not get it."),
},
)
@ -200,7 +201,8 @@ def user_instance_delete(request, pk):
return render(
request,
"common/confirm_delete.html",
{"object": user_instance},
{"object": user_instance,
"consequence": _("The user loses access to this VM; the VM itself is not changed.")},
)

View file

@ -76,7 +76,7 @@ def group_delete(request, pk):
return render(
request,
"common/confirm_delete.html",
{"object": group},
{"object": group, "consequence": _("Its members stay but lose the permissions it gave them.")},
)
@ -182,7 +182,8 @@ def user_delete(request, pk):
return render(
request,
"common/confirm_delete.html",
{"object": user},
{"object": user,
"consequence": _("Their access to VMs, SSH keys and settings go; the VMs themselves stay.")},
)
@ -237,7 +238,8 @@ def tombstone_delete(request, pk):
return render(
request,
"common/confirm_delete.html",
{"object": tombstone},
{"object": tombstone,
"consequence": _("Its owners no longer get the VM back if its UUID shows up again.")},
)

View file

@ -6,6 +6,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from instances.models import Instance
from libvirt import libvirtError
from operations import claims
@ -127,7 +128,9 @@ def compute_delete(request, compute_id):
return render(
request,
"common/confirm_delete.html",
{"object": compute},
{"object": compute,
"consequence": _("Its VMs keep running on the host, but the panel forgets them and who owns them; "
"added again, the host's VMs come back without owners.")},
)

View file

@ -2202,5 +2202,5 @@ def flavor_delete(request, pk):
return render(
request,
"common/confirm_delete.html",
{"object": flavor},
{"object": flavor, "consequence": _("Only the size template goes; VMs made from it keep their size.")},
)

View file

@ -13,7 +13,7 @@
<form method="post">
{% csrf_token %}
<div class="alert alert-warning">
{%trans "Are you sure you want to delete" %} "{{ object }}"?
{% blocktrans %}Delete "{{ object }}"?{% endblocktrans %} {{ consequence }}
</div>
<div class="mb-0 float-end">
<a class="btn btn-primary" href="javascript:history.back()">

View file

@ -0,0 +1,40 @@
"""Each delete page says what deleting its object does, besides naming it."""
from accounts.models import UserInstance, UserSSHKey
from computes.models import Compute
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.test import TestCase
from django.urls import reverse
from instances.models import Flavor, Instance, InstanceTombstone
from lxml import html
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGJ5dGVzLWZvci10aGUtZGVsZXRlLXBhZ2UtdGVzdA== page@example.com"
class DeletePageTests(TestCase):
def test_every_delete_page_says_what_deleting_does(self):
admin = get_user_model().objects.create_superuser("del-admin", "da@example.com", "pw")
user = get_user_model().objects.create_user("del-user", password="pw")
compute = Compute.objects.create(name="del-host", hostname="192.0.2.9", login="u", password="p", type=1)
vm = Instance.objects.create(compute=compute, name="del-vm", uuid="d0000000-0000-4000-8000-000000000001")
pages = {
reverse("compute_delete", args=[compute.id]): "the panel forgets them and who owns them",
reverse("admin:user_delete", args=[user.id]): "the VMs themselves stay",
reverse("admin:group_delete", args=[Group.objects.create(name="del-group").id]): "lose the permissions",
reverse("admin:tombstone_delete", args=[InstanceTombstone.objects.create(uuid=vm.uuid, name="gone").id]):
"no longer get the VM back",
reverse("accounts:user_instance_delete", args=[UserInstance.objects.create(user=user, instance=vm).id]):
"the VM itself is not changed",
reverse("instances:flavor_delete", args=[Flavor.objects.create(label="del-flavor", memory=512, vcpu=1, disk=1).id]):
"VMs made from it keep their size",
}
key = UserSSHKey.objects.create(user=admin, keyname="del-key", keypublic=KEY)
pages[reverse("accounts:ssh_key_delete", args=[key.id])] = "VMs that already have it keep it"
self.client.force_login(admin)
for url, consequence in pages.items():
with self.subTest(url=url):
alert = html.fromstring(self.client.get(url).content).xpath("//div[contains(@class, 'alert-warning')]")
self.assertEqual(len(alert), 1)
self.assertIn(consequence, alert[0].text_content())
self.assertNotIn("Are you sure", alert[0].text_content())