Mercurial > libervia-backend
view sat/plugins/plugin_misc_attach.py @ 3202:2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
"path" refers to a local path of a file, we don't want to store it in database as the file
may be in a temporary location, or even be a temporary file. So once the file has been
uploaded, we remove it.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 06 Mar 2020 18:19:03 +0100 |
parents | 883fb4981958 |
children | 2ba602aef90e |
line wrap: on
line source
#!/usr/bin/env python3 # SàT plugin for attaching files # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from functools import partial from pathlib import Path from twisted.internet import defer from sat.core.i18n import _ from sat.core.constants import Const as C from sat.core.log import getLogger log = getLogger(__name__) PLUGIN_INFO = { C.PI_NAME: "File Attach", C.PI_IMPORT_NAME: "ATTACH", C.PI_TYPE: C.PLUG_TYPE_MISC, C.PI_DEPENDENCIES: ["UPLOAD"], C.PI_MAIN: "AttachPlugin", C.PI_HANDLER: "no", C.PI_DESCRIPTION: _("""Attachments handler"""), } class AttachPlugin: def __init__(self, host): log.info(_("plugin Attach initialization")) self.host = host self._u = host.plugins["UPLOAD"] host.trigger.add("sendMessage", self._sendMessageTrigger) def _attachFiles(self, client, data): # TODO: handle xhtml-im body_elt = next(data["xml"].elements((C.NS_CLIENT, "body"))) for attachment in data["extra"][C.MESS_KEY_ATTACHMENTS]: body_elt.addContent(f'\n{attachment["url"]}') return data async def uploadFiles(self, client, data): uploads_d = [] to_delete = [] attachments = data["extra"]["attachments"] for attachment in attachments: try: # we pop path because we don't want it to be stored, as the image can be # only in a temporary location path = Path(attachment.pop("path")) except KeyError: log.warning("no path in attachment: {attachment}") to_delete.append(attachment) continue if "url" in attachment: url = attachment.pop('url') log.warning( f"unexpected URL in attachment: {url!r}\nattachment: {attachment}" ) try: name = attachment["name"] except KeyError: name = attachment["name"] = path.name options = {} progress_id = attachment.get("progress_id") if progress_id: options["progress_id"] = attachment["progress_id"] check_certificate = self.host.memory.getParamA( "check_certificate", "Connection", profile_key=client.profile) if not check_certificate: options['ignore_tls_errors'] = True log.warning( _("certificate check disabled for upload, this is dangerous!")) if client.encryption.isEncryptionRequested(data): # FIXME: we should not use implementation specific value here # but for now it's the only file encryption method available with # with upload. options['encryption'] = C.ENC_AES_GCM __, upload_d = await self._u.upload( client, filepath=path, filename=name, options=options, ) uploads_d.append(upload_d) for attachment in to_delete: attachments.remove(attachment) upload_results = await defer.DeferredList(uploads_d) for idx, (success, ret) in enumerate(upload_results): attachment = attachments[idx] if not success: # ret is a failure here log.warning(f"error while uploading {attachment}: {ret}") continue attachment["url"] = ret return data def _uploadFiles(self, client, data): return defer.ensureDeferred(self.uploadFiles(client, data)) def _sendMessageTrigger( self, client, mess_data, pre_xml_treatments, post_xml_treatments): if mess_data['extra'].get(C.MESS_KEY_ATTACHMENTS): pre_xml_treatments.addCallback(partial(self._uploadFiles, client)) post_xml_treatments.addCallback(partial(self._attachFiles, client)) return True