Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Installation:
6. Configure ``FILE_UPLOAD_MAX_SIZE`` (optional). This is the maximum size in
bytes before raising form validation errors. If not set there is no restriction
on file size.


Mind that you serve files!
==========================
Expand All @@ -68,6 +69,10 @@ configuration this would look like::
AddType text/plain .html .htm .shtml .php .php5 .php4 .pl .cgi
</Location>

Private attachments (e.g. attachments marked as
``requires_watermark``) are kept in the ``private_attachments``
folder. Make sure this is not public


Tests
=====
Expand Down
2 changes: 1 addition & 1 deletion attachments/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class AttachmentForm(forms.ModelForm):

class Meta:
model = Attachment
fields = ("attachment_file", "title", "description")
fields = ("attachment_file", "title", "description", "requires_watermark")

def save(self, request, obj, *args, **kwargs):
self.instance.creator = request.user
Expand Down
19 changes: 19 additions & 0 deletions attachments/migrations/0005_requires_watermark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.0.8 on 2020-07-15 06:39

from django.db import migrations, models
import attachments.models


class Migration(migrations.Migration):

dependencies = [
('attachments', '0004_change_model_options'),
]

operations = [
migrations.AddField(
model_name='attachment',
name='requires_watermark',
field=models.BooleanField(null=True, verbose_name='Requires Watermark'),
),
]
23 changes: 23 additions & 0 deletions attachments/migrations/0006_requires_watermark_assign_default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.0.8 on 2020-07-15 06:39

from django.db import migrations, models
import attachments.models


def assign_requires_watermark(apps, schema_editor):
Attachment = apps.get_model('attachments', 'Attachment')
Attachment.objects.all().update(requires_watermark=False)


class Migration(migrations.Migration):

dependencies = [
('attachments', '0005_requires_watermark'),
]

operations = [
migrations.RunPython(
code=assign_requires_watermark,
reverse_code=migrations.RunPython.noop,
),
]
19 changes: 19 additions & 0 deletions attachments/migrations/0007_requires_watermark_make_not_null.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.0.8 on 2020-07-15 06:39

from django.db import migrations, models
import attachments.models


class Migration(migrations.Migration):

dependencies = [
('attachments', '0006_requires_watermark_assign_default'),
]

operations = [
migrations.AlterField(
model_name='attachment',
name='requires_watermark',
field=models.BooleanField(null=False, default=False, verbose_name='Requires Watermark'),
),
]
Empty file.
15 changes: 13 additions & 2 deletions attachments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@


def attachment_upload(instance, filename):
"""Stores the attachment in a "per module/appname/primary key" folder"""
return "attachments/{app}_{model}/{pk}/{filename}".format(
"""
Stores the attachment in a "per module/appname/primary key" folder
Attachments that need to be private (i.e. requires_watermark
attachments), go in the private_attachments folder

"""
attachments_prefix = "attachments"
if instance.requires_watermark:
attachments_prefix = "private_attachments"

return "{attachments_prefix}/{app}_{model}/{pk}/{filename}".format(
app=instance.content_object._meta.app_label,
model=instance.content_object._meta.object_name.lower(),
pk=instance.content_object.pk,
filename=filename,
attachments_prefix=attachments_prefix,
)


Expand Down Expand Up @@ -54,6 +64,7 @@ class Attachment(models.Model):
show_in_standard_package = models.BooleanField(
_("Show in standard package"), default=True
)
requires_watermark = models.BooleanField(_("Requires Watermark"), default=False)

class Meta:
verbose_name = _("attachment")
Expand Down
5 changes: 3 additions & 2 deletions attachments/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ def setUp(self):

self.obj = TestModel.objects.create(title="My first test item")

def _upload_testfile(self, file_obj=None):
def _upload_testfile(self, file_obj=None, opts=None):
"""
Uploads a sample file for the given user.
"""
opts = {} if opts == None else opts
Copy link

@MattFisher MattFisher Jul 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparisons with None need to use is. Edit: this is a PEP8 guideline not a requirement so #non-blocking

Suggested change
opts = {} if opts == None else opts
opts = opts or {}

add_url = reverse(
"attachments:add",
kwargs={
Expand All @@ -61,5 +62,5 @@ def _upload_testfile(self, file_obj=None):
content_type="image/jpeg",
)
return self.client.post(
add_url, {"attachment_file": file_obj}, follow=True
add_url, {"attachment_file": file_obj, **opts}, follow=True
)
14 changes: 14 additions & 0 deletions attachments/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,17 @@ def test_delete_does_not_raise_if_os_remove_raises(self):
self.assertEqual(Attachment.objects.count(), 0)
# NOTE: we don't assert the file path here because
# the mock which raises will not actually delete it

def test_requires_watermark_uploads_to_private_location(self):
self.client.login(**self.cred_jon)
self._upload_testfile(file_obj=None, opts={'requires_watermark': True})
self.assertEqual(Attachment.objects.count(), 1)
att = Attachment.objects.attachments_for_object(self.obj)
self.assertTrue(att[0].attachment_file.name.startswith('private_attachments'))

def test_without_requires_watermark_uploads_to_standard_location(self):
self.client.login(**self.cred_jon)
self._upload_testfile(file_obj=None, opts={'requires_watermark': False})
self.assertEqual(Attachment.objects.count(), 1)
att = Attachment.objects.attachments_for_object(self.obj)
self.assertTrue(att[0].attachment_file.name.startswith('attachments'))