Ejemplo n.º 1
0
    def get_latest_version(self):
        """Get the latest version or the PWC"""

        # This always selects the latest version, and if there is a pwc,
        # Alfresco returns both the pwc and the latest major version, while Corsa only returns the pwc.
        query = CMISQuery("SELECT * FROM drc:document WHERE drc:document__uuid = '%s'")

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

        try:
            soap_response = self.client.request(
                "DiscoveryService", soap_envelope=soap_envelope.toxml()
            )
        # Corsa raises an error for queries that return no results
        except CmisRuntimeException as exc:
            if "objectNotFound" in exc.message:
                error_string = f"Object met objectId '{self.objectId}' bestaat niet in het CMIS connection"
                raise DocumentDoesNotExistError(error_string)
            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")
        return extract_latest_version(type(self), extracted_data)
Ejemplo n.º 2
0
    def get_folder(self, object_id: str) -> Folder:
        """Retrieve folder with given objectId"""

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            object_id=object_id,
            cmis_action="getObject",
        )

        logger.debug(soap_envelope.toprettyxml())

        try:
            soap_response = self.request("ObjectService",
                                         soap_envelope=soap_envelope.toxml())
        except CmisRuntimeException as exc:
            if "objectNotFound" in exc.message:
                error_string = f"Folder met objectId '{object_id}' bestaat niet in het CMIS connection"
                raise FolderDoesNotExistError(error_string)
            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, "getObject")[0]
        return Folder(extracted_data)
Ejemplo n.º 3
0
    def delete_object(self):
        """
        Permanently delete the object from the CMIS store, with all its versions.

        By default, all versions should be deleted according to the CMIS standard. If
        the document is currently locked (i.e. there is a private working copy), we need
        to cancel that checkout first.
        """
        latest_version = self.get_latest_version()

        if latest_version.isVersionSeriesCheckedOut:
            soap_envelope = make_soap_envelope(
                auth=(self.client.user, self.client.password),
                repository_id=self.client.main_repo_id,
                object_id=latest_version.objectId,
                cmis_action="cancelCheckOut",
            )
            logger.debug(soap_envelope.toprettyxml())

            soap_response = self.client.request(
                "VersioningService",
                soap_envelope=soap_envelope.toxml(),
            )
            xml_response = extract_xml_from_soap(soap_response)
            logger.debug(pretty_xml(xml_response))

            refreshed_document = self.get_latest_version()
            return refreshed_document.delete_object()

        return super().delete_object()
Ejemplo n.º 4
0
    def checkout(self) -> "Document":
        """Checkout a private working copy of the document"""

        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            cmis_action="checkOut",
            object_id=str(self.objectId),
        )
        logger.debug(soap_envelope.toprettyxml())

        # FIXME temporary solution due to alfresco raising a 500 AFTER locking the document
        try:
            soap_response = self.client.request(
                "VersioningService", 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, "checkOut"
            )[0]
            pwc_id = extracted_data["properties"]["objectId"]["value"]
        except CmisRuntimeException:
            pwc_document = self.get_latest_version()
            pwc_id = pwc_document.objectId

        return self.get_document(pwc_id)
Ejemplo n.º 5
0
    def test_create_document_with_filename(self):
        properties = {
            "bronorganisatie": "159351741",
            "integriteitwaarde": "Something",
            "verwijderd": "false",
            "ontvangstdatum": "2020-07-28",
            "versie": "1.0",
            "creatiedatum": "2018-06-27",
            "titel": "detailed summary",
            "bestandsnaam": "filename.txt",
        }

        cmis_properties = Document.build_properties(data=properties)
        other_folder = self.cmis_client.get_or_create_other_folder()

        soap_envelope = make_soap_envelope(
            auth=(self.cmis_client.user, self.cmis_client.password),
            repository_id=self.cmis_client.main_repo_id,
            folder_id=other_folder.objectId,
            properties=cmis_properties,
            cmis_action="createDocument",
            content_id=str(uuid.uuid4()),
            content_filename="filename.txt",
        )

        self.assertIn("<ns:filename>filename.txt</ns:filename>", soap_envelope.toxml())
        self.assertIn("<ns:mimeType>text/plain</ns:mimeType>", soap_envelope.toxml())
Ejemplo n.º 6
0
    def get_content_object(
        self, object_id: str, object_type: type
    ) -> "CMISContentObject":
        """Get a content object with specified objectId

        :param object_id: string, objectId of the content object
        :param object_type: type, type of the object to return
        :return: CMISContentObject
        """
        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            object_id=object_id,
            cmis_action="getObject",
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.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 object_type(extracted_data)
Ejemplo n.º 7
0
    def _update_properties(self, properties: dict) -> dict:
        """
        Update properties and return the properties of the updated object.

        :param properties: dict, new properties to update
        :return: dict, properties of the updated object
        """
        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            properties=properties,
            cmis_action="updateProperties",
            object_id=self.objectId,
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.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, "updateProperties"
        )[0]

        return extracted_data
Ejemplo n.º 8
0
    def move_object(self, target_folder: "Folder") -> "CMISContentObject":
        """Move a document to the specified folder"""

        source_folder = self.get_parent_folders()[0]

        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            object_id=self.objectId,
            target_folder_id=target_folder.objectId,
            source_folder_id=source_folder.objectId,
            cmis_action="moveObject",
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.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, "moveObject")[
            0
        ]

        return type(self)(extracted_data)
Ejemplo n.º 9
0
    def get_main_repo_id(self, cache: bool = True) -> str:
        configured_main_repo_id = self.config.main_repo_id
        if configured_main_repo_id and cache:
            return configured_main_repo_id

        if self._main_repo_id is None:
            # Retrieving the IDs of all repositories in the CMS
            soap_envelope = make_soap_envelope(auth=(self.user, self.password),
                                               cmis_action="getRepositories")

            logger.debug(soap_envelope.toprettyxml())

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

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

            all_repositories_ids = extract_repository_ids_from_xml(
                xml_response)

            # If no main repository ID is configured, take the ID of the first repository returned.
            if configured_main_repo_id == "":
                self._main_repo_id = all_repositories_ids[0]
            else:
                if configured_main_repo_id not in all_repositories_ids:
                    raise CmisRepositoryDoesNotExist(
                        "The configured repository ID does not exist.")

                self._main_repo_id = configured_main_repo_id

        return self._main_repo_id
Ejemplo n.º 10
0
    def test_create_document_without_filename(self):
        # No bestandsnaam
        properties = {
            "bronorganisatie": "159351741",
            "integriteitwaarde": "Something",
            "verwijderd": "false",
            "ontvangstdatum": "2020-07-28",
            "versie": "1.0",
            "creatiedatum": "2018-06-27",
            "titel": "detailed summary",
        }

        cmis_properties = Document.build_properties(data=properties)
        other_folder = self.cmis_client.get_or_create_other_folder()

        soap_envelope = make_soap_envelope(
            auth=(self.cmis_client.user, self.cmis_client.password),
            repository_id=self.cmis_client.main_repo_id,
            folder_id=other_folder.objectId,
            properties=cmis_properties,
            cmis_action="createDocument",
            content_id=str(uuid.uuid4()),  # No content_filename
        )

        # If the pattern is not found, raises an exception.
        # The default filename is a random string of len 6 with characters A-Z and 0-9
        re.search(
            r"<ns:filename>[0-9A-Z]{6}<\/ns:filename>", soap_envelope.toxml()
        ).group(0)
        self.assertIn(
            "<ns:mimeType>application/octet-stream</ns:mimeType>", soap_envelope.toxml()
        )
Ejemplo n.º 11
0
    def get_content_object(self, drc_uuid: Union[str, UUID],
                           object_type: str) -> CMISContentObject:
        """Get the gebruiksrechten/oio with specified uuid

        :param drc_uuid: string or UUID, the value of drc:oio__uuid or drc:gebruiksrechten__uuid
        :param object_type: string, either "gebruiksrechten" or "oio"
        :return: Either a Gebruiksrechten or ObjectInformatieObject
        """

        assert object_type in [
            "gebruiksrechten",
            "oio",
        ], "'object_type' can be only 'gebruiksrechten' or 'oio'"

        query = CMISQuery("SELECT * FROM drc:%s WHERE drc:%s__uuid = '%s'")

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            statement=query(object_type, object_type, str(drc_uuid)),
            cmis_action="query",
        )

        logger.debug(soap_envelope.toprettyxml())

        error_string = (
            f"{object_type.capitalize()} {object_type} met identificatie drc:{object_type}__uuid {drc_uuid} "
            f"bestaat niet in het CMIS connection")
        does_not_exist = DocumentDoesNotExistError(error_string)

        try:
            soap_response = self.request("DiscoveryService",
                                         soap_envelope=soap_envelope.toxml())
        # Corsa raises an error if the query retrieves 0 results
        except CmisRuntimeException as exc:
            if "objectNotFound" in exc.message:
                raise does_not_exist
            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 does_not_exist

        if object_type == "oio":
            return ObjectInformatieObject(extracted_data[0])
        elif object_type == "gebruiksrechten":
            return Gebruiksrechten(extracted_data[0])
Ejemplo n.º 12
0
    def create_folder(self,
                      name: str,
                      parent_id: str,
                      data: dict = None) -> Folder:
        """Create a new folder inside a parent

        :param name: string, name of the new folder to create
        :param parent_id: string, cmis:objectId of the parent folder
        :param data: dict, contains the properties of the folder to create.
            The names of the properties are already converted to cmis names (e.g. drc:zaaktype__url)
        :return: Folder, the created folder
        """

        object_type_id = CmisId("cmis:folder")

        properties = {
            "cmis:objectTypeId": {
                "value": object_type_id,
                "type": "propertyId"
            },
            "cmis:name": {
                "value": name,
                "type": "propertyString"
            },
        }

        if data is not None:
            properties.update(data)

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            folder_id=parent_id,
            properties=properties,
            cmis_action="createFolder",
        )

        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, "createFolder")[0]

        # Creating a folder only returns the objectId
        folder_id = extracted_data["properties"]["objectId"]["value"]

        return self.get_folder(folder_id)
Ejemplo n.º 13
0
    def get_document(self,
                     drc_uuid: str,
                     filters: Optional[dict] = None) -> Document:
        """Retrieve a document in the main repository with given uuid (drc:document__uuid)

        If the document series is checked out, it returns the private working copy

        :param drc_uuid: string, value of the cmis property drc:document__uuid
        :param filters: dict, filters to find the document
        :return: Document, latest document version
        """
        error_string = f"Document met drc:document__uuid {drc_uuid} bestaat niet in het CMIS connection"
        does_not_exist = DocumentDoesNotExistError(error_string)

        if drc_uuid is None:
            raise does_not_exist

        # This always selects the latest version, and if there is a pwc,
        # Alfresco returns both the pwc and the latest major version, while Corsa only returns the pwc.
        query = CMISQuery(
            "SELECT * FROM drc:document WHERE drc:document__uuid = '%s' %s")

        filter_string = build_query_filters(filters,
                                            filter_string="AND ",
                                            strip_end=True)

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

        try:
            soap_response = self.request("DiscoveryService",
                                         soap_envelope=soap_envelope.toxml())
        # Corsa raises an error if the query retrieves 0 results
        except CmisRuntimeException as exc:
            if "objectNotFound" in exc.message:
                raise does_not_exist
            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")
        return extract_latest_version(self.document_type, extracted_data)
Ejemplo n.º 14
0
    def get_child_folder(
        self, name: str, child_type: dict = None
    ) -> Optional["Folder"]:
        """Get a folder in the current folder that has a specific name

        :param name: str, the cmis:name of the folder to retrieve
        :param child_type: dict, With keys "value" and "type". The value contains the object type ID of
        the children folders to retrieve.
        """
        if child_type is not None:
            object_type_id = child_type["value"]
            # Alfresco case: the object type ID has an extra prefix (F:drc:zaakfolder, instead of drc:zaakfolder)
            # The prefix needs to be removed for the query
            if len(object_type_id.split(":")) > 2:
                object_type_id = ":".join(object_type_id.split(":")[1:])
        else:
            object_type_id = "cmis:folder"

        query = CMISQuery(
            f"SELECT * FROM {object_type_id} WHERE cmis:parentId = '%s' AND cmis:name = '%s'"
        )

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

        try:
            soap_response = self.client.request(
                "DiscoveryService", soap_envelope=soap_envelope.toxml()
            )
        # Corsa raises an error if the query retrieves 0 results
        except CmisRuntimeException as exc:
            if "objectNotFound" in exc.message:
                return None
            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:
            return None
        return type(self)(extracted_data[0])
Ejemplo n.º 15
0
    def delete_object(self):
        """Delete all versions of an object"""

        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            object_id=self.objectId,
            cmis_action="deleteObject",
        )
        logger.debug(soap_envelope.toprettyxml())

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

        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))
Ejemplo n.º 16
0
    def delete_tree(self):
        """Delete the folder and all its contents"""

        # With Corsa, locked documents cause an error, so 'continue_on_failure' is needed
        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            folder_id=self.objectId,
            cmis_action="deleteTree",
            continue_on_failure="true",
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.request(
            "ObjectService", soap_envelope=soap_envelope.toxml()
        )
        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))
Ejemplo n.º 17
0
    def get_content_stream(self) -> BytesIO:
        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            object_id=self.objectId,
            cmis_action="getContentStream",
        )
        logger.debug(soap_envelope.toprettyxml())

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

        xml_response = extract_xml_from_soap(soap_response, binary=True)
        logger.debug(pretty_xml(xml_response))

        # FIXME find a better way to do this
        return extract_content(soap_response)
Ejemplo n.º 18
0
 def get_all_versions(self) -> List["Document"]:
     object_id = self.objectId.split(";")[0]
     soap_envelope = make_soap_envelope(
         auth=(self.client.user, self.client.password),
         repository_id=self.client.main_repo_id,
         cmis_action="getAllVersions",
         object_id=object_id,
     )
     logger.debug(soap_envelope.toprettyxml())
     soap_response = self.client.request(
         "VersioningService", 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, "getAllVersions"
     )
     return [Document(data) for data in extracted_data]
Ejemplo n.º 19
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."
            )
Ejemplo n.º 20
0
    def checkin(self, checkin_comment: str, major: bool = True) -> "Document":
        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            cmis_action="checkIn",
            object_id=str(self.objectId),
            major=str(major).lower(),
            checkin_comment=checkin_comment,
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.request(
            "VersioningService", 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, "checkIn")[0]
        doc_id = extracted_data["properties"]["objectId"]["value"]

        return self.get_document(doc_id)
Ejemplo n.º 21
0
    def set_content_stream(self, content: BytesIO, filename: Optional[str] = None):
        content_id = str(uuid.uuid4())
        attachments = [(content_id, content)]

        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            object_id=self.objectId,
            cmis_action="setContentStream",
            content_id=content_id,
            content_filename=filename,
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.request(
            "ObjectService",
            soap_envelope=soap_envelope.toxml(),
            attachments=attachments,
        )
        xml_response = extract_xml_from_soap(soap_response)
        logger.debug(pretty_xml(xml_response))
Ejemplo n.º 22
0
    def get_parent_folders(self) -> List["Folder"]:
        """Get all the parent folders of an object"""

        soap_envelope = make_soap_envelope(
            auth=(self.client.user, self.client.password),
            repository_id=self.client.main_repo_id,
            object_id=self.objectId,
            cmis_action="getObjectParents",
        )
        logger.debug(soap_envelope.toprettyxml())

        soap_response = self.client.request(
            "NavigationService", 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, "getObjectParents"
        )
        return [Folder(data) for data in extracted_data]
Ejemplo n.º 23
0
    def create_document(
        self,
        identification: str,
        bronorganisatie: str,
        data: dict,
        content: BytesIO = None,
        check_if_already_exists: bool = True,
    ) -> Document:
        """Create a custom Document (with the EnkelvoudigInformatieObject properties)

        :param identification: string, the document ``identificatie``
        :param bronorganisatie: string, The identifier of the organisation.
        :param data: dict, the properties of the document
        :param content: BytesIO, the content of the document
        :param check_if_already_exists: Bool, whether to check if the document with given identificatie/bronorganisatie
        already exists in the DMS.
        :return: Document, the document created
        """

        if check_if_already_exists and identification and bronorganisatie:
            self.check_document_exists(identification, bronorganisatie)

        data.setdefault("versie", "1")
        data.setdefault(
            "object_type_id",
            f"{self.get_object_type_id_prefix('document')}drc:document",
        )
        data["bronorganisatie"] = bronorganisatie
        data["identificatie"] = identification

        content_id = str(uuid.uuid4())
        if content is None:
            content = BytesIO()

        # Create Document in default folder
        other_folder = self.get_or_create_other_folder()

        properties = Document.build_properties(data, new=True)

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            folder_id=other_folder.objectId,
            properties=properties,
            cmis_action="createDocument",
            content_id=content_id,
            content_filename=data.get("bestandsnaam"),
        )

        logger.debug(soap_envelope.toprettyxml())

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

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

        # Creating the document only returns its ID
        extracted_data = extract_object_properties_from_xml(
            xml_response, "createDocument")[0]
        new_document_id = extracted_data["properties"]["objectId"]["value"]

        # Request all the properties of the newly created document
        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            object_id=new_document_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 Document(extracted_data)
Ejemplo n.º 24
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)
Ejemplo n.º 25
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)
Ejemplo n.º 26
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)
Ejemplo n.º 27
0
    def query(self,
              return_type_name: str,
              lhs: List[str] = None,
              rhs: List[str] = None) -> List[CMISBaseObject]:
        """Perform an SQL query in the DMS

        :param return_type_name: string, either Folder, Document, Oio or Gebruiksrechten
        :param lhs: list of strings, with the LHS of the SQL query
        :param rhs: list of strings, with the RHS of the SQL query
        :return: type, either Folder, Document, Oio or Gebruiksrechten
        """

        return_type = self.get_return_type(return_type_name)

        processed_rhs = rhs
        # Any query that filters based on URL fields needs to be converted to use the short URL version
        if settings.CMIS_URL_MAPPING_ENABLED and lhs is not None and rhs is not None:
            processed_rhs = []

            # Join all the queries and find which fields are used to filter
            joined_lhs = " ".join(lhs)
            column_names = re.findall(r"([a-z]+?:.+?__[a-z]+)", joined_lhs)

            for index, item_rhs in enumerate(rhs):
                column_name = column_names[index]
                property_name = reverse_mapper(column_name,
                                               type=return_type_name.lower())
                if (property_name is not None and get_type(
                        return_type.type_class, property_name) == QueriableUrl
                        and item_rhs != ""):
                    processed_rhs.append(shrink_url(item_rhs))
                else:
                    processed_rhs.append(item_rhs)

        table = return_type.table
        where = (" WHERE " + " AND ".join(lhs)) if lhs else ""
        query = CMISQuery("SELECT * FROM %s%s" % (table, where))
        statement = query(*processed_rhs) if processed_rhs else query()

        soap_envelope = make_soap_envelope(
            auth=(self.user, self.password),
            repository_id=self.main_repo_id,
            statement=statement,
            cmis_action="query",
        )

        logger.debug(soap_envelope.toprettyxml())

        try:
            soap_response = self.request("DiscoveryService",
                                         soap_envelope=soap_envelope.toxml())
        # Corsa raises an error if the query retrieves 0 results
        except CmisRuntimeException as exc:
            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")

        return [return_type(cmis_object) for cmis_object in extracted_data]