jubjub 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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