Skip to content

Commit

Permalink
Upadte testcase in privateattachmentfileview
Browse files Browse the repository at this point in the history
  • Loading branch information
sudan45 committed Jul 8, 2024
1 parent 8116ede commit 30735cd
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 48 deletions.
18 changes: 0 additions & 18 deletions apps/entry/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
from django.contrib.postgres.aggregates.general import ArrayAgg
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.conf import settings
from django.urls import reverse
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode

from deep.middleware import get_current_user
from unified_connector.models import ConnectorLeadPreviewAttachment
Expand All @@ -25,7 +21,6 @@
Exportable,
)
from assisted_tagging.models import DraftEntry
from gallery.enums import PrivateFileModuleType


class EntryAttachment(models.Model):
Expand Down Expand Up @@ -71,19 +66,6 @@ def clone_from_lead_attachment(cls, lead_attachment: LeadPreviewAttachment) -> '
entry_attachment.save()
return entry_attachment

def get_file_url(self):
return '{protocol}://{domain}{url}'.format(
protocol=settings.HTTP_PROTOCOL,
domain=settings.DJANGO_API_HOST,
url=reverse(
'external_private_url',
kwargs={
'module': PrivateFileModuleType.ENTRY_ATTACHMENT.value,
'identifier': urlsafe_base64_encode(force_bytes(self.id))
}
)
)


class Entry(UserResource, ProjectEntityMixin):
"""
Expand Down
2 changes: 1 addition & 1 deletion apps/export/entries/excel_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def add_entries_from_excel_data_for_static_column(
return [entry_excerpt, entry.dropped_excerpt]
return entry_excerpt
elif exportable == Export.StaticColumn.LEAD_ENTRY_ENTRY_ATTACHMENT_FILE_PREVIEW:
return get_private_file_url(PrivateFileModuleType.ENTRY_ATTACHMENT.value, entry.entry_attachment.id)
return get_private_file_url(PrivateFileModuleType.ENTRY_ATTACHMENT, entry)

def add_entries_from_excel_data(self, rows, data, export_data):
export_type = data.get('type')
Expand Down
128 changes: 108 additions & 20 deletions apps/gallery/tests/test_apis.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import os
import tempfile

from analysis_framework.factories import AnalysisFrameworkFactory
from django.urls import reverse
from django.conf import settings
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes

from rest_framework import status
from entry.factories import EntryAttachmentFactory, EntryFactory
from lead.factories import LeadFactory

from deep.tests import TestCase
from gallery.models import File, FilePreview
from lead.models import Lead
from project.models import Project
from entry.models import Entry, EntryAttachment
from user.models import User
from entry.models import Entry
from user.factories import UserFactory
from project.factories import ProjectFactory
from gallery.enums import PrivateFileModuleType
from utils.graphene.tests import GraphQLTestCase


class GalleryTests(TestCase):
Expand Down Expand Up @@ -211,36 +215,120 @@ def save_file_with_api(self, kwargs={}):
# NOTE: Test for files


class PrivateAttachmentFileViewTest(TestCase):
class PrivateAttachmentFileViewTest(GraphQLTestCase):
def setUp(self):
super().setUp()
# Create a test user
self.user = User.objects.create_user(username='testuser', password='testpassword')

self.member_user = UserFactory.create()
self.member_user1 = UserFactory.create()
self.normal_user = UserFactory.create()
self.af = AnalysisFrameworkFactory.create()
# Create a test entry attachment
self.project = Project.objects.create()
self.lead = Lead.objects.create(project=Project)
self.attachment = EntryAttachment.objects.create()
self.entry = Entry.objects.create(
# for normal user
self.project = ProjectFactory.create()

# for member user
self.project1 = ProjectFactory.create()
self.project1.add_member(self.member_user, role=self.project_role_admin)

self.lead = LeadFactory.create(project=self.project)
# UNPROTECTED lead
self.lead1 = LeadFactory.create(
project=self.project1,
confidentiality=Lead.Confidentiality.UNPROTECTED
)
# RESTRICTED lead
self.lead2 = LeadFactory.create(
project=self.project1,
confidentiality=Lead.Confidentiality.RESTRICTED
)
# CONFIDENTIAL lead
self.lead3 = LeadFactory.create(
project=self.project1,
confidentiality=Lead.Confidentiality.CONFIDENTIAL
)

self.attachment = EntryAttachmentFactory.create()
self.attachment1 = EntryAttachmentFactory.create()
self.attachment2 = EntryAttachmentFactory.create()
self.attachment3 = EntryAttachmentFactory.create()

self.entry = EntryFactory.create(
analysis_framework=self.af,
lead=self.lead,
project=self.project,
entry=self.attachment
entry_attachment=self.attachment3
)
self.entry1 = EntryFactory.create(
analysis_framework=self.af,
lead=self.lead1,
project=self.project1,
entry_attachment=self.attachment
)
self.url = reverse('private_attachment_file_view', kwargs={
self.entry1 = EntryFactory.create(
analysis_framework=self.af,
lead=self.lead3,
project=self.project1,
entry_attachment=self.attachment1
)

self.entry2 = EntryFactory.create(
analysis_framework=self.af,
lead=self.lead,
project=self.project1,
entry_attachment=self.attachment2
)

self.url1 = reverse('external_private_url', kwargs={
'module': PrivateFileModuleType.ENTRY_ATTACHMENT.value,
'identifier': urlsafe_base64_encode(force_bytes(self.attachment.id)),
'identifier': urlsafe_base64_encode(force_bytes(self.entry.id)),
'filename': "test.pdf"
})

def test_access_by_authenticated_user(self):
self.authenticate()
response = self.client.get(self.url)
self.assert_200(response)
self.url2 = reverse('external_private_url', kwargs={
'module': PrivateFileModuleType.ENTRY_ATTACHMENT.value,
'identifier': urlsafe_base64_encode(force_bytes(self.entry1.id)),
'filename': "test.pdf"
})

self.url3 = reverse('external_private_url', kwargs={
'module': PrivateFileModuleType.ENTRY_ATTACHMENT.value,
'identifier': urlsafe_base64_encode(force_bytes(self.entry2.id)),
'filename': "test.pdf"
})

self.url4 = reverse('external_private_url', kwargs={
'module': PrivateFileModuleType.ENTRY_ATTACHMENT.value,
'identifier': urlsafe_base64_encode(force_bytes(self.entry.id)),
'filename': "test.pdf"
})

def test_without_login(self):
response = self.client.get(self.url1)
self.assertEqual(401, response.status_code)

def test_access_by_normal_user(self):
self.force_login(self.normal_user)
response = self.client.get(self.url2)
self.assertEqual(403, response.status_code)

def test_access_by_non_member_user(self):
self.force_login(self.member_user)
response = self.client.get(self.url4)
self.assertEqual(403, response.status_code)

def test_access_by_member_user(self):
self.force_login(self.member_user)
response = self.client.get(self.url2)
self.assertEqual(302, response.status_code)

def test_access_forbidden(self):
self.authenticate()
invalid_url = reverse('private_attachment_file_view', kwargs={
self.force_login(self.member_user)
invalid_url = reverse('external_private_url', kwargs={
'module': PrivateFileModuleType.ENTRY_ATTACHMENT.value,
'identifier': urlsafe_base64_encode(force_bytes(999999)),
'filename': 'test.pdf'
})
response = self.client.get(invalid_url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(response.data['error'], "Access Forbidden Or File doesn't exists, Contact Admin")
self.assertEqual(404, response.status_code)
21 changes: 18 additions & 3 deletions apps/gallery/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,31 @@
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode

from gallery.enums import PrivateFileModuleType
from deep.permissions import ProjectPermissions as PP
from lead.models import Lead

def get_private_file_url(obj, id):

def get_private_file_url(private_file_module_type: PrivateFileModuleType, entry):
return '{protocol}://{domain}{url}'.format(
protocol=settings.HTTP_PROTOCOL,
domain=settings.DJANGO_API_HOST,
url=reverse(
'external_private_url',
kwargs={
'module': obj,
'identifier': urlsafe_base64_encode(force_bytes(id))
'module': private_file_module_type.value,
'identifier': urlsafe_base64_encode(force_bytes(entry.id)),
'filename': entry.entry_attachment.file.name
}
)
)


def check_private_entry_qs(user, project, level):
permission = PP.get_permissions(project, user)
if PP.Permission.VIEW_ENTRY in permission:
if PP.Permission.VIEW_ALL_LEAD in permission:
return True
elif PP.Permission.VIEW_ONLY_UNPROTECTED_LEAD in permission:
return level == Lead.Confidentiality.UNPROTECTED
return False
20 changes: 15 additions & 5 deletions apps/gallery/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from django.utils.http import urlsafe_base64_decode
from django.shortcuts import redirect, get_object_or_404

from gallery.enums import PrivateFileModuleType
from gallery.enums import PrivateFileModuleType
from gallery.utils import check_private_entry_qs
from rest_framework import (
views,
viewsets,
Expand All @@ -25,7 +26,7 @@
from deep.permalinks import Permalink
from project.models import Project
from lead.models import Lead
from entry.models import Entry, EntryAttachment
from entry.models import Entry
from user_resource.filters import UserResourceFilterSet

from utils.extractor.formats import (
Expand Down Expand Up @@ -86,13 +87,21 @@ def get(self, request, uuid=None, filename=None):
class PrivateAttachmentFileView(views.APIView):
permission_classes = [permissions.IsAuthenticated]

def get(self, request, module=None, identifier=None):
def get(self, request, module=None, identifier=None, filename=None):
id = force_text(urlsafe_base64_decode(identifier))
user = request.user
obj = None
if module == PrivateFileModuleType.ENTRY_ATTACHMENT.value:
obj = get_object_or_404(EntryAttachment, id=id)
obj.entry.get_for(user)
entry = get_object_or_404(Entry, id=id)
if not entry.project.is_member(user):
return response.Response({
'error': 'Unauthorized for the content'
}, status.HTTP_403_FORBIDDEN)
if not check_private_entry_qs(user, entry.project, entry.lead.confidentiality):
return response.Response({
'error': 'Access Denied'
}, status.HTTP_403_FORBIDDEN)
obj = entry.entry_attachment
if obj:
return redirect(request.build_absolute_uri(obj.file.url))
return response.Response({
Expand Down Expand Up @@ -134,6 +143,7 @@ class PublicFileView(View):
"""
NOTE: Public File API is deprecated.
"""

def get(self, request, fidb64=None, token=None, filename=None):
file_id = force_text(urlsafe_base64_decode(fidb64))
file = get_object_or_404(File, id=file_id)
Expand Down
2 changes: 1 addition & 1 deletion deep/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def get_api_path(path):
name='deprecated_gallery_private_url',
),
path(
'external/private-file/<str:module>/<str:identifier>',
'external/private-file/<str:module>/<str:identifier>/<filename:filename>',
PrivateAttachmentFileView.as_view(),
name='external_private_url',
),
Expand Down

0 comments on commit 30735cd

Please sign in to comment.