Mercurial > libervia-backend
changeset 4333:e94799a0908f
core (main): Let plugins have several handlers + various improvements:
`get_handler` can now return several handlers, which is notably useful for component with
several included services.
Various improvements such move to `async` method, docstring/type hints update, and slight
improvment of SatXMPPComponent.
rel 453
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 03 Dec 2024 00:11:00 +0100 |
parents | 71c939e34ca6 |
children | 111dce64dcb5 |
files | libervia/backend/core/core_types.py libervia/backend/core/main.py libervia/backend/core/xmpp.py libervia/backend/memory/memory.py |
diffstat | 4 files changed, 81 insertions(+), 77 deletions(-) [+] |
line wrap: on
line diff
--- a/libervia/backend/core/core_types.py Sat Jul 13 18:28:28 2024 +0200 +++ b/libervia/backend/core/core_types.py Tue Dec 03 00:11:00 2024 +0100 @@ -37,6 +37,12 @@ identities: list[disco.DiscoIdentity] +class SatXMPPComponent(SatXMPPEntity): + + def is_local(self, jid_: t_jid.JID) -> bool: + ... + + EncryptionPlugin = namedtuple( "EncryptionPlugin", ("instance", "name", "namespace", "priority", "directed") )
--- a/libervia/backend/core/main.py Sat Jul 13 18:28:28 2024 +0200 +++ b/libervia/backend/core/main.py Tue Dec 03 00:11:00 2024 +0100 @@ -516,9 +516,9 @@ return raise ImportError("Error during initiation") if C.bool(plugin_info.get(C.PI_HANDLER, C.BOOL_FALSE)): - self.plugins[import_name].is_handler = True + self.plugins[import_name].has_handlers = True else: - self.plugins[import_name].is_handler = False + self.plugins[import_name].has_handlers = False # we keep metadata as a Class attribute self.plugins[import_name]._info = plugin_info # TODO: test xmppclient presence and register handler parent
--- a/libervia/backend/core/xmpp.py Sat Jul 13 18:28:28 2024 +0200 +++ b/libervia/backend/core/xmpp.py Tue Dec 03 00:11:00 2024 +0100 @@ -18,6 +18,7 @@ import asyncio import calendar +from collections.abc import Iterable import copy from functools import partial import mimetypes @@ -146,8 +147,12 @@ self.plugins = plugins = self._get_plugins_list() for plugin in plugins: # we check if plugin handle client mode - if plugin.is_handler: - plugin.get_handler(self).setHandlerParent(self) + if plugin.has_handlers: + handlers = plugin.get_handler(self) + if not isinstance(handlers, Iterable): + handlers = [handlers] + for handler in handlers: + handler.setHandlerParent(self) # profile_connecting/profile_connected methods handling @@ -1085,7 +1090,7 @@ @implementer(iwokkel.IDisco) -class SatXMPPComponent(SatXMPPEntity, component.Component): +class SatXMPPComponent(SatXMPPEntity, core_types.SatXMPPComponent, component.Component): """XMPP component This component are similar but not identical to clients.
--- a/libervia/backend/memory/memory.py Sat Jul 13 18:28:28 2024 +0200 +++ b/libervia/backend/memory/memory.py Tue Dec 03 00:11:00 2024 +0100 @@ -1653,70 +1653,64 @@ async def set_file( self, - client, - name, - file_id=None, - version="", - parent=None, - path=None, - type_=C.FILE_TYPE_FILE, - file_hash=None, - hash_algo=None, - size=None, - namespace=None, - mime_type=None, - public_id=None, - created=None, - modified=None, - owner=None, - access=None, - extra=None, - peer_jid=None, - perms_to_check=(C.ACCESS_PERM_WRITE,), - ): - """Set a file metadata + client: SatXMPPEntity, + name: str, + file_id: str | None = None, + version: str = "", + parent: str | None = None, + path: str | None = None, + type_: str = C.FILE_TYPE_FILE, + file_hash: str | None = None, + hash_algo: str | None = None, + size: int | None = None, + namespace: str | None = None, + mime_type: str | None = None, + public_id: str | None = None, + created: float | None = None, + modified: int | None = None, + owner: jid.JID | None = None, + access: dict | None = None, + extra: dict | None = None, + peer_jid: Any | None = None, + perms_to_check: tuple[str]|None = (C.ACCESS_PERM_WRITE,), + ) -> None: + """Set a file metadata. - @param name(unicode): basename of the file - @param file_id(unicode): unique id of the file - @param version(unicode): version of this file - empty string for current version or when there is no versioning - @param parent(unicode, None): id of the directory containing the files - @param path(unicode, None): virtual path of the file in the namespace - if set, parent must be None. All intermediate directories will be created - if needed, using current access. - @param type_(str, None): type of file filter, can be one of C.FILE_TYPE_* - @param file_hash(unicode): unique hash of the payload - @param hash_algo(unicode): algorithm used for hashing the file (usually sha-256) - @param size(int): size in bytes - @param namespace(unicode, None): identifier (human readable is better) to group - files - For instance, namespace could be used to group files in a specific photo album - @param mime_type(unicode): MIME type of the file, or None if not known/guessed - @param public_id(unicode): id used to share publicly the file via HTTP - @param created(int): UNIX time of creation - @param modified(int,None): UNIX time of last modification, or None to use - created date - @param owner(jid.JID, None): jid of the owner of the file (mainly useful for - component) - will be used to check permission (only bare jid is used, don't use with MUC). - Use None to ignore permission (perms_to_check must be None too) - @param access(dict, None): serialisable dictionary with access rules. + @param name: basename of the file + @param file_id: unique id of the file + @param version: version of this file, empty string for current version or when + there is no versioning + @param parent: id of the directory containing the files + @param path: virtual path of the file in the namespace, if set, parent must be + None. All intermediate directories will be created if needed, using current + access. + @param type_: type of file filter, can be one of C.FILE_TYPE_* + @param file_hash: unique hash of the payload + @param hash_algo: algorithm used for hashing the file (usually sha-256) + @param size: size in bytes + @param namespace: identifier (human readable is better) to group files. For + instance, namespace could be used to group files in a specific photo album. + @param mime_type: MIME type of the file, or None if not known/guessed + @param public_id: id used to share publicly the file via HTTP + @param created: UNIX time of creation + @param modified: UNIX time of last modification, or None to use created date + @param owner: jid of the owner of the file (mainly useful for component). will be + used to check permission (only bare jid is used, don't use with MUC). Use None + to ignore permission (perms_to_check must be None too) + @param access: serialisable dictionary with access rules. None (or empty dict) to use private access, i.e. allow only profile's jid to - access the file - key can be on on C.ACCESS_PERM_*, - then a sub dictionary with a type key is used (one of C.ACCESS_TYPE_*). + access the file. + Key can be on on C.ACCESS_PERM_*, then a sub dictionary with a type key is + used (one of C.ACCESS_TYPE_*). According to type, extra keys can be used: - C.ACCESS_TYPE_PUBLIC: the permission is granted for everybody - C.ACCESS_TYPE_WHITELIST: the permission is granted for jids (as unicode) - in the 'jids' key - will be encoded to json in database - @param extra(dict, None): serialisable dictionary of any extra data - will be encoded to json in database - @param perms_to_check(tuple[unicode],None): permission to check - must be a tuple of C.ACCESS_PERM_* or None - if None, permission will not be checked (peer_jid must be None too in this - case) - @param profile(unicode): profile owning the file + in the 'jids' key. will be encoded to json in database + @param extra: serialisable dictionary of any extra data. will be encoded to json + in database + @param perms_to_check: permission to check. must be a tuple of C.ACCESS_PERM_* or + None. if None, permission will not be checked (peer_jid must be None too in + this case) """ if "/" in name: raise ValueError('name must not contain a slash ("/")') @@ -1768,7 +1762,7 @@ parent=parent, type_=C.FILE_TYPE_DIRECTORY, namespace=namespace, - created=time.time(), + created=created, owner=owner, access=access, extra={}, @@ -1827,10 +1821,9 @@ """ return self.storage.file_update(file_id, column, update_cb) - @defer.inlineCallbacks - def _delete_file( + async def _delete_file( self, - client, + client: SatXMPPEntity, peer_jid: jid.JID, recursive: bool, files_path: Path, @@ -1838,11 +1831,11 @@ ): """Internal method to delete files/directories recursively - @param peer_jid(jid.JID): entity requesting the deletion (must be owner of files + @param peer_jid: entity requesting the deletion (must be owner of files to delete) - @param recursive(boolean): True if recursive deletion is needed - @param files_path(unicode): path of the directory containing the actual files - @param file_data(dict): data of the file to delete + @param recursive: True if recursive deletion is needed + @param files_path: path of the directory containing the actual files + @param file_data: data of the file to delete """ if file_data["owner"] != peer_jid: raise exceptions.PermissionError( @@ -1851,7 +1844,7 @@ ) ) if file_data["type"] == C.FILE_TYPE_DIRECTORY: - sub_files = yield self.get_files(client, peer_jid, parent=file_data["id"]) + sub_files = await self.get_files(client, peer_jid, parent=file_data["id"]) if sub_files and not recursive: raise exceptions.DataError(_("Can't delete directory, it is not empty")) # we first delete the sub-files @@ -1860,19 +1853,19 @@ sub_file_path = files_path / sub_file_data["name"] else: sub_file_path = files_path - yield self._delete_file( + await self._delete_file( client, peer_jid, recursive, sub_file_path, sub_file_data ) # then the directory itself - yield self.storage.file_delete(file_data["id"]) + await self.storage.file_delete(file_data["id"]) elif file_data["type"] == C.FILE_TYPE_FILE: log.info( _("deleting file {name} with hash {file_hash}").format( name=file_data["name"], file_hash=file_data["file_hash"] ) ) - yield self.storage.file_delete(file_data["id"]) - references = yield self.get_files( + await self.storage.file_delete(file_data["id"]) + references = await self.get_files( client, peer_jid, file_hash=file_data["file_hash"] ) if references: