Convert task_delete and task_done views from GET to POST

This commit is contained in:
Scot Hacker 2019-02-10 11:06:36 -08:00
parent 891148e496
commit 01cab7a82f
8 changed files with 109 additions and 52 deletions

View file

@ -168,6 +168,8 @@ The previous `tox` system was removed with the v2 release, since we no longer ai
# Version History # Version History
**2.2.1** Convert task delete and toggle_done views to POST only
**2.2.0** Re-instate enforcement of TODO_STAFF_ONLY setting **2.2.0** Re-instate enforcement of TODO_STAFF_ONLY setting
**2.1.1** Correct Python version requirement in documentation to Python 3.6 **2.1.1** Correct Python version requirement in documentation to Python 3.6

View file

@ -1,7 +1,7 @@
""" """
A multi-user, multi-group task management and assignment system for Django. A multi-user, multi-group task management and assignment system for Django.
""" """
__version__ = '2.2.0' __version__ = '2.2.1'
__author__ = 'Scot Hacker' __author__ = 'Scot Hacker'
__email__ = 'shacker@birdhouse.org' __email__ = 'shacker@birdhouse.org'

View file

@ -52,14 +52,17 @@
{% if task.assigned_to %}{{ task.assigned_to }}{% else %}Anyone{% endif %} {% if task.assigned_to %}{{ task.assigned_to }}{% else %}Anyone{% endif %}
</td> </td>
<td> <td>
<a href="{% url "todo:task_toggle_done" task.id %}" class="btn btn-info btn-sm"> <form method="post" action="{% url "todo:task_toggle_done" task.id %}" role="form">
{% csrf_token %}
<button class="btn btn-info btn-sm" type="submit" name="toggle_done">
{% if view_completed %} {% if view_completed %}
Not Done Not Done
{% else %} {% else %}
Done Done
{% endif %} {% endif %}
</a> </button>
</td> </form>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -12,21 +12,40 @@
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">
<ul class="list-group"> <div class="mb-2">
<li class="list-group-item">
<form action="" method="post">
{% csrf_token %}
<button class="btn btn-sm btn-primary" id="EditTaskButton" type="button" <button
data-toggle="collapse" data-target="#AddEditTask">Edit Task</button> class="btn btn-sm btn-primary"
id="EditTaskButton"
type="button"
data-toggle="collapse"
data-target="#AddEditTask"
>
Edit Task
</button>
<a href="{% url "todo:task_toggle_done" task.id %}" class="btn btn-info btn-sm"> <form method="post" action="{% url "todo:task_toggle_done" task.id %}" role="form" style="display:inline;">
{% csrf_token %}
<div style="display:inline;">
<button class="btn btn-info btn-sm" type="submit" name="toggle_done">
{% if task.completed %} Mark Not Done {% else %} Mark Done {% endif %} {% if task.completed %} Mark Not Done {% else %} Mark Done {% endif %}
</a> </button>
</div>
</form>
<form method="post" action="{% url "todo:delete_task" task.id %}" role="form" style="display:inline;">
{% csrf_token %}
<div style="display:inline;">
<button class="btn btn-danger btn-sm" type="submit" name="submit_delete">
Delete
</button>
</div>
</form>
</div>
<ul class="list-group">
<a href="{% url "todo:delete_task" task.id %}" class="btn btn-danger btn-sm">Delete</a>
</form>
</li>
<li class="list-group-item"> <li class="list-group-item">
<strong>Assigned to:</strong> <strong>Assigned to:</strong>
{% if task.assigned_to %} {{ task.assigned_to.get_full_name }} {% else %} Anyone {% endif %} {% if task.assigned_to %} {{ task.assigned_to.get_full_name }} {% else %} Anyone {% endif %}
@ -37,7 +56,7 @@
<li class="list-group-item"> <li class="list-group-item">
<strong>Due date:</strong> {{ task.due_date }} <strong>Due date:</strong> {{ task.due_date }}
</li> </li>
{% if task.completed %} {% if task.completed %}
<li class="list-group-item"> <li class="list-group-item">
<strong>Completed on:</strong> {{ task.completed_date}} <strong>Completed on:</strong> {{ task.completed_date}}
@ -47,7 +66,7 @@
<strong>Completed:</strong> {{ task.completed|yesno:"Yes,No" }} <strong>Completed:</strong> {{ task.completed|yesno:"Yes,No" }}
</li> </li>
{% endif %} {% endif %}
<li class="list-group-item"> <li class="list-group-item">
<strong>In list:</strong> <strong>In list:</strong>
<a href="{% url 'todo:list_detail' task.task_list.id task.task_list.slug %}"> <a href="{% url 'todo:list_detail' task.task_list.id task.task_list.slug %}">

View file

@ -1,5 +1,4 @@
import bleach import bleach
import json
import pytest import pytest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -14,8 +13,6 @@ Next permissions tests - some views should respond for staffers only.
After that, view contents and behaviors. After that, view contents and behaviors.
""" """
# ### SMOKETESTS ###
@pytest.mark.django_db @pytest.mark.django_db
def test_todo_setup(todo_setup): def test_todo_setup(todo_setup):
@ -85,6 +82,31 @@ def test_view_task_detail(todo_setup, admin_client):
assert response.status_code == 200 assert response.status_code == 200
def test_del_task(todo_setup, admin_user, client):
task = Task.objects.first()
url = reverse("todo:delete_task", kwargs={"task_id": task.id})
# View accepts POST, not GET
client.login(username="admin", password="password")
response = client.get(url)
assert response.status_code == 403
response = client.post(url)
assert not Task.objects.filter(id=task.id).exists()
def test_task_toggle_done(todo_setup, admin_user, client):
task = Task.objects.first()
assert not task.completed
url = reverse("todo:task_toggle_done", kwargs={"task_id": task.id})
# View accepts POST, not GET
client.login(username="admin", password="password")
response = client.get(url)
assert response.status_code == 403
client.post(url)
task.refresh_from_db()
assert task.completed
def test_view_search(todo_setup, admin_client): def test_view_search(todo_setup, admin_client):
url = reverse("todo:search") url = reverse("todo:search")
response = admin_client.get(url) response = admin_client.get(url)

View file

@ -16,20 +16,27 @@ def delete_task(request, task_id: int) -> HttpResponse:
Redirect to the list from which the task came. Redirect to the list from which the task came.
""" """
task = get_object_or_404(Task, pk=task_id) if request.method == "POST":
task = get_object_or_404(Task, pk=task_id)
# Permissions redir_url = reverse(
if not ( "todo:list_detail",
(task.created_by == request.user) kwargs={"list_id": task.task_list.id, "list_slug": task.task_list.slug},
or (task.assigned_to == request.user) )
or (task.task_list.group in request.user.groups.all())
): # Permissions
if not (
(task.created_by == request.user)
or (request.user.is_superuser)
or (task.assigned_to == request.user)
or (task.task_list.group in request.user.groups.all())
):
raise PermissionDenied
task.delete()
messages.success(request, "Task '{}' has been deleted".format(task.title))
return redirect(redir_url)
else:
raise PermissionDenied raise PermissionDenied
tlist = task.task_list
task.delete()
messages.success(request, "Task '{}' has been deleted".format(task.title))
return redirect(
reverse("todo:list_detail", kwargs={"list_id": tlist.id, "list_slug": tlist.slug})
)

View file

@ -20,7 +20,7 @@ def list_lists(request) -> HttpResponse:
searchform = SearchForm(auto_id=False) searchform = SearchForm(auto_id=False)
# Make sure user belongs to at least one group. # Make sure user belongs to at least one group.
if request.user.groups.all().count() == 0: if not request.user.groups.all().exists():
messages.warning( messages.warning(
request, request,
"You do not yet belong to any groups. Ask your administrator to add you to one.", "You do not yet belong to any groups. Ask your administrator to add you to one.",

View file

@ -17,23 +17,27 @@ def toggle_done(request, task_id: int) -> HttpResponse:
Redirect to the list from which the task came. Redirect to the list from which the task came.
""" """
task = get_object_or_404(Task, pk=task_id) if request.method == "POST":
task = get_object_or_404(Task, pk=task_id)
# Permissions redir_url = reverse(
if not (
(request.user.is_superuser)
or (task.created_by == request.user)
or (task.assigned_to == request.user)
or (task.task_list.group in request.user.groups.all())
):
raise PermissionDenied
toggle_task_completed(task.id)
messages.success(request, "Task status changed for '{}'".format(task.title))
return redirect(
reverse(
"todo:list_detail", "todo:list_detail",
kwargs={"list_id": task.task_list.id, "list_slug": task.task_list.slug}, kwargs={"list_id": task.task_list.id, "list_slug": task.task_list.slug},
) )
)
# Permissions
if not (
(task.created_by == request.user)
or (request.user.is_superuser)
or (task.assigned_to == request.user)
or (task.task_list.group in request.user.groups.all())
):
raise PermissionDenied
toggle_task_completed(task.id)
messages.success(request, "Task status changed for '{}'".format(task.title))
return redirect(redir_url)
else:
raise PermissionDenied