Mercurial > libervia-pubsub
annotate idavoll/memory_storage.py @ 150:35977eb964e6
Use uuid.py module [1] for generating unique id's for nodes and items.
Factor out authorization checking.
[1] http://ofxsuite.berlios.de/uuid.py
author | Ralph Meijer <ralphm@ik.nu> |
---|---|
date | Tue, 04 Oct 2005 12:17:01 +0000 |
parents | b03e5ad81173 |
children | 5191ba7c4df8 |
rev | line source |
---|---|
107 | 1 import copy |
2 from zope.interface import implements | |
3 from twisted.internet import defer | |
4 from twisted.words.protocols.jabber import jid | |
5 import storage | |
6 | |
115 | 7 default_config = {"pubsub#persist_items": True, |
8 "pubsub#deliver_payloads": True} | |
107 | 9 |
10 class Storage: | |
11 | |
12 implements(storage.IStorage) | |
13 | |
14 def __init__(self): | |
15 self._nodes = {} | |
16 | |
17 def get_node(self, node_id): | |
18 try: | |
19 node = self._nodes[node_id] | |
20 except KeyError: | |
21 return defer.fail(storage.NodeNotFound()) | |
22 | |
23 return defer.succeed(node) | |
24 | |
25 def get_node_ids(self): | |
26 return defer.succeed(self._nodes.keys()) | |
27 | |
28 def create_node(self, node_id, owner, config = None, type='leaf'): | |
29 if node_id in self._nodes: | |
30 return defer.fail(storage.NodeExists()) | |
31 | |
32 if not config: | |
33 config = copy.copy(default_config) | |
34 | |
35 if type != 'leaf': | |
36 raise NotImplementedError | |
37 | |
38 node = LeafNode(node_id, owner, config) | |
39 self._nodes[node_id] = node | |
40 | |
41 return defer.succeed(None) | |
42 | |
43 def delete_node(self, node_id): | |
44 try: | |
45 del self._nodes[node_id] | |
46 except KeyError: | |
47 return defer.fail(storage.NodeNotFound()) | |
48 | |
49 return defer.succeed(None) | |
50 | |
51 def get_affiliations(self, entity): | |
112 | 52 entity = entity.userhost() |
53 return defer.succeed([(node.id, node._affiliations[entity]) | |
107 | 54 for name, node in self._nodes.iteritems() |
112 | 55 if entity in node._affiliations]) |
107 | 56 |
57 def get_subscriptions(self, entity): | |
58 subscriptions = [] | |
59 for node in self._nodes.itervalues(): | |
60 for subscriber, subscription in node._subscriptions.iteritems(): | |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
61 subscriber = jid.internJID(subscriber) |
112 | 62 if subscriber.userhostJID() == entity.userhostJID(): |
107 | 63 subscriptions.append((node.id, subscriber, |
64 subscription.state)) | |
65 | |
66 return defer.succeed(subscriptions) | |
67 | |
68 class Node: | |
69 | |
70 implements(storage.INode) | |
71 | |
72 def __init__(self, node_id, owner, config): | |
73 self.id = node_id | |
112 | 74 self._affiliations = {owner.userhost(): 'owner'} |
107 | 75 self._subscriptions = {} |
76 self._config = config | |
77 | |
78 def get_type(self): | |
79 return self.type | |
80 | |
81 def get_configuration(self): | |
82 return self._config | |
83 | |
84 def get_meta_data(self): | |
85 config = copy.copy(self._config) | |
86 config["pubsub#node_type"] = self.type | |
87 return config | |
88 | |
89 def set_configuration(self, options): | |
90 for option in options: | |
91 if option in self._config: | |
92 self._config[option] = options[option] | |
93 | |
94 return defer.succeed(None) | |
95 | |
96 def get_affiliation(self, entity): | |
97 return defer.succeed(self._affiliations.get(entity.full())) | |
98 | |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
99 def get_subscription(self, subscriber): |
107 | 100 try: |
101 subscription = self._subscriptions[subscriber.full()] | |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
102 except KeyError: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
103 state = None |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
104 else: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
105 state = subscription.state |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
106 return defer.succeed(state) |
107 | 107 |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
108 def add_subscription(self, subscriber, state): |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
109 if self._subscriptions.get(subscriber.full()): |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
110 return defer.fail(storage.SubscriptionExists()) |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
111 |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
112 subscription = Subscription(state) |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
113 self._subscriptions[subscriber.full()] = subscription |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
114 return defer.succeed(None) |
107 | 115 |
116 def remove_subscription(self, subscriber): | |
120
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
117 try: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
118 del self._subscriptions[subscriber.full()] |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
119 except KeyError: |
8892331314c8
Change Node.add_subscription() to return a Failure when a subscription already
Ralph Meijer <ralphm@ik.nu>
parents:
115
diff
changeset
|
120 return defer.fail(storage.SubscriptionNotFound()) |
107 | 121 |
122 return defer.succeed(None) | |
123 | |
124 def get_subscribers(self): | |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
125 subscribers = [jid.internJID(subscriber) for subscriber, subscription |
107 | 126 in self._subscriptions.iteritems() |
127 if subscription.state == 'subscribed'] | |
128 | |
129 return defer.succeed(subscribers) | |
130 | |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
131 def is_subscribed(self, entity): |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
132 for subscriber, subscription in self._subscriptions.iteritems(): |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
133 if jid.internJID(subscriber).userhost() == entity.userhost() and \ |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
134 subscription.state == 'subscribed': |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
135 return defer.succeed(True) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
136 |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
137 return defer.succeed(False) |
107 | 138 |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
139 def get_affiliations(self): |
148
b03e5ad81173
Change all calls to jid.JID to jid.internJID to avoid redoing stringprep.
Ralph Meijer <ralphm@ik.nu>
parents:
146
diff
changeset
|
140 affiliations = [(jid.internJID(entity), affiliation) for entity, affiliation |
145
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
141 in self._affiliations.iteritems()] |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
142 |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
143 return defer.succeed(affiliations) |
f393bccec4bc
Add get_affiliations to Node class in storage facilities in preparation of
Ralph Meijer <ralphm@ik.nu>
parents:
142
diff
changeset
|
144 |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
145 class LeafNodeMixin: |
107 | 146 |
147 type = 'leaf' | |
148 | |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
149 def __init__(self): |
107 | 150 self._items = {} |
151 self._itemlist = [] | |
152 | |
153 def store_items(self, items, publisher): | |
154 for data in items: | |
155 id = data["id"] | |
139
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
156 data = data.toXml() |
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
157 if isinstance(data, str): |
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
158 data = data.decode('utf-8') |
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
159 item = (data, publisher) |
107 | 160 if id in self._items: |
161 self._itemlist.remove(self._items[id]) | |
162 self._items[id] = item | |
163 self._itemlist.append(item) | |
164 | |
165 return defer.succeed(None) | |
166 | |
167 def remove_items(self, item_ids): | |
168 deleted = [] | |
169 | |
170 for item_id in item_ids: | |
142
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
171 try: |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
172 item = self._items[item_id] |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
173 except KeyError: |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
174 pass |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
175 else: |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
176 self._itemlist.remove(item) |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
177 del self._items[item_id] |
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
178 deleted.append(item_id) |
107 | 179 |
142
812300cdbc22
Changed behaviour of retraction of items so that only the actually deleted
Ralph Meijer <ralphm@ik.nu>
parents:
139
diff
changeset
|
180 return defer.succeed(deleted) |
107 | 181 |
182 def get_items(self, max_items=None): | |
183 if max_items: | |
184 list = self._itemlist[-max_items:] | |
185 else: | |
186 list = self._itemlist | |
139
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
187 return defer.succeed([item[0] for item in list]) |
107 | 188 |
189 def get_items_by_id(self, item_ids): | |
190 items = [] | |
191 for item_id in item_ids: | |
192 try: | |
193 item = self._items[item_id] | |
194 except KeyError: | |
195 pass | |
196 else: | |
139
8f6956b9a688
Follow API change in Twisted Xish, while still being compatible with
Ralph Meijer <ralphm@ik.nu>
parents:
126
diff
changeset
|
197 items.append(item[0]) |
107 | 198 return defer.succeed(items) |
199 | |
200 def purge(self): | |
201 self._items = {} | |
202 self._itemlist = [] | |
203 | |
204 return defer.succeed(None) | |
205 | |
146
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
206 class LeafNode(Node, LeafNodeMixin): |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
207 |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
208 implements(storage.ILeafNode) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
209 |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
210 def __init__(self, node_id, owner, config): |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
211 Node.__init__(self, node_id, owner, config) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
212 LeafNodeMixin.__init__(self) |
b4490bdc77e5
Change semantics of Node.is_subscribed() to match all subscriptions for an
Ralph Meijer <ralphm@ik.nu>
parents:
145
diff
changeset
|
213 |
107 | 214 class Subscription: |
215 | |
216 implements(storage.ISubscription) | |
217 | |
218 def __init__(self, state): | |
219 self.state = state |