Example #1
0
    def get(self, request, pk, pathname):
        resource, _, _ = view_utils.authorize(
            request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)

        if not resource.supports_folders and '/' in pathname:
            return Response("Resource type does not support folders",
                            status.HTTP_403_FORBIDDEN)

        try:
            view_utils.irods_path_is_allowed(pathname)
        except (ValidationError, SuspiciousFileOperation) as ex:
            return Response(ex.message,
                            status_code=status.HTTP_400_BAD_REQUEST)

        try:
            f = hydroshare.get_resource_file(pk, pathname)
        except ObjectDoesNotExist:
            err_msg = 'File with file name {file_name} does not exist for resource with ' \
                      'resource id {res_id}'.format(file_name=pathname, res_id=pk)
            raise NotFound(detail=err_msg)

        # redirects to django_irods/views.download function
        # use new internal url for rest call
        # TODO: (Couch) Migrate model (with a "data migration") so that this hack is not needed.
        redirect_url = f.url.replace('django_irods/download/',
                                     'django_irods/rest_download/')
        return HttpResponseRedirect(redirect_url)
 def test_get_file(self):
     # test if the added test file is obtained
     res_file_object = hydroshare.get_resource_file(
         self.res.short_id, self.file.name).resource_file
     self.assertEqual(self.file.name,
                      os.path.basename(res_file_object.name),
                      msg='file name did not match')
    def get(self, request, pk, pathname):
        resource, _, _ = view_utils.authorize(
            request, pk,
            needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)

        if not resource.supports_folders and '/' in pathname:
            return Response("Resource type does not support folders", status.HTTP_403_FORBIDDEN)

        try:
            view_utils.irods_path_is_allowed(pathname)
        except (ValidationError, SuspiciousFileOperation) as ex:
            return Response(ex.message, status_code=status.HTTP_400_BAD_REQUEST)

        try:
            f = hydroshare.get_resource_file(pk, pathname).resource_file
        except ObjectDoesNotExist:
            err_msg = 'File with file name {file_name} does not exist for resource with ' \
                      'resource id {res_id}'.format(file_name=pathname, res_id=pk)
            raise NotFound(detail=err_msg)

        # redirects to django_irods/views.download function
        # use new internal url for rest call
        # TODO: (Couch) Migrate model (with a "data migration") so that this hack is not needed.
        redirect_url = f.url.replace('django_irods/download/', 'django_irods/rest_download/')
        return HttpResponseRedirect(redirect_url)
Example #4
0
 def get_resource_file(self, pk, filename):
     authorize(self.request, pk, view=True)
     try:
         f = hydroshare.get_resource_file(pk, filename)
     except ObjectDoesNotExist:
         raise Http404
     return HttpResponseRedirect(f.url, content_type='text/plain')
Example #5
0
def ingest_logical_file_metadata(metadata_file, resource, map_files):
    resource.refresh_from_db()
    graph = Graph()
    graph = graph.parse(data=metadata_file.read())
    agg_type_name = None
    for s, _, _ in graph.triples((None, RDFS.isDefinedBy, None)):
        agg_type_name = s.split("/")[-1]
        break
    if not agg_type_name:
        raise Exception("Could not derive aggregation type from {}".format(metadata_file.name))
    subject = None
    for s, _, _ in graph.triples((None, DC.title, None)):
        subject = s.split('/resource/', 1)[1].split("#")[0]
        break
    if not subject:
        raise Exception("Could not derive aggregation path from {}".format(metadata_file.name))

    logical_file_class = get_logical_file(agg_type_name)
    lf = get_logical_file_by_map_file_path(resource, logical_file_class, subject)

    if not lf:
        # see if the files exist and create it
        res_file = None
        if logical_file_class is FileSetLogicalFile:
            file_path = subject.rsplit('/', 1)[0]
            file_path = file_path.split('data/contents/', 1)[1]
            res_file = resource.files.filter(file_folder=file_path).first()
            if res_file:
                FileSetLogicalFile.set_file_type(resource, None, folder_path=file_path)
        elif logical_file_class is GenericLogicalFile:
            map_name = subject.split('data/contents/', 1)[1]
            map_name = map_name.split('#', 1)[0]
            for map_file in map_files:
                if map_file.name.endswith(map_name):
                    ORE = Namespace("http://www.openarchives.org/ore/terms/")
                    map_graph = Graph().parse(data=map_file.read())
                    for _, _, o in map_graph.triples((None, ORE.aggregates, None)):
                        if not str(o).endswith("_meta.xml"):
                            file_path = str(o)
                            break
            if not file_path:
                raise Exception("Could not determine the generic logical file name")
            file_path = file_path.split('data/contents/', 1)[1]
            res_file = get_resource_file(resource.short_id, file_path)
            if res_file:
                set_logical_file_type(res=resource, user=None, file_id=res_file.pk,
                                      logical_file_type_class=logical_file_class, fail_feedback=True)
        if res_file:
            res_file.refresh_from_db()
            lf = res_file.logical_file
        else:
            raise Exception("Could not find aggregation for {}".format(metadata_file.name))
        if not lf:
            raise Exception("Files for aggregation in metadata file {} could not be found".format(metadata_file.name))

    with transaction.atomic():
        lf.metadata.delete_all_elements()
        lf.metadata.ingest_metadata(graph)
        lf.create_aggregation_xml_documents()
Example #6
0
 def get_resource_file(self, pk, filename):
     authorize(self.request, pk, view=True)
     try:
         f = hydroshare.get_resource_file(pk, filename)
     except ObjectDoesNotExist:
         raise Http404
     return HttpResponseRedirect(f.resource_file.url,
                                 content_type='text/plain')
 def test_get_file(self):
     # test if the added test file is obtained
     res_file_object = hydroshare.get_resource_file(self.res.short_id,
                                                    self.file.name).resource_file
     self.assertEqual(
         self.file.name,
         os.path.basename(res_file_object.name),
         msg='file name did not match'
     )
Example #8
0
    def get(self, request, pk, filename):
        view_utils.authorize(request, pk, view=True, edit=True, full=True)
        try:
            f = hydroshare.get_resource_file(pk, filename)
        except ObjectDoesNotExist:
            err_msg = "File with file name {file_name} does not exist for resource with resource id " "{res_id}".format(
                file_name=filename, res_id=pk
            )
            raise NotFound(detail=err_msg)

        # redirects to django_irods/views.download function
        return HttpResponseRedirect(f.url)
Example #9
0
    def test_get_file(self):
        # test if the added test file is obtained
        res_file = hydroshare.get_resource_file(self.res.short_id,
                                                self.file.name)
        res_file_object = res_file.resource_file
        self.assertEqual(self.file.name,
                         os.path.basename(res_file_object.name),
                         msg='file name did not match')

        # test if the last modified time for the file can be obtained
        # assert time is not None without iRODS Session Exception being raised
        self.assertTrue(res_file.modified_time)
        self.assertTrue(res_file.checksum)
    def test_get_file(self):
        # test if the test file is added to the resource
        resource_file_objects = ResourceFile.objects.filter(object_id=self.res.pk)
        self.assertIn(
            self.file.name,
            [os.path.basename(rf.resource_file.name) for rf in resource_file_objects],
            msg='the test file is not added to the resource'
        )

        # test if the added test file is obtained
        self.assertEqual(
            self.file.name,
            os.path.basename(hydroshare.get_resource_file(self.res.short_id, self.file.name).name),
            msg='the added test file is not obtained from the resource'
        )
Example #11
0
 def get_resource_file(self, pk, filename):
     authorize(self.request, pk, view=True)
     f = hydroshare.get_resource_file(pk, filename)
     return HttpResponseRedirect(f.resource_file.url, content_type='text/plain')
Example #12
0
    def get(self, request, pk, pathname):
        """
        Get a resource file's metadata.

        ## Parameters
        * `id` - alphanumeric uuid of the resource, i.e. cde01b3898c94cdab78a2318330cf795
        * `pathname` - The pathname of the file
        to get these

        ## Returns
        ```
        {
            "keywords": [
                "keyword1",
                "keyword2"
            ],
            "spatial_coverage": {
                "units": "Decimal degrees",
                "east": -84.0465,
                "north": 49.6791,
                "name": "12232",
                "projection": "WGS 84 EPSG:4326"
            },
            "extra_metadata": {
                "extended1": "one"
            },
            "temporal_coverage": {
                "start": "2018-02-22",
                "end": "2018-02-24"
            },
            "title": "File Metadata Title",
            "logical_file": {}
        }
        ```
        """
        try:
            resource_file = hydroshare.get_resource_file(pk, pathname)
            logical_file = resource_file.logical_file
            metadata = resource_file.metadata
        except ObjectDoesNotExist:
            # Backwards compatibility for file_id
            try:
                resource_file = ResourceFile.objects.get(id=pathname)
                logical_file = resource_file.logical_file
                metadata = resource_file.metadata
            except Exception:
                # is it a folder?
                resource = hydroshare.get_resource_by_shortkey(pk)
                dir_path = pk + os.path.join("/data/contents/", pathname)
                logical_file = resource.get_folder_aggregation_object(dir_path)
                metadata = None

        title = logical_file.dataset_name \
            if logical_file else ""
        keywords = metadata.keywords \
            if metadata else []
        spatial_coverage = metadata.spatial_coverage.value \
            if metadata and metadata.spatial_coverage else {}
        extra_metadata = metadata.extra_metadata \
            if metadata else {}
        temporal_coverage = metadata.temporal_coverage.value if \
            metadata and metadata.temporal_coverage else {}
        extra_data = logical_file.metadata.dict() \
            if logical_file else {}

        # TODO: How to leverage serializer for this?
        return Response({
            "title": title,
            "keywords": keywords,
            "spatial_coverage": spatial_coverage,
            "extra_metadata": extra_metadata,
            "temporal_coverage": temporal_coverage,
            "logical_file": extra_data
        })
Example #13
0
    def put(self, request, pk, pathname):
        """
        Update a resource file's metadata

        Accepts application/json encoding.

        ## Parameters
        * `id` - alphanumeric uuid of the resource, i.e. cde01b3898c94cdab78a2318330cf795
        * `pathname` - The pathname of the file
        * `data` - see the "returns" section for formatting

        ## Returns
        ```
        {
            "keywords": [
                "keyword1",
                "keyword2"
            ],
            "spatial_coverage": {
                "units": "Decimal degrees",
                "east": -84.0465,
                "north": 49.6791,
                "name": "12232",
                "projection": "WGS 84 EPSG:4326"
            },
            "extra_metadata": {
                "extended1": "one"
            },
            "temporal_coverage": {
                "start": "2018-02-22",
                "end": "2018-02-24"
            },
            "title": "File Metadata Title"
        }
        ```
        """

        file_serializer = FileMetaDataSerializer(request.data)

        try:
            title = file_serializer.data.pop("title", "")
            try:
                resource_file = hydroshare.get_resource_file(pk, pathname)
            except ObjectDoesNotExist:
                # Backwards compatibility for file_id
                resource_file = ResourceFile.objects.get(id=pathname)
            if resource_file is None:
                raise NotFound("File {} in resource {} does not exist".format(
                    pathname, pk))
            resource_file.metadata.logical_file.dataset_name = title
            resource_file.metadata.logical_file.save()

            spatial_coverage = file_serializer.data.pop(
                "spatial_coverage", None)
            if spatial_coverage is not None:
                # defaulting to point if not provided for backwards compatibility
                type = spatial_coverage[
                    "type"] if "type" in spatial_coverage else "point"
                if resource_file.metadata.spatial_coverage is not None:
                    cov_id = resource_file.metadata.spatial_coverage.id
                    resource_file.metadata.update_element(
                        'coverage', cov_id, type=type, value=spatial_coverage)
                elif resource_file.metadata.spatial_coverage is None:
                    resource_file.metadata.create_element(
                        'coverage', type=type, value=spatial_coverage)

            temporal_coverage = file_serializer.data.pop(
                "temporal_coverage", None)
            if temporal_coverage is not None:
                if resource_file.metadata.temporal_coverage is not None:
                    cov_id = resource_file.metadata.temporal_coverage.id
                    resource_file.metadata.update_element(
                        'coverage',
                        cov_id,
                        type='period',
                        value=temporal_coverage)
                elif resource_file.metadata.temporal_coverage is None:
                    resource_file.metadata.create_element(
                        'coverage', type="period", value=temporal_coverage)

            keywords = file_serializer.data.pop("keywords", None)
            if keywords is not None:
                resource_file.metadata.keywords = keywords

            extra_metadata = file_serializer.data.pop("extra_metadata", None)
            if extra_metadata is not None:
                resource_file.metadata.extra_metadata = extra_metadata

            resource_file.metadata.save()
        except Exception as e:
            raise APIException(e)

        # TODO: How to leverage serializer for this?
        title = resource_file.metadata.logical_file.dataset_name \
            if resource_file.metadata.logical_file else ""
        keywords = resource_file.metadata.keywords \
            if resource_file.metadata else []
        spatial_coverage = resource_file.metadata.spatial_coverage.value \
            if resource_file.metadata.spatial_coverage else {}
        extra_metadata = resource_file.metadata.extra_metadata \
            if resource_file.metadata else {}
        temporal_coverage = resource_file.metadata.temporal_coverage.value if \
            resource_file.metadata.temporal_coverage else {}

        return Response({
            "title": title,
            "keywords": keywords,
            "spatial_coverage": spatial_coverage,
            "extra_metadata": extra_metadata,
            "temporal_coverage": temporal_coverage
        })
Example #14
0
    def get(self, request, pk, pathname):
        """
        Get a resource file's metadata.

        ## Parameters
        * `id` - alphanumeric uuid of the resource, i.e. cde01b3898c94cdab78a2318330cf795
        * `pathname` - The pathname of the file
        to get these

        ## Returns
        ```
        {
            "keywords": [
                "keyword1",
                "keyword2"
            ],
            "spatial_coverage": {
                "units": "Decimal degrees",
                "east": -84.0465,
                "north": 49.6791,
                "name": "12232",
                "projection": "WGS 84 EPSG:4326"
            },
            "extra_metadata": {
                "extended1": "one"
            },
            "temporal_coverage": {
                "start": "2018-02-22",
                "end": "2018-02-24"
            },
            "title": "File Metadata Title"
        }
        ```
        """
        try:
            resource_file = hydroshare.get_resource_file(pk, pathname)
        except ObjectDoesNotExist:
            # Backwards compatibility for file_id
            resource_file = ResourceFile.objects.get(id=pathname)
        if resource_file is None:
            raise NotFound("File {} in resource {} does not exist".format(pathname, pk))

        if resource_file.metadata is None or not resource_file.has_logical_file:
            raise NotFound("File {} in resource {} has no metadata".format(pathname, pk))

        title = resource_file.metadata.logical_file.dataset_name \
            if resource_file.metadata.logical_file else ""
        keywords = resource_file.metadata.keywords \
            if resource_file.metadata else []
        spatial_coverage = resource_file.metadata.spatial_coverage.value \
            if resource_file.metadata.spatial_coverage else {}
        extra_metadata = resource_file.metadata.extra_metadata \
            if resource_file.metadata else {}
        temporal_coverage = resource_file.metadata.temporal_coverage.value if \
            resource_file.metadata.temporal_coverage else {}

        # TODO: How to leverage serializer for this?
        return Response({
            "title": title,
            "keywords": keywords,
            "spatial_coverage": spatial_coverage,
            "extra_metadata": extra_metadata,
            "temporal_coverage": temporal_coverage
        })
Example #15
0
    def put(self, request, pk, pathname):
        """
        Update a resource file's metadata

        Accepts application/json encoding.

        ## Parameters
        * `id` - alphanumeric uuid of the resource, i.e. cde01b3898c94cdab78a2318330cf795
        * `pathname` - The pathname of the file
        * `data` - see the "returns" section for formatting

        ## Returns
        ```
        {
            "keywords": [
                "keyword1",
                "keyword2"
            ],
            "spatial_coverage": {
                "units": "Decimal degrees",
                "east": -84.0465,
                "north": 49.6791,
                "name": "12232",
                "projection": "WGS 84 EPSG:4326"
            },
            "extra_metadata": {
                "extended1": "one"
            },
            "temporal_coverage": {
                "start": "2018-02-22",
                "end": "2018-02-24"
            },
            "title": "File Metadata Title"
        }
        ```
        """

        file_serializer = FileMetaDataSerializer(request.data)

        try:
            title = file_serializer.data.pop("title", "")
            try:
                resource_file = hydroshare.get_resource_file(pk, pathname)
            except ObjectDoesNotExist:
                # Backwards compatibility for file_id
                resource_file = ResourceFile.objects.get(id=pathname)
            if resource_file is None:
                raise NotFound("File {} in resource {} does not exist".format(pathname, pk))
            resource_file.metadata.logical_file.dataset_name = title
            resource_file.metadata.logical_file.save()

            spatial_coverage = file_serializer.data.pop("spatial_coverage", None)
            if spatial_coverage is not None:
                # defaulting to point if not provided for backwards compatibility
                type = spatial_coverage["type"] if "type" in spatial_coverage else "point"
                if resource_file.metadata.spatial_coverage is not None:
                    cov_id = resource_file.metadata.spatial_coverage.id
                    resource_file.metadata.update_element('coverage',
                                                          cov_id,
                                                          type=type,
                                                          value=spatial_coverage)
                elif resource_file.metadata.spatial_coverage is None:
                    resource_file.metadata.create_element('coverage', type=type,
                                                          value=spatial_coverage)

            temporal_coverage = file_serializer.data.pop("temporal_coverage", None)
            if temporal_coverage is not None:
                if resource_file.metadata.temporal_coverage is not None:
                    cov_id = resource_file.metadata.temporal_coverage.id
                    resource_file.metadata.update_element('coverage',
                                                          cov_id,
                                                          type='period',
                                                          value=temporal_coverage)
                elif resource_file.metadata.temporal_coverage is None:
                    resource_file.metadata.create_element('coverage', type="period",
                                                          value=temporal_coverage)

            keywords = file_serializer.data.pop("keywords", None)
            if keywords is not None:
                resource_file.metadata.keywords = keywords

            extra_metadata = file_serializer.data.pop("extra_metadata", None)
            if extra_metadata is not None:
                resource_file.metadata.extra_metadata = extra_metadata

            resource_file.metadata.save()
        except Exception as e:
            raise APIException(e)

        # TODO: How to leverage serializer for this?
        title = resource_file.metadata.logical_file.dataset_name \
            if resource_file.metadata.logical_file else ""
        keywords = resource_file.metadata.keywords \
            if resource_file.metadata else []
        spatial_coverage = resource_file.metadata.spatial_coverage.value \
            if resource_file.metadata.spatial_coverage else {}
        extra_metadata = resource_file.metadata.extra_metadata \
            if resource_file.metadata else {}
        temporal_coverage = resource_file.metadata.temporal_coverage.value if \
            resource_file.metadata.temporal_coverage else {}

        return Response({
            "title": title,
            "keywords": keywords,
            "spatial_coverage": spatial_coverage,
            "extra_metadata": extra_metadata,
            "temporal_coverage": temporal_coverage
        })
Example #16
0
    def test_update_resource_file(self):
        # create a user to be used for creating the resource
        user_creator = hydroshare.create_account(
            '*****@*****.**',
            username='******',
            first_name='Creator_FirstName',
            last_name='Creator_LastName',
            superuser=False,
            groups=[]
        )

        # create a resource without any owner
        resource = GenericResource.objects.create(
            user=user_creator,
            title='My resource',
            creator=user_creator,
            last_changed_by=user_creator,
            doi='doi1000100010001'
        )

        # resource should not have any files at this point
        self.assertEqual(resource.files.all().count(), 0, msg="resource file count didn't match")

        # create a file
        original_file_name = 'original.txt'

        original_file = open(original_file_name, 'w')
        original_file.write("original text")
        original_file.close()

        original_file = open(original_file_name, 'r')
        # add the file to the resource
        added_files = hydroshare.add_resource_files(resource.short_id, original_file)

        # resource should have only one file at this point
        self.assertEqual(len(added_files), 1)
        self.assertEqual(resource.files.all().count(), 1, msg="resource file count didn't match")

        self.assertIn(
            original_file_name,
            [os.path.basename(f.resource_file.name) for f in resource.files.all()],
            msg= '%s is not one of the resource files.' % original_file_name
        )

        # create a file that will be used to update the original file -1st update
        new_file_name = 'update.txt'    # file has a different name from the file that we will be updating
        new_file = open(new_file_name, 'w')
        new_file_data = 'data in new file'
        new_file.write(new_file_data)
        new_file.close()
        new_file = open(new_file_name, 'r')

        # this is the api call we are testing
        rf = hydroshare.update_resource_file(resource.short_id, original_file_name, new_file)

        # test if the file name matches
        self.assertEqual(os.path.basename(rf.resource_file.name), new_file_name, msg="resource file name didn't match")

        # since we are updating a file the number of files in the resource needs to be still 1
        self.assertEqual(resource.files.all().count(), 1, msg="resource file count didn't match")

        # test if the content of the file matches
        resource_file = hydroshare.get_resource_file(resource.short_id, new_file_name)
        self.assertEqual(resource_file.read(),  new_file_data, msg="resource file content didn't match")

        # reset the original resource file name for 2nd time resource file update
        original_file_name = new_file_name

        # create a file that will be used to update the resource file - 2nd update
        new_file_name = 'update.txt'    # file has the same name as the file that we will be updating
        new_file = open(new_file_name, 'w')
        new_file_data = 'data in new file'
        new_file.write(new_file_data)
        new_file.close()
        new_file = open(new_file_name, 'r')

        # this is the api call we are testing
        rf = hydroshare.update_resource_file(resource.short_id, original_file_name, new_file)

        # test if the file name matches
        self.assertEqual(os.path.basename(rf.resource_file.name), new_file_name,
                         msg="{0} != {1}".format(os.path.basename(rf.resource_file.name), new_file_name))

        # exception ObjectDoesNotExist should be raised if resource does not have a file
        # for the given file name (file_not_in_resource.txt) to update
        self.assertRaises(
            ObjectDoesNotExist,
            lambda: hydroshare.update_resource_file(resource.short_id, 'file_not_in_resource.txt', new_file)
        )