comparison idavoll/backend.py @ 24:4f3bbefc6fad

Moved memory backend to its own file. Cleaned up exceptions, naming.
author Ralph Meijer <ralphm@ik.nu>
date Sun, 17 Oct 2004 13:51:34 +0000
parents 884268687229
children d4fc29bb5381
comparison
equal deleted inserted replaced
23:884268687229 24:4f3bbefc6fad
1 from twisted.application import service 1 from twisted.python import components
2 from twisted.python import components, failure
3 from twisted.internet import defer, reactor
4 from twisted.protocols.jabber import jid
5 2
6 class IBackendService(components.Interface): 3 class IService(components.Interface):
7 """ Interface to a backend service of a pubsub service """ 4 """ Interface to a backend service of a pubsub service """
8 5
9 def do_publish(self, node, publisher, item): 6 def do_publish(self, node, publisher, item):
10 """ Returns a deferred that returns """ 7 """ Returns a deferred that returns """
11 8
12 class BackendException(Exception): 9 class Error(Exception):
13 def __init__(self, msg = ''): 10 msg = ''
14 self.msg = msg
15 11
16 def __str__(self): 12 def __str__(self):
17 return self.msg 13 return self.msg
18 14
19 class NodeNotFound(BackendException): 15 class NodeNotFound(Error):
20 def __init__(self, msg = 'Node not found'): 16 msg = 'Node not found'
21 BackendException.__init__(self, msg)
22 17
23 class NotAuthorized(BackendException): 18 class NotAuthorized(Error):
24 pass 19 pass
25 20
26 class PayloadExpected(BackendException): 21 class PayloadExpected(Error):
27 def __init__(self, msg = 'Payload expected'): 22 msg = 'Payload expected'
28 BackendException.__init__(self, msg)
29 23
30 class NoPayloadAllowed(BackendException): 24 class NoPayloadAllowed(Error):
31 def __init__(self, msg = 'No payload allowed'): 25 msg = 'No payload allowed'
32 BackendException.__init__(self, msg)
33 26
34 class NoInstantNodes(BackendException): 27 class NoInstantNodes(Error):
35 pass 28 pass
36 29
37 class NodeExists(BackendException): 30 class NodeExists(Error):
38 pass 31 pass
39
40 class Subscription:
41 def __init__(self, state):
42 self.state = state
43
44 class NodeConfiguration:
45 def __init__(self):
46 self.persist_items = False
47 self.deliver_payloads = False
48
49 class Node:
50 def __init__(self, id):
51 self.id = id
52 self.configuration = NodeConfiguration()
53 self.subscriptions = {}
54 self.affiliations = {}
55 self.items = {}
56
57 class MemoryBackendService(service.Service):
58
59 __implements__ = IBackendService,
60
61 def __init__(self):
62 self.nodes = {}
63
64 node = Node("ralphm/mood/ralphm@ik.nu")
65 node.subscriptions["ralphm@doe.ik.nu"] = Subscription("subscribed")
66 node.subscriptions["notify@ik.nu/mood_monitor"] = Subscription("subscribed")
67 node.affiliations["ralphm@ik.nu"] = "owner"
68 node.affiliations["ralphm@doe.ik.nu"] = "publisher"
69 node.configuration.persist_items = True
70 node.configuration.deliver_payloads = True
71 self.nodes[node.id] = node
72
73 def do_publish(self, node_id, publisher, items):
74 try:
75 node = self.nodes[node_id]
76 persist_items = node.configuration.persist_items
77 deliver_payloads = node.configuration.deliver_payloads
78 except KeyError:
79 raise NodeNotFound
80
81 try:
82 if node.affiliations[publisher] not in ['owner', 'publisher']:
83 raise NotAuthorized
84 except KeyError:
85 raise NotAuthorized()
86
87 if items and not persist_items and not deliver_payloads:
88 raise NoPayloadAllowed
89 elif not items and (persist_items or deliver_payloads):
90 raise PayloadExpected
91
92 print "publish by %s to %s" % (publisher, node_id)
93
94 if persist_items or deliver_payloads:
95 for item in items:
96 if item["id"] is None:
97 item["id"] = 'random' # FIXME
98
99 if persist_items:
100 self.storeItems(node_id, publisher, items)
101
102 if items and not deliver_payloads:
103 for item in items:
104 item.children = []
105
106 recipients = self.get_subscribers(node_id)
107 recipients.addCallback(self.magic_filter, node_id, items)
108 recipients.addCallback(self.pubsub_service.do_notification, node_id)
109
110 return defer.succeed(None)
111
112 def do_subscribe(self, node_id, subscriber, requestor):
113 # expect subscriber and requestor to be a jid.JID
114 try:
115 node = self.nodes[node_id]
116 except KeyError:
117 raise NodeNotFound
118
119 affiliation = node.affiliations.get(requestor.full(), 'none')
120
121 if affiliation == 'banned':
122 raise NotAuthorized
123
124 print subscriber.full()
125 print subscriber.userhostJID().full()
126 print requestor.full()
127
128 if subscriber.userhostJID() != requestor:
129 raise NotAuthorized
130
131 try:
132 subscription = node.subscriptions[subscriber.full()]
133 except KeyError:
134 subscription = Subscription('subscribed')
135 node.subscriptions[subscriber.full()] = subscription
136
137 print node.subscriptions
138
139 return defer.succeed({
140 'affiliation': affiliation,
141 'node': node_id,
142 'jid': subscriber,
143 'subscription': subscription.state})
144
145 def magic_filter(self, subscribers, node_id, items):
146 list = {}
147 for subscriber in subscribers:
148 list[subscriber] = items
149
150 return list
151
152 def get_subscribers(self, node_id):
153 d = defer.Deferred()
154 try:
155 return defer.succeed(self.nodes[node_id].subscriptions.keys())
156 except:
157 return defer.fail()
158
159 def storeItems(self, node_id, publisher, items):
160 for item in items:
161 self.nodes[node_id].items[item["id"]] = item
162
163 print self.nodes[node_id].items
164
165 def create_node(self, node_id, owner):
166 result = {}
167
168 if not node_id:
169 raise NoInstantNodes
170
171 if node_id in self.nodes:
172 raise NodeExists
173
174 node = Node(node_id)
175 node.affiliations[owner.full()] = 'owner'
176 self.nodes[node_id] = node
177
178 return defer.succeed({'node_id': node.id})