annotate sat_pubsub/privilege.py @ 463:f520ac3164b0

privilege: improvment on last message sending on presence with `+notify`: - local entities subscribed to the presence of an other local entity which is connecting are now added to presence map. This helps getting their notification even if they didn't connect recently - nodes with `presence` access model are now also used for `+notify` - notifications are not sent anymore in case of status change if the resource was already present.
author Goffi <goffi@goffi.org>
date Fri, 15 Oct 2021 13:40:56 +0200
parents a017af61a32b
children d86e0f8a1405
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
1 #!/usr/bin/env python3
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
2 #
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
3 # Copyright (c) 2015-2021 Jérôme Poisson
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
4
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
5
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
6 # This program is free software: you can redistribute it and/or modify
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
9 # (at your option) any later version.
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
10
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
11 # This program is distributed in the hope that it will be useful,
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
14 # GNU Affero General Public License for more details.
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
15
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
18
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
19 "This module implements XEP-0356 (Privileged Entity) to manage rosters, messages and "
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
20 "presences"
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
21
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
22 import time
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
23 from typing import List, Set
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from wokkel import xmppim
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from wokkel.compat import IQ
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
26 from wokkel import pubsub
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
27 from wokkel import disco
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
28 from wokkel.iwokkel import IPubSubService
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
29 from twisted.python import log
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
30 from twisted.python import failure
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
31 from twisted.internet import defer
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
32 from twisted.words.xish import domish
435
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
33 from twisted.words.protocols.jabber import jid, error
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
34
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
35 FORWARDED_NS = 'urn:xmpp:forward:0'
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
36 PRIV_ENT_NS = 'urn:xmpp:privilege:1'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
37 PRIV_ENT_ADV_XPATH = '/message/privilege[@xmlns="{}"]'.format(PRIV_ENT_NS)
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
38 ROSTER_NS = 'jabber:iq:roster'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
39 PERM_ROSTER = 'roster'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
40 PERM_MESSAGE = 'message'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
41 PERM_PRESENCE = 'presence'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
42 ALLOWED_ROSTER = ('none', 'get', 'set', 'both')
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
43 ALLOWED_MESSAGE = ('none', 'outgoing')
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
44 ALLOWED_PRESENCE = ('none', 'managed_entity', 'roster')
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
45 TO_CHECK = {
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
46 PERM_ROSTER:ALLOWED_ROSTER,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
47 PERM_MESSAGE:ALLOWED_MESSAGE,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
48 PERM_PRESENCE:ALLOWED_PRESENCE
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
49 }
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
50
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
51
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
52 class InvalidStanza(Exception):
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
53 pass
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
54
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
55 class NotAllowedError(Exception):
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
56 pass
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
57
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
58 class PrivilegesHandler(disco.DiscoClientProtocol):
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
59 # FIXME: need to manage updates, XEP-0356 must be updated to get roster pushes
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
60 # TODO: cache
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
61
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
62 def __init__(self, service_jid):
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
63 super(PrivilegesHandler, self).__init__()
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
64 self.backend = None
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
65 self._permissions = {PERM_ROSTER: 'none',
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
66 PERM_MESSAGE: 'none',
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
67 PERM_PRESENCE: 'none'}
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
68 self._pubsub_service = None
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
69 self.caps_map = {} # key: bare jid, value: dict of resources with caps hash
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
70 # key: (hash,version), value: dict with DiscoInfo instance (infos) and nodes to
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
71 # notify (notify)
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
72 self.hash_map = {}
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
73 self.roster_cache = {} # key: jid, value: dict with "timestamp" and "roster"
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
74 # key: jid, value: set of entities who need to receive a notification when we
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
75 # get a presence from them. All entities in value have a presence subscription
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
76 # to the key entity.
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
77 self.presence_map = {}
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
78 # resource currently online
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
79 self.presences = set()
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
80
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
81 @property
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
82 def permissions(self):
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
83 return self._permissions
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
84
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
85 def connectionInitialized(self):
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
86 for handler in self.parent.handlers:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
87 if IPubSubService.providedBy(handler):
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
88 self._pubsub_service = handler
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
89 break
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
90 self.backend = self.parent.parent.getServiceNamed('backend')
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
91 self.xmlstream.addObserver(PRIV_ENT_ADV_XPATH, self.onAdvertise)
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
92 self.xmlstream.addObserver('/presence', self._onPresence)
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
93
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
94 def onAdvertise(self, message):
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
95 """Managage the <message/> advertising privileges
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
96
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
97 self._permissions will be updated according to advertised privileged
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
98 """
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
99 privilege_elt = next(message.elements(PRIV_ENT_NS, 'privilege'))
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
100 for perm_elt in privilege_elt.elements(PRIV_ENT_NS):
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
101 try:
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
102 if perm_elt.name != 'perm':
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
103 raise InvalidStanza('unexpected element {}'.format(perm_elt.name))
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
104 perm_access = perm_elt['access']
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
105 perm_type = perm_elt['type']
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
106 try:
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
107 if perm_type not in TO_CHECK[perm_access]:
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
108 raise InvalidStanza(
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
109 'bad type [{}] for permission {}'
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
110 .format(perm_type, perm_access)
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
111 )
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
112 except KeyError:
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
113 raise InvalidStanza('bad permission [{}]'.format(perm_access))
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
114 except InvalidStanza as e:
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
115 log.msg(
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
116 f"Invalid stanza received ({e}), setting permission to none"
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
117 )
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
118 for perm in self._permissions:
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
119 self._permissions[perm] = 'none'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
120 break
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
121
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
122 self._permissions[perm_access] = perm_type or 'none'
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
123
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
124 log.msg(
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
125 'Privileges updated: roster={roster}, message={message}, presence={presence}'
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
126 .format(**self._permissions)
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
127 )
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
128
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
129 ## roster ##
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
130
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
131 def getRoster(self, to_jid):
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
132 """
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
133 Retrieve contact list.
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
134
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
135 @return: Roster as a mapping from L{JID} to L{RosterItem}.
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
136 @rtype: L{twisted.internet.defer.Deferred}
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
137 """
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
138 # TODO: cache results
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
139 if self._permissions[PERM_ROSTER] not in ('get', 'both'):
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
140 log.msg("WARNING: permission not allowed to get roster")
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
141 raise failure.Failure(NotAllowedError('roster get is not allowed'))
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
142
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
143 def processRoster(result):
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
144 roster = {}
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
145 for element in result.query.elements(ROSTER_NS, 'item'):
253
06494c9b25f2 update to fix broken RemoteRoster after Wokkel 0.7.1 changes
Goffi <goffi@goffi.org>
parents: 242
diff changeset
146 item = xmppim.RosterItem.fromElement(element)
06494c9b25f2 update to fix broken RemoteRoster after Wokkel 0.7.1 changes
Goffi <goffi@goffi.org>
parents: 242
diff changeset
147 roster[item.entity] = item
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
148
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
149 return roster
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
150
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
151 iq = IQ(self.xmlstream, 'get')
285
a87c155d0fd5 replaced former roster dirty hack by a XEP-0356 first draft implementation, only roster get is implemented so far
Goffi <goffi@goffi.org>
parents: 283
diff changeset
152 iq.addElement((ROSTER_NS, 'query'))
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
153 iq["to"] = to_jid.userhost()
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
154 d = iq.send()
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
155 d.addCallback(processRoster)
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
156 return d
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
157
348
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
158 def _isSubscribedFrom(self, roster, entity, roster_owner_jid):
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
159 try:
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
160 return roster[entity.userhostJID()].subscriptionFrom
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
161 except KeyError:
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
162 return False
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
163
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
164 def isSubscribedFrom(self, entity, roster_owner_jid):
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
165 """Check if entity has presence subscription from roster_owner_jid
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
166
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
167 @param entity(jid.JID): entity to check subscription to
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
168 @param roster_owner_jid(jid.JID): owner of the roster to check
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
169 @return D(bool): True if entity has a subscription from roster_owner_jid
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
170 """
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
171 d = self.getRoster(roster_owner_jid)
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
172 d.addCallback(self._isSubscribedFrom, entity, roster_owner_jid)
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
173 return d
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
174
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
175 ## message ##
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
176
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
177 def sendMessage(self, priv_message, to_jid=None):
348
d1f63ae1eaf4 privilege: added isSubscribedFrom method to check if an entity has presence subscription from an other entity.
Goffi <goffi@goffi.org>
parents: 343
diff changeset
178 """Send privileged message (in the name of the server)
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
179
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
180 @param priv_message(domish.Element): privileged message
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
181 @param to_jid(jid.JID, None): main message destinee
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
182 None to use our own server
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
183 """
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
184 if self._permissions[PERM_MESSAGE] not in ('outgoing',):
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
185 log.msg("WARNING: permission not allowed to send privileged messages")
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
186 raise failure.Failure(NotAllowedError('privileged messages are not allowed'))
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
187
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
188 main_message = domish.Element((None, "message"))
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
189 if to_jid is None:
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
190 to_jid = self.backend.server_jid
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
191 main_message['to'] = to_jid.full()
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
192 privilege_elt = main_message.addElement((PRIV_ENT_NS, 'privilege'))
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
193 forwarded_elt = privilege_elt.addElement((FORWARDED_NS, 'forwarded'))
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
194 priv_message['xmlns'] = 'jabber:client'
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
195 forwarded_elt.addChild(priv_message)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
196 self.send(main_message)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
197
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
198 def notifyPublish(self, pep_jid, nodeIdentifier, notifications):
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
199 """Do notifications using privileges"""
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
200 for subscriber, subscriptions, items in notifications:
455
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
201 message = self._pubsub_service._createNotification(
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
202 'items',
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
203 pep_jid,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
204 nodeIdentifier,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
205 subscriber,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
206 subscriptions
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
207 )
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
208 for item in items:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
209 item.uri = pubsub.NS_PUBSUB_EVENT
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
210 message.event.items.addChild(item)
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
211 self.sendMessage(message)
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
212
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
213 def notifyRetract(self, pep_jid, nodeIdentifier, notifications):
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
214 for subscriber, subscriptions, items in notifications:
455
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
215 message = self._pubsub_service._createNotification(
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
216 'items',
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
217 pep_jid,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
218 nodeIdentifier,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
219 subscriber,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
220 subscriptions
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
221 )
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
222 for item in items:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
223 retract = domish.Element((None, "retract"))
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
224 retract['id'] = item['id']
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
225 message.event.items.addChild(retract)
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
226 self.sendMessage(message)
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
227
455
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
228 def notifyDelete(self, pep_jid, nodeIdentifier, subscribers, redirectURI=None):
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
229 for subscriber in subscribers:
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
230 message = self._pubsub_service._createNotification(
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
231 'delete',
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
232 pep_jid,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
233 nodeIdentifier,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
234 subscriber
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
235 )
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
236 if redirectURI:
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
237 redirect = message.event.delete.addElement('redirect')
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
238 redirect['uri'] = redirectURI
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
239 self.sendMessage(message)
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
240
455
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
241 def notifyPurge(self, pep_jid, nodeIdentifier, subscribers):
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
242 for subscriber in subscribers:
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
243 message = self._pubsub_service._createNotification(
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
244 'purge',
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
245 pep_jid,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
246 nodeIdentifier,
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
247 subscriber
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
248 )
0b5233981671 backend: fix `delete` notification + add `purge` notification
Goffi <goffi@goffi.org>
parents: 435
diff changeset
249 self.sendMessage(message)
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
250
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
251 ## presence ##
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
252
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
253 def _onPresence(self, presence_elt: domish.Element) -> None:
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
254 defer.ensureDeferred(self.onPresence(presence_elt))
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
255
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
256 async def onPresence(self, presence_elt: domish.Element) -> None:
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
257 from_jid = jid.JID(presence_elt['from'])
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
258 from_jid_bare = from_jid.userhostJID()
460
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
259 if ((jid.JID(from_jid.host) == self.backend.server_jid
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
260 and from_jid_bare not in self.roster_cache)):
607616f9ef5b backend: new `server_jid` option:
Goffi <goffi@goffi.org>
parents: 455
diff changeset
261 roster = await self.getRoster(from_jid_bare)
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
262 timestamp = time.time()
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
263 self.roster_cache[from_jid_bare] = {'timestamp': timestamp,
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
264 'roster': roster,
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
265 }
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
266 for roster_jid, roster_item in roster.items():
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
267 if roster_item.subscriptionFrom:
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
268 # we need to know who is subscribed to our user, to send them
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
269 # notifications when they send presence to us
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
270 self.presence_map.setdefault(roster_jid, set()).add(from_jid_bare)
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
271 if ((roster_item.subscriptionTo
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
272 and jid.JID(roster_jid.host) == self.backend.server_jid)):
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
273 # we also need to know who on this server we are subscribed to, so
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
274 # we can get their notifications even if they didn't connect so far.
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
275 self.presence_map.setdefault(from_jid_bare, set()).add(roster_jid)
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
276
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
277 presence_type = presence_elt.getAttribute('type')
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
278 if presence_type == "unavailable":
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
279 self.presences.discard(from_jid)
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
280 elif from_jid not in self.presences:
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
281 # new resource available
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
282
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
283 # we keep resources present in cache to avoid sending notifications on each
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
284 # status change
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
285 self.presences.add(from_jid)
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
286
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
287 # we check entity capabilities
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
288 try:
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
289 c_elt = next(
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
290 presence_elt.elements('http://jabber.org/protocol/caps', 'c')
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
291 )
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
292 hash_ = c_elt['hash']
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
293 ver = c_elt['ver']
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
294 except (StopIteration, KeyError):
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
295 # no capabilities, we don't go further
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
296 return
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
297
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
298 # FIXME: hash is not checked (cf. XEP-0115)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
299 disco_tuple = (hash_, ver)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
300
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
301 if disco_tuple not in self.hash_map:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
302 # first time we se this hash, what is behind it?
435
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
303 try:
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
304 infos = await self.requestInfo(from_jid)
435
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
305 except error.StanzaError as e:
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
306 log.msg(
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
307 f"WARNING: can't request disco info for {from_jid!r} (presence: "
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
308 f"{presence_type}): {e}"
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
309 )
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
310 else:
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
311 self.hash_map[disco_tuple] = {
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
312 'notify': {
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
313 f[:-7] for f in infos.features if f.endswith('+notify')
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
314 },
96342e7e9f5d privilege: log error when `requestInfo` is failing
Goffi <goffi@goffi.org>
parents: 414
diff changeset
315 'infos': infos
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
316 }
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
317
400
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
318 # jid_caps must be filled only after hash_map is set, to be sure that
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
319 # the hash data is available in getAutoSubscribers
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
320 jid_caps = self.caps_map.setdefault(from_jid_bare, {})
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
321 if from_jid.resource not in jid_caps:
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
322 jid_caps[from_jid.resource] = disco_tuple
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
323
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
324 # nodes are the nodes subscribed with +notify
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
325 nodes = tuple(self.hash_map[disco_tuple]['notify'])
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
326 if not nodes:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
327 return
462
a017af61a32b privilege: add server JID to `publisher` so `+notify` works with it:
Goffi <goffi@goffi.org>
parents: 460
diff changeset
328 # publishers are entities which have granted presence access to our user
a017af61a32b privilege: add server JID to `publisher` so `+notify` works with it:
Goffi <goffi@goffi.org>
parents: 460
diff changeset
329 # + user itself + server
a017af61a32b privilege: add server JID to `publisher` so `+notify` works with it:
Goffi <goffi@goffi.org>
parents: 460
diff changeset
330 publishers = (
a017af61a32b privilege: add server JID to `publisher` so `+notify` works with it:
Goffi <goffi@goffi.org>
parents: 460
diff changeset
331 tuple(self.presence_map.get(from_jid_bare, ()))
a017af61a32b privilege: add server JID to `publisher` so `+notify` works with it:
Goffi <goffi@goffi.org>
parents: 460
diff changeset
332 + (from_jid_bare, self.backend.server_jid)
a017af61a32b privilege: add server JID to `publisher` so `+notify` works with it:
Goffi <goffi@goffi.org>
parents: 460
diff changeset
333 )
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
334
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
335 # FIXME: add "presence" access_model (for node) for getLastItems
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
336 # TODO: manage other access model (whitelist, …)
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
337 last_items = await self.backend.storage.getLastItems(
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
338 publishers,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
339 nodes,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
340 ('open', 'presence'), ('open', 'presence'), True
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
341 )
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
342 # we send message with last item, as required by
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
343 # https://xmpp.org/extensions/xep-0163.html#notify-last
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
344 for pep_jid, node, item, item_access_model in last_items:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
345 self.notifyPublish(pep_jid, node, [(from_jid, None, [item])])
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
346
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
347 ## misc ##
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
348
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
349 async def getAutoSubscribers(
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
350 self,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
351 recipient: jid.JID,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
352 nodeIdentifier: str,
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
353 explicit_subscribers: Set[jid.JID]
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
354 ) -> List[jid.JID]:
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
355 """Get automatic subscribers
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
356
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
357 Get subscribers with presence subscription and +notify for this node
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
358 @param recipient: jid of the PEP owner of this node
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
359 @param nodeIdentifier: node
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
360 @param explicit_subscribers: jids of people which have an explicit subscription
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
361 @return: full jid of automatically subscribed entities
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
362 """
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
363 auto_subscribers = []
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
364 roster = await self.getRoster(recipient)
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
365 for roster_jid, roster_item in roster.items():
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
366 if roster_jid in explicit_subscribers:
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
367 continue
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
368 if roster_item.subscriptionFrom:
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
369 try:
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
370 online_resources = self.caps_map[roster_jid]
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
371 except KeyError:
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
372 continue
414
ccb2a22ea0fc Python 3 port:
Goffi <goffi@goffi.org>
parents: 405
diff changeset
373 for res, disco_tuple in online_resources.items():
400
371e72871e19 privilege: fill hash_map before jid_caps to avoid KeyError in getAutoSubscribers
Goffi <goffi@goffi.org>
parents: 369
diff changeset
374 notify = self.hash_map[disco_tuple]['notify']
343
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
375 if nodeIdentifier in notify:
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
376 full_jid = jid.JID(tuple=(roster_jid.user, roster_jid.host, res))
ff8aff4c9b79 backend, psql: implemented notifications for auto subscribers in PEP:
Goffi <goffi@goffi.org>
parents: 342
diff changeset
377 auto_subscribers.append(full_jid)
463
f520ac3164b0 privilege: improvment on last message sending on presence with `+notify`:
Goffi <goffi@goffi.org>
parents: 462
diff changeset
378 return auto_subscribers