Skip to content

Commit

Permalink
Merge pull request #691 from velrest/fix_mime_type_check_on_move
Browse files Browse the repository at this point in the history
fix(document): revalidate mimetypes after moving document to different category
  • Loading branch information
velrest authored Nov 18, 2024
2 parents 5fb834e + 46066ac commit d4db4fb
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
4 changes: 3 additions & 1 deletion alexandria/core/tests/__snapshots__/test_viewsets.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,8 @@
'SELECT "alexandria_core_mark"."created_at", "alexandria_core_mark"."created_by_user", "alexandria_core_mark"."created_by_group", "alexandria_core_mark"."modified_at", "alexandria_core_mark"."modified_by_user", "alexandria_core_mark"."modified_by_group", "alexandria_core_mark"."metainfo", "alexandria_core_mark"."slug", "alexandria_core_mark"."name", "alexandria_core_mark"."description" FROM "alexandria_core_mark" WHERE "alexandria_core_mark"."slug" = \'father-should-keep\' LIMIT 21',
'SELECT "alexandria_core_tag"."created_at", "alexandria_core_tag"."created_by_user", "alexandria_core_tag"."created_by_group", "alexandria_core_tag"."modified_at", "alexandria_core_tag"."modified_by_user", "alexandria_core_tag"."modified_by_group", "alexandria_core_tag"."metainfo", "alexandria_core_tag"."id", "alexandria_core_tag"."name", "alexandria_core_tag"."description", "alexandria_core_tag"."tag_synonym_group_id" FROM "alexandria_core_tag" INNER JOIN "alexandria_core_document_tags" ON ("alexandria_core_tag"."id" = "alexandria_core_document_tags"."tag_id") WHERE ("alexandria_core_document_tags"."document_id" = \'9dd4e461268c8034f5c8564e155c67a6\'::uuid AND NOT ("alexandria_core_tag"."id" IN (SELECT U0."id" FROM "alexandria_core_tag" U0 INNER JOIN "alexandria_core_document_tags" U1 ON (U0."id" = U1."tag_id") WHERE U1."document_id" = \'9dd4e461268c8034f5c8564e155c67a6\'::uuid)))',
'SELECT "alexandria_core_mark"."created_at", "alexandria_core_mark"."created_by_user", "alexandria_core_mark"."created_by_group", "alexandria_core_mark"."modified_at", "alexandria_core_mark"."modified_by_user", "alexandria_core_mark"."modified_by_group", "alexandria_core_mark"."metainfo", "alexandria_core_mark"."slug", "alexandria_core_mark"."name", "alexandria_core_mark"."description" FROM "alexandria_core_mark" INNER JOIN "alexandria_core_document_marks" ON ("alexandria_core_mark"."slug" = "alexandria_core_document_marks"."mark_id") WHERE ("alexandria_core_document_marks"."document_id" = \'9dd4e461268c8034f5c8564e155c67a6\'::uuid AND NOT ("alexandria_core_mark"."slug" IN (SELECT U0."slug" FROM "alexandria_core_mark" U0 INNER JOIN "alexandria_core_document_marks" U1 ON (U0."slug" = U1."mark_id") WHERE U1."document_id" = \'9dd4e461268c8034f5c8564e155c67a6\'::uuid)))',
'SELECT "alexandria_core_document"."created_at", "alexandria_core_document"."created_by_user", "alexandria_core_document"."created_by_group", "alexandria_core_document"."modified_at", "alexandria_core_document"."modified_by_user", "alexandria_core_document"."modified_by_group", "alexandria_core_document"."metainfo", "alexandria_core_document"."id", "alexandria_core_document"."title", "alexandria_core_document"."description", "alexandria_core_document"."category_id", "alexandria_core_document"."date" FROM "alexandria_core_document" WHERE "alexandria_core_document"."id" = \'9dd4e461268c8034f5c8564e155c67a6\'::uuid LIMIT 21',
'SELECT "alexandria_core_category"."created_at", "alexandria_core_category"."created_by_user", "alexandria_core_category"."created_by_group", "alexandria_core_category"."modified_at", "alexandria_core_category"."modified_by_user", "alexandria_core_category"."modified_by_group", "alexandria_core_category"."metainfo", "alexandria_core_category"."slug", "alexandria_core_category"."name", "alexandria_core_category"."description", "alexandria_core_category"."allowed_mime_types", "alexandria_core_category"."color", "alexandria_core_category"."parent_id" FROM "alexandria_core_category" WHERE "alexandria_core_category"."slug" = \'note-act-source\' LIMIT 21',
'''
UPDATE "alexandria_core_document" SET "created_at" = '2017-05-21 00:00:00+00:00'::timestamptz, "created_by_user" = 'admin', "created_by_group" = 'admin', "modified_at" = '2017-05-21 00:00:00+00:00'::timestamptz, "modified_by_user" = 'admin', "modified_by_group" = 'admin', "metainfo" = '{}'::jsonb, "title" = 'Michael Edwards', "description" = 'Open else look tree arm responsibility week. Environmental statement bag someone them style.
Public these health team change. Tax final upon stay sing middle suggest.', "category_id" = 'note-act-source', "date" = '1999-11-26'::date WHERE "alexandria_core_document"."id" = '9dd4e461268c8034f5c8564e155c67a6'::uuid
Expand All @@ -2243,7 +2245,7 @@
'BEGIN',
'COMMIT',
]),
'query_count': 19,
'query_count': 21,
'request': dict({
'CONTENT_LENGTH': '813',
'CONTENT_TYPE': 'application/vnd.api+json',
Expand Down
17 changes: 6 additions & 11 deletions alexandria/core/tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from generic_permissions.config import ValidatorsConfig
from generic_permissions.validation import validator_for

from alexandria.core.models import Document
from alexandria.core.models import Tag


def test_custom_validation(db, reset_config_classes, document, file, admin_client):
def test_custom_validation(db, reset_config_classes, tag, file, admin_client):
call_counter = Counter()

class TestValidator:
@validator_for(Document)
@validator_for(Tag)
def validate(self, data, context):
data["created_by_group"] = "foobar"
call_counter["validate"] += 1
Expand All @@ -21,17 +21,12 @@ def validate(self, data, context):

ValidatorsConfig.register_handler_class(TestValidator)

url = reverse("document-detail", args=[document.pk])
url = reverse("tag-detail", args=[tag.pk])

# first, ensure validator is called for Document
admin_client.patch(url, json={})
assert call_counter["validate"] == 1

# See if the validation had some effect
document.refresh_from_db()
assert document.created_by_group == "foobar"

# second, ensure validator is not called for File
url = reverse("file-detail", args=[file.pk])
admin_client.patch(url, json={})
assert call_counter["validate"] == 1
tag.refresh_from_db()
assert tag.created_by_group == "foobar"
31 changes: 31 additions & 0 deletions alexandria/core/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,37 @@ def test_document_delete_some_tags(admin_client, tag_factory, document_factory):
)


def test_move_document_to_new_category(
admin_client, category_factory, file_factory, document_factory
):
category_not_allowed = category_factory.create(allowed_mime_types=["plain/text"])
category_allowed = category_factory.create(allowed_mime_types=["image/jpeg"])
document = document_factory()
file_factory.create(document=document, name="Image.jpeg", mime_type="image/jpeg")

url = reverse("document-detail", args=[document.pk])

data = {
"data": {
"type": "documents",
"id": document.pk,
"relationships": {
"category": {
"data": {"id": category_not_allowed.pk, "type": "categories"}
}
},
}
}

response = admin_client.patch(url, data)

assert response.status_code == HTTP_400_BAD_REQUEST

data["data"]["relationships"]["category"]["data"]["id"] = category_allowed.pk
response = admin_client.patch(url, data)
assert response.status_code == HTTP_200_OK


@pytest.mark.parametrize(
"presigned, expected_status",
[(True, HTTP_200_OK), (False, HTTP_403_FORBIDDEN)],
Expand Down
14 changes: 13 additions & 1 deletion alexandria/core/validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from generic_permissions.validation import validator_for
from rest_framework.exceptions import ValidationError

from alexandria.core.models import File
from alexandria.core.models import Document, File

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -101,3 +101,15 @@ def validate_file(self, data, context):
data["mime_type"] = content_type_header

return data

@validator_for(Document)
def validate_document(self, data, context):
if context["request"].method == "PATCH" and "category" in data:
category = data["category"]
document = context["view"].get_object()
if not document.category.pk == category.pk:
# Validate if a document is moved to another category that the
# mime type of the file is still compatible with the category's
# mime types.
validate_mime_type(document.get_latest_original().mime_type, category)
return data

0 comments on commit d4db4fb

Please sign in to comment.