comparison sat/plugins/plugin_xep_0329.py @ 3541:888109774673

core: various changes and fixes to work with new storage and D-Bus bridge: - fixes coroutines handling in various places - fixes types which are not serialised by Tx DBus - XEP-0384: call storage methods in main thread in XEP: Python OMEMO's Promise use thread which prevent the use of AsyncIO loop. To work around that, callLater is used to launch storage method in main thread. This is a temporary workaround, as Python OMEMO should get rid of Promise implementation and threads soon.
author Goffi <goffi@goffi.org>
date Thu, 03 Jun 2021 15:21:43 +0200
parents e47aa1fb7b24
children 813595f88612
comparison
equal deleted inserted replaced
3540:aa58451b77ba 3541:888109774673
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 18
19 import mimetypes 19 import mimetypes
20 import json 20 import json
21 import os 21 import os
22 import traceback
22 from pathlib import Path 23 from pathlib import Path
23 from typing import Optional, Dict 24 from typing import Optional, Dict
24 from zope.interface import implementer 25 from zope.interface import implementer
25 from twisted.words.protocols.jabber import xmlstream 26 from twisted.words.protocols.jabber import xmlstream
26 from twisted.words.protocols.jabber import jid 27 from twisted.words.protocols.jabber import jid
31 from sat.core.xmpp import SatXMPPEntity 32 from sat.core.xmpp import SatXMPPEntity
32 from sat.core import exceptions 33 from sat.core import exceptions
33 from sat.core.constants import Const as C 34 from sat.core.constants import Const as C
34 from sat.core.log import getLogger 35 from sat.core.log import getLogger
35 from sat.tools import stream 36 from sat.tools import stream
37 from sat.tools import utils
36 from sat.tools.common import regex 38 from sat.tools.common import regex
37 39
38 40
39 log = getLogger(__name__) 41 log = getLogger(__name__)
40 42
451 453
452 def _requestHandler(self, client, iq_elt, root_nodes_cb, files_from_node_cb): 454 def _requestHandler(self, client, iq_elt, root_nodes_cb, files_from_node_cb):
453 iq_elt.handled = True 455 iq_elt.handled = True
454 node = iq_elt.query.getAttribute("node") 456 node = iq_elt.query.getAttribute("node")
455 if not node: 457 if not node:
456 d = defer.maybeDeferred(root_nodes_cb, client, iq_elt) 458 d = utils.asDeferred(root_nodes_cb, client, iq_elt)
457 else: 459 else:
458 d = defer.maybeDeferred(files_from_node_cb, client, iq_elt, node) 460 d = utils.asDeferred(files_from_node_cb, client, iq_elt, node)
459 d.addErrback( 461 d.addErrback(
460 lambda failure_: log.error( 462 lambda failure_: log.error(
461 _("error while retrieving files: {msg}").format(msg=failure_) 463 _("error while retrieving files: {msg}").format(msg=failure_)
462 ) 464 )
463 ) 465 )
587 589
588 @param iq_elt(domish.Element): IQ stanza of the FIS request 590 @param iq_elt(domish.Element): IQ stanza of the FIS request
589 @return (tuple[jid.JID, jid.JID]): peer_jid and owner 591 @return (tuple[jid.JID, jid.JID]): peer_jid and owner
590 """ 592 """
591 593
592 @defer.inlineCallbacks 594 async def _compGetRootNodesCb(self, client, iq_elt):
593 def _compGetRootNodesCb(self, client, iq_elt):
594 peer_jid, owner = client.getOwnerAndPeer(iq_elt) 595 peer_jid, owner = client.getOwnerAndPeer(iq_elt)
595 files_data = yield self.host.memory.getFiles( 596 files_data = await self.host.memory.getFiles(
596 client, 597 client,
597 peer_jid=peer_jid, 598 peer_jid=peer_jid,
598 parent="", 599 parent="",
599 type_=C.FILE_TYPE_DIRECTORY, 600 type_=C.FILE_TYPE_DIRECTORY,
600 owner=owner, 601 owner=owner,
605 name = file_data["name"] 606 name = file_data["name"]
606 directory_elt = query_elt.addElement("directory") 607 directory_elt = query_elt.addElement("directory")
607 directory_elt["name"] = name 608 directory_elt["name"] = name
608 client.send(iq_result_elt) 609 client.send(iq_result_elt)
609 610
610 @defer.inlineCallbacks 611 async def _compGetFilesFromNodeCb(self, client, iq_elt, node_path):
611 def _compGetFilesFromNodeCb(self, client, iq_elt, node_path):
612 """Retrieve files from local files repository according to permissions 612 """Retrieve files from local files repository according to permissions
613 613
614 result stanza is then built and sent to requestor 614 result stanza is then built and sent to requestor
615 @trigger XEP-0329_compGetFilesFromNode(client, iq_elt, owner, node_path, 615 @trigger XEP-0329_compGetFilesFromNode(client, iq_elt, owner, node_path,
616 files_data): 616 files_data):
617 can be used to add data/elements 617 can be used to add data/elements
618 """ 618 """
619 peer_jid, owner = client.getOwnerAndPeer(iq_elt) 619 peer_jid, owner = client.getOwnerAndPeer(iq_elt)
620 try: 620 try:
621 files_data = yield self.host.memory.getFiles( 621 files_data = await self.host.memory.getFiles(
622 client, peer_jid=peer_jid, path=node_path, owner=owner 622 client, peer_jid=peer_jid, path=node_path, owner=owner
623 ) 623 )
624 except exceptions.NotFound: 624 except exceptions.NotFound:
625 self._iqError(client, iq_elt) 625 self._iqError(client, iq_elt)
626 return 626 return
627 except exceptions.PermissionError: 627 except exceptions.PermissionError:
628 self._iqError(client, iq_elt, condition='not-allowed') 628 self._iqError(client, iq_elt, condition='not-allowed')
629 return 629 return
630 except Exception as e: 630 except Exception as e:
631 log.error("internal server error: {e}".format(e=e)) 631 tb = traceback.format_tb(e.__traceback__)
632 log.error(f"internal server error: {e}\n{''.join(tb)}")
632 self._iqError(client, iq_elt, condition='internal-server-error') 633 self._iqError(client, iq_elt, condition='internal-server-error')
633 return 634 return
634 iq_result_elt = xmlstream.toResponse(iq_elt, "result") 635 iq_result_elt = xmlstream.toResponse(iq_elt, "result")
635 query_elt = iq_result_elt.addElement((NS_FIS, "query")) 636 query_elt = iq_result_elt.addElement((NS_FIS, "query"))
636 query_elt["node"] = node_path 637 query_elt["node"] = node_path