From 1f5f98ca7b64cf88d4ca1f2e93fe47c769f40130 Mon Sep 17 00:00:00 2001 From: Vinul Wimalaweera <16556525+vinulw@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:05:27 +0000 Subject: [PATCH] In Progress - List contents of input_file and output_file --- .../oasisapi/analyses/v2_api/viewsets.py | 21 +++++++++++++++++++ src/server/oasisapi/files/models.py | 9 ++++++++ src/server/oasisapi/files/v1_api/views.py | 12 +++++++++-- src/server/oasisapi/schemas/custom_swagger.py | 9 ++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/server/oasisapi/analyses/v2_api/viewsets.py b/src/server/oasisapi/analyses/v2_api/viewsets.py index e04a770c0..d9bf62932 100644 --- a/src/server/oasisapi/analyses/v2_api/viewsets.py +++ b/src/server/oasisapi/analyses/v2_api/viewsets.py @@ -31,6 +31,7 @@ RUN_MODE_PARAM, SUBTASK_STATUS_PARAM, SUBTASK_SLUG_PARAM, + LIST_FILE_PARAM, ) @@ -419,6 +420,17 @@ def input_file(self, request, pk=None, version=None): """ return handle_related_file(self.get_object(), 'input_file', request, ['application/x-gzip', 'application/gzip', 'application/x-tar', 'application/tar']) + + @swagger_auto_schema(methods=['get'], manual_parameters=[LIST_FILE_PARAM,]) + @action(methods=['get'], detail=True) + def list_input_files(self, request, pk=None, version=None): + """ + get: + List the files in `input_file`. + """ + return handle_related_file(self.get_object(), 'input_file', request, ['application/x-gzip', 'application/gzip', 'application/x-tar', 'application/tar']) + + @swagger_auto_schema(methods=['get'], responses={200: FILE_RESPONSE}) @action(methods=['get'], detail=True) def lookup_errors_file(self, request, pk=None, version=None): @@ -503,6 +515,15 @@ def output_file(self, request, pk=None, version=None): """ return handle_related_file(self.get_object(), 'output_file', request, ['application/x-gzip', 'application/gzip', 'application/x-tar', 'application/tar']) + @swagger_auto_schema(methods=['get'], manual_parameters=[LIST_FILE_PARAM,]) + @action(methods=['get'], detail=True) + def list_output_files(self, request, pk=None, version=None): + """ + get: + List the files in `output_file`. + """ + return handle_related_file(self.get_object(), 'output_file', request, ['application/x-gzip', 'application/gzip', 'application/x-tar', 'application/tar']) + @requires_sql_reader @swagger_auto_schema(methods=['get'], responses={200: NestedRelatedFileSerializer}) @action(methods=['get'], detail=True) diff --git a/src/server/oasisapi/files/models.py b/src/server/oasisapi/files/models.py index d70f4a9e7..2d834910a 100644 --- a/src/server/oasisapi/files/models.py +++ b/src/server/oasisapi/files/models.py @@ -3,6 +3,7 @@ from io import BytesIO import pandas as pd +import tarfile from uuid import uuid4 from django.conf import settings @@ -25,6 +26,14 @@ def related_file_to_df(RelatedFile): return pd.read_csv(BytesIO(RelatedFile.read())) +def list_tar_file(RelatedFile): + if not RelatedFile: + return None + # Need to verify this is a tar file + tarf = tarfile.open(fileobj=BytesIO(RelatedFile.read()), mode='r') + return tarf.getnames() + + def random_file_name(instance, filename): if getattr(instance, "store_as_filename", False): return filename diff --git a/src/server/oasisapi/files/v1_api/views.py b/src/server/oasisapi/files/v1_api/views.py index 62b0252f0..a9bfe9e86 100644 --- a/src/server/oasisapi/files/v1_api/views.py +++ b/src/server/oasisapi/files/v1_api/views.py @@ -4,13 +4,13 @@ from django.conf import settings from django.core.files import File -from django.http import StreamingHttpResponse, Http404 +from django.http import StreamingHttpResponse, Http404, JsonResponse from rest_framework.response import Response from rest_framework.exceptions import ValidationError from oasis_data_manager.df_reader.config import get_df_reader from oasis_data_manager.df_reader.exceptions import InvalidSQLException -from ..models import RelatedFile +from ..models import RelatedFile, list_tar_file from .serializers import RelatedFileSerializer, EXPOSURE_ARGS from ...permissions.group_auth import verify_user_is_in_obj_groups @@ -45,9 +45,12 @@ def _handle_get_related_file(parent, field, request): if not f: raise Http404() + verify_user_is_in_obj_groups(request.user, f, 'You do not have permission to read this file') file_format = request.GET.get('file_format', None) + list_files = request.query_params.get('file_mode', False) + if 'converted' in request.GET: if not (f.converted_file and f.conversion_state == RelatedFile.ConversionState.DONE): raise Http404() @@ -86,6 +89,11 @@ def _handle_get_related_file(parent, field, request): response['Content-Disposition'] = 'attachment; filename="{}{}"'.format(download_name, '.csv') return response + if list_files: + files = list_tar_file(f) + # todo: change this to a proper response + return JsonResponse({'files': files}) + # Original Fallback method - Reutrn data 'as is' response = StreamingHttpResponse(_get_chunked_content(file_obj), content_type=f.content_type) response['Content-Disposition'] = 'attachment; filename="{}"'.format(download_name) diff --git a/src/server/oasisapi/schemas/custom_swagger.py b/src/server/oasisapi/schemas/custom_swagger.py index 5b1ed0fdd..fecac3f32 100644 --- a/src/server/oasisapi/schemas/custom_swagger.py +++ b/src/server/oasisapi/schemas/custom_swagger.py @@ -7,6 +7,7 @@ 'SUBTASK_STATUS_PARAM', 'SUBTASK_SLUG_PARAM', 'FILE_VALIDATION_PARAM', + 'LIST_FILE_PARAM', ] from drf_yasg import openapi @@ -109,3 +110,11 @@ description="Validate OED files on upload, default `True`", type=openapi.TYPE_BOOLEAN, ) + +LIST_FILE_PARAM = openapi.Parameter( + 'file_mode', + openapi.IN_QUERY, + required=False, + description="List file, if directory or tar, list contents.", + type=openapi.TYPE_BOOLEAN, +)