annotate sat_pubsub/privilege.py @ 338:6d059f07c2d3

privilege: added presence and +notify initial support: presence privilege is now used and capabilities are cached. When an entity is connected, last items are sent according to +notify nodes in disco. This is initial support, XEP-0356 doesn't allow yet to get roster updated, or synchronises contacts on startup. Only "open" access model is supported for now. "presence" should be added soon as it is trivial to support now. Only last items sending is handled for now, notifications support for new items/deletions should follow. Capabilities hash is not checked yet, with the security concerns that this imply. Check should be added in the future.
author Goffi <goffi@goffi.org>
date Sat, 12 Aug 2017 18:29:32 +0200
parents c7fe09894952
children 28c9579901d3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/python
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
2 #-*- coding: utf-8 -*-
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
3 #
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
4 # Copyright (c) 2015 Jérôme Poisson
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
5
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
6
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
7 # 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
8 # 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
9 # 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
10 # (at your option) any later version.
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
11
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
12 # 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
13 # 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
14 # 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
15 # GNU Affero General Public License for more details.
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
16
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
17 # 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
18 # 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
19
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
20 # ---
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
21
312
5d7c3787672e fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents: 293
diff changeset
22 # This module implements XEP-0356 (Privileged Entity) to manage rosters, messages and presences
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
23
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
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
33 from twisted.words.protocols.jabber import jid
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
34 import time
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
35
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
36 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
37 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
38 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
39 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
40 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
41 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
42 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
43 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
44 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
45 ALLOWED_PRESENCE = ('none', 'managed_entity', '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
46 TO_CHECK = {PERM_ROSTER:ALLOWED_ROSTER, PERM_MESSAGE:ALLOWED_MESSAGE, PERM_PRESENCE:ALLOWED_PRESENCE}
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
47
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
48
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
49 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
50 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
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 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
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
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
55 class PrivilegesHandler(disco.DiscoClientProtocol):
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
56 #FIXME: need to manage updates, and database sync
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
57 #TODO: cache
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
58
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
59 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
60 super(PrivilegesHandler, self).__init__()
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
61 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
62 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
63 PERM_PRESENCE: 'none'}
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
64 self._pubsub_service = None
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
65 self._backend = None
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
66 # FIXME: we use a hack supposing that our privilege come from hostname
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
67 # and we are a component named [name].hostname
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
68 # but we need to manage properly server
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
69 # TODO: do proper server handling
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
70 self.server_jid = jid.JID(service_jid.host.split('.', 1)[1])
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
71 self.caps_map = {} # key: full jid, value: caps_hash
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
72 self.hash_map = {} # key: (hash,version), value: DiscoInfo instance
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"
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
74 self.presence_map = {} # inverted roster: key: jid, value: set of entities who has this jid in roster (with presence of "from" or "both")
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
75 self.server = 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
76
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
77 @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
78 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
79 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
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 def connectionInitialized(self):
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
82 for handler in self.parent.handlers:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
83 if IPubSubService.providedBy(handler):
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
84 self._pubsub_service = handler
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
85 break
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
86 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
87 self.xmlstream.addObserver(PRIV_ENT_ADV_XPATH, self.onAdvertise)
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
88 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
89
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
90 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
91 """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
92
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 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
94 """
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 privilege_elt = message.elements(PRIV_ENT_NS, 'privilege').next()
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 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
97 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
98 if perm_elt.name != 'perm':
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
99 raise InvalidStanza(u'unexpected element {}'.format(perm_elt.name))
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 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
101 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
102 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
103 if perm_type not in TO_CHECK[perm_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
104 raise InvalidStanza(u'bad type [{}] for permission {}'.format(perm_type, perm_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 except KeyError:
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 raise InvalidStanza(u'bad permission [{}]'.format(perm_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
107 except InvalidStanza as e:
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
108 log.msg("Invalid stanza received ({}), setting permission to none".format(e))
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
109 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
110 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
111 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
112
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
113 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
114
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
115 log.msg('Privileges updated: roster={roster}, message={message}, presence={presence}'.format(**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
116
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
117 ## 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
118
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
119 def getRoster(self, to_jid):
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
120 """
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
121 Retrieve contact list.
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
122
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
123 @return: Roster as a mapping from L{JID} to L{RosterItem}.
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
124 @rtype: L{twisted.internet.defer.Deferred}
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
125 """
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
126 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
127 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
128 raise failure.Failure(NotAllowedError('roster get is not allowed'))
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
129
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
130 def processRoster(result):
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
131 roster = {}
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
132 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
133 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
134 roster[item.entity] = item
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
135
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
136 return roster
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
137
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
138 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
139 iq.addElement((ROSTER_NS, 'query'))
242
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
140 iq["to"] = to_jid.userhost()
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
141 d = iq.send()
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
142 d.addCallback(processRoster)
a6170637690d remote roster partial support
Goffi <goffi@goffi.org>
parents:
diff changeset
143 return d
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
144
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
145 ## message ##
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
146
321
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
147 def sendMessage(self, priv_message, to_jid=None):
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
148 """ Send privileged message (in the name of the server)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
149
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
150 @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
151 @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
152 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
153 """
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
154 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
155 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
156 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
157
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
158 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
159 if to_jid is None:
c7fe09894952 privilege: better handling of main message 'to' attribute (i.e. privileged entity's server)
Goffi <goffi@goffi.org>
parents: 312
diff changeset
160 to_jid = self.server_jid
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
161 main_message['to'] = to_jid.full()
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
162 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
163 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
164 priv_message['xmlns'] = 'jabber:client'
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
165 forwarded_elt.addChild(priv_message)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
166 self.send(main_message)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
167
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
168 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
169 """Do notifications using privileges"""
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
170 for subscriber, subscriptions, items in notifications:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
171 message = self._pubsub_service._createNotification('items', pep_jid,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
172 nodeIdentifier, subscriber,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
173 subscriptions)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
174 for item in items:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
175 item.uri = pubsub.NS_PUBSUB_EVENT
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
176 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
177 self.sendMessage(message)
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
178
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 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
181 for subscriber, subscriptions, items in notifications:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
182 message = self._pubsub_service._createNotification('items', pep_jid,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
183 nodeIdentifier, subscriber,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
184 subscriptions)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
185 for item in items:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
186 retract = domish.Element((None, "retract"))
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
187 retract['id'] = item['id']
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
188 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
189 self.sendMessage(message)
293
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
190
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
191
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
192 # def notifyDelete(self, service, nodeIdentifier, subscribers,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
193 # redirectURI=None):
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
194 # # TODO
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
195 # for subscriber in subscribers:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
196 # message = self._createNotification('delete', service,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
197 # nodeIdentifier,
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
198 # subscriber)
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
199 # if redirectURI:
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
200 # redirect = message.event.delete.addElement('redirect')
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
201 # redirect['uri'] = redirectURI
b96a4ac25f8b privilege: added methods to send privileged messages and notifications
Goffi <goffi@goffi.org>
parents: 286
diff changeset
202 # self.send(message)
338
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
203
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
204
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
205 ## presence ##
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
206
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
207 @defer.inlineCallbacks
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
208 def onPresence(self, presence_elt):
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
209 if self.server is None:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
210 # FIXME: we use a hack supposing that our delegation come from hostname
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
211 # and we are a component named [name].hostname
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
212 # but we need to manage properly allowed servers
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
213 # TODO: do proper origin security check
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
214 _, self.server = presence_elt['to'].split('.', 1)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
215 from_jid = jid.JID(presence_elt['from'])
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
216 from_jid_bare = from_jid.userhostJID()
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
217 if from_jid.host == self.server and from_jid_bare not in self.roster_cache:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
218 roster = yield self.getRoster(from_jid_bare)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
219 timestamp = time.time()
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
220 self.roster_cache[from_jid_bare] = {'timestamp': timestamp,
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
221 'roster': roster,
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
222 }
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
223 for roster_jid, roster_item in roster.iteritems():
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
224 if roster_item.subscriptionFrom:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
225 self.presence_map.setdefault(roster_jid, set()).add(from_jid_bare)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
226
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
227 presence_type = presence_elt.getAttribute('type')
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
228 if presence_type != "unavailable":
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
229 # new resource available, we check entity capabilities
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
230 try:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
231 c_elt = next(presence_elt.elements('http://jabber.org/protocol/caps', 'c'))
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
232 hash_ = c_elt['hash']
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
233 ver = c_elt['ver']
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
234 except (StopIteration, KeyError):
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
235 # no capabilities, we don't go further
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
236 return
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
237
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
238 # FIXME: hash is not checked (cf. XEP-0115)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
239 disco_tuple = (hash_, ver)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
240 if from_jid not in self.caps_map:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
241 self.caps_map[from_jid] = disco_tuple
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
242
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
243 if disco_tuple not in self.hash_map:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
244 # first time we se this hash, what is behind it?
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
245 infos = yield self.requestInfo(from_jid)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
246 self.hash_map[disco_tuple] = {
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
247 'notify': {f[:-7] for f in infos.features if f.endswith('+notify')},
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
248 'infos': infos
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
249 }
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 # nodes are the nodes subscribed with +notify
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
252 nodes = tuple(self.hash_map[disco_tuple]['notify'])
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
253 if not nodes:
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
254 return
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
255 # publishers are entities which have granted presence access to our user + user itself
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
256 publishers = self.presence_map.get(from_jid_bare, ()) + (from_jid_bare,)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
257
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
258 last_items = yield self._backend.storage.getLastItems(publishers, nodes, ('open',), ('open',), True)
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
259 # we send message with last item, as required by https://xmpp.org/extensions/xep-0163.html#notify-last
6d059f07c2d3 privilege: added presence and +notify initial support:
Goffi <goffi@goffi.org>
parents: 321
diff changeset
260 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
261 self.notifyPublish(pep_jid, node, [(from_jid, None, [item])])