Mercurial > libervia-backend
annotate sat/plugins/plugin_exp_invitation_pubsub.py @ 3934:e345d93fb6e5
plugin OXPS: OpenPGP for XMPP Pubsub implementation:
OpenPGP for XMPP Pubsub (https://xmpp.org/extensions/inbox/pubsub-encryption.html,
currently a protoXEP) is implemented and activated when `encrypted` is set to `True` in
pubsub's `extra` data.
On item retrieval, the decryption is transparent if the key is known, except if the
`decrypt` key in `extra` is set to `False` (notably useful when one wants to checks that
data is well encrypted).
Methods and corresponding bridge methods have been implemented to manage shared secrets
(to share, revoke or rotate the secrets).
plugin XEP-0060's `XEP-0060_publish` trigger point as been move before actual publish so
item can be modified (here e2ee) by the triggers. A new `XEP-0060_items` trigger point has
also been added.
`encrypted` flag can be used with plugin XEP-0277's microblog data
rel 380
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 15 Oct 2022 20:36:53 +0200 |
parents | edc79cefe968 |
children | 26c3e1bc7fb7 |
rev | line source |
---|---|
3462 | 1 #!/usr/bin/env python3 |
2 | |
3 # SàT plugin to send invitations for Pubsub | |
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
5 | |
6 # This program is free software: you can redistribute it and/or modify | |
7 # it under the terms of the GNU Affero General Public License as published by | |
8 # the Free Software Foundation, either version 3 of the License, or | |
9 # (at your option) any later version. | |
10 | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU Affero General Public License for more details. | |
15 | |
16 # You should have received a copy of the GNU Affero General Public License | |
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 from typing import Optional | |
20 from twisted.internet import defer | |
21 from twisted.words.protocols.jabber import jid | |
22 from twisted.words.xish import domish | |
23 from sat.core.i18n import _ | |
24 from sat.core.constants import Const as C | |
25 from sat.core.log import getLogger | |
26 from sat.core.xmpp import SatXMPPEntity | |
27 from sat.tools import utils | |
28 from sat.tools.common import data_format | |
29 | |
30 log = getLogger(__name__) | |
31 | |
32 | |
33 PLUGIN_INFO = { | |
34 C.PI_NAME: "Pubsub Invitation", | |
35 C.PI_IMPORT_NAME: "PUBSUB_INVITATION", | |
36 C.PI_TYPE: "EXP", | |
37 C.PI_PROTOCOLS: [], | |
38 C.PI_DEPENDENCIES: ["XEP-0060", "INVITATION"], | |
39 C.PI_RECOMMENDATIONS: [], | |
40 C.PI_MAIN: "PubsubInvitation", | |
41 C.PI_HANDLER: "no", | |
42 C.PI_DESCRIPTION: _("Invitations for pubsub based features"), | |
43 } | |
44 | |
45 | |
46 class PubsubInvitation: | |
47 | |
48 def __init__(self, host): | |
49 log.info(_("Pubsub Invitation plugin initialization")) | |
50 self.host = host | |
51 self._p = host.plugins["XEP-0060"] | |
52 # namespace to handler map | |
53 self._ns_handler = {} | |
54 host.bridge.addMethod( | |
55 "psInvite", | |
56 ".plugin", | |
57 in_sign="sssssss", | |
58 out_sign="", | |
59 method=self._sendPubsubInvitation, | |
60 async_=True | |
61 ) | |
62 | |
63 def register( | |
64 self, | |
65 namespace: str, | |
66 handler | |
67 ) -> None: | |
68 self._ns_handler[namespace] = handler | |
69 self.host.plugins["INVITATION"].registerNamespace(namespace, self.onInvitation) | |
70 | |
71 def _sendPubsubInvitation( | |
72 self, invitee_jid_s, service_s, node, item_id=None, | |
73 name=None, extra_s='', profile_key=C.PROF_KEY_NONE): | |
74 client = self.host.getClient(profile_key) | |
75 invitee_jid = jid.JID(invitee_jid_s) | |
76 service = jid.JID(service_s) | |
77 extra = data_format.deserialise(extra_s) | |
78 return defer.ensureDeferred( | |
79 self.invite( | |
80 client, | |
81 invitee_jid, | |
82 service, | |
83 node, | |
84 item_id or None, | |
85 name=name or None, | |
86 extra=extra | |
87 ) | |
88 ) | |
89 | |
90 async def invite( | |
91 self, | |
92 client: SatXMPPEntity, | |
93 invitee_jid: jid.JID, | |
94 service: jid.JID, | |
95 node: str, | |
96 item_id: Optional[str] = None, | |
97 name: str = '', | |
98 extra: Optional[dict] = None, | |
99 ) -> None: | |
100 if extra is None: | |
101 extra = {} | |
102 else: | |
103 namespace = extra.get("namespace") | |
104 if namespace: | |
105 try: | |
106 handler = self._ns_handler[namespace] | |
107 preflight = handler.invitePreflight | |
108 except KeyError: | |
109 pass | |
110 except AttributeError: | |
111 log.debug(f"no invitePreflight method found for {namespace!r}") | |
112 else: | |
113 await utils.asDeferred( | |
114 preflight, | |
115 client, invitee_jid, service, node, item_id, name, extra | |
116 ) | |
117 if item_id is None: | |
118 item_id = extra.pop("default_item_id", None) | |
119 | |
120 # we authorize our invitee to see the nodes of interest | |
121 await self._p.setNodeAffiliations(client, service, node, {invitee_jid: "member"}) | |
122 log.debug(f"affiliation set on {service}'s {node!r} node") | |
123 | |
124 # now we send the invitation | |
125 self.host.plugins["INVITATION"].sendPubsubInvitation( | |
126 client, | |
127 invitee_jid, | |
128 service, | |
129 node, | |
130 item_id, | |
131 name=name or None, | |
132 extra=extra | |
133 ) | |
134 | |
135 async def onInvitation( | |
136 self, | |
137 client: SatXMPPEntity, | |
138 namespace: str, | |
139 name: str, | |
140 extra: dict, | |
141 service: jid.JID, | |
142 node: str, | |
143 item_id: Optional[str], | |
144 item_elt: domish.Element | |
145 ) -> None: | |
146 if extra is None: | |
147 extra = {} | |
148 try: | |
149 handler = self._ns_handler[namespace] | |
150 preflight = handler.onInvitationPreflight | |
151 except KeyError: | |
152 pass | |
153 except AttributeError: | |
154 log.debug(f"no onInvitationPreflight method found for {namespace!r}") | |
155 else: | |
156 await utils.asDeferred( | |
157 preflight, | |
158 client, namespace, name, extra, service, node, item_id, item_elt | |
159 ) | |
160 if item_id is None: | |
161 item_id = extra.pop("default_item_id", None) | |
162 creator = extra.pop("creator", False) | |
163 element = extra.pop("element", None) | |
164 if not name: | |
165 name = extra.pop("name", "") | |
166 | |
3584
edc79cefe968
plugin XEP-0060: `getItem(s)`, `publish` and `(un)subscribe` are now coroutines
Goffi <goffi@goffi.org>
parents:
3462
diff
changeset
|
167 return await self.host.plugins['LIST_INTEREST'].registerPubsub( |
3462 | 168 client, namespace, service, node, item_id, creator, |
169 name, element, extra) |