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)
Exemple #2
0
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
Exemple #3
0
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")
Exemple #6
0
 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)
Exemple #7
0
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.')
Exemple #8
0
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)
Exemple #9
0
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")
Exemple #10
0
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
Exemple #11
0
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.")
Exemple #12
0
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
Exemple #13
0
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.')
Exemple #14
0
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