Esempio n. 1
0
 def test_data_check_xml_file_is_valid_raises_xml_error_if_failed_during_validation(self):
     # Arrange
     template = _get_template()
     data = _create_data(template, user_id='3', title='title', content='<new_tag></new_tag>')
     # Act # Assert
     with self.assertRaises(exceptions.XMLError):
         data_api.check_xml_file_is_valid(data)
Esempio n. 2
0
 def test_data_check_xml_file_is_valid_raises_xml_error_if_failed_during_xml_validation(
         self):
     # Arrange
     data = _create_data(None, user_id='3', title='title', content='')
     # Act # Assert
     with self.assertRaises(exceptions.XMLError):
         data_api.check_xml_file_is_valid(data)
Esempio n. 3
0
 def test_data_check_xml_file_is_valid_raises_xml_error_if_failed_during_xml_validation(
     self,
 ):
     # Arrange
     user = create_mock_user("3")
     mock_request = create_mock_request(user=user)
     data = _create_data(None, user_id="3", title="title", content="")
     # Act # Assert
     with self.assertRaises(exceptions.XMLError):
         data_api.check_xml_file_is_valid(data, request=mock_request)
Esempio n. 4
0
 def test_data_check_xml_file_is_valid_raises_xsd_error_if_failed_during_xsd_validation(
     self,
 ):
     # Arrange
     user = create_mock_user("3")
     mock_request = create_mock_request(user=user)
     template = _get_template()
     template.content += "<"
     data = _create_data(
         template, user_id="3", title="title", content="<new_tag></new_tag>"
     )
     # Act # Assert
     with self.assertRaises(exceptions.XSDError):
         data_api.check_xml_file_is_valid(data, request=mock_request)
Esempio n. 5
0
def upsert_data(data):
    """Upsert data

    Args:
        data:

    Returns:

    """
    from core_main_app.components.data.api import check_xml_file_is_valid

    if data.xml_content is None:
        raise exceptions.ApiError(
            "Unable to save data: xml_content field is not set.")

    check_xml_file_is_valid(data)
    return data.convert_and_save()
Esempio n. 6
0
 def test_data_check_xml_data_valid_return_true_if_validation_success(self):
     # Arrange
     template = _get_template()
     data = _create_data(template, user_id='3', title='title', content='<tag>toto</tag>')
     # Act
     result = data_api.check_xml_file_is_valid(data)
     # Assert
     self.assertEqual(result, True)
Esempio n. 7
0
 def test_data_check_xml_data_valid_return_true_if_validation_success(self):
     # Arrange
     mock_user = create_mock_user("3")
     mock_request = create_mock_request(user=mock_user)
     template = _get_template()
     data = _create_data(
         template, user_id="3", title="title", content="<tag>toto</tag>"
     )
     # Act
     result = data_api.check_xml_file_is_valid(data, request=mock_request)
     # Assert
     self.assertEqual(result, True)
Esempio n. 8
0
def async_template_migration_task(templates, xslt_id, target_template_id,
                                  user_id, migrate):
    """Async task which perform a migration / validation of all the data which belong to the given template id list

    Args:
        templates:
        xslt_id:
        target_template_id:
        user_id
        migrate: (boolean) Perform the migration

    Return:
        {"valid": <number>, "wrong": <number>}
    """
    # get the data list to check
    current_data_progress = 0
    current_template_progress = -1
    total_data = 0
    total_template = len(templates)
    success = []
    error = []
    try:
        if target_template_id and total_template > 0:
            # get the user
            user = user_api.get_user_by_id(user_id)
            # get the target template
            target_template = system_api.get_template_by_id(target_template_id)
            # get xsl transformation if selected
            if xslt_id is not None:
                xslt = xsl_transformation_api.get_by_id(str(xslt_id))

            for template_id in templates:

                # increase the number of processed template
                current_template_progress += 1
                # rest de number of data
                current_data_progress = 0

                # get a QuerySet of all the data with the given template
                data_list = data_api.execute_query(
                    {"template": ObjectId(template_id)}, user=user)

                total_data = data_list.count()

                # extract the data id from the list
                data_list_id = data_list.values_list("id")

                for data_id in data_list_id:

                    # get the data
                    data = data_api.get_by_id(data_id, user)

                    # modify the data temporarily with the new targeted template
                    data.template = target_template

                    if xslt_id is not None:
                        # modify the xml content temporarily with the transformed data content
                        data.xml_content = xsl_transformation_api.xsl_transform(
                            data.xml_content, xslt.name)

                    # check if the data is valid
                    try:
                        # save the new template for the data if the migration is True
                        if migrate:
                            system_api.upsert_data(data)
                        else:
                            data_api.check_xml_file_is_valid(data)

                        success.append(str(data.id))
                    except Exception as e:
                        error.append(str(data.id))
                    finally:
                        # increase the current progress and update the task state
                        current_data_progress += 1
                        async_template_migration_task.update_state(
                            state="PROGRESS",
                            meta={
                                "template_current": current_template_progress,
                                "template_total": total_template,
                                "data_current": current_data_progress,
                                "data_total": total_data,
                            },
                        )

            return {"valid": success, "wrong": error}

        else:
            async_template_migration_task.update_state(
                state="ABORT",
                meta={
                    "template_current": current_template_progress,
                    "template_total": total_template,
                    "data_current": current_data_progress,
                    "data_total": total_data,
                },
            )
            raise Exception("Wrong template id." if not target_template_id else
                            "Please provide template id.")
    except Exception as e:
        async_template_migration_task.update_state(
            state="ABORT",
            meta={
                "template_current": current_template_progress,
                "template_total": total_data,
                "data_current": current_data_progress,
                "data_total": total_data,
            },
        )
        raise Exception(f"Something went wrong: {str(e)}")
Esempio n. 9
0
def async_migration_task(data_list, xslt_id, template_id, user_id, migrate):
    """Async task which perform a migration / validation of the data list for the given target template id

    Args:
        data_list:
        xslt_id:
        template_id:
        user_id:
        migrate: (boolean) Perform the migration

    Return:
        {"valid": ["id"...], "wrong": ["id"...]}
    """
    success = []
    errors = []
    current_progress = 0
    total_data = len(data_list)

    try:
        user = user_api.get_user_by_id(user_id)
        target_template = system_api.get_template_by_id(template_id)

        # get xsl transformation if selected
        if xslt_id is not None:
            xslt = xsl_transformation_api.get_by_id(str(xslt_id))

        for data_id in data_list:
            data = data_api.get_by_id(data_id, user=user)
            # modify the data temporarily with the new targeted template
            data.template = target_template

            if xslt_id is not None:
                # modify the xml content temporarily with the transformed data content
                data.xml_content = xsl_transformation_api.xsl_transform(
                    data.xml_content, xslt.name)

            try:
                # save the new template for the data if the migration is True
                if migrate:
                    system_api.upsert_data(data)
                else:
                    # check if the data is valid
                    data_api.check_xml_file_is_valid(data)

                success.append(str(data.id))
            except Exception as e:
                errors.append(str(data.id))
            finally:
                # increase the current progress and update the task state
                current_progress += 1
                async_migration_task.update_state(
                    state="PROGRESS",
                    meta={
                        "current": current_progress,
                        "total": total_data
                    },
                )
    except Exception as e:
        async_migration_task.update_state(state="ABORT",
                                          meta={
                                              "current": current_progress,
                                              "total": total_data
                                          })
        raise Exception(f"Something went wrong: {str(e)}")

    return {"valid": success, "wrong": errors}
Esempio n. 10
0
def set_data_pid(sender, document, **kwargs):
    """Set the PID in the XML field specified in the settings. If the PID
    already exists and is valid, it is not reset.

    Params:
        sender:
        document:
        kwargs:

    Returns:
    """
    if not pid_settings_api.get().auto_set_pid:
        return

    pid_xpath = get_xpath_from_dot_notation(PID_XPATH)

    # Retrieve namespaces
    xml_tree = XSDTree.build_tree(document.xml_content)
    pid_xpath, namespaces = get_xpath_with_target_namespace(
        pid_xpath, document.template.content
    )

    try:  # Get the PID from the `pid_xpath` value
        document_pid = get_value_at_xpath(xml_tree, pid_xpath, namespaces)
        if type(document_pid) == str and document_pid.endswith(
            "/"
        ):  # Cleanup PID if it ends with a '/'
            document_pid = document_pid[:-1]
    except AssertionError:  # PID XPath not found in document
        try:  # Try to create the element at the given PID
            # Import libs that need to wait for apps to be ready
            from core_main_app.components.data import api as data_api

            modified_xml_tree = create_tree_from_xpath(pid_xpath, xml_tree, namespaces)
            set_value_at_xpath(
                modified_xml_tree, pid_xpath, "http://sample_pid.org", namespaces
            )
            document.xml_content = XSDTree.tostring(modified_xml_tree)
            data_api.check_xml_file_is_valid(document)

            # Replace the current by the modified tree (containing mock PID) and
            # force document PID to be regenerated.
            xml_tree = modified_xml_tree
            document_pid = None
        except Exception as exc:  # Cannot create PID at given XPath
            LOGGER.warning("Cannot create PID at %s: %s" % (pid_xpath, str(exc)))
            return

    # Identify provider name for registration and ensure the PID has not been
    # already defined in another document.
    provider_manager = ProviderManager()

    # Retrieve previous PID and remove it from DB.
    if document.pk is not None:
        previous_pid = system_api.get_pid_for_data(document.pk)

        previous_provider_name = provider_manager.find_provider_from_pid(previous_pid)
        previous_provider = provider_manager.get(previous_provider_name)
        previous_pid_url = previous_pid.replace(
            previous_provider.provider_url, previous_provider.local_url
        )

        previous_pid_delete_response = send_delete_request(
            "%s?format=json" % previous_pid_url
        )

        # Log any error that happen during PID deletion
        if previous_pid_delete_response.status_code != HTTP_200_OK:
            LOGGER.warning(
                "Deletion of PID %s returned %s"
                % (previous_pid, previous_pid_delete_response.status_code)
            )

    if document_pid is None or document_pid == "":  # PID field left blank
        # Select the default provider if no PID has been chosen.
        provider_name = list(settings.ID_PROVIDER_SYSTEMS.keys())[0]
        document_pid = join(
            provider_manager.get(provider_name).provider_url,
            settings.ID_PROVIDER_PREFIX_DEFAULT,
        )
    else:  # PID specified in document.
        # Check that the PID is not defined for a document other than the current
        # document.
        if system_api.is_pid_defined(document_pid) and (
            document.pk is None
            or not system_api.is_pid_defined_for_document(document_pid, document.pk)
        ):
            raise exceptions.ModelError("PID already defined for another document")

        provider_name = provider_manager.find_provider_from_pid(document_pid)

    # PID specified but not matching any possible provider URLs for the
    # generation.
    if provider_name is None:
        raise exceptions.ModelError("Invalid PID provided")

    provider = provider_manager.get(provider_name)
    registration_url = document_pid.replace(provider.provider_url, provider.local_url)

    document_pid_response = send_post_request("%s?format=json" % registration_url)

    if document_pid_response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR:
        default_error_message = "An error occurred while creating the PID"
        try:
            raise exceptions.ModelError(
                document_pid_response.json().get("message", default_error_message)
            )
        except ValueError:  # If the response is not JSON parsable
            raise exceptions.ModelError(default_error_message)

    if (
        document_pid_response.status_code != status.HTTP_201_CREATED
        and document_pid_response.status_code != status.HTTP_200_OK
        and system_api.get_data_by_pid(document_pid).pk != document.pk
    ):
        raise exceptions.ModelError("Invalid PID provided")

    # FIXME assert the value is not changed when saving
    document_pid = document_pid_response.json()["url"]

    # Set the document PID into XML data and update `xml_content`
    set_value_at_xpath(xml_tree, pid_xpath, document_pid, namespaces)
    document.xml_content = XSDTree.tostring(xml_tree)

    # Update the whole document with the updated XML content
    document.convert_to_file()
    document.convert_to_dict()