Skip to content

Commit

Permalink
add project delete ui view (#1090)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jan 20, 2025
1 parent ed935b5 commit b562ec2
Show file tree
Hide file tree
Showing 9 changed files with 519 additions and 200 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Added
- ``SiteAppSettingsFormView`` view (#1304)
- ``SODARAppSettingFormMixin`` form helper mixin (#1545)
- Old owner "remove role" option in ``RoleAssignmentOwnerTransferForm`` (#836)
- Project deletion (#1090)

Changed
-------
Expand Down
1 change: 1 addition & 0 deletions docs/source/major_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ v1.1.0 (WIP)
Release Highlights
==================

- Add project deletion
- Add site read-only mode
- Add siteappsettings site app plugin
- Add removeroles management command
Expand Down
6 changes: 6 additions & 0 deletions projectroles/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@ def is_site_writable():
is_project_update_user & is_site_writable,
)

# Allow project deletion
rules.add_perm(
'projectroles.delete_project',
is_project_update_user & is_site_writable,
)

# Allow creation of projects
rules.add_perm(
'projectroles.create_project', is_project_create_user & can_create_projects
Expand Down
40 changes: 40 additions & 0 deletions projectroles/templates/projectroles/project_confirm_delete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{% extends 'projectroles/project_base.html' %}

{% load rules %}
{% load projectroles_tags %}
{% load projectroles_common_tags %}

{% block title %}
Confirm Deletion of {% get_display_name object.type True %}
{% endblock title %}

{% block projectroles_extend %}

<div class="container-fluid sodar-page-container">
<h3>Confirm Deletion of {% get_display_name object.type True %}</h3>

<div class="alert alert-danger" role="alert">
Are you sure you want to delete this {% get_display_name object.type %}?
{% if object.type == 'PROJECT' %}
This will also delete all data within the project.
{% endif %}
This action can <strong>NOT</strong> be undone!
</div>

{# TODO: Add host name verification here #}

<form method="post">
{% csrf_token %}
<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">
<i class="iconify" data-icon="mdi:close-thick"></i> Delete
</button>
</div>
</form>
</div>

{% endblock projectroles_extend %}
8 changes: 7 additions & 1 deletion projectroles/templates/projectroles/project_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ <h3 id="sodar-pr-project-form-title" data-project-type={{ object.type }}>
Update {% get_display_name object.type title=True %}
</h3>
{% if object.type == 'PROJECT' %}
<div class="ml-auto">
<div class="btn-group ml-auto" role="group">
{# TODO: Add logic to disable button with tooltip #}
<a role="button" class="btn btn-danger"
href="{% url 'projectroles:delete' project=object.sodar_uuid %}"
id="sodar-pr-btn-delete">
<i class="iconify" data-icon="mdi:close-thick"></i> Delete
</a>
<a role="button" class="btn btn-warning"
href="{% url 'projectroles:archive' project=object.sodar_uuid %}"
id="sodar-pr-btn-archive">
Expand Down
100 changes: 100 additions & 0 deletions projectroles/tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,106 @@ def test_get_category_anon(self):
self.assert_response(self.url_cat, self.user_no_roles, 302)


class TestProjectDeleteView(ProjectPermissionTestBase):
"""Tests for ProjectDeleteView permissions"""

def setUp(self):
super().setUp()
self.url = reverse(
'projectroles:delete', kwargs={'project': self.project.sodar_uuid}
)
self.url_cat = reverse(
'projectroles:delete', kwargs={'project': self.category.sodar_uuid}
)
self.good_users = [
self.superuser,
self.user_owner_cat,
self.user_delegate_cat,
self.user_owner,
self.user_delegate,
]
self.bad_users = [
self.user_contributor_cat,
self.user_guest_cat,
self.user_finder_cat,
self.user_contributor,
self.user_guest,
self.user_no_roles,
self.anonymous,
]

def test_get(self):
"""Test ProjectDeleteView GET"""
self.assert_response(self.url, self.good_users, 200)
self.assert_response(self.url, self.bad_users, 302)
self.project.set_public()
self.assert_response(self.url, self.user_no_roles, 302)

@override_settings(PROJECTROLES_ALLOW_ANONYMOUS=True)
def test_get_anon(self):
"""Test GET with anonymous access"""
self.project.set_public()
self.assert_response(self.url, self.user_no_roles, 302)

def test_get_archive(self):
"""Test GET with archived project"""
self.project.set_archive()
self.assert_response(self.url, self.good_users, 200)
self.assert_response(self.url, self.bad_users, 302)
self.project.set_public()
self.assert_response(self.url, self.user_no_roles, 302)

def test_get_read_only(self):
"""Test GET with site read-only mode"""
self.set_site_read_only()
self.assert_response(self.url, self.superuser, 200)
self.assert_response(self.url, self.non_superusers, 302)

# TODO: Test category with and without children once checks are implemented
'''
def test_get_category(self):
"""Test GET with category"""
bad_users_cat = [
self.superuser,
self.user_owner_cat,
self.user_delegate_cat,
]
bad_users_non_cat = [
self.user_contributor_cat,
self.user_guest_cat,
self.user_finder_cat,
self.user_owner,
self.user_delegate,
self.user_contributor,
self.user_guest,
self.user_no_roles,
self.anonymous,
]
self.assert_response(
self.url_cat,
bad_users_cat,
302,
redirect_user=reverse(
'projectroles:detail',
kwargs={'project': self.category.sodar_uuid},
),
)
self.assert_response(
self.url_cat,
bad_users_non_cat,
302, # Non-category users get redirected to home
)
self.project.set_public()
self.assert_response(self.url_cat, self.user_no_roles, 302)
@override_settings(PROJECTROLES_ALLOW_ANONYMOUS=True)
def test_get_category_anon(self):
"""Test GET with category and anonymous access"""
self.project.set_public()
self.assert_response(self.url_cat, self.user_no_roles, 302)
'''


class TestProjectRoleView(ProjectPermissionTestBase):
"""Tests for ProjectRoleView permissions"""

Expand Down
Loading

0 comments on commit b562ec2

Please sign in to comment.