Mercurial > libervia-pubsub
annotate src/pgsql_storage.py @ 398:845ed0f71dd6
mam: don't crash on missing <first> element in RSM on archive request
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 11 Mar 2019 20:50:54 +0100 |
parents | 728b08c0d000 |
children | 724e39d596a9 |
rev | line source |
---|---|
233 | 1 #!/usr/bin/python |
2 #-*- coding: utf-8 -*- | |
3 | |
384 | 4 # Copyright (c) 2012-2019 Jérôme Poisson |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
5 # Copyright (c) 2013-2016 Adrien Cossa |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
6 # Copyright (c) 2003-2011 Ralph Meijer |
233 | 7 |
8 | |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
9 # 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:
311
diff
changeset
|
10 # 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:
311
diff
changeset
|
11 # 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:
311
diff
changeset
|
12 # (at your option) any later version. |
233 | 13 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
14 # 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:
311
diff
changeset
|
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
17 # GNU Affero General Public License for more details. |
233 | 18 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
19 # 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:
311
diff
changeset
|
20 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
21 # -- |
233 | 22 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
23 # This program is based on Idavoll (http://idavoll.ik.nu/), |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
24 # originaly written by Ralph Meijer (http://ralphm.net/blog/) |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
25 # It is sublicensed under AGPL v3 (or any later version) as allowed by the original |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
26 # license. |
233 | 27 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
28 # -- |
233 | 29 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
30 # Here is a copy of the original license: |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
31 |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
32 # Copyright (c) 2003-2011 Ralph Meijer |
233 | 33 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
34 # Permission is hereby granted, free of charge, to any person obtaining |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
35 # a copy of this software and associated documentation files (the |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
36 # "Software"), to deal in the Software without restriction, including |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
37 # without limitation the rights to use, copy, modify, merge, publish, |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
38 # distribute, sublicense, and/or sell copies of the Software, and to |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
39 # permit persons to whom the Software is furnished to do so, subject to |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
40 # the following conditions: |
233 | 41 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
42 # The above copyright notice and this permission notice shall be |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
43 # included in all copies or substantial portions of the Software. |
233 | 44 |
312
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
45 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
46 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
47 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
48 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
49 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
50 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
5d7c3787672e
fixed copyright put in docstring instead of comments
Goffi <goffi@goffi.org>
parents:
311
diff
changeset
|
51 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
233 | 52 |
155
5191ba7c4df8
Work towards first release 0.5.0.
Ralph Meijer <ralphm@ik.nu>
parents:
148
diff
changeset
|
53 |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
54 import copy, logging |
202
77c61e2b8c75
Use `domish.Element`s to represent items, instead of serialized XML.
Ralph Meijer <ralphm@ik.nu>
parents:
198
diff
changeset
|
55 |
77c61e2b8c75
Use `domish.Element`s to represent items, instead of serialized XML.
Ralph Meijer <ralphm@ik.nu>
parents:
198
diff
changeset
|
56 from zope.interface import implements |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
57 |
344
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
58 from twisted.internet import reactor |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
59 from twisted.internet import defer |
107 | 60 from twisted.words.protocols.jabber import jid |
323 | 61 from twisted.python import log |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
62 |
271
232002e132db
pgsql_backend unicode fix: parseXml was expecting str and getting unicode
Goffi <goffi@goffi.org>
parents:
270
diff
changeset
|
63 from wokkel import generic |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
64 from wokkel.pubsub import Subscription |
107 | 65 |
317
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
66 from sat_pubsub import error |
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
67 from sat_pubsub import iidavoll |
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
68 from sat_pubsub import const |
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
69 from sat_pubsub import container |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
70 from sat_pubsub import exceptions |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
71 import uuid |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
72 import psycopg2 |
270
f17034e4cf4a
fixed unicode handling with psycopg2
Goffi <goffi@goffi.org>
parents:
265
diff
changeset
|
73 import psycopg2.extensions |
271
232002e132db
pgsql_backend unicode fix: parseXml was expecting str and getting unicode
Goffi <goffi@goffi.org>
parents:
270
diff
changeset
|
74 # we wants psycopg2 to return us unicode, not str |
270
f17034e4cf4a
fixed unicode handling with psycopg2
Goffi <goffi@goffi.org>
parents:
265
diff
changeset
|
75 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) |
f17034e4cf4a
fixed unicode handling with psycopg2
Goffi <goffi@goffi.org>
parents:
265
diff
changeset
|
76 psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY) |
244 | 77 |
271
232002e132db
pgsql_backend unicode fix: parseXml was expecting str and getting unicode
Goffi <goffi@goffi.org>
parents:
270
diff
changeset
|
78 # parseXml manage str, but we get unicode |
232002e132db
pgsql_backend unicode fix: parseXml was expecting str and getting unicode
Goffi <goffi@goffi.org>
parents:
270
diff
changeset
|
79 parseXml = lambda unicode_data: generic.parseXml(unicode_data.encode('utf-8')) |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
80 ITEMS_SEQ_NAME = u'node_{node_id}_seq' |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
81 PEP_COL_NAME = 'pep' |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
82 CURRENT_VERSION = '4' |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
83 # retrieve the maximum integer item id + 1 |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
84 NEXT_ITEM_ID_QUERY = r"SELECT COALESCE(max(item::integer)+1,1) as val from items where node_id={node_id} and item ~ E'^\\d+$'" |
271
232002e132db
pgsql_backend unicode fix: parseXml was expecting str and getting unicode
Goffi <goffi@goffi.org>
parents:
270
diff
changeset
|
85 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
86 |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
87 def withPEP(query, values, pep, recipient): |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
88 """Helper method to facilitate PEP management |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
89 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
90 @param query: SQL query basis |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
91 @param values: current values to replace in query |
364
8bd8be6815ab
completed docstrings + use short notation for sets
Arnaud Joset <info@agayon.be>
parents:
357
diff
changeset
|
92 @param pep(bool): True if we are in PEP mode |
8bd8be6815ab
completed docstrings + use short notation for sets
Arnaud Joset <info@agayon.be>
parents:
357
diff
changeset
|
93 @param recipient(jid.JID): jid of the recipient |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
94 @return: query + PEP AND check, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
95 recipient's bare jid is added to value if needed |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
96 """ |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
97 if pep: |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
98 pep_check="AND {}=%s".format(PEP_COL_NAME) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
99 values=list(values) + [recipient.userhost()] |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
100 else: |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
101 pep_check="AND {} IS NULL".format(PEP_COL_NAME) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
102 return "{} {}".format(query, pep_check), values |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
103 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
104 |
107 | 105 class Storage: |
106 | |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
107 implements(iidavoll.IStorage) |
107 | 108 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
109 defaultConfig = { |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
110 'leaf': { |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
111 const.OPT_PERSIST_ITEMS: True, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
112 const.OPT_DELIVER_PAYLOADS: True, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
113 const.OPT_SEND_LAST_PUBLISHED_ITEM: 'on_sub', |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
114 const.OPT_ACCESS_MODEL: const.VAL_AMODEL_DEFAULT, |
260 | 115 const.OPT_PUBLISH_MODEL: const.VAL_PMODEL_DEFAULT, |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
116 const.OPT_SERIAL_IDS: False, |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
117 }, |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
118 'collection': { |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
119 const.OPT_DELIVER_PAYLOADS: True, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
120 const.OPT_SEND_LAST_PUBLISHED_ITEM: 'on_sub', |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
121 const.OPT_ACCESS_MODEL: const.VAL_AMODEL_DEFAULT, |
260 | 122 const.OPT_PUBLISH_MODEL: const.VAL_PMODEL_DEFAULT, |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
123 } |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
124 } |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
125 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
126 def __init__(self, dbpool): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
127 self.dbpool = dbpool |
344
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
128 d = self.dbpool.runQuery("SELECT value FROM metadata WHERE key='version'") |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
129 d.addCallbacks(self._checkVersion, self._versionEb) |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
130 |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
131 def _checkVersion(self, row): |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
132 version = row[0].value |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
133 if version != CURRENT_VERSION: |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
134 logging.error("Bad database schema version ({current}), please upgrade to {needed}".format( |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
135 current=version, needed=CURRENT_VERSION)) |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
136 reactor.stop() |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
137 |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
138 def _versionEb(self, failure): |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
139 logging.error("Can't check schema version: {reason}".format(reason=failure)) |
8cf1be9572f8
pgsql: check schema version and exit with a message asking to upgrade if it's not the current one
Goffi <goffi@goffi.org>
parents:
341
diff
changeset
|
140 reactor.stop() |
107 | 141 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
142 def _buildNode(self, row): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
143 """Build a note class from database result row""" |
107 | 144 configuration = {} |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
145 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
146 if not row: |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
147 raise error.NodeNotFound() |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
148 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
149 if row[2] == 'leaf': |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
150 configuration = { |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
151 'pubsub#persist_items': row[3], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
152 'pubsub#deliver_payloads': row[4], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
153 'pubsub#send_last_published_item': row[5], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
154 const.OPT_ACCESS_MODEL:row[6], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
155 const.OPT_PUBLISH_MODEL:row[7], |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
156 const.OPT_SERIAL_IDS:row[8], |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
157 } |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
158 schema = row[9] |
352 | 159 if schema is not None: |
160 schema = parseXml(schema) | |
161 node = LeafNode(row[0], row[1], configuration, schema) | |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
162 node.dbpool = self.dbpool |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
163 return node |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
164 elif row[2] == 'collection': |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
165 configuration = { |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
166 'pubsub#deliver_payloads': row[4], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
167 'pubsub#send_last_published_item': row[5], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
168 const.OPT_ACCESS_MODEL: row[6], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
169 const.OPT_PUBLISH_MODEL:row[7], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
170 } |
352 | 171 node = CollectionNode(row[0], row[1], configuration, None) |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
172 node.dbpool = self.dbpool |
107 | 173 return node |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
174 else: |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
175 raise ValueError("Unknown node type !") |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
176 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
177 def getNodeById(self, nodeDbId): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
178 """Get node using database ID insted of pubsub identifier |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
179 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
180 @param nodeDbId(unicode): database ID |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
181 """ |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
182 return self.dbpool.runInteraction(self._getNodeById, nodeDbId) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
183 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
184 def _getNodeById(self, cursor, nodeDbId): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
185 cursor.execute("""SELECT node_id, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
186 node, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
187 node_type, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
188 persist_items, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
189 deliver_payloads, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
190 send_last_published_item, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
191 access_model, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
192 publish_model, |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
193 serial_ids, |
352 | 194 schema::text, |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
195 pep |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
196 FROM nodes |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
197 WHERE node_id=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
198 (nodeDbId,)) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
199 row = cursor.fetchone() |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
200 return self._buildNode(row) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
201 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
202 def getNode(self, nodeIdentifier, pep, recipient=None): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
203 return self.dbpool.runInteraction(self._getNode, nodeIdentifier, pep, recipient) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
204 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
205 def _getNode(self, cursor, nodeIdentifier, pep, recipient): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
206 cursor.execute(*withPEP("""SELECT node_id, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
207 node, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
208 node_type, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
209 persist_items, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
210 deliver_payloads, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
211 send_last_published_item, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
212 access_model, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
213 publish_model, |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
214 serial_ids, |
352 | 215 schema::text, |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
216 pep |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
217 FROM nodes |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
218 WHERE node=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
219 (nodeIdentifier,), pep, recipient)) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
220 row = cursor.fetchone() |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
221 return self._buildNode(row) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
222 |
349
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
223 def getNodeIds(self, pep, recipient, allowed_accesses=None): |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
224 """retrieve ids of existing nodes |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
225 |
364
8bd8be6815ab
completed docstrings + use short notation for sets
Arnaud Joset <info@agayon.be>
parents:
357
diff
changeset
|
226 @param pep(bool): True if it's a PEP request |
8bd8be6815ab
completed docstrings + use short notation for sets
Arnaud Joset <info@agayon.be>
parents:
357
diff
changeset
|
227 @param recipient(jid.JID, None): recipient of the PEP request |
349
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
228 @param allowed_accesses(None, set): only nodes with access |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
229 in this set will be returned |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
230 None to return all nodes |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
231 @return (list[unicode]): ids of nodes |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
232 """ |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
233 if not pep: |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
234 query = "SELECT node from nodes WHERE pep is NULL" |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
235 values = [] |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
236 else: |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
237 query = "SELECT node from nodes WHERE pep=%s" |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
238 values = [recipient.userhost()] |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
239 |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
240 if allowed_accesses is not None: |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
241 query += "AND access_model IN %s" |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
242 values.append(tuple(allowed_accesses)) |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
243 |
20b82fb8de02
backend: check nodes/items permission on disco#items:
Goffi <goffi@goffi.org>
parents:
347
diff
changeset
|
244 d = self.dbpool.runQuery(query, values) |
107 | 245 d.addCallback(lambda results: [r[0] for r in results]) |
246 return d | |
247 | |
352 | 248 def createNode(self, nodeIdentifier, owner, config, schema, pep, recipient=None): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
249 return self.dbpool.runInteraction(self._createNode, nodeIdentifier, |
352 | 250 owner, config, schema, pep, recipient) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
251 |
352 | 252 def _createNode(self, cursor, nodeIdentifier, owner, config, schema, pep, recipient): |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
253 if config['pubsub#node_type'] != 'leaf': |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
254 raise error.NoCollections() |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
255 |
136
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
256 owner = owner.userhost() |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
257 |
107 | 258 try: |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
259 cursor.execute("""INSERT INTO nodes |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
260 (node, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
261 node_type, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
262 persist_items, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
263 deliver_payloads, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
264 send_last_published_item, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
265 access_model, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
266 publish_model, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
267 serial_ids, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
268 schema, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
269 pep) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
270 VALUES |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
271 (%s, 'leaf', %s, %s, %s, %s, %s, %s, %s, %s)""", |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
272 (nodeIdentifier, |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
273 config['pubsub#persist_items'], |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
274 config['pubsub#deliver_payloads'], |
240
70c8bb90d75f
added access_model to config, default to 'open'
Goffi <goffi@goffi.org>
parents:
235
diff
changeset
|
275 config['pubsub#send_last_published_item'], |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
276 config[const.OPT_ACCESS_MODEL], |
260 | 277 config[const.OPT_PUBLISH_MODEL], |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
278 config[const.OPT_SERIAL_IDS], |
352 | 279 schema, |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
280 recipient.userhost() if pep else None |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
281 ) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
282 ) |
332
31cbd8b9fa7f
pgsql: node creation now return error.NodeExists in case of unique violation, and InvalidConfigurationOption else
Goffi <goffi@goffi.org>
parents:
331
diff
changeset
|
283 except cursor._pool.dbapi.IntegrityError as e: |
31cbd8b9fa7f
pgsql: node creation now return error.NodeExists in case of unique violation, and InvalidConfigurationOption else
Goffi <goffi@goffi.org>
parents:
331
diff
changeset
|
284 if e.pgcode == "23505": |
31cbd8b9fa7f
pgsql: node creation now return error.NodeExists in case of unique violation, and InvalidConfigurationOption else
Goffi <goffi@goffi.org>
parents:
331
diff
changeset
|
285 # unique_violation |
31cbd8b9fa7f
pgsql: node creation now return error.NodeExists in case of unique violation, and InvalidConfigurationOption else
Goffi <goffi@goffi.org>
parents:
331
diff
changeset
|
286 raise error.NodeExists() |
31cbd8b9fa7f
pgsql: node creation now return error.NodeExists in case of unique violation, and InvalidConfigurationOption else
Goffi <goffi@goffi.org>
parents:
331
diff
changeset
|
287 else: |
31cbd8b9fa7f
pgsql: node creation now return error.NodeExists in case of unique violation, and InvalidConfigurationOption else
Goffi <goffi@goffi.org>
parents:
331
diff
changeset
|
288 raise error.InvalidConfigurationOption() |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
289 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
290 cursor.execute(*withPEP("""SELECT node_id FROM nodes WHERE node=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
291 (nodeIdentifier,), pep, recipient)); |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
292 node_id = cursor.fetchone()[0] |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
293 |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
294 cursor.execute("""SELECT 1 as bool from entities where jid=%s""", |
227
8540825f85e0
Replaced unmaintained pyPgSQL by Psycopg 2
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
295 (owner,)) |
107 | 296 |
297 if not cursor.fetchone(): | |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
298 # XXX: we can NOT rely on the previous query! Commit is needed now because |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
299 # if the entry exists the next query will leave the database in a corrupted |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
300 # state: the solution is to rollback. I tried with other methods like |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
301 # "WHERE NOT EXISTS" but none of them worked, so the following solution |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
302 # looks like the sole - unless you have auto-commit on. More info |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
303 # about this issue: http://cssmay.com/question/tag/tag-psycopg2 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
304 cursor.connection.commit() |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
305 try: |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
306 cursor.execute("""INSERT INTO entities (jid) VALUES (%s)""", |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
307 (owner,)) |
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
308 except psycopg2.IntegrityError as e: |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
309 cursor.connection.rollback() |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
310 logging.warning("during node creation: %s" % e.message) |
107 | 311 |
312 cursor.execute("""INSERT INTO affiliations | |
313 (node_id, entity_id, affiliation) | |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
314 SELECT %s, entity_id, 'owner' FROM |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
315 (SELECT entity_id FROM entities |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
316 WHERE jid=%s) as e""", |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
317 (node_id, owner)) |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
318 |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
319 if config[const.OPT_ACCESS_MODEL] == const.VAL_AMODEL_PUBLISHER_ROSTER: |
259
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
320 if const.OPT_ROSTER_GROUPS_ALLOWED in config: |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
321 allowed_groups = config[const.OPT_ROSTER_GROUPS_ALLOWED] |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
322 else: |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
323 allowed_groups = [] |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
324 for group in allowed_groups: |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
325 #TODO: check that group are actually in roster |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
326 cursor.execute("""INSERT INTO node_groups_authorized (node_id, groupname) |
6fe7da6b4b32
node "roster" access model management
Goffi <goffi@goffi.org>
parents:
255
diff
changeset
|
327 VALUES (%s,%s)""" , (node_id, group)) |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
328 # XXX: affiliations can't be set on during node creation (at least not with XEP-0060 alone) |
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
329 # so whitelist affiliations need to be done afterward |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
330 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
331 # no we may have to do extra things according to config options |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
332 default_conf = self.defaultConfig['leaf'] |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
333 # XXX: trigger works on node creation because OPT_SERIAL_IDS is False in defaultConfig |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
334 # if this value is changed, the _configurationTriggers method should be adapted. |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
335 Node._configurationTriggers(cursor, node_id, default_conf, config) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
336 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
337 def deleteNodeByDbId(self, db_id): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
338 """Delete a node using directly its database id""" |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
339 return self.dbpool.runInteraction(self._deleteNodeByDbId, db_id) |
107 | 340 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
341 def _deleteNodeByDbId(self, cursor, db_id): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
342 cursor.execute("""DELETE FROM nodes WHERE node_id=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
343 (db_id,)) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
344 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
345 if cursor.rowcount != 1: |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
346 raise error.NodeNotFound() |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
347 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
348 def deleteNode(self, nodeIdentifier, pep, recipient=None): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
349 return self.dbpool.runInteraction(self._deleteNode, nodeIdentifier, pep, recipient) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
350 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
351 def _deleteNode(self, cursor, nodeIdentifier, pep, recipient): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
352 cursor.execute(*withPEP("""DELETE FROM nodes WHERE node=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
353 (nodeIdentifier,), pep, recipient)) |
107 | 354 |
355 if cursor.rowcount != 1: | |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
356 raise error.NodeNotFound() |
107 | 357 |
331 | 358 def getAffiliations(self, entity, nodeIdentifier, pep, recipient=None): |
359 return self.dbpool.runInteraction(self._getAffiliations, entity, nodeIdentifier, pep, recipient) | |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
360 |
331 | 361 def _getAffiliations(self, cursor, entity, nodeIdentifier, pep, recipient=None): |
362 query = ["""SELECT node, affiliation FROM entities | |
363 NATURAL JOIN affiliations | |
364 NATURAL JOIN nodes | |
365 WHERE jid=%s"""] | |
366 args = [entity.userhost()] | |
367 | |
368 if nodeIdentifier is not None: | |
369 query.append("AND node=%s") | |
370 args.append(nodeIdentifier) | |
371 | |
372 cursor.execute(*withPEP(' '.join(query), args, pep, recipient)) | |
373 rows = cursor.fetchall() | |
374 return [tuple(r) for r in rows] | |
107 | 375 |
357
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
376 def getSubscriptions(self, entity, nodeIdentifier=None, pep=False, recipient=None): |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
377 """retrieve subscriptions of an entity |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
378 |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
379 @param entity(jid.JID): entity to check |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
380 @param nodeIdentifier(unicode, None): node identifier |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
381 None to retrieve all subscriptions |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
382 @param pep: True if we are in PEP mode |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
383 @param recipient: jid of the recipient |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
384 """ |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
385 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
386 def toSubscriptions(rows): |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
387 subscriptions = [] |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
388 for row in rows: |
357
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
389 subscriber = jid.internJID('%s/%s' % (row.jid, |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
390 row.resource)) |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
391 subscription = Subscription(row.node, subscriber, row.state) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
392 subscriptions.append(subscription) |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
393 return subscriptions |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
394 |
357
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
395 query = ["""SELECT node, |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
396 jid, |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
397 resource, |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
398 state |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
399 FROM entities |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
400 NATURAL JOIN subscriptions |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
401 NATURAL JOIN nodes |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
402 WHERE jid=%s"""] |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
403 |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
404 args = [entity.userhost()] |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
405 |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
406 if nodeIdentifier is not None: |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
407 query.append("AND node=%s") |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
408 args.append(nodeIdentifier) |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
409 |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
410 d = self.dbpool.runQuery(*withPEP(' '.join(query), args, pep, recipient)) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
411 d.addCallback(toSubscriptions) |
107 | 412 return d |
413 | |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
414 def getDefaultConfiguration(self, nodeType): |
366
81e6d4a516c3
storage (pgsql): getDefaultConfiguration now returns a shallow copy of default conf dict, to avoid modification.
Goffi <goffi@goffi.org>
parents:
365
diff
changeset
|
415 return self.defaultConfig[nodeType].copy() |
107 | 416 |
337
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
417 def formatLastItems(self, result): |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
418 last_items = [] |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
419 for pep_jid_s, node, data, item_access_model in result: |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
420 pep_jid = jid.JID(pep_jid_s) |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
421 item = generic.stripNamespace(parseXml(data)) |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
422 last_items.append((pep_jid, node, item, item_access_model)) |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
423 return last_items |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
424 |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
425 def getLastItems(self, entities, nodes, node_accesses, item_accesses, pep): |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
426 """get last item for several nodes and entities in a single request""" |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
427 if not entities or not nodes or not node_accesses or not item_accesses: |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
428 raise ValueError("entities, nodes and accesses must not be empty") |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
429 if node_accesses != ('open',) or item_accesses != ('open',): |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
430 raise NotImplementedError('only "open" access model is handled for now') |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
431 if not pep: |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
432 raise NotImplementedError(u"getLastItems is only implemented for PEP at the moment") |
351
2098295747fd
pgsql: cast items.data to text when needed + db schema version bump.
Goffi <goffi@goffi.org>
parents:
349
diff
changeset
|
433 d = self.dbpool.runQuery("""SELECT DISTINCT ON (node_id) pep, node, data::text, items.access_model |
337
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
434 FROM items |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
435 NATURAL JOIN nodes |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
436 WHERE nodes.pep IN %s |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
437 AND node IN %s |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
438 AND nodes.access_model in %s |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
439 AND items.access_model in %s |
374 | 440 ORDER BY node_id DESC, items.updated DESC""", |
337
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
441 (tuple([e.userhost() for e in entities]), |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
442 nodes, |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
443 node_accesses, |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
444 item_accesses)) |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
445 d.addCallback(self.formatLastItems) |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
446 return d |
57a3051ee435
storage (pgsql): added getLastItems method, to get last items from a series of nodes and entities (needed for PEP compliance).
Goffi <goffi@goffi.org>
parents:
332
diff
changeset
|
447 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
448 |
107 | 449 class Node: |
450 | |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
451 implements(iidavoll.INode) |
107 | 452 |
352 | 453 def __init__(self, nodeDbId, nodeIdentifier, config, schema): |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
454 self.nodeDbId = nodeDbId |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
455 self.nodeIdentifier = nodeIdentifier |
107 | 456 self._config = config |
352 | 457 self._schema = schema |
107 | 458 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
459 def _checkNodeExists(self, cursor): |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
460 cursor.execute("""SELECT 1 as exist FROM nodes WHERE node_id=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
461 (self.nodeDbId,)) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
462 if not cursor.fetchone(): |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
463 raise error.NodeNotFound() |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
464 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
465 def getType(self): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
466 return self.nodeType |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
467 |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
468 def getOwners(self): |
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
469 d = self.dbpool.runQuery("""SELECT jid FROM nodes NATURAL JOIN affiliations NATURAL JOIN entities WHERE node_id=%s and affiliation='owner'""", (self.nodeDbId,)) |
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
470 d.addCallback(lambda rows: [jid.JID(r[0]) for r in rows]) |
243
42048e37699e
added experimental roster access_model (use remote_roster)
Goffi <goffi@goffi.org>
parents:
240
diff
changeset
|
471 return d |
42048e37699e
added experimental roster access_model (use remote_roster)
Goffi <goffi@goffi.org>
parents:
240
diff
changeset
|
472 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
473 def getConfiguration(self): |
107 | 474 return self._config |
475 | |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
476 def getNextId(self): |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
477 """return XMPP item id usable for next item to publish |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
478 |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
479 the return value will be next int if serila_ids is set, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
480 else an UUID will be returned |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
481 """ |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
482 if self._config[const.OPT_SERIAL_IDS]: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
483 d = self.dbpool.runQuery("SELECT nextval('{seq_name}')".format( |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
484 seq_name = ITEMS_SEQ_NAME.format(node_id=self.nodeDbId))) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
485 d.addCallback(lambda rows: unicode(rows[0][0])) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
486 return d |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
487 else: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
488 return defer.succeed(unicode(uuid.uuid4())) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
489 |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
490 @staticmethod |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
491 def _configurationTriggers(cursor, node_id, old_config, new_config): |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
492 """trigger database relative actions needed when a config is changed |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
493 |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
494 @param cursor(): current db cursor |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
495 @param node_id(unicode): database ID of the node |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
496 @param old_config(dict): config of the node before the change |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
497 @param new_config(dict): new options that will be changed |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
498 """ |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
499 serial_ids = new_config[const.OPT_SERIAL_IDS] |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
500 if serial_ids != old_config[const.OPT_SERIAL_IDS]: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
501 # serial_ids option has been modified, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
502 # we need to handle corresponding sequence |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
503 |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
504 # XXX: we use .format in following queries because values |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
505 # are generated by ourself |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
506 seq_name = ITEMS_SEQ_NAME.format(node_id=node_id) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
507 if serial_ids: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
508 # the next query get the max value +1 of all XMPP items ids |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
509 # which are integers, and default to 1 |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
510 cursor.execute(NEXT_ITEM_ID_QUERY.format(node_id=node_id)) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
511 next_val = cursor.fetchone()[0] |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
512 cursor.execute("DROP SEQUENCE IF EXISTS {seq_name}".format(seq_name = seq_name)) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
513 cursor.execute("CREATE SEQUENCE {seq_name} START {next_val} OWNED BY nodes.node_id".format( |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
514 seq_name = seq_name, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
515 next_val = next_val)) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
516 else: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
517 cursor.execute("DROP SEQUENCE IF EXISTS {seq_name}".format(seq_name = seq_name)) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
518 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
519 def setConfiguration(self, options): |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
520 config = copy.copy(self._config) |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
521 |
107 | 522 for option in options: |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
523 if option in config: |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
524 config[option] = options[option] |
180
fc687620599b
Properly add send_last_published_item configuration item.
Ralph Meijer <ralphm@ik.nu>
parents:
173
diff
changeset
|
525 |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
526 d = self.dbpool.runInteraction(self._setConfiguration, config) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
527 d.addCallback(self._setCachedConfiguration, config) |
124
c4ee16bc48e5
Change Node.set_configuration() to set cached configuration in a callback.
Ralph Meijer <ralphm@ik.nu>
parents:
121
diff
changeset
|
528 return d |
c4ee16bc48e5
Change Node.set_configuration() to set cached configuration in a callback.
Ralph Meijer <ralphm@ik.nu>
parents:
121
diff
changeset
|
529 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
530 def _setConfiguration(self, cursor, config): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
531 self._checkNodeExists(cursor) |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
532 self._configurationTriggers(cursor, self.nodeDbId, self._config, config) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
533 cursor.execute("""UPDATE nodes SET persist_items=%s, |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
534 deliver_payloads=%s, |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
535 send_last_published_item=%s, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
536 access_model=%s, |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
537 publish_model=%s, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
538 serial_ids=%s |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
539 WHERE node_id=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
540 (config[const.OPT_PERSIST_ITEMS], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
541 config[const.OPT_DELIVER_PAYLOADS], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
542 config[const.OPT_SEND_LAST_PUBLISHED_ITEM], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
543 config[const.OPT_ACCESS_MODEL], |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
544 config[const.OPT_PUBLISH_MODEL], |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
545 config[const.OPT_SERIAL_IDS], |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
546 self.nodeDbId)) |
107 | 547 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
548 def _setCachedConfiguration(self, void, config): |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
549 self._config = config |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
550 |
352 | 551 def getSchema(self): |
552 return self._schema | |
553 | |
554 def setSchema(self, schema): | |
555 d = self.dbpool.runInteraction(self._setSchema, schema) | |
556 d.addCallback(self._setCachedSchema, schema) | |
557 return d | |
558 | |
559 def _setSchema(self, cursor, schema): | |
560 self._checkNodeExists(cursor) | |
561 cursor.execute("""UPDATE nodes SET schema=%s | |
562 WHERE node_id=%s""", | |
563 (schema.toXml() if schema else None, | |
564 self.nodeDbId)) | |
565 | |
566 def _setCachedSchema(self, void, schema): | |
567 self._schema = schema | |
568 | |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
569 def getMetaData(self): |
107 | 570 config = copy.copy(self._config) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
571 config["pubsub#node_type"] = self.nodeType |
107 | 572 return config |
573 | |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
574 def getAffiliation(self, entity): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
575 return self.dbpool.runInteraction(self._getAffiliation, entity) |
107 | 576 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
577 def _getAffiliation(self, cursor, entity): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
578 self._checkNodeExists(cursor) |
107 | 579 cursor.execute("""SELECT affiliation FROM affiliations |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
580 NATURAL JOIN nodes |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
581 NATURAL JOIN entities |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
582 WHERE node_id=%s AND jid=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
583 (self.nodeDbId, |
136
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
584 entity.userhost())) |
107 | 585 |
586 try: | |
587 return cursor.fetchone()[0] | |
588 except TypeError: | |
589 return None | |
590 | |
240
70c8bb90d75f
added access_model to config, default to 'open'
Goffi <goffi@goffi.org>
parents:
235
diff
changeset
|
591 def getAccessModel(self): |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
592 return self._config[const.OPT_ACCESS_MODEL] |
240
70c8bb90d75f
added access_model to config, default to 'open'
Goffi <goffi@goffi.org>
parents:
235
diff
changeset
|
593 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
594 def getSubscription(self, subscriber): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
595 return self.dbpool.runInteraction(self._getSubscription, subscriber) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
596 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
597 def _getSubscription(self, cursor, subscriber): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
598 self._checkNodeExists(cursor) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
599 |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
600 userhost = subscriber.userhost() |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
601 resource = subscriber.resource or '' |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
602 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
603 cursor.execute("""SELECT state FROM subscriptions |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
604 NATURAL JOIN nodes |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
605 NATURAL JOIN entities |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
606 WHERE node_id=%s AND jid=%s AND resource=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
607 (self.nodeDbId, |
136
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
608 userhost, |
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
609 resource)) |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
610 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
611 row = cursor.fetchone() |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
612 if not row: |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
613 return None |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
614 else: |
227
8540825f85e0
Replaced unmaintained pyPgSQL by Psycopg 2
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
615 return Subscription(self.nodeIdentifier, subscriber, row[0]) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
616 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
617 def getSubscriptions(self, state=None): |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
618 return self.dbpool.runInteraction(self._getSubscriptions, state) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
619 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
620 def _getSubscriptions(self, cursor, state): |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
621 self._checkNodeExists(cursor) |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
622 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
623 query = """SELECT node, jid, resource, state, |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
624 subscription_type, subscription_depth |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
625 FROM subscriptions |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
626 NATURAL JOIN nodes |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
627 NATURAL JOIN entities |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
628 WHERE node_id=%s""" |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
629 values = [self.nodeDbId] |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
630 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
631 if state: |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
632 query += " AND state=%s" |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
633 values.append(state) |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
634 |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
635 cursor.execute(query, values) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
636 rows = cursor.fetchall() |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
637 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
638 subscriptions = [] |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
639 for row in rows: |
357
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
640 subscriber = jid.JID(u'%s/%s' % (row.jid, row.resource)) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
641 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
642 options = {} |
357
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
643 if row.subscription_type: |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
644 options['pubsub#subscription_type'] = row.subscription_type; |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
645 if row.subscription_depth: |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
646 options['pubsub#subscription_depth'] = row.subscription_depth; |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
647 |
357
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
648 subscriptions.append(Subscription(row.node, subscriber, |
1167e48e5f52
handle single node on subscriptions request
Goffi <goffi@goffi.org>
parents:
356
diff
changeset
|
649 row.state, options)) |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
650 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
651 return subscriptions |
107 | 652 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
653 def addSubscription(self, subscriber, state, config): |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
654 return self.dbpool.runInteraction(self._addSubscription, subscriber, |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
655 state, config) |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
656 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
657 def _addSubscription(self, cursor, subscriber, state, config): |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
658 self._checkNodeExists(cursor) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
659 |
107 | 660 userhost = subscriber.userhost() |
661 resource = subscriber.resource or '' | |
662 | |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
663 subscription_type = config.get('pubsub#subscription_type') |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
664 subscription_depth = config.get('pubsub#subscription_depth') |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
665 |
107 | 666 try: |
667 cursor.execute("""INSERT INTO entities (jid) VALUES (%s)""", | |
227
8540825f85e0
Replaced unmaintained pyPgSQL by Psycopg 2
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
668 (userhost,)) |
8540825f85e0
Replaced unmaintained pyPgSQL by Psycopg 2
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
669 except cursor._pool.dbapi.IntegrityError: |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
670 cursor.connection.rollback() |
107 | 671 |
672 try: | |
673 cursor.execute("""INSERT INTO subscriptions | |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
674 (node_id, entity_id, resource, state, |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
675 subscription_type, subscription_depth) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
676 SELECT %s, entity_id, %s, %s, %s, %s FROM |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
677 (SELECT entity_id FROM entities |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
678 WHERE jid=%s) AS ent_id""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
679 (self.nodeDbId, |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
680 resource, |
136
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
681 state, |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
682 subscription_type, |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
683 subscription_depth, |
136
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
684 userhost)) |
227
8540825f85e0
Replaced unmaintained pyPgSQL by Psycopg 2
Goffi <goffi@goffi.org>
parents:
206
diff
changeset
|
685 except cursor._pool.dbapi.IntegrityError: |
167
ef22e4150caa
Move protocol implementations (pubsub, disco, forms) to and depend on wokkel.
Ralph Meijer <ralphm@ik.nu>
parents:
163
diff
changeset
|
686 raise error.SubscriptionExists() |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
687 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
688 def removeSubscription(self, subscriber): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
689 return self.dbpool.runInteraction(self._removeSubscription, |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
690 subscriber) |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
691 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
692 def _removeSubscription(self, cursor, subscriber): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
693 self._checkNodeExists(cursor) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
694 |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
695 userhost = subscriber.userhost() |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
696 resource = subscriber.resource or '' |
107 | 697 |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
698 cursor.execute("""DELETE FROM subscriptions WHERE |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
699 node_id=%s AND |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
700 entity_id=(SELECT entity_id FROM entities |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
701 WHERE jid=%s) AND |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
702 resource=%s""", |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
703 (self.nodeDbId, |
136
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
704 userhost, |
327de183f48d
Discover client_encoding parameter to pyPgSQL, removing all encode() calls.
Ralph Meijer <ralphm@ik.nu>
parents:
127
diff
changeset
|
705 resource)) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
706 if cursor.rowcount != 1: |
171
bc269696ef42
Reply with the correct error condition on subscription when not subscribed.
Ralph Meijer <ralphm@ik.nu>
parents:
170
diff
changeset
|
707 raise error.NotSubscribed() |
107 | 708 |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
709 return None |
107 | 710 |
341
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
711 def setSubscriptions(self, subscriptions): |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
712 return self.dbpool.runInteraction(self._setSubscriptions, subscriptions) |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
713 |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
714 def _setSubscriptions(self, cursor, subscriptions): |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
715 self._checkNodeExists(cursor) |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
716 |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
717 entities = self.getOrCreateEntities(cursor, [s.subscriber for s in subscriptions]) |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
718 entities_map = {jid.JID(e.jid): e for e in entities} |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
719 |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
720 # then we construct values for subscriptions update according to entity_id we just got |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
721 placeholders = ','.join(len(subscriptions) * ["%s"]) |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
722 values = [] |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
723 for subscription in subscriptions: |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
724 entity_id = entities_map[subscription.subscriber].entity_id |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
725 resource = subscription.subscriber.resource or u'' |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
726 values.append((self.nodeDbId, entity_id, resource, subscription.state, None, None)) |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
727 # we use upsert so new values are inserted and existing one updated. This feature is only available for PostgreSQL >= 9.5 |
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
728 cursor.execute("INSERT INTO subscriptions(node_id, entity_id, resource, state, subscription_type, subscription_depth) VALUES " + placeholders + " ON CONFLICT (entity_id, resource, node_id) DO UPDATE SET state=EXCLUDED.state", [v for v in values]) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
729 |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
730 def isSubscribed(self, entity): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
731 return self.dbpool.runInteraction(self._isSubscribed, entity) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
732 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
733 def _isSubscribed(self, cursor, entity): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
734 self._checkNodeExists(cursor) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
735 |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
736 cursor.execute("""SELECT 1 as bool FROM entities |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
737 NATURAL JOIN subscriptions |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
738 NATURAL JOIN nodes |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
739 WHERE entities.jid=%s |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
740 AND node_id=%s AND state='subscribed'""", |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
741 (entity.userhost(), |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
742 self.nodeDbId)) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
743 |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
744 return cursor.fetchone() is not None |
107 | 745 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
746 def getAffiliations(self): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
747 return self.dbpool.runInteraction(self._getAffiliations) |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
748 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
749 def _getAffiliations(self, cursor): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
750 self._checkNodeExists(cursor) |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
751 |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
752 cursor.execute("""SELECT jid, affiliation FROM nodes |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
753 NATURAL JOIN affiliations |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
754 NATURAL JOIN entities |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
755 WHERE node_id=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
756 (self.nodeDbId,)) |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
757 result = cursor.fetchall() |
180
fc687620599b
Properly add send_last_published_item configuration item.
Ralph Meijer <ralphm@ik.nu>
parents:
173
diff
changeset
|
758 |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
759 return {jid.internJID(r[0]): r[1] for r in result} |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
760 |
331 | 761 def getOrCreateEntities(self, cursor, entities_jids): |
762 """Get entity_id from entities in entities table | |
763 | |
764 Entities will be inserted it they don't exist | |
765 @param entities_jid(list[jid.JID]): entities to get or create | |
341
b49f75a26156
backend, pgsql: implemented subscriptionsGet and subscriptionsSet
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
766 @return list[record(entity_id,jid)]]: list of entity_id and jid (as plain string) |
331 | 767 both existing and inserted entities are returned |
768 """ | |
769 # cf. http://stackoverflow.com/a/35265559 | |
770 placeholders = ','.join(len(entities_jids) * ["(%s)"]) | |
771 query = ( | |
772 """ | |
773 WITH | |
774 jid_values (jid) AS ( | |
775 VALUES {placeholders} | |
776 ), | |
777 inserted (entity_id, jid) AS ( | |
778 INSERT INTO entities (jid) | |
779 SELECT jid | |
780 FROM jid_values | |
781 ON CONFLICT DO NOTHING | |
782 RETURNING entity_id, jid | |
783 ) | |
784 SELECT e.entity_id, e.jid | |
785 FROM entities e JOIN jid_values jv ON jv.jid = e.jid | |
786 UNION ALL | |
787 SELECT entity_id, jid | |
788 FROM inserted""".format(placeholders=placeholders)) | |
789 cursor.execute(query, [j.userhost() for j in entities_jids]) | |
790 return cursor.fetchall() | |
791 | |
792 def setAffiliations(self, affiliations): | |
793 return self.dbpool.runInteraction(self._setAffiliations, affiliations) | |
794 | |
795 def _setAffiliations(self, cursor, affiliations): | |
796 self._checkNodeExists(cursor) | |
797 | |
798 entities = self.getOrCreateEntities(cursor, affiliations) | |
799 | |
800 # then we construct values for affiliations update according to entity_id we just got | |
801 placeholders = ','.join(len(affiliations) * ["(%s,%s,%s)"]) | |
802 values = [] | |
803 map(values.extend, ((e.entity_id, affiliations[jid.JID(e.jid)], self.nodeDbId) for e in entities)) | |
804 | |
805 # we use upsert so new values are inserted and existing one updated. This feature is only available for PostgreSQL >= 9.5 | |
806 cursor.execute("INSERT INTO affiliations(entity_id,affiliation,node_id) VALUES " + placeholders + " ON CONFLICT (entity_id,node_id) DO UPDATE SET affiliation=EXCLUDED.affiliation", values) | |
807 | |
808 def deleteAffiliations(self, entities): | |
809 return self.dbpool.runInteraction(self._deleteAffiliations, entities) | |
810 | |
811 def _deleteAffiliations(self, cursor, entities): | |
812 """delete affiliations and subscriptions for this entity""" | |
813 self._checkNodeExists(cursor) | |
814 placeholders = ','.join(len(entities) * ["%s"]) | |
815 cursor.execute("DELETE FROM affiliations WHERE node_id=%s AND entity_id in (SELECT entity_id FROM entities WHERE jid IN (" + placeholders + ")) RETURNING entity_id", [self.nodeDbId] + [e.userhost() for e in entities]) | |
816 | |
817 rows = cursor.fetchall() | |
818 placeholders = ','.join(len(rows) * ["%s"]) | |
819 cursor.execute("DELETE FROM subscriptions WHERE node_id=%s AND entity_id in (" + placeholders + ")", [self.nodeDbId] + [r[0] for r in rows]) | |
820 | |
821 def getAuthorizedGroups(self): | |
822 return self.dbpool.runInteraction(self._getNodeGroups) | |
823 | |
824 def _getAuthorizedGroups(self, cursor): | |
825 cursor.execute("SELECT groupname FROM node_groups_authorized NATURAL JOIN nodes WHERE node=%s", | |
826 (self.nodeDbId,)) | |
827 rows = cursor.fetchall() | |
828 return [row[0] for row in rows] | |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
829 |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
830 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
831 class LeafNode(Node): |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
832 |
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
833 implements(iidavoll.ILeafNode) |
107 | 834 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
835 nodeType = 'leaf' |
107 | 836 |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
837 def getOrderBy(self, ext_data, direction='DESC'): |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
838 """Return ORDER BY clause corresponding to Order By key in ext_data |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
839 |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
840 @param ext_data (dict): extra data as used in getItems |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
841 @param direction (unicode): ORDER BY direction (ASC or DESC) |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
842 @return (unicode): ORDER BY clause to use |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
843 """ |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
844 keys = ext_data.get('order_by') |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
845 if not keys: |
378
22832c1d2827
storage (pgsql): don't specify table name in ORDER BY clause as it can cause troubles in some requests.
Goffi <goffi@goffi.org>
parents:
375
diff
changeset
|
846 return u'ORDER BY updated ' + direction |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
847 cols_statmnt = [] |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
848 for key in keys: |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
849 if key == 'creation': |
378
22832c1d2827
storage (pgsql): don't specify table name in ORDER BY clause as it can cause troubles in some requests.
Goffi <goffi@goffi.org>
parents:
375
diff
changeset
|
850 column = 'item_id' # could work with items.created too |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
851 elif key == 'modification': |
378
22832c1d2827
storage (pgsql): don't specify table name in ORDER BY clause as it can cause troubles in some requests.
Goffi <goffi@goffi.org>
parents:
375
diff
changeset
|
852 column = 'updated' |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
853 else: |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
854 log.msg(u"WARNING: Unknown order by key: {key}".format(key=key)) |
378
22832c1d2827
storage (pgsql): don't specify table name in ORDER BY clause as it can cause troubles in some requests.
Goffi <goffi@goffi.org>
parents:
375
diff
changeset
|
855 column = 'updated' |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
856 cols_statmnt.append(column + u' ' + direction) |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
857 |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
858 return u"ORDER BY " + u",".join([col for col in cols_statmnt]) |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
859 |
393
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
860 @defer.inlineCallbacks |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
861 def storeItems(self, items_data, publisher): |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
862 # XXX: runInteraction doesn't seem to work when there are several "insert" |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
863 # or "update". |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
864 # Before the unpacking was done in _storeItems, but this was causing trouble |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
865 # in case of multiple items_data. So this has now be moved here. |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
866 # FIXME: investigate the issue with runInteraction |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
867 for item_data in items_data: |
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
868 yield self.dbpool.runInteraction(self._storeItems, item_data, publisher) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
869 |
393
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
870 def _storeItems(self, cursor, item_data, publisher): |
250 | 871 self._checkNodeExists(cursor) |
393
728b08c0d000
storage (pgsql): fixed storage of multiple items
Goffi <goffi@goffi.org>
parents:
390
diff
changeset
|
872 self._storeItem(cursor, item_data, publisher) |
244 | 873 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
874 def _storeItem(self, cursor, item_data, publisher): |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
875 # first try to insert the item |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
876 # - if it fails (conflict), and the item is new and we have serial_ids options, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
877 # current id will be recomputed using next item id query (note that is not perfect, as |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
878 # table is not locked and this can fail if two items are added at the same time |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
879 # but this can only happen with serial_ids and if future ids have been set by a client, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
880 # this case should be rare enough to consider this situation acceptable) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
881 # - if item insertion fail and the item is not new, we do an update |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
882 # - in other cases, exception is raised |
301
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
883 item, access_model, item_config = item_data.item, item_data.access_model, item_data.config |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
884 data = item.toXml() |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
885 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
886 insert_query = """INSERT INTO items (node_id, item, publisher, data, access_model) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
887 SELECT %s, %s, %s, %s, %s FROM nodes |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
888 WHERE node_id=%s |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
889 RETURNING item_id""" |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
890 insert_data = [self.nodeDbId, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
891 item["id"], |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
892 publisher.full(), |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
893 data, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
894 access_model, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
895 self.nodeDbId] |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
896 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
897 try: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
898 cursor.execute(insert_query, insert_data) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
899 except cursor._pool.dbapi.IntegrityError as e: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
900 if e.pgcode != "23505": |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
901 # we only handle unique_violation, every other exception must be raised |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
902 raise e |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
903 cursor.connection.rollback() |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
904 # the item already exist |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
905 if item_data.new: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
906 # the item is new |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
907 if self._config[const.OPT_SERIAL_IDS]: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
908 # this can happen with serial_ids, if a item has been stored |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
909 # with a future id (generated by XMPP client) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
910 cursor.execute(NEXT_ITEM_ID_QUERY.format(node_id=self.nodeDbId)) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
911 next_id = cursor.fetchone()[0] |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
912 # we update the sequence, so we can skip conflicting ids |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
913 cursor.execute(u"SELECT setval('{seq_name}', %s)".format( |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
914 seq_name = ITEMS_SEQ_NAME.format(node_id=self.nodeDbId)), [next_id]) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
915 # and now we can retry the query with the new id |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
916 item['id'] = insert_data[1] = unicode(next_id) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
917 # item saved in DB must also be updated with the new id |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
918 insert_data[3] = item.toXml() |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
919 cursor.execute(insert_query, insert_data) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
920 else: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
921 # but if we have not serial_ids, we have a real problem |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
922 raise e |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
923 else: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
924 # this is an update |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
925 cursor.execute("""UPDATE items SET updated=now(), publisher=%s, data=%s |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
926 FROM nodes |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
927 WHERE nodes.node_id = items.node_id AND |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
928 nodes.node_id = %s and items.item=%s |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
929 RETURNING item_id""", |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
930 (publisher.full(), |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
931 data, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
932 self.nodeDbId, |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
933 item["id"])) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
934 if cursor.rowcount != 1: |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
935 raise exceptions.InternalError("item has not been updated correctly") |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
936 item_id = cursor.fetchone()[0]; |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
937 self._storeCategories(cursor, item_id, item_data.categories, update=True) |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
938 return |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
939 |
301
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
940 item_id = cursor.fetchone()[0]; |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
941 self._storeCategories(cursor, item_id, item_data.categories) |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
942 |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
943 if access_model == const.VAL_AMODEL_PUBLISHER_ROSTER: |
250 | 944 if const.OPT_ROSTER_GROUPS_ALLOWED in item_config: |
945 item_config.fields[const.OPT_ROSTER_GROUPS_ALLOWED].fieldType='list-multi' #XXX: needed to force list if there is only one value | |
946 allowed_groups = item_config[const.OPT_ROSTER_GROUPS_ALLOWED] | |
245
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
947 else: |
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
948 allowed_groups = [] |
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
949 for group in allowed_groups: |
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
950 #TODO: check that group are actually in roster |
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
951 cursor.execute("""INSERT INTO item_groups_authorized (item_id, groupname) |
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
952 VALUES (%s,%s)""" , (item_id, group)) |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
953 # TODO: whitelist access model |
245
e11e99246be5
allowed groups from item_config are now stored
Goffi <goffi@goffi.org>
parents:
244
diff
changeset
|
954 |
301
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
955 def _storeCategories(self, cursor, item_id, categories, update=False): |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
956 # TODO: handle canonical form |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
957 if update: |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
958 cursor.execute("""DELETE FROM item_categories |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
959 WHERE item_id=%s""", (item_id,)) |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
960 |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
961 for category in categories: |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
962 cursor.execute("""INSERT INTO item_categories (item_id, category) |
05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
Goffi <goffi@goffi.org>
parents:
297
diff
changeset
|
963 VALUES (%s, %s)""", (item_id, category)) |
107 | 964 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
965 def removeItems(self, itemIdentifiers): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
966 return self.dbpool.runInteraction(self._removeItems, itemIdentifiers) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
967 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
968 def _removeItems(self, cursor, itemIdentifiers): |
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
969 self._checkNodeExists(cursor) |
180
fc687620599b
Properly add send_last_published_item configuration item.
Ralph Meijer <ralphm@ik.nu>
parents:
173
diff
changeset
|
970 |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
971 deleted = [] |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
972 |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
973 for itemIdentifier in itemIdentifiers: |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
974 cursor.execute("""DELETE FROM items WHERE |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
975 node_id=%s AND |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
976 item=%s""", |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
977 (self.nodeDbId, |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
978 itemIdentifier)) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
979 |
142
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
136
diff
changeset
|
980 if cursor.rowcount: |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
981 deleted.append(itemIdentifier) |
142
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
136
diff
changeset
|
982 |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
136
diff
changeset
|
983 return deleted |
107 | 984 |
278 | 985 def getItems(self, authorized_groups, unrestricted, maxItems=None, ext_data=None): |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
986 """ Get all authorised items |
346 | 987 |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
988 @param authorized_groups: we want to get items that these groups can access |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
989 @param unrestricted: if true, don't check permissions (i.e.: get all items) |
318 | 990 @param maxItems: nb of items we want to get |
991 @param ext_data: options for extra features like RSM and MAM | |
278 | 992 |
317
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
993 @return: list of container.ItemData |
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
994 if unrestricted is False, access_model and config will be None |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
995 """ |
278 | 996 if ext_data is None: |
997 ext_data = {} | |
347 | 998 return self.dbpool.runInteraction(self._getItems, authorized_groups, unrestricted, maxItems, ext_data, ids_only=False) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
999 |
346 | 1000 def getItemsIds(self, authorized_groups, unrestricted, maxItems=None, ext_data=None): |
1001 """ Get all authorised items ids | |
1002 | |
1003 @param authorized_groups: we want to get items that these groups can access | |
1004 @param unrestricted: if true, don't check permissions (i.e.: get all items) | |
1005 @param maxItems: nb of items we want to get | |
1006 @param ext_data: options for extra features like RSM and MAM | |
1007 | |
1008 @return list(unicode): list of ids | |
1009 """ | |
1010 if ext_data is None: | |
1011 ext_data = {} | |
1012 return self.dbpool.runInteraction(self._getItems, authorized_groups, unrestricted, maxItems, ext_data, ids_only=True) | |
1013 | |
318 | 1014 def _appendSourcesAndFilters(self, query, args, authorized_groups, unrestricted, ext_data): |
1015 """append sources and filters to sql query requesting items and return ORDER BY | |
278 | 1016 |
318 | 1017 arguments query, args, authorized_groups, unrestricted and ext_data are the same as for |
1018 _getItems | |
1019 """ | |
1020 # SOURCES | |
323 | 1021 query.append("FROM nodes INNER JOIN items USING (node_id)") |
1022 | |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1023 if unrestricted: |
323 | 1024 query_filters = ["WHERE node_id=%s"] |
318 | 1025 args.append(self.nodeDbId) |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1026 else: |
323 | 1027 query.append("LEFT JOIN item_groups_authorized USING (item_id)") |
318 | 1028 args.append(self.nodeDbId) |
1029 if authorized_groups: | |
1030 get_groups = " or (items.access_model='roster' and groupname in %s)" | |
1031 args.append(authorized_groups) | |
1032 else: | |
1033 get_groups = "" | |
278 | 1034 |
323 | 1035 query_filters = ["WHERE node_id=%s AND (items.access_model='open'" + get_groups + ")"] |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1036 |
318 | 1037 # FILTERS |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
278
diff
changeset
|
1038 if 'filters' in ext_data: # MAM filters |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
278
diff
changeset
|
1039 for filter_ in ext_data['filters']: |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
278
diff
changeset
|
1040 if filter_.var == 'start': |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1041 query_filters.append("AND created>=%s") |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1042 args.append(filter_.value) |
323 | 1043 elif filter_.var == 'end': |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1044 query_filters.append("AND created<=%s") |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1045 args.append(filter_.value) |
323 | 1046 elif filter_.var == 'with': |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
278
diff
changeset
|
1047 jid_s = filter_.value |
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
278
diff
changeset
|
1048 if '/' in jid_s: |
323 | 1049 query_filters.append("AND publisher=%s") |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1050 args.append(filter_.value) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1051 else: |
323 | 1052 query_filters.append("AND publisher LIKE %s") |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1053 args.append(u"{}%".format(filter_.value)) |
323 | 1054 elif filter_.var == const.MAM_FILTER_CATEGORY: |
1055 query.append("LEFT JOIN item_categories USING (item_id)") | |
1056 query_filters.append("AND category=%s") | |
1057 args.append(filter_.value) | |
1058 else: | |
1059 log.msg("WARNING: unknown filter: {}".format(filter_.encode('utf-8'))) | |
1060 | |
1061 query.extend(query_filters) | |
282
7d54ff2eeaf2
actually retrieve the MAM messages
souliane <souliane@mailoo.org>
parents:
278
diff
changeset
|
1062 |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
1063 return self.getOrderBy(ext_data) |
318 | 1064 |
346 | 1065 def _getItems(self, cursor, authorized_groups, unrestricted, maxItems, ext_data, ids_only): |
318 | 1066 self._checkNodeExists(cursor) |
1067 | |
1068 if maxItems == 0: | |
1069 return [] | |
1070 | |
1071 args = [] | |
1072 | |
1073 # SELECT | |
346 | 1074 if ids_only: |
1075 query = ["SELECT item"] | |
1076 else: | |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1077 query = ["SELECT data::text,items.access_model,item_id,created,updated"] |
318 | 1078 |
1079 query_order = self._appendSourcesAndFilters(query, args, authorized_groups, unrestricted, ext_data) | |
278 | 1080 |
1081 if 'rsm' in ext_data: | |
1082 rsm = ext_data['rsm'] | |
1083 maxItems = rsm.max | |
1084 if rsm.index is not None: | |
319
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1085 # We need to know the item_id of corresponding to the index (offset) of the current query |
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1086 # so we execute the query to look for the item_id |
318 | 1087 tmp_query = query[:] |
1088 tmp_args = args[:] | |
319
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1089 tmp_query[0] = "SELECT item_id" |
318 | 1090 tmp_query.append("{} LIMIT 1 OFFSET %s".format(query_order)) |
1091 tmp_args.append(rsm.index) | |
1092 cursor.execute(' '.join(query), args) | |
1093 # FIXME: bad index is not managed yet | |
319
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1094 item_id = cursor.fetchall()[0][0] |
318 | 1095 |
319
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1096 # now that we have the id, we can use it |
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1097 query.append("AND item_id<=%s") |
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1098 args.append(item_id) |
278 | 1099 elif rsm.before is not None: |
1100 if rsm.before != '': | |
319
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1101 query.append("AND item_id>(SELECT item_id FROM items WHERE item=%s LIMIT 1)") |
278 | 1102 args.append(rsm.before) |
318 | 1103 if maxItems is not None: |
1104 # if we have maxItems (i.e. a limit), we need to reverse order | |
1105 # in a first query to get the right items | |
1106 query.insert(0,"SELECT * from (") | |
375
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
1107 query.append(self.getOrderBy(ext_data, direction='ASC')) |
9a787881b824
implemented Order-By ProtoXEP (MAM + PubSub)
Goffi <goffi@goffi.org>
parents:
374
diff
changeset
|
1108 query.append("LIMIT %s) as x") |
318 | 1109 args.append(maxItems) |
278 | 1110 elif rsm.after: |
319
a51947371625
pgsql storage: use item_id instead of date to order and select items
Goffi <goffi@goffi.org>
parents:
318
diff
changeset
|
1111 query.append("AND item_id<(SELECT item_id FROM items WHERE item=%s LIMIT 1)") |
278 | 1112 args.append(rsm.after) |
1113 | |
318 | 1114 query.append(query_order) |
278 | 1115 |
297
4115999d85e9
fixes behavior when maxItems is 0
souliane <souliane@mailoo.org>
parents:
294
diff
changeset
|
1116 if maxItems is not None: |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1117 query.append("LIMIT %s") |
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1118 args.append(maxItems) |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
1119 |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1120 cursor.execute(' '.join(query), args) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
1121 |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
1122 result = cursor.fetchall() |
346 | 1123 if unrestricted and not ids_only: |
318 | 1124 # with unrestricted query, we need to fill the access_list for a roster access items |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1125 ret = [] |
356
95c83899b5e9
pgsql: fixed bad data filling in getItemsData:
Goffi <goffi@goffi.org>
parents:
352
diff
changeset
|
1126 for item_data in result: |
95c83899b5e9
pgsql: fixed bad data filling in getItemsData:
Goffi <goffi@goffi.org>
parents:
352
diff
changeset
|
1127 item = generic.stripNamespace(parseXml(item_data.data)) |
95c83899b5e9
pgsql: fixed bad data filling in getItemsData:
Goffi <goffi@goffi.org>
parents:
352
diff
changeset
|
1128 access_model = item_data.access_model |
95c83899b5e9
pgsql: fixed bad data filling in getItemsData:
Goffi <goffi@goffi.org>
parents:
352
diff
changeset
|
1129 item_id = item_data.item_id |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1130 created = item_data.created |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1131 updated = item_data.updated |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1132 access_list = {} |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
1133 if access_model == const.VAL_AMODEL_PUBLISHER_ROSTER: |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1134 cursor.execute('SELECT groupname FROM item_groups_authorized WHERE item_id=%s', (item_id,)) |
356
95c83899b5e9
pgsql: fixed bad data filling in getItemsData:
Goffi <goffi@goffi.org>
parents:
352
diff
changeset
|
1135 access_list[const.OPT_ROSTER_GROUPS_ALLOWED] = [r.groupname for r in cursor.fetchall()] |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1136 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1137 ret.append(container.ItemData(item, access_model, access_list, created=created, updated=updated)) |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
1138 # TODO: whitelist item access model |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1139 return ret |
318 | 1140 |
346 | 1141 if ids_only: |
356
95c83899b5e9
pgsql: fixed bad data filling in getItemsData:
Goffi <goffi@goffi.org>
parents:
352
diff
changeset
|
1142 return [r.item for r in result] |
346 | 1143 else: |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1144 items_data = [container.ItemData(generic.stripNamespace(parseXml(r.data)), r.access_model, created=r.created, updated=r.updated) for r in result] |
317
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
1145 return items_data |
107 | 1146 |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1147 def getItemsById(self, authorized_groups, unrestricted, itemIdentifiers): |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
1148 """Get items which are in the given list |
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
1149 |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1150 @param authorized_groups: we want to get items that these groups can access |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1151 @param unrestricted: if true, don't check permissions |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1152 @param itemIdentifiers: list of ids of the items we want to get |
317
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
1153 @return: list of container.ItemData |
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
1154 ItemData.config will contains access_list (managed as a dictionnary with same key as for item_config) |
34adc4a8aa64
new container module, with an ItemData container:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
1155 if unrestricted is False, access_model and config will be None |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1156 """ |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1157 return self.dbpool.runInteraction(self._getItemsById, authorized_groups, unrestricted, itemIdentifiers) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
1158 |
248
50f6ee966da8
item are gotten according to item's access model in getItems
Goffi <goffi@goffi.org>
parents:
247
diff
changeset
|
1159 def _getItemsById(self, cursor, authorized_groups, unrestricted, itemIdentifiers): |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
1160 self._checkNodeExists(cursor) |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1161 ret = [] |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1162 if unrestricted: #we get everything without checking permissions |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1163 for itemIdentifier in itemIdentifiers: |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1164 cursor.execute("""SELECT data::text,items.access_model,item_id,created,updated FROM nodes |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1165 INNER JOIN items USING (node_id) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1166 WHERE node_id=%s AND item=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1167 (self.nodeDbId, |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1168 itemIdentifier)) |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1169 result = cursor.fetchone() |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1170 if not result: |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1171 raise error.ItemNotFound() |
107 | 1172 |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1173 item = generic.stripNamespace(parseXml(result[0])) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1174 access_model = result[1] |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1175 item_id = result[2] |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1176 created= result[3] |
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1177 updated= result[4] |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1178 access_list = {} |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
1179 if access_model == const.VAL_AMODEL_PUBLISHER_ROSTER: |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1180 cursor.execute('SELECT groupname FROM item_groups_authorized WHERE item_id=%s', (item_id,)) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1181 access_list[const.OPT_ROSTER_GROUPS_ALLOWED] = [r[0] for r in cursor.fetchall()] |
330
82d1259b3e36
backend, pgsql storage: better items/notification handling, various fixes:
Goffi <goffi@goffi.org>
parents:
324
diff
changeset
|
1182 #TODO: WHITELIST access_model |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1183 |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1184 ret.append(container.ItemData(item, access_model, access_list, created=created, updated=updated)) |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1185 else: #we check permission before returning items |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1186 for itemIdentifier in itemIdentifiers: |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1187 args = [self.nodeDbId, itemIdentifier] |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1188 if authorized_groups: |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1189 args.append(authorized_groups) |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1190 cursor.execute("""SELECT data::text, created, updated FROM nodes |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1191 INNER JOIN items USING (node_id) |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1192 LEFT JOIN item_groups_authorized USING (item_id) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1193 WHERE node_id=%s AND item=%s AND |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
1194 (items.access_model='open' """ + |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1195 ("or (items.access_model='roster' and groupname in %s)" if authorized_groups else '') + ")", |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1196 args) |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1197 |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1198 result = cursor.fetchone() |
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1199 if result: |
367
a772f7dac930
backend, storage(pgsql): creation/update date + serial ids:
Goffi <goffi@goffi.org>
parents:
366
diff
changeset
|
1200 ret.append(container.ItemData(generic.stripNamespace(parseXml(result[0])), created=result[1], updated=result[2])) |
262
7b821432d012
fixed node auto-create feature
souliane <souliane@mailoo.org>
parents:
260
diff
changeset
|
1201 |
252
25a1dc7181cc
full items, with item-configuration, are returned if items are asked by the owner
Goffi <goffi@goffi.org>
parents:
250
diff
changeset
|
1202 return ret |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
1203 |
318 | 1204 def getItemsCount(self, authorized_groups, unrestricted, ext_data=None): |
1205 """Count expected number of items in a getItems query | |
1206 | |
1207 @param authorized_groups: we want to get items that these groups can access | |
1208 @param unrestricted: if true, don't check permissions (i.e.: get all items) | |
1209 @param ext_data: options for extra features like RSM and MAM | |
1210 """ | |
1211 if ext_data is None: | |
1212 ext_data = {} | |
1213 return self.dbpool.runInteraction(self._getItemsCount, authorized_groups, unrestricted, ext_data) | |
1214 | |
1215 def _getItemsCount(self, cursor, authorized_groups, unrestricted, ext_data): | |
1216 self._checkNodeExists(cursor) | |
1217 args = [] | |
1218 | |
1219 # SELECT | |
1220 query = ["SELECT count(1)"] | |
1221 | |
1222 self._appendSourcesAndFilters(query, args, authorized_groups, unrestricted, ext_data) | |
1223 | |
1224 cursor.execute(' '.join(query), args) | |
1225 return cursor.fetchall()[0][0] | |
1226 | |
1227 def getItemsIndex(self, item_id, authorized_groups, unrestricted, ext_data=None): | |
1228 """Get expected index of first item in the window of a getItems query | |
1229 | |
1230 @param item_id: id of the item | |
1231 @param authorized_groups: we want to get items that these groups can access | |
1232 @param unrestricted: if true, don't check permissions (i.e.: get all items) | |
1233 @param ext_data: options for extra features like RSM and MAM | |
1234 """ | |
1235 if ext_data is None: | |
1236 ext_data = {} | |
1237 return self.dbpool.runInteraction(self._getItemsIndex, item_id, authorized_groups, unrestricted, ext_data) | |
1238 | |
1239 def _getItemsIndex(self, cursor, item_id, authorized_groups, unrestricted, ext_data): | |
1240 self._checkNodeExists(cursor) | |
1241 args = [] | |
1242 | |
1243 # SELECT | |
1244 query = [] | |
1245 | |
1246 query_order = self._appendSourcesAndFilters(query, args, authorized_groups, unrestricted, ext_data) | |
1247 | |
1248 query_select = "SELECT row_number from (SELECT row_number() OVER ({}), item".format(query_order) | |
1249 query.insert(0, query_select) | |
1250 query.append(") as x WHERE item=%s") | |
1251 args.append(item_id) | |
1252 | |
1253 cursor.execute(' '.join(query), args) | |
1254 # XXX: row_number start at 1, but we want that index start at 0 | |
324
e73e42b4f6ff
pgsql storage: getItemsIndex raise NodeNotFound in this make sense
Goffi <goffi@goffi.org>
parents:
323
diff
changeset
|
1255 try: |
e73e42b4f6ff
pgsql storage: getItemsIndex raise NodeNotFound in this make sense
Goffi <goffi@goffi.org>
parents:
323
diff
changeset
|
1256 return cursor.fetchall()[0][0] - 1 |
e73e42b4f6ff
pgsql storage: getItemsIndex raise NodeNotFound in this make sense
Goffi <goffi@goffi.org>
parents:
323
diff
changeset
|
1257 except IndexError: |
e73e42b4f6ff
pgsql storage: getItemsIndex raise NodeNotFound in this make sense
Goffi <goffi@goffi.org>
parents:
323
diff
changeset
|
1258 raise error.NodeNotFound() |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1259 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1260 def getItemsPublishers(self, itemIdentifiers): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1261 """Get the publishers for all given identifiers |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1262 |
308
087b705493a6
fixed publisher check on item publishing
Goffi <goffi@goffi.org>
parents:
301
diff
changeset
|
1263 @return (dict[unicode, jid.JID]): map of itemIdentifiers to publisher |
087b705493a6
fixed publisher check on item publishing
Goffi <goffi@goffi.org>
parents:
301
diff
changeset
|
1264 if item is not found, key is skipped in resulting dict |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1265 """ |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1266 return self.dbpool.runInteraction(self._getItemsPublishers, itemIdentifiers) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1267 |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1268 def _getItemsPublishers(self, cursor, itemIdentifiers): |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1269 self._checkNodeExists(cursor) |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1270 ret = {} |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1271 for itemIdentifier in itemIdentifiers: |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1272 cursor.execute("""SELECT publisher FROM items |
390
fba96e95e329
storage (pgsql): fixed filtering in getItemsPublishers
Goffi <goffi@goffi.org>
parents:
384
diff
changeset
|
1273 WHERE node_id=%s AND item=%s""", |
fba96e95e329
storage (pgsql): fixed filtering in getItemsPublishers
Goffi <goffi@goffi.org>
parents:
384
diff
changeset
|
1274 (self.nodeDbId, itemIdentifier,)) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1275 result = cursor.fetchone() |
308
087b705493a6
fixed publisher check on item publishing
Goffi <goffi@goffi.org>
parents:
301
diff
changeset
|
1276 if result: |
087b705493a6
fixed publisher check on item publishing
Goffi <goffi@goffi.org>
parents:
301
diff
changeset
|
1277 ret[itemIdentifier] = jid.JID(result[0]) |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1278 return ret |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1279 |
107 | 1280 def purge(self): |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1281 return self.dbpool.runInteraction(self._purge) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
1282 |
127
d3689da18ed2
Don't use encode('utf-8') on serialized XML.
Ralph Meijer <ralphm@ik.nu>
parents:
124
diff
changeset
|
1283 def _purge(self, cursor): |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
1284 self._checkNodeExists(cursor) |
121
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
1285 |
4f0113adb7ed
Add Node._check_node_exists() calls to all Node methods, because nodes could
Ralph Meijer <ralphm@ik.nu>
parents:
113
diff
changeset
|
1286 cursor.execute("""DELETE FROM items WHERE |
294
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1287 node_id=%s""", |
df1edebb0466
PEP implementation, draft (huge patch sorry):
Goffi <goffi@goffi.org>
parents:
283
diff
changeset
|
1288 (self.nodeDbId,)) |
198
e404775b12df
Change naming and spacing conventions to match Twisted's.
Ralph Meijer <ralphm@ik.nu>
parents:
181
diff
changeset
|
1289 |
263
9dfd3890e646
added the constant FLAG_RETRACT_ALLOW_PUBLISHER to allow a publisher to retract an item he has published in a node of "open" publish model.
souliane <souliane@mailoo.org>
parents:
262
diff
changeset
|
1290 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
1291 class CollectionNode(Node): |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
1292 |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
1293 nodeType = 'collection' |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1294 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1295 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1296 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1297 class GatewayStorage(object): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1298 """ |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1299 Memory based storage facility for the XMPP-HTTP gateway. |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1300 """ |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1301 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1302 def __init__(self, dbpool): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1303 self.dbpool = dbpool |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1304 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1305 def _countCallbacks(self, cursor, service, nodeIdentifier): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1306 """ |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1307 Count number of callbacks registered for a node. |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1308 """ |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1309 cursor.execute("""SELECT count(*) FROM callbacks |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1310 WHERE service=%s and node=%s""", |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1311 (service.full(), |
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1312 nodeIdentifier)) |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1313 results = cursor.fetchall() |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1314 return results[0][0] |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1315 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1316 def addCallback(self, service, nodeIdentifier, callback): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1317 def interaction(cursor): |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1318 cursor.execute("""SELECT 1 as bool FROM callbacks |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1319 WHERE service=%s and node=%s and uri=%s""", |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1320 (service.full(), |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1321 nodeIdentifier, |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1322 callback)) |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1323 if cursor.fetchall(): |
206
274a45d2a5ab
Implement root collection that includes all leaf nodes.
Ralph Meijer <ralphm@ik.nu>
parents:
204
diff
changeset
|
1324 return |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1325 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1326 cursor.execute("""INSERT INTO callbacks |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1327 (service, node, uri) VALUES |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1328 (%s, %s, %s)""", |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1329 (service.full(), |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1330 nodeIdentifier, |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1331 callback)) |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1332 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1333 return self.dbpool.runInteraction(interaction) |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1334 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1335 def removeCallback(self, service, nodeIdentifier, callback): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1336 def interaction(cursor): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1337 cursor.execute("""DELETE FROM callbacks |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1338 WHERE service=%s and node=%s and uri=%s""", |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1339 (service.full(), |
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1340 nodeIdentifier, |
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1341 callback)) |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1342 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1343 if cursor.rowcount != 1: |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1344 raise error.NotSubscribed() |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1345 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1346 last = not self._countCallbacks(cursor, service, nodeIdentifier) |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1347 return last |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1348 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1349 return self.dbpool.runInteraction(interaction) |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1350 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1351 def getCallbacks(self, service, nodeIdentifier): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1352 def interaction(cursor): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1353 cursor.execute("""SELECT uri FROM callbacks |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1354 WHERE service=%s and node=%s""", |
276
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1355 (service.full(), |
b757c29b20d7
import changes from idavoll changeset 233 (24be3a11ddbc), by Ralph Meijer and based on a patch by Nuno Santos
souliane <souliane@mailoo.org>
parents:
271
diff
changeset
|
1356 nodeIdentifier)) |
204
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1357 results = cursor.fetchall() |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1358 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1359 if not results: |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1360 raise error.NoCallbacks() |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1361 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1362 return [result[0] for result in results] |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1363 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1364 return self.dbpool.runInteraction(interaction) |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1365 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1366 def hasCallbacks(self, service, nodeIdentifier): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1367 def interaction(cursor): |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1368 return bool(self._countCallbacks(cursor, service, nodeIdentifier)) |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1369 |
b4bf0a5ce50d
Implement storage facilities for the HTTP gateway.
Ralph Meijer <ralphm@ik.nu>
parents:
202
diff
changeset
|
1370 return self.dbpool.runInteraction(interaction) |