Limit attachments to specified file types
This commit is contained in:
parent
8cd169e502
commit
ab929b07e1
3 changed files with 28 additions and 8 deletions
10
README.md
10
README.md
|
@ -15,6 +15,7 @@ assignment application for Django, designed to be dropped into an existing site
|
||||||
* Mobile-friendly (work in progress)
|
* Mobile-friendly (work in progress)
|
||||||
* Separate view for My Tasks (across lists)
|
* Separate view for My Tasks (across lists)
|
||||||
* Batch-import tasks via CSV
|
* Batch-import tasks via CSV
|
||||||
|
* Multiple file attachments per task (see settings)
|
||||||
* Integrated mail tracking (unify a task list with an email box)
|
* Integrated mail tracking (unify a task list with an email box)
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ Identical list names can exist in different groups, but not in the same group.
|
||||||
|
|
||||||
Emails are generated to the assigned-to person when new tasks are created.
|
Emails are generated to the assigned-to person when new tasks are created.
|
||||||
|
|
||||||
|
File attachments of a few types are allowed on tasks by default. See settings to disable or to limit filetypes.
|
||||||
|
|
||||||
Comment threads can be added to tasks. Each participant in a thread receives email when new comments are added.
|
Comment threads can be added to tasks. Each participant in a thread receives email when new comments are added.
|
||||||
|
|
||||||
django-todo is auth-only. You must set up a login system and at least one group before deploying.
|
django-todo is auth-only. You must set up a login system and at least one group before deploying.
|
||||||
|
@ -101,7 +104,7 @@ Add links to your site's navigation system:
|
||||||
<a href="{% url 'todo:mine' %}">My Tasks</a>
|
<a href="{% url 'todo:mine' %}">My Tasks</a>
|
||||||
```
|
```
|
||||||
|
|
||||||
django-todo makes use of the Django `messages` system. Make sure you have something like [this](https://docs.djangoproject.com/en/2.0/ref/contrib/messages/#displaying-messages) (link) in your `base.html`.
|
django-todo makes use of the Django `messages` system. Make sure you have something like [this](https://docs.djangoproject.com/en/2.1/ref/contrib/messages/#displaying-messages) (link) in your `base.html`.
|
||||||
|
|
||||||
Log in and access `/todo`!
|
Log in and access `/todo`!
|
||||||
|
|
||||||
|
@ -136,6 +139,11 @@ TODO_DEFAULT_LIST_SLUG = 'tickets'
|
||||||
# Defaults to "/"
|
# Defaults to "/"
|
||||||
TODO_PUBLIC_SUBMIT_REDIRECT = 'dashboard'
|
TODO_PUBLIC_SUBMIT_REDIRECT = 'dashboard'
|
||||||
|
|
||||||
|
# Enable or disable file attachments on Tasks
|
||||||
|
# Optionally limit list of allowed filetypes
|
||||||
|
TODO_ALLOW_FILE_ATTACHMENTS = True
|
||||||
|
TODO_ALLOWED_FILE_ATTACHMENTS = [".jpg", ".gif", ".csv", ".pdf", ".zip"]
|
||||||
|
|
||||||
# additionnal classes the comment body should hold
|
# additionnal classes the comment body should hold
|
||||||
# adding "text-monospace" makes comment monospace
|
# adding "text-monospace" makes comment monospace
|
||||||
TODO_COMMENT_CLASSES = []
|
TODO_COMMENT_CLASSES = []
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
<div class="card-body pb-0">
|
<div class="card-body pb-0">
|
||||||
{% if task.attachment_set.count %}
|
{% if task.attachment_set.count %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table mb-0">
|
<table class="table mb-3">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>File</th>
|
<th>File</th>
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<form method="POST" action="#" enctype="multipart/form-data">
|
<form method="POST" action="" enctype="multipart/form-data" style="width:50%;">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<div class="custom-file">
|
<div class="custom-file">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
import os
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
from django import forms
|
from django import forms
|
||||||
|
@ -117,15 +118,26 @@ def task_detail(request, task_id: int) -> HttpResponse:
|
||||||
|
|
||||||
# Handle uploaded files
|
# Handle uploaded files
|
||||||
if request.FILES.get("attachment_file_input"):
|
if request.FILES.get("attachment_file_input"):
|
||||||
|
file = request.FILES.get("attachment_file_input")
|
||||||
|
|
||||||
|
# Validate inbound file extension against allowed filetypes
|
||||||
|
# FIXME: Move defaults to centralized module
|
||||||
|
allowed_extensions = (
|
||||||
|
settings.TODO_ALLOWED_FILE_ATTACHMENTS
|
||||||
|
if hasattr(settings, "TODO_ALLOWED_FILE_ATTACHMENTS")
|
||||||
|
else [".jpg", ".gif", ".csv", ".pdf", ".zip"]
|
||||||
|
)
|
||||||
|
name, extension = os.path.splitext(file.name)
|
||||||
|
if extension not in allowed_extensions:
|
||||||
|
messages.error(request, f"This site does not allow upload of {extension} files.")
|
||||||
|
return redirect("todo:task_detail", task_id=task.id)
|
||||||
|
|
||||||
Attachment.objects.create(
|
Attachment.objects.create(
|
||||||
task=task,
|
task=task, added_by=request.user, timestamp=datetime.datetime.now(), file=file
|
||||||
added_by=request.user,
|
|
||||||
timestamp=datetime.datetime.now(),
|
|
||||||
file=request.FILES.get("attachment_file_input"),
|
|
||||||
)
|
)
|
||||||
return redirect("todo:task_detail", task_id=task.id)
|
return redirect("todo:task_detail", task_id=task.id)
|
||||||
|
|
||||||
# For the context: Settings for file attachments defaults to True
|
# Settings for file attachments defaults to True
|
||||||
# FIXME: Move settings defaults to a central location?
|
# FIXME: Move settings defaults to a central location?
|
||||||
attachments_enabled = True
|
attachments_enabled = True
|
||||||
if (
|
if (
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue