def delete(self, request, pk):
        view_utils.authorize(
            request,
            pk,
            needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE_ACCESS)
        keys = request.query_params.keys()
        user_access = UserAccess(user=request.user)
        resource = hydroshare.get_resource_by_shortkey(shortkey=pk)

        if "user_id" in keys and "group_id" in keys:
            message = "Request cannot contain both a 'user_id' and a 'group_id' parameter."
            return Response(data={'error': message},
                            status=status.HTTP_400_BAD_REQUEST)

        if "user_id" in keys:
            user_to_remove = utils.user_from_id(
                request.query_params['user_id'])
            user_access.unshare_resource_with_user(resource, user_to_remove)
            return Response(
                data={'success': "Resource access privileges removed."},
                status=status.HTTP_202_ACCEPTED)

        if "group_id" in keys:
            group_to_remove = utils.group_from_id(
                request.query_params['group_id'])
            user_access.unshare_resource_with_group(resource, group_to_remove)
            return Response(
                data={'success': "Resource access privileges removed."},
                status=status.HTTP_202_ACCEPTED)

        message = "Request must contain a 'resource' ID as well as a 'user_id' or 'group_id'"
        return Response(data={'error': message},
                        status=status.HTTP_400_BAD_REQUEST)
Beispiel #2
0
 def get(self, request, pk):
     view_utils.authorize(
         request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_METADATA)
     resource = hydroshare.get_resource_by_shortkey(shortkey=pk)
     serializer = resource.metadata.serializer
     self.serializer_class = resource.metadata.serializer
     return Response(data=serializer.data, status=status.HTTP_200_OK)
    def delete(self, request, pk):
        view_utils.authorize(request, pk,
                             needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE_ACCESS)
        keys = request.query_params.keys()
        user_access = UserAccess(user=request.user)
        resource = hydroshare.get_resource_by_shortkey(shortkey=pk)

        if "user_id" in keys and "group_id" in keys:
            message = "Request cannot contain both a 'user_id' and a 'group_id' parameter."
            return Response(
                data={'error': message},
                status=status.HTTP_400_BAD_REQUEST
            )

        if "user_id" in keys:
            user_to_remove = utils.user_from_id(request.query_params['user_id'])
            user_access.unshare_resource_with_user(resource, user_to_remove)
            return Response(
                data={'success': "Resource access privileges removed."},
                status=status.HTTP_202_ACCEPTED
            )

        if "group_id" in keys:
            group_to_remove = utils.group_from_id(request.query_params['group_id'])
            user_access.unshare_resource_with_group(resource, group_to_remove)
            return Response(
                data={'success': "Resource access privileges removed."},
                status=status.HTTP_202_ACCEPTED
            )

        message = "Request must contain a 'resource' ID as well as a 'user_id' or 'group_id'"
        return Response(
            data={'error': message},
            status=status.HTTP_400_BAD_REQUEST
        )
Beispiel #4
0
    def get(self, request, pk):
        view_utils.authorize(
            request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_METADATA)

        resmap_url = hydroshare.utils.current_site_url(
        ) + AbstractResource.resmap_url(pk)
        return redirect(resmap_url)
    def get(self, request, pk):
        """ Get resource in zipped BagIt format
        """
        view_utils.authorize(request, pk, view=True, full=True)

        bag_url = hydroshare.utils.current_site_url() + AbstractResource.bag_url(pk)
        return HttpResponseRedirect(bag_url)
    def get(self, request, pk):
        """ Get resource system metadata, as well as URLs to the bag and science metadata
        """
        view_utils.authorize(request, pk, view=True, full=True)
        res = get_resource_by_shortkey(pk)
        ser = self.get_serializer_class()(self.resourceToResourceListItem(res))

        return Response(data=ser.data, status=status.HTTP_200_OK)
Beispiel #7
0
 def delete(self, request, pk):
     # only resource owners are allowed to delete
     view_utils.authorize(
         request, pk, needed_permission=ACTION_TO_AUTHORIZE.DELETE_RESOURCE)
     hydroshare.delete_resource(pk)
     # spec says we need return the id of the resource that got deleted - otherwise would
     # have used status code 204 and not 200
     return Response(data={'resource_id': pk}, status=status.HTTP_200_OK)
 def _run_tests(self, request, parameters):
     for params in parameters:
         if params['exception'] is None:
             res, authorized, user = authorize(request, res_id=params['res_id'],
                                               needed_permission=params['needed_permission'])
             self.assertEquals(params['success'], authorized)
         else:
             with self.assertRaises(params['exception']):
                 authorize(request, res_id=params['res_id'], needed_permission=params['needed_permission'])
    def put(self, request, pk):
        view_utils.authorize(request, pk,
                             needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE_ACCESS)
        user_access = UserAccess(user=request.user)
        resource = hydroshare.get_resource_by_shortkey(shortkey=pk)
        keys = request.data.keys()

        if "user_id" in keys and "group_id" in keys:
            return Response(
                data={
                    'error': "Request cannot contain both a 'user_id' and a 'group_id' parameter."
                },
                status=status.HTTP_400_BAD_REQUEST
            )

        if "user_id" in keys and "privilege" in keys:
            if int(request.data['privilege']) in (1, 2, 3, 4):
                try:
                    user_to_add = utils.user_from_id(request.data['user_id'])
                    user_access.share_resource_with_user(resource,
                                                         user_to_add,
                                                         request.data['privilege'])
                    return Response(
                        data={'success': "Resource access privileges added."},
                        status=status.HTTP_202_ACCEPTED
                    )
                except Exception:
                    return Response(
                        data={'error': "This resource may not be shared with that user."},
                        status=status.HTTP_400_BAD_REQUEST
                    )

        if "group_id" in keys and "privilege" in keys:
            if int(request.data['privilege']) in (1, 2, 3, 4):
                group_to_add = utils.group_from_id(request.data['group_id'])
                try:
                    user_access.share_resource_with_group(resource,
                                                          group_to_add,
                                                          request.data['privilege'])
                    return Response(
                        data={'success': "Resource access privileges added."},
                        status=status.HTTP_202_ACCEPTED
                    )
                except Exception:
                    return Response(
                        data={'error': "This group may not be added to any resources."},
                        status=status.HTTP_400_BAD_REQUEST
                    )

        message = "Request must contain a 'resource' ID as well as a 'user_id' or " \
                  "'group_id', and 'privilege' must be one of 1, 2, or 3."
        return Response(
            data={'error': message},
            status=status.HTTP_400_BAD_REQUEST
        )
Beispiel #10
0
    def has_permission(self, request, view):
        if not view.kwargs.get('pk', False):
            return True

        if request.method == "GET":
            _, authorized, _ = authorize(request, view.kwargs.get('pk'),
                                         needed_permission=ACTION_TO_AUTHORIZE.VIEW_METADATA)
        else:
            _, authorized, _ = authorize(request, view.kwargs.get('pk'),
                                         needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
        return authorized
Beispiel #11
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)
    def put(self, request, pk):
        view_utils.authorize(
            request,
            pk,
            needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE_ACCESS)
        user_access = UserAccess(user=request.user)
        resource = hydroshare.get_resource_by_shortkey(shortkey=pk)
        keys = request.data.keys()

        if "user_id" in keys and "group_id" in keys:
            return Response(data={
                'error':
                "Request cannot contain both a 'user_id' and a 'group_id' parameter."
            },
                            status=status.HTTP_400_BAD_REQUEST)

        if "user_id" in keys and "privilege" in keys:
            if int(request.data['privilege']) in (1, 2, 3, 4):
                try:
                    user_to_add = utils.user_from_id(request.data['user_id'])
                    user_access.share_resource_with_user(
                        resource, user_to_add, request.data['privilege'])
                    return Response(
                        data={'success': "Resource access privileges added."},
                        status=status.HTTP_202_ACCEPTED)
                except Exception:
                    return Response(data={
                        'error':
                        "This resource may not be shared with that user."
                    },
                                    status=status.HTTP_400_BAD_REQUEST)

        if "group_id" in keys and "privilege" in keys:
            if int(request.data['privilege']) in (1, 2, 3, 4):
                group_to_add = utils.group_from_id(request.data['group_id'])
                try:
                    user_access.share_resource_with_group(
                        resource, group_to_add, request.data['privilege'])
                    return Response(
                        data={'success': "Resource access privileges added."},
                        status=status.HTTP_202_ACCEPTED)
                except Exception:
                    return Response(data={
                        'error':
                        "This group may not be added to any resources."
                    },
                                    status=status.HTTP_400_BAD_REQUEST)

        message = "Request must contain a 'resource' ID as well as a 'user_id' or " \
                  "'group_id', and 'privilege' must be one of 1, 2, or 3."
        return Response(data={'error': message},
                        status=status.HTTP_400_BAD_REQUEST)
 def _run_tests(self, request, parameters):
     for params in parameters:
         if params['exception'] is None:
             res, authorized, user = authorize(
                 request,
                 res_id=params['res_id'],
                 needed_permission=params['needed_permission'])
             self.assertEquals(params['success'], authorized)
         else:
             with self.assertRaises(params['exception']):
                 authorize(request,
                           res_id=params['res_id'],
                           needed_permission=params['needed_permission'])
    def get(self, request, pk):
        view_utils.authorize(request, pk,
                             needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE_ACCESS)

        user_resource_serializer, group_resource_serializer = self.get_serializer_classes()
        user_resource_privilege, group_resource_privilege = self.get_queryset(pk, request.user)

        response_data = dict()
        response_data['users'] = \
            user_resource_serializer(user_resource_privilege, many=True).data
        response_data['groups'] = \
            group_resource_serializer(group_resource_privilege, many=True).data

        return Response(data=response_data, status=status.HTTP_200_OK)
Beispiel #15
0
    def put(self, request, pk):
        """ Update access rules
        """
        view_utils.authorize(request, pk, edit=True, full=True)

        access_rules_validator = serializers.AccessRulesRequestValidator(data=request.data)
        if not access_rules_validator.is_valid():
            raise ValidationError(detail=access_rules_validator.errors)

        validated_request_data = access_rules_validator.validated_data
        res = get_resource_by_shortkey(pk)
        res.public = validated_request_data["public"]
        res.save()

        return Response(data={"resource_id": pk}, status=status.HTTP_200_OK)
Beispiel #16
0
def update_sqlite_file(request, file_type_id, **kwargs):
    """updates (writes the metadata) the SQLite file associated with a instance of a specified
    TimeSeriesLogicalFile file object
    """

    hs_file_type = "TimeSeriesLogicalFile"
    logical_file, json_response = _get_logical_file(hs_file_type, file_type_id)
    if json_response is not None:
        return json_response

    resource_id = logical_file.resource.short_id
    resource, authorized, _ = authorize(request, resource_id,
                                        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
                                        raises_exception=False)
    if not authorized:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'element_name': 'datatset_name', 'message': "Permission denied"}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    try:
        logical_file.update_sqlite_file(request.user)
    except Exception as ex:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'message': ex.message}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    resource_modified(resource, request.user, overwrite_bag=False)
    ajax_response_data = {'status': 'success', 'logical_file_type': logical_file.type_name(),
                          'message': "SQLite file update was successful"}
    return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)
Beispiel #17
0
def update_timeseries_abstract(request, file_type_id, **kwargs):
    """updates the abstract for time series specified logical file object
    """

    logical_file, json_response = _get_logical_file('TimeSeriesLogicalFile', file_type_id)
    if json_response is not None:
        return json_response

    resource_id = logical_file.resource.short_id
    resource, authorized, _ = authorize(request, resource_id,
                                        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
                                        raises_exception=False)
    if not authorized:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'element_name': 'abstract', 'message': "Permission denied"}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    abstract = request.POST['abstract']
    if abstract.strip():
        metadata = logical_file.metadata
        metadata.abstract = abstract
        metadata.is_dirty = True
        metadata.save()
        resource_modified(resource, request.user, overwrite_bag=False)
        ajax_response_data = {'status': 'success', 'logical_file_type': logical_file.type_name(),
                              'element_name': 'abstract', "is_dirty": metadata.is_dirty,
                              'can_update_sqlite': logical_file.can_update_sqlite_file,
                              'message': "Update was successful"}
    else:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'element_name': 'abstract', 'message': "Data is missing for abstract"}

    return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)
Beispiel #18
0
def delete_key_value_metadata(request, hs_file_type, file_type_id, **kwargs):
    """deletes one pair of key/value extended metadata for a given logical file
    key data is expected as part of the request.POST data
    If key is found the matching key/value pair is deleted from the hstore dict type field
    """
    logical_file, json_response = _get_logical_file(hs_file_type, file_type_id)
    if json_response is not None:
        return json_response

    resource_id = logical_file.resource.short_id
    resource, authorized, _ = authorize(request, resource_id,
                                        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
                                        raises_exception=False)
    if not authorized:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'element_name': 'key_value', 'message': "Permission denied"}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    key = request.POST['key']
    if key in logical_file.metadata.extra_metadata.keys():
        del logical_file.metadata.extra_metadata[key]
        logical_file.metadata.is_dirty = True
        logical_file.metadata.save()
        resource_modified(resource, request.user, overwrite_bag=False)

    extra_metadata_div = super(logical_file.metadata.__class__,
                               logical_file.metadata).get_extra_metadata_html_form()
    context = Context({})
    template = Template(extra_metadata_div.render())
    rendered_html = template.render(context)
    ajax_response_data = {'status': 'success', 'logical_file_type': logical_file.type_name(),
                          'extra_metadata': rendered_html,
                          'message': "Delete was successful"}
    return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)
Beispiel #19
0
def remove_aggregation(request, resource_id, hs_file_type, file_type_id, **kwargs):
    """Deletes an instance of a specific file type (aggregation) and all the associated metadata.
    However, it doesn't delete resource files associated with the aggregation.
    """

    response_data = {'status': 'error'}

    res, _, _ = authorize(request, resource_id, needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    if res.resource_type != "CompositeResource":
        err_msg = "Aggregation type can be deleted only in composite resource."
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)

    if hs_file_type not in FILE_TYPE_MAP:
        err_msg = "Unsupported aggregation type. Supported aggregation types are: {}"
        err_msg = err_msg.format(FILE_TYPE_MAP.keys())
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)

    content_type = ContentType.objects.get(app_label="hs_file_types", model=hs_file_type.lower())
    logical_file_type_class = content_type.model_class()
    aggregation = logical_file_type_class.objects.filter(id=file_type_id).first()
    if aggregation is None:
        err_msg = "No matching aggregation was found."
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)

    aggregation.remove_aggregation()
    msg = "Aggregation was successfully removed."
    response_data['status'] = 'success'
    response_data['message'] = msg
    spatial_coverage_dict = get_coverage_data_dict(res)
    response_data['spatial_coverage'] = spatial_coverage_dict
    return JsonResponse(response_data, status=status.HTTP_200_OK)
Beispiel #20
0
    def get(self, request, pk, ticket):
        """
        list a ticket


        """
        try:
            resource, authorized, user = view_utils.authorize(
                request,
                pk,
                needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
                raises_exception=False)
        except NotFound as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        if not authorized:
            return Response("Insufficient permission",
                            status=status.HTTP_401_UNAUTHORIZED)

        try:
            return Response(data=resource.list_ticket(ticket),
                            status=status.HTTP_200_OK)
        except ValidationError as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        except SessionException as ex:
            return Response(ex.stderr, status=status.HTTP_400_BAD_REQUEST)
Beispiel #21
0
def update_sqlite_file(request, resource_id, *args, **kwargs):
    res, _, user = authorize(request, resource_id,
                             needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    log = logging.getLogger()
    if res.resource_type != "TimeSeriesResource":
        log.exception("Failed to update SQLite file. Error:This is not a timeseries resource. "
                      "Resource ID:{}".format(res.short_id))
        raise ValidationError("The resource is not of type TimeSeries. SQLite file update is "
                              "allowed only for timeseries resources.")
    else:
        try:
            res.metadata.update_sqlite_file(user)
            messages.success(request, "SQLite file update was successful.")
            log.info("SQLite file update was successful for resource ID:{}.".format(res.short_id))
        except Exception as ex:
            messages.error(request, "Failed to update SQLite file. Error:{}".format(ex.message))
            log.exception("Failed to update SQLite file. Error:{}".format(ex.message))

    if 'resource-mode' in request.POST:
        request.session['resource-mode'] = 'edit'

    # remove if there exits any previous form validation errors
    if 'validation_error' in request.session:
        del request.session['validation_error']

    return HttpResponseRedirect(request.META['HTTP_REFERER'])
Beispiel #22
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)
Beispiel #23
0
def calculate_collection_coverages(request, shortkey, *args, **kwargs):
    """
    Calculate latest coverages of the specified collection resource
    This func is a wrapper of the _calculate_collection_coverages func
    """
    ajax_response_data = {'status': "success"}
    try:
        collection_res, is_authorized, user \
            = authorize(request, shortkey,
                        needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)

        if collection_res.resource_type.lower() != "collectionresource":
            raise Exception(
                "Resource {0} is not a collection resource.".format(shortkey))

        new_coverage_list = _calculate_collection_coverages(collection_res)
        ajax_response_data['new_coverage_list'] = new_coverage_list

    except Exception as ex:
        logger.error(
            "Failed to calculate collection coverages. Collection resource ID: {0}. "
            "Error:{1} ".format(shortkey, str(ex)))

        ajax_response_data = {'status': "error", 'message': str(ex)}
    finally:
        return JsonResponse(ajax_response_data)
 def get_queryset(self):
     resource, _, _ = view_utils.authorize(self.request, self.kwargs['pk'],
                                           needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)
     resource_file_info_list = []
     for f in resource.files.all():
         resource_file_info_list.append(self.resourceFileToListItem(f))
     return resource_file_info_list
    def delete(self, request, pk, ticket):
        """
        Delete a ticket.

        """
        try:
            resource, authorized, user = view_utils.authorize(
                request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
                raises_exception=False)
        except NotFound as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        if not authorized:
            return Response("Insufficient permission", status=status.HTTP_401_UNAUTHORIZED)

        # list the ticket details to return to user
        try:
            data = resource.list_ticket(ticket)
        except ValidationError as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        except SessionException as ex:
            return Response(ex.stderr, status=status.HTTP_400_BAD_REQUEST)

        # try to delete the ticket; this rejects deletion if user isn't authorized
        try:
            resource.delete_ticket(request.user, ticket)
        except PermissionDenied as ex:
            return Response(ex.stderr, status=status.HTTP_403_PERMISSION_DENIED)
        except ValidationError as ex:
            return Response(ex.message, status=status.HTTP_400_BAD_REQUEST)
        except SessionException as ex:
            return Response(ex.stderr, status=status.HTTP_400_BAD_REQUEST)

        # return ticket details
        return Response(data, status=status.HTTP_200_OK)
Beispiel #26
0
def update_netcdf_file(request, resource_id, *args, **kwargs):
    res, _, user = authorize(
        request,
        resource_id,
        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    log = logging.getLogger()
    if res.resource_type != "NetcdfResource":
        log.exception("Failed to update NetCDF file. Error:This is not a "
                      "multidimensional (NetCDF) resource. "
                      "Resource ID:{}".format(res.short_id))
        raise ValidationError(
            "The resource is not of type NetCDF. NetCDF file update is "
            "allowed only for multidimensional (NetCDF) resources.")
    else:
        try:
            res.update_netcdf_file(user)
            messages.success(request, "NetCDF file update was successful.")
            log.info(
                "NetCDF file update was successful for resource ID:{}.".format(
                    res.short_id))
        except Exception as ex:
            messages.error(
                request,
                "Failed to update NetCDF file. Error:{}".format(str(ex)))
            log.exception("Failed to update NetCDF file. Error:{}".format(
                str(ex)))

    if 'resource-mode' in request.POST:
        request.session['resource-mode'] = 'edit'

    # remove if there exits any previous form validation errors
    if 'validation_error' in request.session:
        del request.session['validation_error']

    return HttpResponseRedirect(request.META['HTTP_REFERER'])
    def get(self, request, pk):
        """
        create a ticket for a bag

        :param pk: key of resource for which to issue ticket
        :param pathname: path for which to issue ticket. If empty, whole data directory is assumed.
        """
        try:
            resource, authorized, user = view_utils.authorize(
                request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
                raises_exception=False)
        except NotFound as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        if not authorized:
            return Response("Insufficient permission", status=status.HTTP_403_FORBIDDEN)

        fullpath = resource.bag_path
        try:
            ticket, abspath = resource.create_ticket(request.user, path=fullpath, write=False)
        except SessionException as e:
            return Response(e.stderr, status=status.HTTP_400_BAD_REQUEST)
        except ValidationError as e:
            return Response(e.message, status=status.HTTP_400_BAD_REQUEST)

        return Response(
            {'resource_id': pk,
             'path': abspath,
             'ticket_id': ticket,
             'operation': 'read'},
            status=status.HTTP_201_CREATED)
Beispiel #28
0
def rest_download_refts_resource_bag(request, shortkey, *args, **kwargs):
    tempdir = None
    _, authorized, _ = authorize(
        request,
        shortkey,
        needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
        raises_exception=True)
    try:

        path = "bags/" + str(shortkey) + ".zip"
        response_irods = download_bag_from_irods(request,
                                                 path,
                                                 rest_call=True,
                                                 use_async=False)

        if not response_irods.streaming:
            raise Exception("Failed to stream RefTS bag")
        else:
            tempdir = tempfile.mkdtemp()
            response = assemble_refts_bag(shortkey,
                                          response_irods.streaming_content,
                                          temp_dir=tempdir)
            return response

    except Exception as e:
        logger.exception("rest_download_refts_resource_bag: %s" % (e.message))
        response = HttpResponse(status=503)
        response.content = "Failed to download this resource!"
        return response
    finally:
        if tempdir is not None:
            shutil.rmtree(tempdir)
Beispiel #29
0
def delete_file_type(request, resource_id, hs_file_type, file_type_id,
                     **kwargs):
    """deletes an instance of a specific file type and all its associated resource files"""

    res, _, _ = authorize(request,
                          resource_id,
                          needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    if res.resource_type != "CompositeResource":
        err_msg = "File type can be deleted only in composite resource."
        messages.error(request, err_msg)
        return HttpResponseRedirect(request.META['HTTP_REFERER'])
    if hs_file_type != "GeoRaster":
        err_msg = "Currently only an instance of Geo Raster file type can be deleted."
        messages.error(request, err_msg)
        return HttpResponseRedirect(request.META['HTTP_REFERER'])

    logical_file_to_delete = GeoRasterLogicalFile.objects.filter(
        id=file_type_id).first()
    if logical_file_to_delete is None:
        err_msg = "No matching Geo Raster file type was found."
        messages.error(request, err_msg)
        return HttpResponseRedirect(request.META['HTTP_REFERER'])

    if logical_file_to_delete.resource.short_id != res.short_id:
        err_msg = "Geo Raster file type doesn't belong to the specified resource."
        messages.error(request, err_msg)
        return HttpResponseRedirect(request.META['HTTP_REFERER'])

    logical_file_to_delete.logical_delete(request.user)
    resource_modified(res, request.user, overwrite_bag=False)
    msg = "Geo Raster file type was deleted."
    messages.success(request, msg)
    return HttpResponseRedirect(request.META['HTTP_REFERER'])
    def get(self, request, pk, pathname):
        """
        list a given folder

        """
        try:
            resource, authorized, user = view_utils.authorize(
                request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
                raises_exception=False)
        except NotFound as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        if not authorized:
            return Response("Insufficient permission", status=status.HTTP_403_FORBIDDEN)

        if not resource.supports_folders:
            return Response("Resource type does not support subfolders",
                            status=status.HTTP_403_FORBIDDEN)

        try:
            view_utils.irods_path_is_allowed(pathname)  # check for hacking attempts
        except (ValidationError, SuspiciousFileOperation) as ex:
            return Response(ex.message, status=status.HTTP_400_BAD_REQUEST)

        relpath = os.path.join('data', 'contents', pathname)
        try:
            contents = view_utils.list_folder(pk, relpath)
        except SessionException:
            return Response("Cannot list path", status=status.HTTP_404_NOT_FOUND)

        return Response(
            {'resource_id': pk,
             'path': pathname,
             'files': contents[1],
             'folders': contents[0]},
            status=status.HTTP_200_OK)
Beispiel #31
0
def set_file_type(request, resource_id, hs_file_type, file_id=None, **kwargs):
    """Set a file (*file_id*) to a specific file type - aggregation (*hs_file_type*)
    :param  request: an instance of HttpRequest
    :param  resource_id: id of the resource in which this file type needs to be set
    :param  file_id: id of the file which needs to be set to a file type. If file_id is not provided
    then the request must have a file_folder key. In that case the specified folder will be used
    for creating the logical file (aggregation)
    :param  hs_file_type: file type to be set (e.g, SingleFile, NetCDF, GeoRaster, RefTimeseries,
    TimeSeries and GeoFeature)
    :return an instance of JsonResponse type
    """

    response_data = {'status': 'error'}
    folder_path = None
    if file_id is None:
        folder_path = request.POST.get('folder_path', "")
        if not folder_path:
            err_msg = "Must provide id of the file or folder path for setting aggregation type."
            response_data['message'] = err_msg
            return JsonResponse(response_data,
                                status=status.HTTP_400_BAD_REQUEST)

    res, authorized, _ = authorize(
        request,
        resource_id,
        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
        raises_exception=False)
    response_data = {'status': 'error'}
    if not authorized:
        err_msg = "Permission denied"
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_401_UNAUTHORIZED)

    if res.resource_type != "CompositeResource":
        err_msg = "Aggregation type can be set only for files in composite resource."
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)

    try:
        set_logical_file_type(res, request.user, file_id, hs_file_type,
                              folder_path)
        resource_modified(res, request.user, overwrite_bag=False)

        msg = "{} was successfully set to the selected aggregation type."
        if folder_path is None:
            msg = msg.format("Selected file")
        else:
            msg = msg.format("Selected folder")

        response_data['status'] = 'success'
        response_data['message'] = msg
        return JsonResponse(response_data, status=status.HTTP_201_CREATED)

    except ValidationError as ex:
        response_data['message'] = ex.message
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)
    except Exception as ex:
        response_data['message'] = ex.message
        return JsonResponse(response_data,
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    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)
Beispiel #33
0
def ingest_metadata_files(request, pk):
    from hs_file_types.utils import identify_and_ingest_metadata_files
    resource, _, _ = view_utils.authorize(
        request, pk, needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    resource_files = list(request.FILES.values())
    identify_and_ingest_metadata_files(resource, resource_files)
    return Response(status=204)
Beispiel #34
0
def update_dataset_name(request, hs_file_type, file_type_id, **kwargs):
    """updates the dataset_name (title) attribute of the specified logical file object
    """

    logical_file, json_response = _get_logical_file(hs_file_type, file_type_id)
    if json_response is not None:
        return json_response

    resource_id = logical_file.resource.short_id
    resource, authorized, _ = authorize(request, resource_id,
                                        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
                                        raises_exception=False)
    if not authorized:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'element_name': 'datatset_name', 'message': "Permission denied"}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    dataset_name = request.POST['dataset_name']
    logical_file.dataset_name = dataset_name
    logical_file.save()
    logical_file.metadata.is_dirty = True
    logical_file.metadata.save()
    resource_modified(resource, request.user, overwrite_bag=False)
    ajax_response_data = {'status': 'success', 'logical_file_type': logical_file.type_name(),
                          'element_name': 'datatset_name', 'message': "Update was successful"}
    return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)
Beispiel #35
0
def download_refts_resource_bag(request, shortkey, *args, **kwargs):
    tempdir = None
    try:
        _, authorized, _ = authorize(
            request,
            shortkey,
            needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
            raises_exception=False)
        if not authorized:
            response = HttpResponse(status=401)
            response.content = "<h3>You do not have permission to download this resource!</h3>"
            return response

        path = "bags/" + str(shortkey) + ".zip"
        response_irods = download_bag_from_irods(request,
                                                 path,
                                                 use_async=False,
                                                 use_reverse_proxy=False)

        tempdir = tempfile.mkdtemp()
        response = assemble_refts_bag(shortkey,
                                      response_irods.streaming_content,
                                      temp_dir=tempdir)

        return response
    except Exception as e:
        logger.exception("download_refts_resource_bag: %s" % (str(e)))
        response = HttpResponse(status=503)
        response.content = "<h3>Failed to download this resource!</h3>"
        return response
    finally:
        if tempdir is not None:
            shutil.rmtree(tempdir)
def irods_issues(request, shortkey):
    """ Debug view for resource depicts output of various integrity checking scripts, runs async """
    resource, _, _ = authorize(
        request, shortkey, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)

    task = resource_debug.apply_async((resource.short_id, ))
    return redirect("get_debug_task_status", task_id=task.task_id)
Beispiel #37
0
    def put(self, request, pk):
        # Update science metadata
        resource, _, _ = view_utils.authorize(
            request, pk,
            needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)

        metadata = []
        put_data = request.data.copy()

        # convert the QueryDict to dict
        if isinstance(put_data, QueryDict):
            put_data = put_data.dict()

        try:
            resource.metadata.parse_for_bulk_update(put_data, metadata)
            hydroshare.update_science_metadata(pk=pk, metadata=metadata, user=request.user)
        except Exception as ex:
            error_msg = {
                'resource': "Resource metadata update failed: %s, %s"
                            % (ex.__class__, ex.message)
            }
            raise ValidationError(detail=error_msg)

        resource = hydroshare.get_resource_by_shortkey(shortkey=pk)
        serializer = resource.metadata.serializer
        return Response(data=serializer.data, status=status.HTTP_202_ACCEPTED)
    def delete(self, request, pk, pathname):
        """
        Delete a folder.

        """
        try:
            resource, authorized, user = view_utils.authorize(
                request, pk, needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
                raises_exception=False)
        except NotFound as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        if not authorized:
            return Response("Insufficient permission", status=status.HTTP_401_UNAUTHORIZED)

        if not resource.supports_folders:
            return Response("Resource type does not support subfolders",
                            status=status.HTTP_403_FORBIDDEN)

        try:
            view_utils.irods_path_is_allowed(pathname)  # check for hacking attempts
        except (ValidationError, SuspiciousFileOperation) as ex:
            return Response(ex.message, status=status.HTTP_400_BAD_REQUEST)

        # relativise the path
        relpath = os.path.join('data', 'contents', pathname)
        try:
            view_utils.remove_folder(request.user, pk, relpath)
        except SessionException:
            return Response("Cannot remove folder", status=status.HTTP_400_BAD_REQUEST)

        return Response(data={'resource_id': pk, 'path': pathname},
                        status=status.HTTP_200_OK)
Beispiel #39
0
def data_store_edit_reference_url(request):
    """
    edit the referenced url in an url file
    :param request:
    :return: JsonResponse on success or HttpResponse with error status code on error
    """
    res_id = request.POST.get('res_id', None)
    curr_path = request.POST.get('curr_path', None)
    url_filename = request.POST.get('url_filename', None)
    new_ref_url = request.POST.get('new_ref_url', None)

    if not res_id:
        return HttpResponseBadRequest('Must have res_id included in the POST data')
    if not curr_path:
        return HttpResponseBadRequest('Must have curr_path included in the POST data')
    if not url_filename:
        return HttpResponseBadRequest('Must have url_filename included in the POST data')
    if not new_ref_url:
        return HttpResponseBadRequest('Must have new_ref_url included in the POST data')

    try:
        res, _, _ = authorize(request, res_id,
                              needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    except NotFound:
        return HttpResponseBadRequest('Bad request - resource not found')
    except PermissionDenied:
        return HttpResponse('Permission denied', status=status.HTTP_401_UNAUTHORIZED)

    ret_status, msg = edit_reference_url_in_resource(request.user, res, new_ref_url,
                                                     curr_path, url_filename)
    if ret_status == status.HTTP_200_OK:
        return JsonResponse({'status': 'success'})
    else:
        return JsonResponse({'message': msg}, status=ret_status)
    def put(self, request, pk):
        # Update science metadata
        resource, _, _ = view_utils.authorize(
            request, pk,
            needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)

        metadata = []
        put_data = request.data.copy()

        # convert the QueryDict to dict
        if isinstance(put_data, QueryDict):
            put_data = put_data.dict()
        try:
            resource.metadata.parse_for_bulk_update(put_data, metadata)
            hydroshare.update_science_metadata(pk=pk, metadata=metadata, user=request.user)
        except Exception as ex:
            error_msg = {
                'resource': "Resource metadata update failed: %s, %s"
                            % (ex.__class__, ex.message)
            }
            raise ValidationError(detail=error_msg)

        resource = hydroshare.get_resource_by_shortkey(shortkey=pk)
        serializer = resource.metadata.serializer
        return Response(data=serializer.data, status=status.HTTP_202_ACCEPTED)
Beispiel #41
0
def _check_user_can_view_resource(request_obj, resource_obj):
    _, user_can_view_res, _ = authorize(
        request_obj,
        resource_obj.short_id,
        needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
        raises_exception=False)
    return user_can_view_res
Beispiel #42
0
    def get(self, request, pk):
        """ Get resource system metadata, as well as URLs to the bag and science metadata
        """
        res, _, _ = view_utils.authorize(
            request, pk, needed_permission=ACTION_TO_AUTHORIZE.VIEW_METADATA)
        ser = self.get_serializer_class()(self.resourceToResourceListItem(res))

        return Response(data=ser.data, status=status.HTTP_200_OK)
Beispiel #43
0
def update_metadata_element(request, hs_file_type, file_type_id, element_name,
                            element_id, **kwargs):
    err_msg = "Failed to update metadata element '{}'. {}."
    content_type = ContentType.objects.get(app_label="hs_file_types", model=hs_file_type.lower())
    logical_file_type_class = content_type.model_class()
    logical_file = logical_file_type_class.objects.filter(id=file_type_id).first()
    if logical_file is None:
        err_msg = "No matching logical file type was found."
        ajax_response_data = {'status': 'error', 'message': err_msg}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    resource_id = logical_file.resource.short_id
    resource, authorized, _ = authorize(request, resource_id,
                                        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
                                        raises_exception=False)

    if not authorized:
        ajax_response_data = {'status': 'error', 'logical_file_type': logical_file.type_name(),
                              'element_name': element_name, 'message': "Permission denied"}
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)

    validation_response = logical_file.metadata.validate_element_data(request, element_name)
    is_update_success = False
    if validation_response['is_valid']:
        element_data_dict = validation_response['element_data_dict']
        try:
            logical_file.metadata.update_element(element_name, element_id, **element_data_dict)
            resource_modified(resource, request.user, overwrite_bag=False)
            is_update_success = True
        except ValidationError as ex:
            err_msg = err_msg.format(element_name, ex.message)
        except Error as ex:
            err_msg = err_msg.format(element_name, ex.message)
    else:
        err_msg = err_msg.format(element_name, validation_response['errors'])

    if is_update_success:
        if resource.can_be_public_or_discoverable:
            metadata_status = METADATA_STATUS_SUFFICIENT
        else:
            metadata_status = METADATA_STATUS_INSUFFICIENT

        ajax_response_data = {'status': 'success', 'element_name': element_name,
                              'metadata_status': metadata_status,
                              'logical_file_type': logical_file.type_name()
                              }

        if element_name.lower() == 'coverage':
            spatial_coverage_dict = get_coverage_data_dict(resource)
            temporal_coverage_dict = get_coverage_data_dict(resource, coverage_type='temporal')
            ajax_response_data['spatial_coverage'] = spatial_coverage_dict
            ajax_response_data['temporal_coverage'] = temporal_coverage_dict

        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)
    else:
        ajax_response_data = {'status': 'error', 'message': err_msg}
        # need to return http status 200 to show form errors
        return JsonResponse(ajax_response_data, status=status.HTTP_200_OK)
Beispiel #44
0
def set_file_type(request, resource_id, file_id, hs_file_type, **kwargs):
    """Set a file (*file_id*) to a specific file type (*hs_file_type*)
    :param  request: an instance of HttpRequest
    :param  resource_id: id of the resource in which this file type needs to be set
    :param  file_id: id of the file which needs to be set to a file type
    :param  hs_file_type: file type to be set (e.g, NetCDF, GeoRaster, GeoFeature etc)
    :return an instance of JsonResponse type
    """
    res, authorized, _ = authorize(
        request,
        resource_id,
        needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE,
        raises_exception=False)
    file_type_map = {
        "GeoRaster": GeoRasterLogicalFile,
        "NetCDF": NetCDFLogicalFile,
        'GeoFeature': GeoFeatureLogicalFile,
        'RefTimeseries': RefTimeseriesLogicalFile,
        'TimeSeries': TimeSeriesLogicalFile
    }
    response_data = {'status': 'error'}
    if not authorized:
        err_msg = "Permission denied"
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_401_UNAUTHORIZED)

    if res.resource_type != "CompositeResource":
        err_msg = "File type can be set only for files in composite resource."
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)

    if hs_file_type not in file_type_map:
        err_msg = "Unsupported file type. Supported file types are: {}".format(
            file_type_map.keys())
        response_data['message'] = err_msg
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)

    try:
        logical_file_type_class = file_type_map[hs_file_type]
        logical_file_type_class.set_file_type(resource=res,
                                              file_id=file_id,
                                              user=request.user)
        resource_modified(res, request.user, overwrite_bag=False)
        msg = "File was successfully set to selected file type. " \
              "Metadata extraction was successful."
        response_data['status'] = 'success'
        response_data['message'] = msg
        spatial_coverage_dict = get_coverage_data_dict(res)
        response_data['spatial_coverage'] = spatial_coverage_dict
        return JsonResponse(response_data, status=status.HTTP_201_CREATED)

    except ValidationError as ex:
        response_data['message'] = ex.message
        return JsonResponse(response_data, status=status.HTTP_400_BAD_REQUEST)
    except Exception as ex:
        response_data['message'] = ex.message
        return JsonResponse(response_data,
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Beispiel #45
0
def add_file_to_resource(request, *args, **kwargs):
    try:
        shortkey = kwargs['shortkey']
    except KeyError:
        raise TypeError('shortkey must be specified...')

    res, _, _ = authorize(request, shortkey, edit=True, full=True, superuser=True)
    res.files.add(ResourceFile(content_object=res, resource_file=request.FILES['file']))
    return HttpResponseRedirect(request.META['HTTP_REFERER'])
Beispiel #46
0
 def get_queryset(self):
     resource, _, _ = view_utils.authorize(
         self.request,
         self.kwargs['pk'],
         needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)
     resource_file_info_list = []
     for f in resource.files.all():
         resource_file_info_list.append(self.resourceFileToListItem(f))
     return resource_file_info_list
Beispiel #47
0
    def test_return_data(self):
        # test authorization True
        self.request.user = self.user
        res, authorized, user = authorize(self.request, res_id=self.res.short_id,
                                          needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)
        self.assertEquals(authorized, True)
        self.assertEquals(res, self.res)
        self.assertEquals(user, self.user)

        # test authorization False
        anonymous_user = AnonymousUser()
        self.request.user = anonymous_user
        res, authorized, user = authorize(self.request, res_id=self.res.short_id,
                                          needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE,
                                          raises_exception=False)
        self.assertEquals(authorized, False)
        self.assertEquals(res, self.res)
        self.assertEquals(user, anonymous_user)
    def get(self, request, pk):
        view_utils.authorize(
            request,
            pk,
            needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE_ACCESS)

        user_resource_serializer, group_resource_serializer = self.get_serializer_classes(
        )
        user_resource_privilege, group_resource_privilege = self.get_queryset(
            pk, request.user)

        response_data = dict()
        response_data['users'] = \
            user_resource_serializer(user_resource_privilege, many=True).data
        response_data['groups'] = \
            group_resource_serializer(group_resource_privilege, many=True).data

        return Response(data=response_data, status=status.HTTP_200_OK)
    def put(self, request, pk):
        """ Update access rules
        """
        # only resource owners are allowed to change resource flags (e.g., public)
        view_utils.authorize(request, pk, needed_permission=ACTION_TO_AUTHORIZE.SET_RESOURCE_FLAG)

        access_rules_validator = serializers.AccessRulesRequestValidator(data=request.data)
        if not access_rules_validator.is_valid():
            raise ValidationError(detail=access_rules_validator.errors)

        validated_request_data = access_rules_validator.validated_data
        res = get_resource_by_shortkey(pk)
        try:
            res.set_public(validated_request_data['public'], request.user)
        except CoreValidationError:
            return Response(data={'resource_id': pk}, status=status.HTTP_403_FORBIDDEN)

        return Response(data={'resource_id': pk}, status=status.HTTP_200_OK)
Beispiel #50
0
    def delete(self, request, pk, filename):
        resource, _, user = view_utils.authorize(request, pk, edit=True, full=True)
        try:
            hydroshare.delete_resource_file(pk, filename, user)
        except ObjectDoesNotExist as ex:  # matching file not found
            raise NotFound(detail=ex.message)

        # prepare response data
        response_data = {"resource_id": pk, "file_name": filename}
        return Response(data=response_data, status=status.HTTP_200_OK)
Beispiel #51
0
def download(request, path, *args, **kwargs):
    
    split_path_strs = path.split('/')
    if split_path_strs[0] == 'bags':
        res_id = os.path.splitext(split_path_strs[1])[0]
    else:
        res_id = split_path_strs[0]
    _, authorized, _ = authorize(request, res_id, needed_permission=Action_To_Authorize.VIEW_RESOURCE,
                                 raises_exception=False)
    if not authorized:
        response = HttpResponse()
        response.content = "<h1>You do not have permission to download this resource!</h1>"
        return response

    if 'environment' in kwargs:
        environment = int(kwargs['environment'])
        environment = m.RodsEnvironment.objects.get(pk=environment)
        session = Session("/tmp/django_irods", settings.IRODS_ICOMMANDS_PATH, session_id=uuid4())
        session.create_environment(environment)
        session.run('iinit', None, environment.auth)
    elif getattr(settings, 'IRODS_GLOBAL_SESSION', False):
        session = GLOBAL_SESSION
    elif icommands.ACTIVE_SESSION:
        session = icommands.ACTIVE_SESSION
    else:
        raise KeyError('settings must have IRODS_GLOBAL_SESSION set if there is no environment object')

    # do on-demand bag creation
    istorage = IrodsStorage()
    bag_modified = "false"
    # needs to check whether res_id collection exists before getting/setting AVU on it to accommodate the case
    # where the very same resource gets deleted by another request when it is getting downloaded
    if istorage.exists(res_id):
        bag_modified = istorage.getAVU(res_id, 'bag_modified')
    if bag_modified == "true":
        create_bag_by_irods(res_id, istorage)
        if istorage.exists(res_id):
            istorage.setAVU(res_id, 'bag_modified', "false")

    # obtain mime_type to set content_type
    mtype = 'application-x/octet-stream'
    mime_type = mimetypes.guess_type(path)
    if mime_type[0] is not None:
        mtype = mime_type[0]

    # retrieve file size to set up Content-Length header
    stdout = session.run("ils", None, "-l", path)[0].split()
    flen = int(stdout[3])

    options = ('-',) # we're redirecting to stdout.
    proc = session.run_safe('iget', None, path, *options)
    response = FileResponse(proc.stdout, content_type=mtype)
    response['Content-Disposition'] = 'attachment; filename="{name}"'.format(name=path.split('/')[-1])
    response['Content-Length'] = flen
    return response
def data_store_folder_unzip(request, **kwargs):
    """
    Unzip requested zip file while preserving folder structures in hydroshareZone or
    any federated zone used for HydroShare resource backend store. It is invoked by an AJAX call,
    and returns json object that holds the root path that contains the zipped content if it
    succeeds, and an empty string if it fails. The AJAX request must be a POST request with
    input data passed in for res_id, zip_with_rel_path, and remove_original_zip where
    zip_with_rel_path is the zip file name with relative path under res_id collection to be
    unzipped, and remove_original_zip has a value of "true" or "false" (default is "true")
    indicating whether original zip file will be deleted after unzipping.
    """
    res_id = request.POST.get('res_id', kwargs.get('res_id'))
    if res_id is None:
        return HttpResponse('Bad request - resource id is not included',
                            status=status.HTTP_400_BAD_REQUEST)
    res_id = str(res_id).strip()
    try:
        resource, _, user = authorize(request, res_id,
                                      needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    except NotFound:
        return HttpResponse('Bad request - resource not found', status=status.HTTP_400_BAD_REQUEST)
    except PermissionDenied:
        return HttpResponse('Permission denied', status=status.HTTP_401_UNAUTHORIZED)

    zip_with_rel_path = request.POST.get('zip_with_rel_path', kwargs.get('zip_with_rel_path'))

    try:
        zip_with_rel_path = _validate_path(zip_with_rel_path, 'zip_with_rel_path')
    except ValidationError as ex:
        return HttpResponse(ex.message, status=status.HTTP_400_BAD_REQUEST)

    overwrite = request.POST.get('overwrite', 'false').lower() == 'true'  # False by default
    remove_original_zip = request.POST.get('remove_original_zip', 'true').lower() == 'true'

    try:
        unzip_file(user, res_id, zip_with_rel_path, bool_remove_original=remove_original_zip,
                   overwrite=overwrite)
    except SessionException as ex:
        specific_msg = "iRODS error resulted in unzip being cancelled. This may be due to " \
                       "protection from overwriting existing files. Unzip in a different " \
                       "location (e.g., folder) or move or rename the file being overwritten. " \
                       "iRODS error follows: "
        return HttpResponse(specific_msg + ex.stderr, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except DRF_ValidationError as ex:
        return HttpResponse(ex.detail, status=status.HTTP_400_BAD_REQUEST)

    # this unzipped_path can be used for POST request input to data_store_structure()
    # to list the folder structure after unzipping
    return_object = {'unzipped_path': os.path.dirname(zip_with_rel_path)}

    return HttpResponse(
        json.dumps(return_object),
        content_type="application/json"
    )
    def post(self, request, pk, pathname):
        """
        Add a file to a resource.
        :param request:
        :param pk: Primary key of the resource (i.e. resource short ID)
        :param pathname: the path to the containing folder in the folder hierarchy
        :return:

        Leaving out pathname in the URI calls a different class function in ResourceFileListCreate
        that stores in the root directory instead.
        """
        resource, _, _ = view_utils.authorize(request, pk,
                                              needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)

        resource_files = request.FILES.values()
        if len(resource_files) == 0:
            error_msg = {'file': 'No file was found to add to the resource.'}
            raise ValidationError(detail=error_msg)
        elif len(resource_files) > 1:
            error_msg = {'file': 'More than one file was found. Only one file can be '
                                 'added at a time.'}
            raise ValidationError(detail=error_msg)

        # TODO: (Brian) I know there has been some discussion when to validate a file
        # I agree that we should not validate and extract metadata as part of the file add api
        # Once we have a decision, I will change this implementation accordingly. In that case
        # we have to implement additional rest endpoints for file validation and extraction.
        try:
            hydroshare.utils.resource_file_add_pre_process(resource=resource,
                                                           files=[resource_files[0]],
                                                           user=request.user, extract_metadata=True)

        except (hydroshare.utils.ResourceFileSizeException,
                hydroshare.utils.ResourceFileValidationException, Exception) as ex:
            error_msg = {'file': 'Adding file to resource failed. %s' % ex.message}
            raise ValidationError(detail=error_msg)

        try:
            res_file_objects = hydroshare.utils.resource_file_add_process(resource=resource,
                                                                          files=[resource_files[0]],
                                                                          folder=pathname,
                                                                          user=request.user,
                                                                          extract_metadata=True)

        except (hydroshare.utils.ResourceFileValidationException, Exception) as ex:
            error_msg = {'file': 'Adding file to resource failed. %s' % ex.message}
            raise ValidationError(detail=error_msg)

        # prepare response data
        file_name = os.path.basename(res_file_objects[0].resource_file.name)
        file_path = res_file_objects[0].resource_file.name.split('/data/contents/')[1]
        response_data = {'resource_id': pk, 'file_name': file_name, 'file_path': file_path}
        resource_modified(resource, request.user, overwrite_bag=False)
        return Response(data=response_data, status=status.HTTP_201_CREATED)
    def get(self, request, pk):
        res, _, _ = view_utils.authorize(request, pk,
                                         needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)
        if res.resource_type.lower() == "reftimeseriesresource":

            # if res is RefTimeSeriesResource
            bag_url = reverse('rest_download_refts_resource_bag',
                              kwargs={'shortkey': pk})
        else:
            bag_url = reverse('rest_download',
                              kwargs={'path': 'bags/{}.zip'.format(pk)})
        return HttpResponseRedirect(bag_url)
    def get(self, request, pk, op, pathname):
        """
        create a ticket for a specific file or folder

        :param pk: key of resource for which to issue ticket
        :param op: operation: 'read' or 'write'
        :param pathname: path for which to issue ticket. If empty, whole data directory is assumed.
        """
        if op != 'read' and op != 'write':
            return Response("Operation must be read or write", status=status.HTTP_400_BAD_REQUEST)

        write = (op == 'write')
        needed_permission = ACTION_TO_AUTHORIZE.EDIT_RESOURCE if write \
            else ACTION_TO_AUTHORIZE.VIEW_RESOURCE

        try:
            resource, authorized, user = view_utils.authorize(
                request, pk, needed_permission=needed_permission, raises_exception=False)
        except NotFound as ex:
            return Response(ex.message, status=status.HTTP_404_NOT_FOUND)
        if not authorized:
            return Response("Insufficient permission", status=status.HTTP_403_FORBIDDEN)

        try:
            view_utils.irods_path_is_allowed(pathname)  # check for hacking attempts
        except (ValidationError, SuspiciousFileOperation) as ex:
            return Response(ex.message, status=status.HTTP_400_BAD_REQUEST)

        if pathname is not None and pathname != '':
            fullpath = os.path.join(resource.root_path, pathname)
        elif op == 'read':  # allow reading anything in path
            fullpath = resource.root_path
        else:  # op == 'write'
            return Response("Write operation must specify path", status=status.HTTP_400_BAD_REQUEST)

        # TODO: check for folder support before allowing folders to be written to
        # The API allows existing files that should not exist to be read anyway.
        # It should not allow files that should not exist to be created.

        try:
            ticket, abspath = resource.create_ticket(request.user, path=fullpath, write=write)
        except SessionException as e:
            return Response(e.stderr, status=status.HTTP_400_BAD_REQUEST)
        except ValidationError as e:
            return Response(e.message, status=status.HTTP_400_BAD_REQUEST)

        return Response(
            {'resource_id': pk,
             'path': abspath,
             'ticket_id': ticket,
             'operation': op},
            status=status.HTTP_201_CREATED)
Beispiel #56
0
    def post(self, request, pk, privilege, group_id):
        res, _, user = authorize(request, pk,
                                 needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE)
        to_group = hs_core_utils.group_from_id(group_id)
        privilege_code = PrivilegeCodes.from_string(privilege)
        if not privilege_code:
            raise ParseError("Bad privilege code")
        if privilege_code == PrivilegeCodes.NONE:
            user.uaccess.unshare_resource_with_group(res, to_group)
        else:
            user.uaccess.share_resource_with_group(res, to_group, privilege_code)

        return Response(status=status.HTTP_204_NO_CONTENT)
Beispiel #57
0
def update_collection_for_deleted_resources(request, shortkey, *args, **kwargs):
    """
    If there are any tracked deleted resource objects for a collection resource
    (identified by shortkey), those are deleted and resource bag is regenerated
    for the collection resource to avoid the possibility of broken links in resource map
    as a result of collection referenced resource being deleted by resource owner.
    """

    ajax_response_data = {'status': "success"}
    try:
        with transaction.atomic():
            collection_res, is_authorized, user \
                = authorize(request, shortkey,
                            needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)

            if collection_res.resource_type.lower() != "collectionresource":
                raise Exception("Resource {0} is not a collection resource.".format(shortkey))

            # handle "Relation" metadata
            hasPart = "hasPart"
            for deleted_res_log in collection_res.deleted_resources:
                relation_value = RES_LANDING_PAGE_URL_TEMPLATE.format(deleted_res_log.resource_id)

                add_or_remove_relation_metadata(add=False,
                                                target_res_obj=collection_res,
                                                relation_type=hasPart,
                                                relation_value=relation_value,
                                                set_res_modified=False)

            new_coverage_list = _update_collection_coverages(collection_res)
            ajax_response_data['new_coverage_list'] = new_coverage_list

            # remove all logged deleted resources for the collection
            collection_res.deleted_resources.all().delete()

            update_collection_list_csv(collection_res)

            resource_modified(collection_res, user, overwrite_bag=False)

    except Exception as ex:
        logger.error("Failed to update collection for "
                     "deleted resources.Collection resource ID: {}. "
                     "Error:{} ".format(shortkey, ex.message))

        ajax_response_data = {'status': "error", 'message': ex.message}
    finally:
        return JsonResponse(ajax_response_data)
Beispiel #58
0
    def test_raise_no_exception(self):
        # create user - has no assigned resource access privilege
        authenticated_user = users.create_account(
            '*****@*****.**',
            username='******',
            first_name='user_first_name',
            last_name='user_last_name',
            superuser=False,
            groups=[])

        self.request.user = authenticated_user

        res, authorized, user = authorize(self.request, res_id=self.res.short_id,
                                          needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE, raises_exception=False)
        self.assertEquals(authorized, False)
        self.assertEquals(res, self.res)
        self.assertEquals(user, authenticated_user)
def data_store_file_or_folder_move_or_rename(request, res_id=None):
    """
    Move or rename a file or folder in hydroshareZone or any federated zone used for HydroShare
    resource backend store. It is invoked by an AJAX call and returns json object that has the
    relative path of the target file or folder being moved to if succeeds, and return empty string
    if fails. The AJAX request must be a POST request with input data passed in for res_id,
    source_path, and target_path where source_path and target_path are the relative paths
    (relative to path res_id/data/contents) for the source and target file or folder under
    res_id collection/directory.
    """
    res_id = request.POST.get('res_id', res_id)
    if res_id is None:
        return HttpResponse('Bad request - resource id is not included',
                            status=status.HTTP_400_BAD_REQUEST)
    res_id = str(res_id).strip()
    try:
        resource, _, user = authorize(request, res_id,
                                      needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE)
    except NotFound:
        return HttpResponse('Bad request - resource not found', status=status.HTTP_400_BAD_REQUEST)
    except PermissionDenied:
        return HttpResponse('Permission denied', status=status.HTTP_401_UNAUTHORIZED)

    src_path = resolve_request(request).get('source_path', None)
    tgt_path = resolve_request(request).get('target_path', None)
    try:
        src_path = _validate_path(src_path, 'src_path')
        tgt_path = _validate_path(tgt_path, 'tgt_path')
    except ValidationError as ex:
        return HttpResponse(ex.message, status=status.HTTP_400_BAD_REQUEST)

    try:
        move_or_rename_file_or_folder(user, res_id, src_path, tgt_path)
    except SessionException as ex:
        return HttpResponse(ex.stderr, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except DRF_ValidationError as ex:
        return HttpResponse(ex.detail, status=status.HTTP_400_BAD_REQUEST)

    return_object = {'target_rel_path': tgt_path}

    return HttpResponse(
        json.dumps(return_object),
        content_type='application/json'
    )