Example #1
0
    def copy_gebruiksrechten(self, source_object: Gebruiksrechten,
                             destination_folder: Folder) -> Gebruiksrechten:
        """Copy a gebruiksrechten to a folder

        :param source_object: Gebruiksrechten, the gebruiksrechten to copy
        :param destination_folder: Folder, the folder in which to place the copied gebruiksrechten
        :return: the copied object
        """
        # copy the properties from the source object
        properties = {
            property_name: property_details["value"]
            for property_name, property_details in
            source_object.properties.items() if "cmis:" not in property_name
        }

        file_name = get_random_string()

        properties.update(
            **{
                "cmis:objectTypeId": source_object.objectTypeId,
                "cmis:name": file_name,
                mapper("kopie_van", type="gebruiksrechten"): source_object.
                objectId,  # Keep tack of where this is copied from.
                mapper("uuid", type="gebruiksrechten"): str(uuid.uuid4()),
            })

        data = create_json_request_body(destination_folder, properties)
        logger.debug("CMIS_ADAPTER: copy_gebruiksrechten: request data: %s",
                     data)

        json_response = self.post_request(self.root_folder_url, data=data)
        logger.debug("CMIS_ADAPTER: copy_gebruiksrechten: response data: %s",
                     json_response)

        return Gebruiksrechten(json_response)
Example #2
0
    def build_properties(cls, data: dict, new: bool = True) -> dict:

        props = {}
        for key, value in data.items():
            prop_name = mapper(key, type="document")
            if not prop_name:
                logger.debug(
                    "CMIS_ADAPTER: No property name found for key '%s'", key)
                continue
            props[prop_name] = value

        # For documents that are not new, the uuid shouldn't be written
        props.pop(mapper("uuid"), None)

        if new:
            # increase likelihood of uniqueness of title by appending a random string
            title, suffix = data.get("titel"), get_random_string()
            if title is not None:
                props["cmis:name"] = f"{title}-{suffix}"

            # For new documents, the uuid needs to be set
            new_uuid = str(uuid.uuid4())
            props[mapper("uuid", type="document")] = new_uuid

            # The identification needs to be set ONLY for newly created documents.
            # identificatie is immutable once the document is created
            if not props.get(mapper("identificatie")):
                prop_name = mapper("identificatie")
                props[prop_name] = new_uuid

        return props
Example #3
0
    def _normalize_filters(
            self, filters: List[Tuple]) -> Tuple[List[str], List[str]]:
        """
        Normalize the various flavours of ORM filters.

        Turn dict filters into something that looks like SQL 92 suitable for Alfresco
        CMIS query. Note that all filters are AND-ed together.

        Ideally, this would be an implementation of the as_sql for a custom database
        backend, returning lhs and rhs parts.
        """
        _lhs = []
        _rhs = []

        # TODO: make this more declarative

        for key, value in filters:
            name = mapper(key, type="document")

            if key == "begin_registratie":
                # begin_registratie is a LTE filter, so define it as such:
                column = mapper("begin_registratie", type="document")
                _lhs.append(f"{column} <= '%s'")
                _rhs.append(value.isoformat().replace("+00:00", "Z"))
                continue
            elif key == "_va_order":
                continue
            elif key == "informatieobjecttype":
                if isinstance(value, list) and len(value) == 0:
                    # In this case there are no authorised informatieobjecttypes
                    _lhs.append("drc:document__informatieobjecttype = '%s'")
                    _rhs.append("")
                    continue
                else:
                    # In this case there are multiple allowed informatieobjecttypes
                    lhs, rhs = self._build_authorisation_filter(name, value)
                    _lhs.append(lhs)
                    _rhs += rhs
                    continue
            elif key == "creatiedatum" and value == "":
                _lhs.append(f"{name} LIKE '%s'")
                _rhs.append("%-%-%")
                continue

            if name is None:
                raise NotImplementedError(
                    f"Filter on '{key}' is not implemented yet")

            _rhs.append(value)
            _lhs.append(f"{name} = '%s'")

        return _lhs, _rhs
Example #4
0
    def unlock_document(self,
                        drc_uuid: str,
                        lock: str,
                        force: bool = False) -> Document:
        """Unlock a document with given uuid

        :param drc_uuid: string, the value of drc:document__uuid
        :param lock: string, value of the lock
        :param force: bool, whether to force the unlocking
        :return: Document, the unlocked document
        """
        cmis_doc = self.get_document(drc_uuid)

        if not cmis_doc.isVersionSeriesCheckedOut:
            raise DocumentNotLockedException(
                "Document is not checked out and/or locked.")

        if constant_time_compare(cmis_doc.lock, lock) or force:
            lock_property = {
                mapper("lock"): {
                    "value": "",
                    "type": get_cmis_type(EnkelvoudigInformatieObject, "lock"),
                }
            }
            cmis_doc.update_properties(lock_property)
            return cmis_doc.checkin("Updated via Documenten API")

        raise LockDidNotMatchException("Lock did not match",
                                       code="unlock-failed")
Example #5
0
    def _normalize_filters(
            self, filters: List[Tuple]) -> Tuple[List[str], List[str]]:
        """
        Normalize the various flavours of ORM filters.

        Turn dict filters into something that looks like SQL 92 suitable for Alfresco
        CMIS query. Note that all filters are AND-ed together.

        Ideally, this would be an implementation of the as_sql for a custom database
        backend, returning lhs and rhs parts.
        """
        _lhs = []
        _rhs = []

        for key, value in filters:
            name = mapper(key, type="gebruiksrechten")

            if name is None:
                raise NotImplementedError(
                    f"Filter on '{key}' is not implemented yet")

            lhs_filter, rhs_filter = build_filter(name, value)

            _rhs += rhs_filter
            _lhs += lhs_filter

        return _lhs, _rhs
Example #6
0
    def lock_document(self, drc_uuid: str, lock: str):
        """Lock a EnkelvoudigInformatieObject with given drc:document__uuid

        :param drc_uuid: string, the value of drc:document__uuid
        :param lock: string, value of the lock
        """
        cmis_doc = self.get_document(drc_uuid)

        already_locked = DocumentLockedException(
            "Document was already checked out", code="double_lock")

        try:
            pwc = cmis_doc.checkout()
            if pwc.lock:
                raise already_locked

            # store the lock value on the PWC so we can compare it later
            lock_property = {
                mapper("lock"): {
                    "value": lock,
                    "type": get_cmis_type(EnkelvoudigInformatieObject, "lock"),
                }
            }
            pwc.update_properties(lock_property)
        except CmisUpdateConflictException as exc:
            raise already_locked from exc
Example #7
0
    def check_document_exists(self, identification: Union[str, UUID],
                              bronorganisatie: str) -> None:
        """Check if a document with the same (identificatie, bronorganisatie) already exists in the repository

        :param identification: string, document ``identificatie``
        :param bronorganisatie: string, document ``bronorganisatie``
        """
        cmis_identificatie = mapper("identificatie", type="document")
        cmis_bronorganisatie = mapper("bronorganisatie", type="document")

        query = CMISQuery(
            f"SELECT * FROM drc:document WHERE {cmis_identificatie} = '%s' AND {cmis_bronorganisatie} = '%s'"
        )

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            statement=query(str(identification), bronorganisatie),
            cmis_action="query",
        )
        logger.debug(soap_envelope.toprettyxml())

        try:
            soap_response = self.request("DiscoveryService",
                                         soap_envelope=soap_envelope.toxml())
        except CmisRuntimeException as exc:
            # Corsa raises an error if the query gives no results, while Alfresco a 200
            if "objectNotFound" in exc.message:
                return
            else:
                raise exc

        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))

        extracted_data = extract_object_properties_from_xml(
            xml_response, "query")

        if len(extracted_data) > 0:
            raise DocumentExistsError(
                "Een document met dezelfde identificatie en bronorganisatie al bestaat."
            )
Example #8
0
def build_query_filters(
    filters: dict,
    object_type: str = None,
    filter_string: str = "",
    strip_end: bool = False,
):
    """Build filters for SQL query"""
    from drc_cmis.utils.mapper import mapper

    if filters:
        for key, value in filters.items():
            if object_type is None:
                if mapper(key):
                    key = mapper(key)
                elif mapper(key, type="connection"):
                    key = mapper(key, type="connection")
                elif mapper(key, type="gebruiksrechten"):
                    key = mapper(key, type="gebruiksrechten")
                elif mapper(key, type="oio"):
                    key = mapper(key, type="oio")
            else:
                key = mapper(key, type=object_type)

            if value and value in ["NULL", "NOT NULL"]:
                filter_string += f"{key} IS {value} AND "
            elif isinstance(value, Decimal):
                filter_string += f"{key} = {value} AND "
            elif isinstance(value, list):
                if len(value) == 0:
                    continue
                filter_string += "( "
                for item in value:
                    sub_filter_string = build_query_filters({key: item},
                                                            strip_end=True)
                    filter_string += f"{sub_filter_string} OR "
                filter_string = filter_string[:-3]
                filter_string += " ) AND "
            elif value:
                filter_string += f"{key} = '{value}' AND "

    if strip_end and filter_string[-4:] == "AND ":
        filter_string = filter_string[:-4]

    return filter_string
Example #9
0
    def check_document_exists(self, identification: Union[str, UUID],
                              bronorganisatie: str):
        """Check if a document with the same (identificatie, bronorganisatie) already exists in the repository"""

        cmis_identificatie = mapper("identificatie", type="document")
        cmis_bronorganisatie = mapper("bronorganisatie", type="document")

        query = CMISQuery(
            f"SELECT * FROM drc:document WHERE {cmis_identificatie} = '%s' AND {cmis_bronorganisatie} = '%s'"
        )

        data = {
            "cmisaction": "query",
            "statement": query(str(identification), bronorganisatie),
        }
        logger.debug("CMIS_ADAPTER: check_document_exists: request data: %s",
                     data)
        json_response = self.post_request(self.base_url, data)
        logger.debug("CMIS_ADAPTER: check_document_exists: response data: %s",
                     json_response)
        if json_response["numItems"] > 0:
            raise DocumentExistsError(
                "Een document met dezelfde identificatie en bronorganisatie al bestaat."
            )
Example #10
0
    def unlock_document(self,
                        drc_uuid: str,
                        lock: str,
                        force: bool = False) -> Document:
        """Unlock a document with objectId workspace://SpacesStore/<uuid>"""
        cmis_doc = self.get_document(drc_uuid)
        pwc = cmis_doc.get_private_working_copy()

        if constant_time_compare(pwc.lock, lock) or force:
            pwc.update_properties({mapper("lock"): ""})
            new_doc = pwc.checkin("Updated via Documenten API")
            return new_doc

        raise LockDidNotMatchException("Lock did not match",
                                       code="unlock-failed")
Example #11
0
    def build_properties(cls, data: dict) -> dict:
        """Construct property dictionary."""

        props = {}
        for key, value in data.items():
            prop_name = mapper(key, type=cls.type_name)
            if not prop_name:
                logger.debug(
                    "CMIS_ADAPTER: No property name found for key '%s'", key)
                continue
            if value is not None:
                if isinstance(value, datetime.date) or isinstance(
                        value, datetime.date):
                    value = value.strftime("%Y-%m-%dT%H:%M:%S.000Z")
                props[prop_name] = str(value)

        return props
Example #12
0
    def copy_document(self, document: Document,
                      destination_folder: Folder) -> Document:
        """Copy document to a folder

        :param document: Document, the document to copy
        :param destination_folder: Folder, the folder in which to place the copied document
        :return: the copied document
        """

        # copy the properties from the source document
        properties = {
            property_name: property_details["value"]
            for property_name, property_details in document.properties.items()
            if "cmis:" not in property_name
        }

        properties.update(
            **{
                "cmis:objectTypeId": document.objectTypeId,
                mapper("titel", type="document"): f"{document.titel} - copy",
                "drc:kopie_van":
                document.uuid,  # Keep tack of where this is copied from.
                "drc:document__uuid": str(uuid.uuid4()),
            })

        # Update the cmis:name to make it more unique
        file_name = f"{document.titel}-{get_random_string()}"
        properties["cmis:name"] = file_name

        data = create_json_request_body(destination_folder, properties)
        logger.debug("CMIS_ADAPTER: copy_document: request data: %s", data)

        content = document.get_content_stream()
        json_response = self.post_request(self.root_folder_url, data=data)
        logger.debug("CMIS_ADAPTER: copy_document: response data: %s",
                     json_response)

        cmis_doc = Document(json_response)
        content.seek(0)

        return cmis_doc.set_content_stream(content,
                                           filename=document.bestandsnaam)
Example #13
0
    def build_properties(cls, data: dict) -> dict:
        """Construct property dictionary.

        The structure of the dictionary is (where ``property_name``, ``property_value``
        and ``property_type`` are the name, value and type of the property):

            .. code-block:: python

                properties = {
                    "property_name": {
                        "value": property_value,
                        "type": property_type,
                    }
                }
        """
        config = CMISConfig.objects.get()

        props = {}
        for key, value in data.items():
            prop_name = mapper(key, type=cls.type_name)
            if not prop_name:
                logger.debug("CMIS_ADAPTER: No property name found for key '%s'", key)
                continue
            if value is not None:
                prop_type = get_cmis_type(cls.type_class, key)

                if (
                    get_type(cls.type_class, key) == QueriableUrl
                    and settings.CMIS_URL_MAPPING_ENABLED
                ):
                    value = shrink_url(value)
                elif isinstance(value, datetime.datetime):
                    value = value.astimezone(pytz.timezone(config.time_zone)).strftime(
                        "%Y-%m-%dT%H:%M:%S.000Z"
                    )
                elif isinstance(value, datetime.date):
                    # In CMIS, there is no propertyDate, only propertyDateTime.
                    # So dates need to be in the datetime format
                    value = value.strftime("%Y-%m-%dT00:00:00.000Z")
                props[prop_name] = {"value": str(value), "type": prop_type}

        return props
Example #14
0
    def lock_document(self, drc_uuid: str, lock: str):
        """
        Check out the CMIS document and store the lock value for check in/unlock.
        """
        cmis_doc = self.get_document(drc_uuid)

        already_locked = DocumentLockedException(
            "Document was already checked out", code="double_lock")

        try:
            pwc = cmis_doc.checkout()
        except CmisInvalidArgumentException:
            raise already_locked

        if pwc.lock:
            raise already_locked

        try:
            # store the lock value on the PWC so we can compare it later
            pwc.update_properties({mapper("lock"): lock})
        except CmisUpdateConflictException as exc:
            raise already_locked from exc
Example #15
0
    def create_content_object(
            self,
            data: dict,
            object_type: str,
            destination_folder: Folder = None) -> CMISContentObject:
        """Create a Gebruiksrechten or a ObjectInformatieObject

        :param data: dict, properties of the object to create
        :param object_type: string, either "gebruiksrechten" or "oio"
        :param destination_folder: Folder, a folder where to create the object. If not provided,
            the object will be placed in a temporary folder.
        :return: Either a Gebruiksrechten or ObjectInformatieObject
        """
        assert object_type in [
            "gebruiksrechten",
            "oio",
        ], "'object_type' can be only 'gebruiksrechten' or 'oio'"

        if destination_folder is None:
            other_folder = self.get_or_create_other_folder()
            destination_folder = self.get_or_create_folder(
                "Related data", other_folder)

        properties = {
            mapper(key, type=object_type): value
            for key, value in data.items() if mapper(key, type=object_type)
        }

        json_data = {
            "objectId": destination_folder.objectId,
            "cmisaction": "createDocument",
            "propertyId[0]": "cmis:name",
            "propertyValue[0]": get_random_string(),
            "propertyId[1]": f"drc:{object_type}__uuid",
            "propertyValue[1]": str(uuid.uuid4()),
        }

        json_data["propertyId[2]"] = "cmis:objectTypeId"
        if "cmis:objectTypeId" in properties.keys():
            json_data["propertyValue[2]"] = properties.pop("cmis:objectTypeId")
        else:
            json_data[
                "propertyValue[2]"] = f"{self.get_object_type_id_prefix(object_type)}drc:{object_type}"

        prop_count = 3
        for prop_key, prop_value in properties.items():
            if isinstance(prop_value, datetime.date):
                prop_value = prop_value.strftime("%Y-%m-%dT%H:%M:%S.000Z")

            json_data[f"propertyId[{prop_count}]"] = prop_key
            json_data[f"propertyValue[{prop_count}]"] = prop_value
            prop_count += 1

        logger.debug("CMIS_ADAPTER: create_content_object: request data: %s",
                     json_data)
        json_response = self.post_request(self.root_folder_url, data=json_data)
        logger.debug("CMIS_ADAPTER: create_content_object: response data: %s",
                     json_response)

        if object_type == "gebruiksrechten":
            return Gebruiksrechten(json_response)
        elif object_type == "oio":
            return ObjectInformatieObject(json_response)
Example #16
0
 def test_mapper_get_gebruiksrechten(self):
     self.assertIs(mapper("informatieobject"), None)
     self.assertEqual(
         mapper("informatieobject", "gebruiksrechten"),
         "drc:gebruiksrechten__informatieobject",
     )
Example #17
0
 def test_mapper_get_oio(self):
     self.assertIs(mapper("informatieobject"), None)
     self.assertEqual(mapper("informatieobject", "oio"),
                      "drc:oio__informatieobject")
Example #18
0
 def test_mapper_get_unknown(self):
     self.assertIsNone(mapper("identificatie", "unknown"))
Example #19
0
    def create_content_object(
            self,
            data: dict,
            object_type: str,
            destination_folder: Folder = None) -> CMISContentObject:
        """Create a Gebruiksrechten or a ObjectInformatieObject

        :param data: dict, properties of the object to create
        :param object_type: string, either "gebruiksrechten" or "oio"
        :param destination_folder: Folder, the folder in which to place the object
        :return: Either a Gebruiksrechten or ObjectInformatieObject
        """
        assert object_type in [
            "gebruiksrechten",
            "oio",
        ], "'object_type' can be only 'gebruiksrechten' or 'oio'"

        if object_type == "oio":
            return_type = ObjectInformatieObject
            data_class = Oio
        elif object_type == "gebruiksrechten":
            return_type = Gebruiksrechten
            data_class = GebruiksRechtDoc

        if destination_folder is None:
            other_folder = self.get_or_create_other_folder()
            destination_folder = self.get_or_create_folder(
                "Related data", other_folder)

        properties = return_type.build_properties(data)

        properties.setdefault(
            "cmis:objectTypeId",
            {
                "value":
                f"{self.get_object_type_id_prefix(object_type)}drc:{object_type}",
                "type": "propertyId",
            },
        )
        properties.setdefault("cmis:name", {
            "value": get_random_string(),
            "type": "propertyString"
        })
        properties.setdefault(
            mapper("uuid", type=object_type),
            {
                "value": str(uuid.uuid4()),
                "type": get_cmis_type(data_class, "uuid")
            },
        )

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            folder_id=destination_folder.objectId,
            properties=properties,
            cmis_action="createDocument",
        )

        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.request(
            "ObjectService",
            soap_envelope=soap_envelope.toxml(),
        )

        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))

        extracted_data = extract_object_properties_from_xml(
            xml_response, "createDocument")[0]
        new_object_id = extracted_data["properties"]["objectId"]["value"]

        # Request all the properties of the newly created object
        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            object_id=new_object_id,
            cmis_action="getObject",
        )

        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.request("ObjectService",
                                     soap_envelope=soap_envelope.toxml())

        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))

        extracted_data = extract_object_properties_from_xml(
            xml_response, "getObject")[0]

        return return_type(extracted_data)
Example #20
0
    def copy_gebruiksrechten(self, source_object: Gebruiksrechten,
                             destination_folder: Folder) -> Gebruiksrechten:
        """Copy a gebruiksrechten to a folder

        :param source_object: Gebruiksrechten, the gebruiksrechten to copy
        :param destination_folder: Folder, the folder in which to place the copied gebruiksrechten
        :return: the copied object
        """

        # copy the properties from the source document
        drc_properties = {}
        drc_url_properties = {}
        for property_name, property_details in source_object.properties.items(
        ):
            if ("cmis:" not in property_name and property_details["value"]
                    is not None) or property_name == "cmis:objectTypeId":
                drc_property_name = reverse_mapper(property_name,
                                                   type="gebruiksrechten")

                # Urls are handled separately, because they are already in the 'short' form
                if get_type(GebruiksRechtDoc,
                            drc_property_name) == QueriableUrl:
                    drc_url_properties[property_name] = {
                        "value": property_details["value"],
                        "type": "propertyString",
                    }
                else:
                    drc_properties[drc_property_name] = property_details[
                        "value"]

        cmis_properties = Gebruiksrechten.build_properties(drc_properties)

        cmis_properties.update(
            **{
                "cmis:objectTypeId": {
                    "value": source_object.objectTypeId,
                    "type": "propertyId",
                },
                mapper("kopie_van", type="gebruiksrechten"): {
                    "value": source_object.objectId,
                    "type":
                    "propertyString",  # Keep tack of where this is copied from.
                },
                "cmis:name": {
                    "value": get_random_string(),
                    "type": "propertyString"
                },
                "drc:gebruiksrechten__uuid": {
                    "value": str(uuid.uuid4()),
                    "type": "propertyString",
                },
                **drc_url_properties,
            })

        # Create copy gebruiksrechten
        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            folder_id=destination_folder.objectId,
            properties=cmis_properties,
            cmis_action="createDocument",
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.request(
            "ObjectService",
            soap_envelope=soap_envelope.toxml(),
        )

        # Creating the document only returns its ID
        xml_response = extract_xml_from_soap(soap_response)

        logger.debug(pretty_xml(xml_response))

        extracted_data = extract_object_properties_from_xml(
            xml_response, "createDocument")[0]
        copy_gebruiksrechten_id = extracted_data["properties"]["objectId"][
            "value"]

        # Request all the properties of the newly created object
        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            object_id=copy_gebruiksrechten_id,
            cmis_action="getObject",
        )

        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.request("ObjectService",
                                     soap_envelope=soap_envelope.toxml())

        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))

        extracted_data = extract_object_properties_from_xml(
            xml_response, "getObject")[0]

        return Gebruiksrechten(extracted_data)
Example #21
0
 def test_mapper_get_document(self):
     self.assertEqual(mapper("identificatie"),
                      "drc:document__identificatie")
     self.assertEqual(mapper("identificatie", "document"),
                      "drc:document__identificatie")
Example #22
0
 def test_mapper_get_zaak(self):
     self.assertEqual(mapper("identificatie", "zaak"),
                      "drc:zaak__identificatie")
Example #23
0
    def copy_document(self, document: Document,
                      destination_folder: Folder) -> Document:
        """Copy document to a folder

        :param document: Document, the document to copy
        :param destination_folder: Folder, the folder in which to place the copied document
        :return: the copied document
        """

        # copy the properties from the source document
        drc_properties = {}
        drc_url_properties = {}
        for property_name, property_details in document.properties.items():
            if ("cmis:" not in property_name and property_details["value"]
                    is not None) or property_name == "cmis:objectTypeId":
                drc_property_name = reverse_mapper(property_name,
                                                   type="document")

                # Urls are handled separately, because they are already in the 'short' form
                if (get_type(EnkelvoudigInformatieObject,
                             drc_property_name) == QueriableUrl):
                    drc_url_properties[property_name] = {
                        "value": property_details["value"],
                        "type": "propertyString",
                    }
                else:
                    drc_properties[drc_property_name] = property_details[
                        "value"]

        cmis_properties = Document.build_properties(drc_properties, new=False)

        cmis_properties.update(
            **{
                "cmis:objectTypeId": {
                    "value": document.objectTypeId,
                    "type": "propertyId",
                },
                mapper("titel", type="document"): {
                    "value": f"{document.titel} - copy",
                    "type": "propertyString",
                },
                "drc:kopie_van": {
                    "value": document.uuid,
                    "type": "propertyString",
                },  # Keep tack of where this is copied from.
                "drc:document__uuid": {
                    "value": str(uuid.uuid4()),
                    "type": "propertyString",
                },
                **drc_url_properties,
            })

        # Update the cmis:name to make it more unique
        file_name = f"{document.titel}-{get_random_string()}"
        cmis_properties["cmis:name"] = {
            "value": file_name,
            "type": "propertyString"
        }

        # Create copy document
        content_id = str(uuid.uuid4())
        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            folder_id=destination_folder.objectId,
            properties=cmis_properties,
            cmis_action="createDocument",
            content_id=content_id,
            content_filename=drc_properties.get("bestandsnaam"),
        )

        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.request(
            "ObjectService",
            soap_envelope=soap_envelope.toxml(),
            attachments=[(content_id, document.get_content_stream())],
        )

        # Creating the document only returns its ID
        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))

        extracted_data = extract_object_properties_from_xml(
            xml_response, "createDocument")[0]
        copy_document_id = extracted_data["properties"]["objectId"]["value"]

        return document.get_document(copy_document_id)
Example #24
0
    def build_properties(cls, data: dict, new: bool = True) -> dict:
        """Construct property dictionary.

        The structure of the dictionary is (where ``property_name``, ``property_value``
        and ``property_type`` are the name, value and type of the property):

            .. code-block:: python

                properties = {
                    "property_name": {
                        "value": property_value,
                        "type": property_type,
                    }
                }
        """

        config = CMISConfig.objects.get()

        props = {}
        for key, value in data.items():
            prop_name = mapper(key, type="document")
            if not prop_name:
                logger.debug("CMIS_ADAPTER: No property name found for key '%s'", key)
                continue
            if value is not None:
                prop_type = get_cmis_type(EnkelvoudigInformatieObject, key)

                if (
                    settings.CMIS_URL_MAPPING_ENABLED
                    and get_type(EnkelvoudigInformatieObject, key) == QueriableUrl
                    and value != ""
                ):
                    value = shrink_url(value)
                elif isinstance(value, datetime.datetime):
                    value = value.astimezone(pytz.timezone(config.time_zone)).strftime(
                        "%Y-%m-%dT%H:%M:%S.000Z"
                    )
                elif isinstance(value, datetime.date):
                    # In CMIS, there is no propertyDate, only propertyDateTime.
                    # So dates need to be in the datetime format
                    value = value.strftime("%Y-%m-%dT00:00:00.000Z")
                elif isinstance(value, bool):
                    value = str(value).lower()

                props[prop_name] = {"value": str(value), "type": prop_type}
            # When a Gebruiksrechten object is deleted, the field in the Document needs to be None.
            elif key == "indicatie_gebruiksrecht":
                prop_type = get_cmis_type(EnkelvoudigInformatieObject, key)
                props[prop_name] = {"value": "", "type": prop_type}

        # For documents that are not new, the uuid shouldn't be written
        props.pop(mapper("uuid"), None)

        if new:
            # increase likelihood of uniqueness of title by appending a random string
            title, suffix = data.get("titel"), get_random_string()
            if title is not None:
                props["cmis:name"] = {
                    "value": f"{title}-{suffix}",
                    "type": get_cmis_type(EnkelvoudigInformatieObject, "name"),
                }

            # For new documents, the uuid needs to be set
            prop_name = mapper("uuid")
            prop_type = get_cmis_type(EnkelvoudigInformatieObject, "uuid")
            new_uuid = str(uuid.uuid4())
            props[prop_name] = {"value": new_uuid, "type": prop_type}

            # The identification needs to be set ONLY for newly created documents.
            # identificatie is immutable once the document is created
            prop_name = mapper("identificatie")
            if not props.get(prop_name, {}).get("value"):
                prop_type = get_cmis_type(EnkelvoudigInformatieObject, "identificatie")
                props[prop_name] = {"value": new_uuid, "type": prop_type}

        return props