jubjub 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README.mdown +42 -6
  2. data/lib/jubjub/connection/xmpp_gateway/muc.rb +4 -20
  3. data/lib/jubjub/connection/xmpp_gateway/pubsub.rb +194 -13
  4. data/lib/jubjub/data_form.rb +30 -0
  5. data/lib/jubjub/muc.rb +4 -93
  6. data/lib/jubjub/muc/collection.rb +55 -0
  7. data/lib/jubjub/muc/configuration.rb +5 -0
  8. data/lib/jubjub/muc/muc.rb +37 -0
  9. data/lib/jubjub/pubsub.rb +8 -201
  10. data/lib/jubjub/pubsub/affiliation.rb +83 -0
  11. data/lib/jubjub/pubsub/affiliation_collection.rb +38 -0
  12. data/lib/jubjub/pubsub/collection.rb +68 -0
  13. data/lib/jubjub/pubsub/configuration.rb +5 -0
  14. data/lib/jubjub/pubsub/item.rb +35 -0
  15. data/lib/jubjub/pubsub/item_collection.rb +35 -0
  16. data/lib/jubjub/pubsub/pubsub.rb +66 -0
  17. data/lib/jubjub/pubsub/subscription.rb +24 -0
  18. data/lib/jubjub/user.rb +2 -2
  19. data/spec/connection/xmpp_gateway_muc_spec.rb +3 -3
  20. data/spec/connection/xmpp_gateway_pubsub_spec.rb +167 -11
  21. data/spec/fixtures/dataform_1.xml +65 -0
  22. data/spec/fixtures/vcr_cassettes/pubsub_default_configuration.yml +118 -0
  23. data/spec/fixtures/vcr_cassettes/pubsub_modify_affiliations.yml +275 -0
  24. data/spec/fixtures/vcr_cassettes/pubsub_purge.yml +68 -0
  25. data/spec/fixtures/vcr_cassettes/pubsub_retrieve_affiliations.yml +99 -0
  26. data/spec/mixins/user_spec.rb +8 -8
  27. data/spec/models/muc_collection_spec.rb +17 -12
  28. data/spec/models/muc_configuration_spec.rb +1 -1
  29. data/spec/models/pubsub_affiliation_collection_spec.rb +86 -0
  30. data/spec/models/pubsub_affiliation_spec.rb +244 -0
  31. data/spec/models/pubsub_collection_spec.rb +50 -18
  32. data/spec/models/pubsub_item_collection_spec.rb +12 -12
  33. data/spec/models/pubsub_item_spec.rb +9 -2
  34. data/spec/models/pubsub_spec.rb +27 -2
  35. data/spec/models/pubsub_subscription_spec.rb +2 -2
  36. data/spec/spec_helper.rb +1 -1
  37. data/spec/support/helpers.rb +7 -0
  38. data/spec/support/shared_examples.rb +30 -0
  39. metadata +46 -19
@@ -0,0 +1,5 @@
1
+ require 'jubjub/data_form'
2
+
3
+ class Jubjub::Pubsub::Configuration < Jubjub::DataForm
4
+
5
+ end
@@ -0,0 +1,35 @@
1
+ class Jubjub::Pubsub::Item
2
+
3
+ attr_reader :jid, :node, :item_id, :data
4
+
5
+ def initialize(jid, node, item_id, data, connection)
6
+ @jid = Jubjub::Jid.new jid
7
+ @node = node
8
+ @item_id = item_id
9
+ @data = data
10
+ @connection = connection
11
+ end
12
+
13
+ # Hide the connection details and show jid as string for compactness
14
+ def inspect
15
+ obj_id = "%x" % (object_id << 1)
16
+ "#<#{self.class}:0x#{obj_id} @jid=\"#{jid}\" @node=#{node.inspect} @item_id=#{item_id.inspect} @data=#{data.inspect}>"
17
+ end
18
+
19
+ def retract
20
+ @connection.pubsub.retract jid, node, item_id
21
+ end
22
+
23
+ def ==(other)
24
+ other.is_a?( self.class ) &&
25
+ other.jid == self.jid &&
26
+ other.node == self.node &&
27
+ other.item_id == self.item_id &&
28
+ other.data == self.data
29
+ end
30
+
31
+ def uri
32
+ "xmpp:#{@jid}?;node=#{@node};item=#{@item_id}"
33
+ end
34
+
35
+ end
@@ -0,0 +1,35 @@
1
+ class Jubjub::Pubsub::ItemCollection
2
+
3
+ attr_reader :jid, :node
4
+
5
+ def initialize(jid,node,connection)
6
+ @jid = Jubjub::Jid.new jid
7
+ @node = node
8
+ @connection = connection
9
+ end
10
+
11
+ def [](item_num)
12
+ case item_num
13
+ when Fixnum
14
+ items[item_num]
15
+ else
16
+ items.find{|i| i.item_id == item_num }
17
+ end
18
+ end
19
+
20
+ # Hint that methods are actually applied to list using method_missing
21
+ def inspect
22
+ items.inspect
23
+ end
24
+
25
+ private
26
+
27
+ def method_missing(name, *args, &block)
28
+ items.send(name, *args, &block)
29
+ end
30
+
31
+ def items
32
+ @items ||= @connection.pubsub.retrieve_items( @jid, @node )
33
+ end
34
+
35
+ end
@@ -0,0 +1,66 @@
1
+ class Jubjub::Pubsub
2
+
3
+ attr_reader :jid, :node
4
+
5
+ def initialize(jid, node, connection)
6
+ @jid = Jubjub::Jid.new jid
7
+ @node = node
8
+ @connection = connection
9
+ end
10
+
11
+ def destroy(redirect_jid = nil, redirect_node = nil)
12
+ redirect_jid = Jubjub::Jid.new(redirect_jid) if redirect_jid
13
+ @connection.pubsub.destroy jid, node, redirect_jid, redirect_node
14
+ end
15
+
16
+ def purge
17
+ @connection.pubsub.purge jid, node
18
+ end
19
+
20
+ def subscribe
21
+ @connection.pubsub.subscribe jid, node
22
+ end
23
+
24
+ def unsubscribe(subid = nil)
25
+ @connection.pubsub.unsubscribe jid, node, subid
26
+ end
27
+
28
+ def publish(data, item_id = nil)
29
+ @connection.pubsub.publish jid, node, data, item_id
30
+ end
31
+
32
+ def retract(item_id)
33
+ @connection.pubsub.retract jid, node, item_id
34
+ end
35
+
36
+ # Hide the connection details and show jid as string for compactness
37
+ def inspect
38
+ obj_id = "%x" % (object_id << 1)
39
+ "#<#{self.class}:0x#{obj_id} @jid=\"#{jid}\" @node=#{node.inspect}>"
40
+ end
41
+
42
+ def items
43
+ ItemCollection.new jid, node, @connection
44
+ end
45
+
46
+ def affiliations
47
+ AffiliationCollection.new jid, node, @connection
48
+ end
49
+
50
+ def uri
51
+ "xmpp:#{@jid}?;node=#{@node}"
52
+ end
53
+
54
+ def ==(other)
55
+ other.is_a?( self.class ) &&
56
+ other.jid == self.jid &&
57
+ other.node == self.node
58
+ end
59
+
60
+ private
61
+
62
+ def method_missing(name, *args, &block)
63
+ items.send(name, *args, &block)
64
+ end
65
+
66
+ end
@@ -0,0 +1,24 @@
1
+ class Jubjub::Pubsub::Subscription
2
+
3
+ attr_reader :jid, :node, :subscriber, :subid, :subscription
4
+
5
+ def initialize(jid, node, subscriber, subid, subscription, connection)
6
+ @jid = Jubjub::Jid.new jid
7
+ @node = node
8
+ @subscriber = Jubjub::Jid.new subscriber
9
+ @subid = subid
10
+ @subscription = subscription
11
+ @connection = connection
12
+ end
13
+
14
+ def unsubscribe
15
+ @connection.pubsub.unsubscribe jid, node, subid
16
+ end
17
+
18
+ # Hide the connection details and show jid as string for compactness
19
+ def inspect
20
+ obj_id = "%x" % (object_id << 1)
21
+ "#<#{self.class}:0x#{obj_id} @jid=\"#{jid}\" @node=#{node.inspect} @subscriber=\"#{subscriber}\" @subid=#{subid.inspect} @subscription=#{subscription.inspect}>"
22
+ end
23
+
24
+ end
@@ -54,12 +54,12 @@ module Jubjub
54
54
  # if no jid is specified will default to 'connection.JID_DOMAIN'
55
55
  def mucs(jid = nil)
56
56
  jid ||= "conference.#{jubjub_jid.domain}"
57
- Jubjub::MucCollection.new jid, jubjub_connection
57
+ Jubjub::Muc::Collection.new jid, jubjub_connection
58
58
  end
59
59
 
60
60
  def pubsub(jid = nil)
61
61
  jid ||= "pubsub.#{jubjub_jid.domain}"
62
- Jubjub::PubsubCollection.new jid, jubjub_connection
62
+ Jubjub::Pubsub::Collection.new jid, jubjub_connection
63
63
  end
64
64
  end
65
65
 
@@ -29,7 +29,7 @@ describe Jubjub::Connection::XmppGateway do
29
29
  use_vcr_cassette 'muc create with configuration', :record => :new_episodes
30
30
 
31
31
  it "return a Jubjub::Muc" do
32
- @config = Jubjub::MucConfiguration.new("allow_query_users" => { :type => "boolean", :value => "1", :label => "Allow users to query other users" })
32
+ @config = Jubjub::Muc::Configuration.new("allow_query_users" => { :type => "boolean", :value => "1", :label => "Allow users to query other users" })
33
33
 
34
34
  @room = @connection.muc.create( Jubjub::Jid.new( 'room@conference.theo-template.local/nick' ), @config )
35
35
  @room.should be_a_kind_of Jubjub::Muc
@@ -46,7 +46,7 @@ describe Jubjub::Connection::XmppGateway do
46
46
 
47
47
  use_vcr_cassette 'muc configuration', :record => :new_episodes
48
48
 
49
- it "return a Jubjub::MucConfiguration" do
49
+ it "return a Jubjub::Muc::Configuration" do
50
50
  config = @connection.muc.configuration( Jubjub::Jid.new 'room@conference.theo-template.local/nick' )
51
51
 
52
52
  expected_config = {
@@ -88,7 +88,7 @@ describe Jubjub::Connection::XmppGateway do
88
88
  { :value => "200", :label => "200" }]}
89
89
  }
90
90
 
91
- config.should == Jubjub::MucConfiguration.new(expected_config)
91
+ config.should == Jubjub::Muc::Configuration.new(expected_config)
92
92
  end
93
93
 
94
94
  end
@@ -26,6 +26,67 @@ describe Jubjub::Connection::XmppGateway do
26
26
  end
27
27
  end
28
28
 
29
+ describe "default_configuration" do
30
+ use_vcr_cassette 'pubsub default configuration', :record => :new_episodes
31
+
32
+ it "should return a Jubjub::Pubsub::Configuration" do
33
+ expected_config = {
34
+ "pubsub#deliver_payloads" => { :type => "boolean", :value => "1", :label => "Deliver payloads with event notifications" },
35
+ "pubsub#subscribe" => { :type => "boolean", :value => "1", :label => "Whether to allow subscriptions" },
36
+ "pubsub#notify_delete" => { :type => "boolean", :value => "0", :label => "Notify subscribers when the node is deleted" },
37
+ "pubsub#deliver_notifications" => { :type => "boolean", :value => "1", :label => "Deliver event notifications" },
38
+ "pubsub#persist_items" => { :type => "boolean", :value => "1", :label => "Persist items to storage" },
39
+ "pubsub#presence_based_delivery" => { :type => "boolean", :value => "0", :label => "Only deliver notifications to available users" },
40
+ "pubsub#notify_retract" => { :type => "boolean", :value => "1", :label => "Notify subscribers when items are removed from the node" },
41
+ "pubsub#notify_config" => { :type => "boolean", :value => "0", :label => "Notify subscribers when the node configuration changes" },
42
+ "pubsub#max_payload_size" => { :type => "text-single", :value => "60000", :label => "Max payload size in bytes" },
43
+ "pubsub#title" => { :type => "text-single", :value => "", :label => "A friendly name for the node" },
44
+ "pubsub#max_items" => { :type => "text-single", :value => "10", :label => "Max # of items to persist" },
45
+ "pubsub#collection" => { :type => "text-multi", :value => [], :label => "The collections with which a node is affiliated" },
46
+ "pubsub#roster_groups_allowed" => { :type => "list-multi", :value => [], :label => "Roster groups allowed to subscribe" },
47
+ "FORM_TYPE" => { :type => "hidden", :value => "http://jabber.org/protocol/pubsub#node_config", :label => "" },
48
+ "pubsub#send_last_published_item" => {
49
+ :type => "list-single",
50
+ :value => "on_sub_and_presence",
51
+ :label => "When to send the last published item",
52
+ :options => [
53
+ { :value => "never", :label => nil },
54
+ { :value => "on_sub", :label => nil },
55
+ { :value => "on_sub_and_presence", :label => nil }]},
56
+ "pubsub#access_model" => {
57
+ :type => "list-single",
58
+ :value => "open",
59
+ :label => "Specify the access model",
60
+ :options => [
61
+ { :value => "open", :label => nil },
62
+ { :value => "authorize", :label => nil },
63
+ { :value => "presence", :label => nil },
64
+ { :value => "roster", :label => nil },
65
+ { :value => "whitelist", :label => nil }]},
66
+ "pubsub#publish_model" => {
67
+ :type => "list-single",
68
+ :value => "publishers",
69
+ :label => "Specify the publisher model",
70
+ :options => [
71
+ { :value => "publishers", :label => nil },
72
+ { :value => "subscribers", :label => nil },
73
+ { :value => "open", :label => nil }]},
74
+ "pubsub#notification_type" => {
75
+ :type => "list-single",
76
+ :value => "headline",
77
+ :label => "Specify the event message type",
78
+ :options => [
79
+ { :value => "headline", :label => nil },
80
+ { :value => "normal", :label => nil }]}
81
+ }
82
+
83
+ config = @connection.pubsub.default_configuration 'pubsub.theo-template.local'
84
+
85
+ config.should be_a_kind_of Jubjub::Pubsub::Configuration
86
+ config.should == Jubjub::Pubsub::Configuration.new( expected_config )
87
+ end
88
+ end
89
+
29
90
  describe "destroy" do
30
91
  use_vcr_cassette 'pubsub destroy', :record => :new_episodes
31
92
 
@@ -40,6 +101,24 @@ describe Jubjub::Connection::XmppGateway do
40
101
  end
41
102
  end
42
103
 
104
+ describe "purge" do
105
+ use_vcr_cassette 'pubsub purge', :record => :new_episodes
106
+
107
+ before do
108
+ @connection.pubsub.create 'pubsub.theo-template.local', 'node_pubsub_purge'
109
+ end
110
+
111
+ it "should send correct stanza" do
112
+ # will attempt to create new vcr cassette if the stanza is wrong
113
+ # relies on cassette being manually checked
114
+ @connection.pubsub.purge('pubsub.theo-template.local', 'node_pubsub_purge').should be_true
115
+ end
116
+
117
+ after do
118
+ @connection.pubsub.destroy 'pubsub.theo-template.local', 'node_pubsub_purge'
119
+ end
120
+ end
121
+
43
122
  describe "list" do
44
123
 
45
124
  use_vcr_cassette 'pubsub list', :record => :new_episodes
@@ -91,10 +170,10 @@ describe Jubjub::Connection::XmppGateway do
91
170
  @connection.pubsub.create 'pubsub.theo-template.local', 'node_1'
92
171
  end
93
172
 
94
- it "return a Jubjub::PubsubSubscription" do
173
+ it "return a Jubjub::Pubsub::Subscription" do
95
174
  @subscription = @connection.pubsub.subscribe( 'pubsub.theo-template.local', 'node_1' )
96
175
 
97
- @subscription.should be_a_kind_of Jubjub::PubsubSubscription
176
+ @subscription.should be_a_kind_of Jubjub::Pubsub::Subscription
98
177
  @subscription.jid.should == Jubjub::Jid.new('pubsub.theo-template.local')
99
178
  @subscription.node.should == 'node_1'
100
179
  @subscription.subscriber.should == @jid
@@ -158,9 +237,9 @@ describe Jubjub::Connection::XmppGateway do
158
237
  describe "with id" do
159
238
  use_vcr_cassette 'pubsub publish with id', :record => :new_episodes
160
239
 
161
- it "should return a Jubjub::PubsubItem" do
240
+ it "should return a Jubjub::Pubsub::Item" do
162
241
  i = @connection.pubsub.publish 'pubsub.theo-template.local', 'node_1', Jubjub::DataForm.new, '123'
163
- i.should be_a_kind_of Jubjub::PubsubItem
242
+ i.should be_a_kind_of Jubjub::Pubsub::Item
164
243
  i.item_id.should == '123'
165
244
  i.data.should == "<x xmlns=\"jabber:x:data\" type=\"submit\"/>"
166
245
  end
@@ -170,10 +249,10 @@ describe Jubjub::Connection::XmppGateway do
170
249
  describe "with string payload" do
171
250
  use_vcr_cassette 'pubsub publish with string payload', :record => :new_episodes
172
251
 
173
- it "should return a Jubjub::PubsubItem" do
252
+ it "should return a Jubjub::Pubsub::Item" do
174
253
  item = "<x xmlns=\"jabber:x:data\" type=\"submit\"><field var=\"foo\"><value>true</value></field></x>"
175
254
  i = @connection.pubsub.publish 'pubsub.theo-template.local', 'node_1', item
176
- i.should be_a_kind_of Jubjub::PubsubItem
255
+ i.should be_a_kind_of Jubjub::Pubsub::Item
177
256
  i.item_id.should be_a_kind_of String
178
257
  i.data.should == "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"foo\">\n <value>true</value>\n </field>\n</x>"
179
258
  end
@@ -183,9 +262,9 @@ describe Jubjub::Connection::XmppGateway do
183
262
  describe "with dataform payload" do
184
263
  use_vcr_cassette 'pubsub publish with dataform payload', :record => :new_episodes
185
264
 
186
- it "should return a Jubjub::PubsubItem" do
265
+ it "should return a Jubjub::Pubsub::Item" do
187
266
  i = @connection.pubsub.publish 'pubsub.theo-template.local', 'node_1', Jubjub::DataForm.new({ :foo => {:type => "boolean", :value => true }})
188
- i.should be_a_kind_of Jubjub::PubsubItem
267
+ i.should be_a_kind_of Jubjub::Pubsub::Item
189
268
  i.item_id.should be_a_kind_of String
190
269
  i.data.should == "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"foo\">\n <value>true</value>\n </field>\n</x>"
191
270
  end
@@ -231,10 +310,10 @@ describe Jubjub::Connection::XmppGateway do
231
310
  @connection.pubsub.publish 'pubsub.theo-template.local', 'node_retrieve_items', Jubjub::DataForm.new(:foo => {:type => :boolean, :value => false}), 'abc'
232
311
  end
233
312
 
234
- it "should return array of PubsubItem when successful" do
313
+ it "should return array of Pubsub::Item when successful" do
235
314
  expected = [
236
- Jubjub::PubsubItem.new( 'pubsub.theo-template.local', 'node_retrieve_items', 'abc', "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"foo\">\n <value>false</value>\n </field>\n </x>", @connection ),
237
- Jubjub::PubsubItem.new( 'pubsub.theo-template.local', 'node_retrieve_items', 'efg', "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"bar\">\n <value>true</value>\n </field>\n </x>", @connection )
315
+ Jubjub::Pubsub::Item.new( 'pubsub.theo-template.local', 'node_retrieve_items', 'abc', "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"foo\">\n <value>false</value>\n </field>\n </x>", @connection ),
316
+ Jubjub::Pubsub::Item.new( 'pubsub.theo-template.local', 'node_retrieve_items', 'efg', "<x xmlns=\"jabber:x:data\" type=\"submit\">\n <field var=\"bar\">\n <value>true</value>\n </field>\n </x>", @connection )
238
317
  ]
239
318
 
240
319
  @connection.pubsub.retrieve_items( 'pubsub.theo-template.local', 'node_retrieve_items' ).should == expected
@@ -250,6 +329,83 @@ describe Jubjub::Connection::XmppGateway do
250
329
  end
251
330
  end
252
331
 
332
+ describe "retrieve_affiliations" do
333
+ use_vcr_cassette 'pubsub retrieve affiliations', :record => :new_episodes
334
+
335
+ it "should return array of Pubsub::Affiliation when successful" do
336
+ @connection.pubsub.create 'pubsub.theo-template.local', 'node_retrieve_affiliations'
337
+
338
+ expected = [
339
+ Jubjub::Pubsub::Affiliation.new(
340
+ 'pubsub.theo-template.local',
341
+ 'node_retrieve_affiliations',
342
+ Jubjub::Jid.new('theozaurus@theo-template.local'),
343
+ 'owner',
344
+ @connection
345
+ )
346
+ ]
347
+
348
+ @connection.pubsub.retrieve_affiliations( 'pubsub.theo-template.local', 'node_retrieve_affiliations' ).should == expected
349
+
350
+ # Clean up the node
351
+ @connection.pubsub.destroy 'pubsub.theo-template.local', 'node_retrieve_affiliations'
352
+ end
353
+
354
+ it "should return empty array when not successful" do
355
+ @connection.pubsub.retrieve_affiliations( 'pubsub.theo-template.local', 'made-up' ).should == []
356
+ end
357
+ end
358
+
359
+ describe "modify_affiliations" do
360
+ use_vcr_cassette 'pubsub modify affiliations', :record => :new_episodes
361
+
362
+ it "should return true when successful" do
363
+ pubsub = 'pubsub.theo-template.local'
364
+ node = 'node_modify_affiliations_1'
365
+ @connection.pubsub.create pubsub, node
366
+
367
+ affiliation = Jubjub::Pubsub::Affiliation.new pubsub, node, 'theozaurus@theo-template.local', 'owner', @connection
368
+ @connection.pubsub.modify_affiliations( pubsub, node, affiliation).should equal(true)
369
+
370
+ @connection.pubsub.destroy pubsub, node
371
+ end
372
+
373
+ it "should allow affiliations to be specified as an array" do
374
+ pubsub = 'pubsub.theo-template.local'
375
+ node = 'node_modify_affiliations_2'
376
+ @connection.pubsub.create pubsub, node
377
+
378
+ affiliation_1 = Jubjub::Pubsub::Affiliation.new pubsub, node, 'theozaurus@theo-template.local','owner', @connection
379
+ affiliation_2 = Jubjub::Pubsub::Affiliation.new pubsub, node, 'trex@theo-template.local', 'publisher', @connection
380
+ @connection.pubsub.modify_affiliations pubsub, node, [affiliation_1, affiliation_2]
381
+
382
+ @connection.pubsub.destroy pubsub, node
383
+ end
384
+
385
+ it "should allow affiliations to be specified as arguments" do
386
+ pubsub = 'pubsub.theo-template.local'
387
+ node = 'node_modify_affiliations_3'
388
+ @connection.pubsub.create pubsub, node
389
+
390
+ affiliation_1 = Jubjub::Pubsub::Affiliation.new pubsub, node, 'theozaurus@theo-template.local', 'owner', @connection
391
+ affiliation_2 = Jubjub::Pubsub::Affiliation.new pubsub, node, 'trex@theo-template.local', 'publisher', @connection
392
+ @connection.pubsub.modify_affiliations pubsub, node, affiliation_1, affiliation_2
393
+
394
+ @connection.pubsub.destroy pubsub, node
395
+ end
396
+
397
+ it "should return false if unsuccessful" do
398
+ pubsub = 'pubsub.theo-template.local'
399
+ node = 'node_modify_affiliations_4'
400
+ @connection.pubsub.create pubsub, node
401
+
402
+ affiliation = Jubjub::Pubsub::Affiliation.new pubsub, node, 'theozaurus@theo-template.local', 'WIBBLE', @connection
403
+ @connection.pubsub.modify_affiliations( pubsub, node, affiliation ).should equal(false)
404
+
405
+ @connection.pubsub.destroy pubsub, node
406
+ end
407
+ end
408
+
253
409
  end
254
410
 
255
411
  end