Skip to content

Commit

Permalink
add host name confirmation (#1090)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jan 22, 2025
1 parent ba70721 commit bb03a62
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ <h3>Confirm Deletion of {% get_display_name object.type True %}</h3>

<form method="post">
{% csrf_token %}
<input class="form-control mb-3"
name="delete_host_confirm"
autocomplete="off"
required="true"
placeholder="Type the host name of this server (e.g. &quot;site.example.org&quot;) to confirm deletion." />
<div class="btn-group pull-right">
<a role="button" class="btn btn-secondary"
href="{% url 'projectroles:update' project=object.sodar_uuid %}">
<i class="iconify" data-icon="mdi:arrow-left-circle"></i> Cancel
</a>
<button type="submit" class="btn btn-danger">
<button type="submit" class="btn btn-danger sodar-btn-submit-once"
id="sodar-pr-btn-confirm-delete">
<i class="iconify" data-icon="mdi:close-thick"></i> Delete
</button>
</div>
Expand Down
17 changes: 17 additions & 0 deletions projectroles/tests/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,23 @@ def test_archive_button_archived(self):
)


class TestProjectDeleteView(UITestBase):
"""Tests for ProjectDeleteView UI"""

def test_render(self):
"""Test rendering of project delete confirmation form"""
url = reverse(
'projectroles:delete', kwargs={'project': self.project.sodar_uuid}
)
self.login_and_redirect(self.superuser, url)
self.assertIsNotNone(
self.selenium.find_element(By.ID, 'sodar-pr-btn-confirm-delete')
)
self.assertIsNotNone(
self.selenium.find_element(By.NAME, 'delete_host_confirm')
)


class TestProjectRoleView(RemoteTargetMixin, UITestBase):
"""Tests for ProjectRoleView UI"""

Expand Down
27 changes: 22 additions & 5 deletions projectroles/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2686,6 +2686,7 @@ def setUp(self):
'projectroles:delete',
kwargs={'project': self.category.sodar_uuid},
)
self.post_data = {'delete_host_confirm': 'testserver'}

def test_get(self):
"""Test ProjectDeleteView GET with project"""
Expand Down Expand Up @@ -2717,7 +2718,7 @@ def test_post(self):
self.assertEqual(len(mail.outbox), 0)

with self.login(self.user):
response = self.client.post(self.url)
response = self.client.post(self.url, data=self.post_data)
self.assertRedirects(
response,
reverse(
Expand Down Expand Up @@ -2758,7 +2759,7 @@ def test_post_as_owner(self):
self.assertEqual(len(mail.outbox), 0)

with self.login(self.user_owner): # POST as owner
response = self.client.post(self.url)
response = self.client.post(self.url, data=self.post_data)

self.assertEqual(response.status_code, 302)
self.assertEqual(Project.objects.count(), 1)
Expand All @@ -2780,7 +2781,7 @@ def test_post_disable_email(self):
self.assertEqual(len(mail.outbox), 0)

with self.login(self.user): # POST as self.user again
response = self.client.post(self.url)
response = self.client.post(self.url, data=self.post_data)

self.assertEqual(response.status_code, 302)
self.assertEqual(Project.objects.count(), 1)
Expand All @@ -2792,7 +2793,7 @@ def test_post_category_with_children(self):
"""Test POST with category and children (should fail)"""
self.assertEqual(Project.objects.count(), 2)
with self.login(self.user):
response = self.client.post(self.url_cat)
response = self.client.post(self.url_cat, data=self.post_data)
self.assertRedirects(response, reverse('home'))
self.assertEqual(Project.objects.count(), 2)

Expand All @@ -2801,10 +2802,26 @@ def test_post_category_without_children(self):
self.project.delete()
self.assertEqual(Project.objects.count(), 1)
with self.login(self.user):
response = self.client.post(self.url_cat)
response = self.client.post(self.url_cat, data=self.post_data)
self.assertRedirects(response, reverse('home'))
self.assertEqual(Project.objects.count(), 0)

def test_post_invalid_host_name(self):
"""Test POST with invalid host name (should fail)"""
self.assertEqual(Project.objects.count(), 2)
with self.login(self.user):
response = self.client.post(
self.url, data={'delete_host_confirm': 'INVALID-HOST'}
)
self.assertRedirects(
response,
reverse(
'projectroles:update',
kwargs={'project': self.project.sodar_uuid},
),
)
self.assertEqual(Project.objects.count(), 2)


class TestProjectRoleView(ProjectMixin, RoleAssignmentMixin, ViewTestBase):
"""Tests for ProjectRoleView"""
Expand Down
22 changes: 19 additions & 3 deletions projectroles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1849,6 +1849,25 @@ def dispatch(self, request, *args, **kwargs):

def post(self, *args, **kwargs):
project = self.get_object()
redirect_url = reverse(
'projectroles:update', kwargs={'project': project.sodar_uuid}
)

# Don't allow deletion unless user has input the host name
host_confirm = self.request.POST.get('delete_host_confirm')
actual_host = self.request.get_host().split(':')[0]
if not host_confirm or host_confirm != actual_host:
msg = (
f'Incorrect host name for confirming sheet deletion: '
f'"{host_confirm}"'
)
logger.error(msg + ' (correct={})'.format(actual_host))
messages.error(
self.request, 'Host name input incorrect, deletion cancelled.'
)
return redirect(redirect_url)

# Proceed with deletion
try:
with transaction.atomic():
self.handle_delete(project, self.request)
Expand All @@ -1860,9 +1879,6 @@ def post(self, *args, **kwargs):
raise ex
p_type = get_display_name(project.type, title=False)
messages.error(self.request, f'Failed to delete {p_type}: {ex}')
redirect_url = reverse(
'projectroles:update', kwargs={'project': project.sodar_uuid}
)
return redirect(redirect_url)


Expand Down

0 comments on commit bb03a62

Please sign in to comment.