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)
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 )
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)
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 )
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
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)
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)
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)
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)
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)
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)
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)
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'])
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 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)
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)
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)
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)
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)
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)
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)
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)
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)
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 _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
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)
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)
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)
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'])
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 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)
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)
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)
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)
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)
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' )