def post(self, request): """Upload a Blob with a PID. Available only for superusers. Args: request: HTTP request Returns: - code: 200 content: Created blob - code: 400 content: Validation error - code: 500 content: Internal server error """ if not request.user.is_superuser: return Response( {"message": "Only a superuser can use this feature."}, status=status.HTTP_403_FORBIDDEN, ) try: if "pid" not in request.POST: raise CoreError("Missing PID field in POST data.") # Check that the PID has not yet been assigned try: local_id_api.get_by_name("/".join(request.POST["pid"].split("/")[-2:])) raise CoreError("PID has already been assigned.") except DoesNotExist: pass # Upload the blob and return the error if there is one. blob_upload_response = super().post(request) if blob_upload_response.status_code != status.HTTP_201_CREATED: return blob_upload_response serialized_data = blob_upload_response.data serialized_data["pid"] = request.POST["pid"] # Assign PID to blob blob_api.set_pid_for_blob(serialized_data["id"], serialized_data["pid"]) # Return the serialized data return Response(serialized_data, status=status.HTTP_201_CREATED) except Exception as api_exception: content = {"message": str(api_exception)} return Response(content, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def lmxl_uri_resolver(*args, **kwargs): """Return lxml uri resolver according to the settings Returns: """ uri_resolver = None try: request = kwargs.pop("request") session_id = request.session.session_key except: logger.info("No request or session id is None") session_id = None if XSD_URI_RESOLVER: # Check that the setting is an accepted value if XSD_URI_RESOLVER not in XSD_URI_RESOLVERS: raise CoreError( "Error: XSD_URI_RESOLVER setting has an incorrect value.") # Return the correct resolver depending on the setting uri_resolver = XSD_URI_RESOLVERS[XSD_URI_RESOLVER]( session_id=session_id) return uri_resolver
def check_type_core_support(xsd_string): """Check that the format of the the type is supported by the current version of the Core. Return the type definition (simpleType or complexType). Args: xsd_string: Returns: type_definition: simpleType or complexType. """ type_definition = "" error_message = ( "A type should be a valid XML schema containing only one type definition " "(Allowed tags are: simpleType or complexType and include).") # check that well formatted first if not is_well_formed_xml(xsd_string): raise XMLError("Uploaded file is not well formatted XML.") # build the tree xsd_tree = XSDTree.build_tree(xsd_string) # get elements elements = xsd_tree.findall("*") if len(elements) > 0: # only simpleType, complexType or include for element in elements: if ("complexType" not in element.tag and "simpleType" not in element.tag and "include" not in element.tag): raise CoreError(error_message) # only one type cpt_type = 0 for element in elements: if "complexType" in element.tag or "simpleType" in element.tag: cpt_type += 1 if cpt_type > 1: raise CoreError(error_message) type_definition = (COMPLEX_TYPE if "complexType" in element.tag else SIMPLE_TYPE) else: raise CoreError(error_message) return type_definition
def setUp(self): """Insert needed data. Returns: """ if self.fixture is None: raise CoreError("Fixtures must be initialized") self.fixture.insert_data()
def get_request_from_args(*args, **kwargs): # get request from parameters request = kwargs["request"] if ( isinstance(request, HttpRequest) or isinstance(request, Request) or request is None ): return request raise CoreError("request parameter improperly set")
def ready(self): """When the app is ready, run the discovery and init the indexes.""" if "migrate" not in sys.argv: # check celery settings if (settings.CELERYBEAT_SCHEDULER != "django_celery_beat.schedulers:DatabaseScheduler"): raise CoreError( "CELERYBEAT_SCHEDULER setting needs to be set to 'django_celery_beat.schedulers:DatabaseScheduler'." ) check_ssl_certificates_dir_setting(SSL_CERTIFICATES_DIR) discover.init_rules(self.apps) discover.create_public_workspace() init_text_index(Data)
def get_base_64_content_from_response(response): """ Get ascii content from HTTP response Args: response: HTTP response Returns: """ try: b64_content = base64.b64encode(response.content) return b64_content.decode('ascii') except Exception: raise CoreError('An error occurred while decoding the response.')
def _check_can_write_data(request, accessed_object): """Check if the object can be accessed by the user in write mode. Args: request: accessed_object: Returns: """ try: # Super user can access everything if not request.user.is_superuser: check_can_write_data(accessed_object.data, request.user) except Exception, e: raise CoreError(e.message)
def _check_owner(request, accessed_object): """Check if the object can be accessed by the user. Args: request: accessed_object: Returns: """ # Super user can access everything if not request.user.is_superuser: # If not the owner of the accessed object if str(request.user.id) != accessed_object.user: raise CoreError("You are not the owner of the " + get_form_label() + " that you are trying to access")
def _create_xsd_element(tag, attrib): """Create an XSD element. Args: tag: attrib: Returns: """ if tag not in ["element", "include", "import"]: raise CoreError("Unable to create XSD element: invalid tag") xsd_element = XSDTree.create_element("{0}{1}".format( LXML_SCHEMA_NAMESPACE, tag), attrib=attrib) return xsd_element
def get_file_http_response(file_content, file_name, content_type=None, extension=""): """Return http response with file to download Args: file_content: file_name: content_type: extension: Returns: """ try: # set file content try: _file = BytesIO(file_content.encode("utf-8")) except Exception: _file = BytesIO(file_content) # guess file content type if not set if content_type is None: # The function 'guess_type' returns a tuple (type, encoding). The # HttpResponse only needs the type of the file sent, otherwise it # cannot detect the proper content type of the file. # # See https://docs.python.org/3/library/mimetypes.html#mimetypes.guess_type content_type = guess_type(file_name)[0] # set file in http response response = HttpResponse(_file, content_type=content_type) # set filename extension if not file_name.endswith(extension): if not extension.startswith("."): extension = "." + extension file_name += extension # set content disposition in response response["Content-Disposition"] = "attachment; filename=" + file_name # return response return response except Exception: raise CoreError("An unexpected error occurred.")
def _get_ns_type_name(prefix, type_name, prefix_required=False): """Return type name formatted with namespace prefix. Args: prefix: type_name: Returns: """ if prefix != "": ns_type_name = "{0}:{1}".format(prefix, type_name) else: if not prefix_required: ns_type_name = type_name else: raise CoreError( "Unable to add the type because no prefix is defined for the target namespace." ) return ns_type_name
def get_file_http_response(file_content, file_name, content_type=None, extension=''): """ Return http response with file to download Args: file_content: file_name: content_type: extension: Returns: """ try: # set file content try: _file = BytesIO(file_content.encode('utf-8')) except Exception: _file = BytesIO(file_content) # guess file content type if not set if content_type is None: content_type = guess_type(file_name) # set file in http response response = HttpResponse(_file, content_type=content_type) # set filename extension if not file_name.endswith(extension): if not extension.startswith("."): extension = "." + extension file_name += extension # set content disposition in response response['Content-Disposition'] = 'attachment; filename=' + file_name # return response return response except Exception: raise CoreError('An unexpected error occurred.')
def _insert_element_type(xsd_string, xpath, type_content, element_type_name, include_url): """Insert an element of given type in xsd string. Args: xsd_string: xsd string xpath: xpath where to insert the element type_content: string content of the type to insert element_type_name: name of the type include_url: url used to reference the type in schemaLocation Returns: """ # build the dom tree of the schema being built xsd_tree = XSDTree.build_tree(xsd_string) # get namespaces information for the schema namespaces = get_namespaces(xsd_string) # get the default namespace default_prefix = get_default_prefix(namespaces) # get target namespace information target_namespace, target_namespace_prefix = get_target_namespace( xsd_tree, namespaces) # build xpath to element xpath = xpath.replace(default_prefix + ":", LXML_SCHEMA_NAMESPACE) # build xsd tree type_xsd_tree = XSDTree.build_tree(type_content) # get namespaces information for the type type_namespaces = get_namespaces(type_content) # get target namespace information type_target_namespace, type_target_namespace_prefix = get_target_namespace( type_xsd_tree, type_namespaces) # get the type from the included/imported file # If there is a complex type element_type = type_xsd_tree.find( "{}complexType".format(LXML_SCHEMA_NAMESPACE)) if element_type is None: # If there is a simple type element_type = type_xsd_tree.find( "{}simpleType".format(LXML_SCHEMA_NAMESPACE)) type_name = element_type.attrib["name"] # format type name to avoid forbidden xml characters element_type_name = _get_valid_xml_name(element_type_name) # variable that indicates if namespaces map needs to be updated update_ns_map = False # Schema without target namespace if target_namespace is None: # Type without target namespace if type_target_namespace is None: # create type name with namespace ns_type_name = type_name # create include element dependency_tag = "include" dependency_attrib = {"schemaLocation": include_url} # Type with target namespace else: # create type name with namespace ns_type_name = _get_ns_type_name(type_target_namespace_prefix, type_name, prefix_required=True) # create import element dependency_tag = "import" dependency_attrib = { "schemaLocation": include_url, "namespace": type_target_namespace, } update_ns_map = True # Schema with target namespace else: # Type without target namespace if type_target_namespace is None: # create type name with namespace ns_type_name = _get_ns_type_name(target_namespace_prefix, type_name) # create include element dependency_tag = "include" dependency_attrib = {"schemaLocation": include_url} # Type with target namespace else: # Same target namespace as base template if target_namespace == type_target_namespace: # create type name with namespace ns_type_name = _get_ns_type_name(target_namespace_prefix, type_name) # create include element dependency_tag = "include" dependency_attrib = {"schemaLocation": include_url} # Different target namespace as base template else: # create type name with namespace ns_type_name = _get_ns_type_name(type_target_namespace_prefix, type_name, prefix_required=True) # create import element dependency_tag = "import" dependency_attrib = { "schemaLocation": include_url, "namespace": type_target_namespace, } update_ns_map = True # create dependency element dependency_element = _create_xsd_element(dependency_tag, dependency_attrib) # create xsd element xsd_element = _create_xsd_element("element", attrib={ "name": element_type_name, "type": ns_type_name }) # check if dependency element (include/import) is already present dependency_tag = "{0}[@schemaLocation='{1}']".format( dependency_element.tag, dependency_element.attrib["schemaLocation"]) dependency_present = xsd_tree.find(dependency_tag) is not None if not dependency_present: # add dependency element (include/import) xsd_tree.getroot().insert(0, dependency_element) # add xsd element xsd_tree.find(xpath).append(xsd_element) # if namespace map of the schema needs to be updated if not dependency_present and update_ns_map: root = xsd_tree.getroot() root_ns_map = root.nsmap if (type_target_namespace_prefix in list(root_ns_map.keys()) and root_ns_map[type_target_namespace_prefix] != type_target_namespace): raise CoreError( "The namespace prefix is already declared for a different namespace." ) else: root_ns_map[type_target_namespace_prefix] = type_target_namespace new_root = XSDTree.create_element(root.tag, nsmap=root_ns_map, attrib=root.attrib) new_root[:] = root[:] # return result tree return new_root else: # return result tree return xsd_tree
def is_data_structure_element_owner(fn, *args, **kwargs): """Check that user is the owner of all input and output DataStructureElement. Args: fn: args: kwargs: Returns: """ from core_parser_app.components.data_structure_element.models import ( DataStructureElement, ) if "request" in kwargs.keys() and ( isinstance(kwargs["request"], HttpRequest) or isinstance(kwargs["request"], Request) ): request_user = kwargs["request"].user else: request = next( ( arg for arg in args if isinstance(arg, HttpRequest) or isinstance(arg, Request) ), None, ) request_user: User = request.user if request and request.user else None if request_user.is_superuser: # Superusers bypass ACL return fn(*args, **kwargs) # Check user has the right to query the input DataStructureElement list. _check_data_structure_elements_access( [arg for arg in args if isinstance(arg, DataStructureElement)] + [ kwarg_value for kwarg_value in kwargs.values() if isinstance(kwarg_value, DataStructureElement) ], request_user, ) # Run the function and add outputs to checklist fn_output = fn(*args, **kwargs) fn_output_data_structure_element_list = list() if isinstance(fn_output, DataStructureElement): fn_output_data_structure_element_list.append(fn_output) elif isinstance(fn_output, list) or isinstance(fn_output, QuerySet): output_data_structure_element_list = [ out for out in fn_output if isinstance(out, DataStructureElement) ] # Check that all elements are DataStructureElement if len(fn_output) != len(output_data_structure_element_list): raise CoreError("Function returned unexpected elements") fn_output_data_structure_element_list += output_data_structure_element_list else: # Outputs are neither a list nor an instance of DataStrctureElement raise CoreError("Function returned unexpected elements") # Check that the user is authorized to retrieve all outputs. _check_data_structure_elements_access( fn_output_data_structure_element_list, request_user, ) return fn_output