diff libervia/backend/plugins/plugin_comp_file_sharing.py @ 4270:0d7bb4df2343

Reformatted code base using black.
author Goffi <goffi@goffi.org>
date Wed, 19 Jun 2024 18:44:57 +0200
parents 6784d07b99c8
children
line wrap: on
line diff
--- a/libervia/backend/plugins/plugin_comp_file_sharing.py	Tue Jun 18 12:06:45 2024 +0200
+++ b/libervia/backend/plugins/plugin_comp_file_sharing.py	Wed Jun 19 18:44:57 2024 +0200
@@ -82,10 +82,7 @@
     "{used_space}, you can't upload {file_size} more."
 )
 
-HTTP_VERSION = unicodedata.normalize(
-    'NFKD',
-    f"{C.APP_NAME} file sharing {C.APP_VERSION}"
-)
+HTTP_VERSION = unicodedata.normalize("NFKD", f"{C.APP_NAME} file sharing {C.APP_VERSION}")
 
 
 class HTTPFileServer(resource.Resource):
@@ -94,32 +91,32 @@
     def errorPage(self, request, code):
         request.setResponseCode(code)
         if code == http.BAD_REQUEST:
-            brief = 'Bad Request'
+            brief = "Bad Request"
             details = "Your request is invalid"
         elif code == http.FORBIDDEN:
-            brief = 'Forbidden'
+            brief = "Forbidden"
             details = "You're not allowed to use this resource"
         elif code == http.NOT_FOUND:
-            brief = 'Not Found'
+            brief = "Not Found"
             details = "No resource found at this URL"
         else:
-            brief = 'Error'
+            brief = "Error"
             details = "This resource can't be used"
             log.error(f"Unexpected return code used: {code}")
         log.warning(
-            f'Error returned while trying to access url {request.uri.decode()}: '
+            f"Error returned while trying to access url {request.uri.decode()}: "
             f'"{brief}" ({code}): {details}'
         )
 
         return resource.ErrorPage(code, brief, details).render(request)
 
     def get_disposition_type(self, media_type, media_subtype):
-        if media_type in ('image', 'video'):
-            return 'inline'
-        elif media_type == 'application' and media_subtype == 'pdf':
-            return 'inline'
+        if media_type in ("image", "video"):
+            return "inline"
+        elif media_type == "application" and media_subtype == "pdf":
+            return "inline"
         else:
-            return 'attachment'
+            return "attachment"
 
     def render(self, request):
         request.setHeader("server", HTTP_VERSION)
@@ -127,13 +124,14 @@
         request.setHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, PUT")
         request.setHeader(
             "Access-Control-Allow-Headers",
-            "Content-Type, Range, Xmpp-File-Path, Xmpp-File-No-Http")
+            "Content-Type, Range, Xmpp-File-Path, Xmpp-File-No-Http",
+        )
         request.setHeader("Access-Control-Allow-Credentials", "true")
         request.setHeader("Accept-Ranges", "bytes")
 
         request.setHeader(
-            "Access-Control-Expose-Headers",
-            "Date, Content-Length, Content-Range")
+            "Access-Control-Expose-Headers", "Date, Content-Length, Content-Range"
+        )
         return super().render(request)
 
     def render_OPTIONS(self, request):
@@ -157,7 +155,8 @@
             request.finish()
             return
         found_files = await request.file_sharing.host.memory.get_files(
-            client=None, peer_jid=None, perms_to_check=None, public_id=upload_id)
+            client=None, peer_jid=None, perms_to_check=None, public_id=upload_id
+        )
         if not found_files:
             request.write(self.errorPage(request, http.NOT_FOUND))
             request.finish()
@@ -166,22 +165,22 @@
             log.error(f"more that one files found for public id {upload_id!r}")
 
         found_file = found_files[0]
-        file_path = request.file_sharing.files_path/found_file['file_hash']
+        file_path = request.file_sharing.files_path / found_file["file_hash"]
         file_res = static.File(file_path)
         file_res.type = f'{found_file["media_type"]}/{found_file["media_subtype"]}'
-        file_res.encoding = file_res.contentEncodings.get(Path(found_file['name']).suffix)
+        file_res.encoding = file_res.contentEncodings.get(Path(found_file["name"]).suffix)
         disp_type = self.get_disposition_type(
-            found_file['media_type'], found_file['media_subtype'])
+            found_file["media_type"], found_file["media_subtype"]
+        )
         # the URL is percent encoded, and not all browsers/tools unquote the file name,
         # thus we add a content disposition header
         request.setHeader(
-            'Content-Disposition',
-            f"{disp_type}; filename*=UTF-8''{quote(found_file['name'])}"
+            "Content-Disposition",
+            f"{disp_type}; filename*=UTF-8''{quote(found_file['name'])}",
         )
         # cf. https://xmpp.org/extensions/xep-0363.html#server
         request.setHeader(
-            'Content-Security-Policy',
-            "default-src 'none'; frame-ancestors 'none';"
+            "Content-Security-Policy", "default-src 'none'; frame-ancestors 'none';"
         )
         ret = file_res.render(request)
         if ret != server.NOT_DONE_YET:
@@ -215,7 +214,7 @@
         if path:
             path = unquote(path)
         else:
-            path =  "/uploads"
+            path = "/uploads"
         if request.getHeader("Xmpp-File-No-Http") is not None:
             public_id = None
         else:
@@ -225,11 +224,14 @@
             "name": unquote(upload_request.filename),
             "mime_type": upload_request.content_type,
             "size": upload_request.size,
-            "path": path
+            "path": path,
         }
 
         await request.file_sharing.register_received_file(
-            client, upload_request.from_, file_data, tmp_file_path,
+            client,
+            upload_request.from_,
+            file_data,
+            tmp_file_path,
             public_id=public_id,
         )
 
@@ -256,11 +258,13 @@
         # we normalise the path
         path = urlparse(path.decode()).path
         try:
-            __, upload_id, filename = path.split('/')
+            __, upload_id, filename = path.split("/")
         except ValueError:
             raise exceptions.DataError("no enought path elements")
         if len(upload_id) < 10:
-            raise exceptions.DataError(f"invalid upload ID received for a PUT: {upload_id!r}")
+            raise exceptions.DataError(
+                f"invalid upload ID received for a PUT: {upload_id!r}"
+            )
 
         self._upload_data = (upload_id, filename)
         return self._upload_data
@@ -276,11 +280,11 @@
     def refuse_request(self):
         if self.content is not None:
             self.content.close()
-        self.content = open(os.devnull, 'w+b')
+        self.content = open(os.devnull, "w+b")
         self.channel._respondToBadRequestAndDisconnect()
 
     def gotLength(self, length):
-        if self.channel._command.decode().upper() == 'PUT':
+        if self.channel._command.decode().upper() == "PUT":
             # for PUT we check early if upload_id is fine, to avoid buffering a file we'll refuse
             # we buffer the fileĀ in component's TMP_BUFFER_DIR, so we just have to rename it at the end
             try:
@@ -289,9 +293,13 @@
                 log.warning(f"Invalid PUT request, we stop here: {e}")
                 return self.refuse_request()
             try:
-                client, upload_request, timer = self.file_sharing.expected_uploads.pop(upload_id)
+                client, upload_request, timer = self.file_sharing.expected_uploads.pop(
+                    upload_id
+                )
             except KeyError:
-                log.warning(f"unknown (expired?) upload ID received for a PUT: {upload_id!r}")
+                log.warning(
+                    f"unknown (expired?) upload ID received for a PUT: {upload_id!r}"
+                )
                 return self.refuse_request()
 
             if not timer.active:
@@ -309,10 +317,9 @@
 
             self.upload_request_data = (client, upload_request)
 
-            file_tmp_path = files_utils.get_unique_name(
-                self.file_tmp_dir/upload_id)
+            file_tmp_path = files_utils.get_unique_name(self.file_tmp_dir / upload_id)
 
-            self.content = open(file_tmp_path, 'w+b')
+            self.content = open(file_tmp_path, "w+b")
         else:
             return super().gotLength(length)
 
@@ -331,8 +338,8 @@
         super().__init__(HTTPFileServer())
 
     def getContentFile(self, length):
-        file_tmp_path = self.file_tmp_dir/shortuuid.uuid()
-        return open(file_tmp_path, 'w+b')
+        file_tmp_path = self.file_tmp_dir / shortuuid.uuid()
+        return open(file_tmp_path, "w+b")
 
 
 class FileSharing:
@@ -356,37 +363,53 @@
         self._t = self.host.plugins["XEP-0264"]
         self._hu = self.host.plugins["XEP-0363"]
         self._hu.register_handler(self._on_http_upload)
-        self.host.trigger.add_with_check("FILE_getDestDir", self, self._get_dest_dir_trigger)
+        self.host.trigger.add_with_check(
+            "FILE_getDestDir", self, self._get_dest_dir_trigger
+        )
         self.host.trigger.add_with_check(
-            "XEP-0234_fileSendingRequest", self, self._file_sending_request_trigger, priority=1000
+            "XEP-0234_fileSendingRequest",
+            self,
+            self._file_sending_request_trigger,
+            priority=1000,
         )
-        self.host.trigger.add_with_check("XEP-0234_buildFileElement", self, self._add_file_metadata_elts)
-        self.host.trigger.add_with_check("XEP-0234_parseFileElement", self, self._get_file_metadata_elts)
-        self.host.trigger.add_with_check("XEP-0329_compGetFilesFromNode", self, self._add_file_metadata)
+        self.host.trigger.add_with_check(
+            "XEP-0234_buildFileElement", self, self._add_file_metadata_elts
+        )
+        self.host.trigger.add_with_check(
+            "XEP-0234_parseFileElement", self, self._get_file_metadata_elts
+        )
+        self.host.trigger.add_with_check(
+            "XEP-0329_compGetFilesFromNode", self, self._add_file_metadata
+        )
         self.host.trigger.add_with_check(
             "XEP-0329_compGetFilesFromNode_build_directory",
             self,
-            self._add_directory_metadata_elts)
+            self._add_directory_metadata_elts,
+        )
         self.host.trigger.add_with_check(
-            "XEP-0329_parseResult_directory",
-            self,
-            self._get_directory_metadata_elts)
+            "XEP-0329_parseResult_directory", self, self._get_directory_metadata_elts
+        )
         self.files_path = self.host.get_local_path(None, C.FILES_DIR)
-        self.http_port = int(self.host.memory.config_get(
-            'component file-sharing', 'http_upload_port', 8888))
+        self.http_port = int(
+            self.host.memory.config_get(
+                "component file-sharing", "http_upload_port", 8888
+            )
+        )
         connection_type = self.host.memory.config_get(
-            'component file-sharing', 'http_upload_connection_type', 'https')
-        if connection_type not in ('http', 'https'):
+            "component file-sharing", "http_upload_connection_type", "https"
+        )
+        if connection_type not in ("http", "https"):
             raise exceptions.ConfigError(
                 'bad http_upload_connection_type, you must use one of "http" or "https"'
             )
         self.server = FileSharingSite(self)
         self.expected_uploads = {}
-        if connection_type == 'http':
+        if connection_type == "http":
             reactor.listenTCP(self.http_port, self.server)
         else:
             options = tls.get_options_from_config(
-                self.host.memory.config, "component file-sharing")
+                self.host.memory.config, "component file-sharing"
+            )
             tls.tls_options_check(options)
             context_factory = tls.get_tls_context_factory(options)
             reactor.listenSSL(self.http_port, self.server, context_factory)
@@ -400,7 +423,8 @@
 
         self.init()
         public_base_url = self.host.memory.config_get(
-            'component file-sharing', 'http_upload_public_facing_url')
+            "component file-sharing", "http_upload_public_facing_url"
+        )
         if public_base_url is None:
             client._file_sharing_base_url = f"https://{client.host}:{self.http_port}"
         else:
@@ -441,7 +465,8 @@
             thumbnails.append({"id": thumb_id, "size": thumb_size})
 
     async def register_received_file(
-            self, client, peer_jid, file_data, file_path, public_id=None, extra=None):
+        self, client, peer_jid, file_data, file_path, public_id=None, extra=None
+    ):
         """Post file reception tasks
 
         once file is received, this method create hash/thumbnails if necessary
@@ -463,9 +488,9 @@
             file_hash = file_data["hash_hasher"].hexdigest()
         else:
             hasher = self._h.get_hasher(HASH_ALGO)
-            with file_path.open('rb') as f:
+            with file_path.open("rb") as f:
                 file_hash = await self._h.calculate_hash(f, hasher)
-        final_path = self.files_path/file_hash
+        final_path = self.files_path / file_hash
 
         if final_path.is_file():
             log.debug(
@@ -490,8 +515,11 @@
                 try:
                     await video.get_thumbnail(final_path, thumb_path)
                 except Exception as e:
-                    log.warning(_("Can't get thumbnail for {final_path}: {e}").format(
-                        final_path=final_path, e=e))
+                    log.warning(
+                        _("Can't get thumbnail for {final_path}: {e}").format(
+                            final_path=final_path, e=e
+                        )
+                    )
                 else:
                     await self.generate_thumbnails(extra, thumb_path)
 
@@ -534,14 +562,15 @@
                     text=OVER_QUOTA_TXT.format(
                         quota=utils.get_human_size(quota),
                         used_space=utils.get_human_size(used_space),
-                        file_size=utils.get_human_size(file_data['size'])
-                    )
+                        file_size=utils.get_human_size(file_data["size"]),
+                    ),
                 )
         file_tmp_dir = self.host.get_local_path(
             None, C.FILES_TMP_DIR, peer_jid.userhost(), component=True
         )
-        file_tmp_path = file_data['file_path'] = files_utils.get_unique_name(
-            file_tmp_dir/filename)
+        file_tmp_path = file_data["file_path"] = files_utils.get_unique_name(
+            file_tmp_dir / filename
+        )
 
         transfer_data["finished_d"].addCallback(
             lambda __: defer.ensureDeferred(
@@ -559,8 +588,8 @@
     ):
         """This method retrieve a file on request, and send if after checking permissions"""
         peer_jid = session["peer_jid"]
-        if session['local_jid'].user:
-            owner = client.get_owner_from_jid(session['local_jid'])
+        if session["local_jid"].user:
+            owner = client.get_owner_from_jid(session["local_jid"])
         else:
             owner = peer_jid
         try:
@@ -592,9 +621,10 @@
 
         # we only use the first found file
         found_file = found_files[0]
-        if found_file['type'] != C.FILE_TYPE_FILE:
-            raise TypeError("a file was expected, type is {type_}".format(
-                type_=found_file['type']))
+        if found_file["type"] != C.FILE_TYPE_FILE:
+            raise TypeError(
+                "a file was expected, type is {type_}".format(type_=found_file["type"])
+            )
         file_hash = found_file["file_hash"]
         file_path = self.files_path / file_hash
         file_data["hash_hasher"] = hasher = self._h.get_hasher(found_file["hash_algo"])
@@ -624,9 +654,11 @@
         else:
             return (
                 False,
-                defer.ensureDeferred(self._retrieve_files(
-                    client, session, content_data, content_name, file_data, file_elt
-                )),
+                defer.ensureDeferred(
+                    self._retrieve_files(
+                        client, session, content_data, content_name, file_data, file_elt
+                    )
+                ),
             )
 
     ## HTTP Upload ##
@@ -639,7 +671,7 @@
 
     async def _on_http_upload(self, client, request):
         # filename should be already cleaned, but it's better to double check
-        assert '/' not in request.filename
+        assert "/" not in request.filename
         # client._file_sharing_allowed_hosts is set in plugin XEP-0329
         if request.from_.host not in client._file_sharing_allowed_hosts:
             raise error.StanzaError("forbidden")
@@ -654,13 +686,15 @@
                     text=OVER_QUOTA_TXT.format(
                         quota=utils.get_human_size(quota),
                         used_space=utils.get_human_size(used_space),
-                        file_size=utils.get_human_size(request.size)
+                        file_size=utils.get_human_size(request.size),
                     ),
-                    appCondition = self._hu.get_file_too_large_elt(max(quota - used_space, 0))
+                    appCondition=self._hu.get_file_too_large_elt(
+                        max(quota - used_space, 0)
+                    ),
                 )
 
         upload_id = shortuuid.ShortUUID().random(length=30)
-        assert '/' not in upload_id
+        assert "/" not in upload_id
         timer = reactor.callLater(30, self._purge_slot, upload_id)
         self.expected_uploads[upload_id] = (client, request, timer)
         url = urljoin(client._file_sharing_base_url, f"{upload_id}/{request.filename}")
@@ -675,7 +709,7 @@
 
     def _add_file_metadata_elts(self, client, file_elt, extra_args):
         # affiliation
-        affiliation = extra_args.get('affiliation')
+        affiliation = extra_args.get("affiliation")
         if affiliation is not None:
             file_elt.addElement((NS_FS_AFFILIATION, "affiliation"), content=affiliation)
 
@@ -715,7 +749,8 @@
         return True
 
     def _add_file_metadata(
-            self, client, iq_elt, iq_result_elt, owner, node_path, files_data):
+        self, client, iq_elt, iq_result_elt, owner, node_path, files_data
+    ):
         for file_data in files_data:
             file_data["comments_url"] = uri.build_xmpp_uri(
                 "pubsub",
@@ -725,22 +760,21 @@
         return True
 
     def _add_directory_metadata_elts(
-            self, client, file_data, directory_elt, owner, node_path):
-        affiliation = file_data.get('affiliation')
+        self, client, file_data, directory_elt, owner, node_path
+    ):
+        affiliation = file_data.get("affiliation")
         if affiliation is not None:
             directory_elt.addElement(
-                (NS_FS_AFFILIATION, "affiliation"),
-                content=affiliation
+                (NS_FS_AFFILIATION, "affiliation"), content=affiliation
             )
 
-    def _get_directory_metadata_elts(
-            self, client, elt, file_data):
+    def _get_directory_metadata_elts(self, client, elt, file_data):
         try:
             affiliation_elt = next(elt.elements(NS_FS_AFFILIATION, "affiliation"))
         except StopIteration:
             pass
         else:
-            file_data['affiliation'] = str(affiliation_elt)
+            file_data["affiliation"] = str(affiliation_elt)
 
 
 class Comments_handler(pubsub.PubSubService):
@@ -841,7 +875,9 @@
             peer_jid = None
         else:
             peer_jid = requestor.userhost()
-        update_cb = partial(self.comments_update, new_comments=comments, peer_jid=peer_jid)
+        update_cb = partial(
+            self.comments_update, new_comments=comments, peer_jid=peer_jid
+        )
         try:
             await self.host.memory.file_update(file_id, "extra", update_cb)
         except exceptions.PermissionError: