hootenanny 0.0.1 → 0.1.0

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 (112) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +5 -0
  3. data/Gemfile +5 -7
  4. data/Gemfile.lock +46 -28
  5. data/app/controllers/hootenanny/notifications_controller.rb +31 -0
  6. data/app/controllers/hootenanny/parameters.rb +16 -0
  7. data/app/controllers/hootenanny/subscriptions_controller.rb +24 -3
  8. data/app/models/hootenanny/publish_notification.rb +90 -0
  9. data/app/models/hootenanny/subscription.rb +72 -23
  10. data/config/routes.rb +2 -1
  11. data/db/migrate/20130607182642_add_started_at_and_lease_duration_to_subscriptions.rb +15 -0
  12. data/db/migrate/20130608225621_add_hmac_secret_to_subscription.rb +5 -0
  13. data/db/migrate/20130611235218_add_publish_notifications.rb +9 -0
  14. data/db/migrate/20130612153138_add_timestamps_to_publish_notification.rb +5 -0
  15. data/db/migrate/20130705200729_add_processed_flag_to_publish_notifications.rb +6 -0
  16. data/db/migrate/20130711061329_switch_publish_notification_process_state_from_boolean_to_string.rb +11 -0
  17. data/db/migrate/20130711061558_add_index_to_notifications_state.rb +5 -0
  18. data/hootenanny.gemspec +6 -2
  19. data/lib/hootenanny/configuration.rb +43 -0
  20. data/lib/hootenanny/correspondent.rb +44 -0
  21. data/lib/hootenanny/errors.rb +42 -1
  22. data/lib/hootenanny/feed.rb +75 -0
  23. data/lib/hootenanny/feed/atom_feed.rb +18 -0
  24. data/lib/hootenanny/feed/atom_feed_item.rb +8 -0
  25. data/lib/hootenanny/feed/digest_feed.rb +14 -0
  26. data/lib/hootenanny/feed/digest_feed_item.rb +11 -0
  27. data/lib/hootenanny/feed/feed_item.rb +30 -0
  28. data/lib/hootenanny/feed/file.rb +66 -0
  29. data/lib/hootenanny/feed/json_feed.rb +48 -0
  30. data/lib/hootenanny/feed/json_feed_item.rb +8 -0
  31. data/lib/hootenanny/feed/null_feed.rb +27 -0
  32. data/lib/hootenanny/feed/rss_feed.rb +52 -0
  33. data/lib/hootenanny/feed/rss_feed_item.rb +8 -0
  34. data/lib/hootenanny/feed_store.rb +30 -0
  35. data/lib/hootenanny/feed_store/file_feed_store.rb +55 -0
  36. data/lib/hootenanny/feed_store/web_feed_store.rb +42 -0
  37. data/lib/hootenanny/hub.rb +116 -22
  38. data/lib/hootenanny/publish_notification_expiration_policy.rb +17 -0
  39. data/lib/hootenanny/request.rb +40 -0
  40. data/lib/hootenanny/request/publish_notification.rb +94 -0
  41. data/lib/hootenanny/request/subscription.rb +153 -0
  42. data/lib/hootenanny/subscription_delivery.rb +47 -0
  43. data/lib/hootenanny/topic.rb +38 -0
  44. data/lib/hootenanny/topic_synchronizer.rb +71 -0
  45. data/lib/hootenanny/uri.rb +53 -0
  46. data/lib/hootenanny/verification.rb +108 -0
  47. data/lib/hootenanny/version.rb +1 -1
  48. data/spec/dummy/config/database.yml +12 -6
  49. data/spec/dummy/db/migrate/20130607183149_add_started_at_and_lease_duration_to_subscriptions.hootenanny.rb +16 -0
  50. data/spec/dummy/db/migrate/20130608231253_add_hmac_secret_to_subscription.hootenanny.rb +6 -0
  51. data/spec/dummy/db/migrate/20130611235546_add_publish_notifications.hootenanny.rb +10 -0
  52. data/spec/dummy/db/migrate/20130612153353_add_timestamps_to_publish_notification.hootenanny.rb +6 -0
  53. data/spec/dummy/db/migrate/20130705200832_add_processed_flag_to_publish_notifications.hootenanny.rb +7 -0
  54. data/spec/dummy/db/migrate/20130711061518_switch_publish_notification_process_state_from_boolean_to_string.hootenanny.rb +12 -0
  55. data/spec/dummy/db/migrate/20130711061629_add_index_to_notifications_state.hootenanny.rb +6 -0
  56. data/spec/factories/publish_notification.rb +13 -0
  57. data/spec/factories/requests/publish_notification.rb +11 -0
  58. data/spec/factories/requests/subscription.rb +46 -0
  59. data/spec/factories/subscription.rb +14 -2
  60. data/spec/factories/verification.rb +15 -0
  61. data/spec/features/publishers/can_notify_the_hub_of_content_updates_spec.rb +58 -0
  62. data/spec/features/subscribers/are_protected_from_unwarranted_subscriptions_spec.rb +59 -0
  63. data/spec/features/subscribers/can_receive_distributions_of_topic_content_spec.rb +175 -0
  64. data/spec/features/subscribers/can_subscribe_to_a_topic_spec.rb +76 -7
  65. data/spec/fixtures/feeds/atom/97d79220f68b4bf27.atom +0 -0
  66. data/spec/fixtures/feeds/atom/sample_feed.atom +51 -0
  67. data/spec/fixtures/feeds/digest/97d79220f68b4bf27.digest +1 -0
  68. data/spec/fixtures/feeds/digest/complete_broadcasted_items/5b187098da59f077f/97d79220f68b4bf27.digest +6 -0
  69. data/spec/fixtures/feeds/digest/incomplete_broadcasted_items/5b187098da59f077f/97d79220f68b4bf27.digest +5 -0
  70. data/spec/fixtures/feeds/digest/sample_feed.digest +6 -0
  71. data/spec/fixtures/feeds/json/97d79220f68b4bf27.json +1 -0
  72. data/spec/fixtures/feeds/json/feed_with_one_item.json +21 -0
  73. data/spec/fixtures/feeds/json/sample_feed.json +30 -0
  74. data/spec/fixtures/feeds/rss/5b187098da59f077f/97d79220f68b4bf27.rss +21 -0
  75. data/spec/fixtures/feeds/rss/97d79220f68b4bf27.rss +0 -0
  76. data/spec/fixtures/feeds/rss/feed_with_one_item.rss +15 -0
  77. data/spec/fixtures/feeds/rss/minimal_feed.rss +12 -0
  78. data/spec/fixtures/feeds/rss/sample_feed.rss +22 -0
  79. data/spec/fixtures/feeds/rss/sample_feed_2.rss +22 -0
  80. data/spec/lib/hootenanny/configuration_spec.rb +7 -0
  81. data/spec/lib/hootenanny/correspondent_spec.rb +94 -0
  82. data/spec/lib/hootenanny/errors_spec.rb +21 -0
  83. data/spec/lib/hootenanny/feed/atom_feed_item_spec.rb +9 -0
  84. data/spec/lib/hootenanny/feed/atom_feed_spec.rb +40 -0
  85. data/spec/lib/hootenanny/feed/digest_feed_item_spec.rb +9 -0
  86. data/spec/lib/hootenanny/feed/digest_feed_spec.rb +40 -0
  87. data/spec/lib/hootenanny/feed/feed_item_spec.rb +49 -0
  88. data/spec/lib/hootenanny/feed/file_spec.rb +66 -0
  89. data/spec/lib/hootenanny/feed/json_feed_item_spec.rb +9 -0
  90. data/spec/lib/hootenanny/feed/json_feed_spec.rb +128 -0
  91. data/spec/lib/hootenanny/feed/null_feed_spec.rb +9 -0
  92. data/spec/lib/hootenanny/feed/rss_feed_item_spec.rb +9 -0
  93. data/spec/lib/hootenanny/feed/rss_feed_spec.rb +143 -0
  94. data/spec/lib/hootenanny/feed_spec.rb +159 -0
  95. data/spec/lib/hootenanny/feed_store/file_feed_store_spec.rb +58 -0
  96. data/spec/lib/hootenanny/feed_store/web_feed_store_spec.rb +47 -0
  97. data/spec/lib/hootenanny/feed_store_spec.rb +27 -0
  98. data/spec/lib/hootenanny/hub_spec.rb +73 -0
  99. data/spec/lib/hootenanny/publish_notification_expiration_policy_spec.rb +35 -0
  100. data/spec/lib/hootenanny/request/publish_notification_spec.rb +43 -0
  101. data/spec/lib/hootenanny/request/subscription_spec.rb +89 -0
  102. data/spec/lib/hootenanny/request_spec.rb +21 -0
  103. data/spec/lib/hootenanny/subscription_delivery_spec.rb +54 -0
  104. data/spec/lib/hootenanny/topic_spec.rb +15 -0
  105. data/spec/lib/hootenanny/topic_synchronizer_spec.rb +98 -0
  106. data/spec/lib/hootenanny/uri_spec.rb +32 -0
  107. data/spec/lib/hootenanny/verification_spec.rb +92 -0
  108. data/spec/models/hootenanny/publish_notification_spec.rb +55 -0
  109. data/spec/models/hootenanny/subscription_spec.rb +58 -19
  110. data/spec/support/verification.rb +63 -0
  111. metadata +231 -14
  112. data/spec/controllers/hootenanny/hub_spec.rb +0 -15
@@ -0,0 +1,92 @@
1
+ require 'rspectacular'
2
+ require 'support/verification'
3
+ require 'hootenanny/verification'
4
+
5
+ module Hootenanny
6
+ describe Verification do
7
+ context 'when the verification representation can be verified' do
8
+ before { confirmed_verification 'mymode',
9
+ 'http://example.com',
10
+ 'http://example.org' }
11
+
12
+ it 'can determine that it is verified' do
13
+ verification = build(:verification, url: 'http://example.com',
14
+ topic: 'http://example.org',
15
+ mode: 'mymode')
16
+
17
+ expect(verification).to be_verified
18
+ end
19
+ end
20
+
21
+ context 'when the verification representation cannot be verified' do
22
+ before { unconfirmed_verification 'mymode',
23
+ 'http://example.com',
24
+ 'http://example.org' }
25
+
26
+ it 'can determine that it is verified' do
27
+ verification = build(:verification, url: 'http://example.com',
28
+ topic: 'http://example.org',
29
+ mode: 'mymode')
30
+
31
+ expect(verification).not_to be_verified
32
+ end
33
+ end
34
+
35
+ context 'when the verification representation cannot be verified' do
36
+ before { unverified_verification 'mymode',
37
+ 'http://example.com',
38
+ 'http://example.org' }
39
+
40
+ it 'can determine that it is verified' do
41
+ verification = build(:verification, url: 'http://example.com',
42
+ topic: 'http://example.org',
43
+ mode: 'mymode')
44
+
45
+ expect(verification).not_to be_verified
46
+ end
47
+ end
48
+
49
+ it 'appends the mode to the URI' do
50
+ verification = build(:verification, mode: 'foo')
51
+
52
+ expect(verification.uri.query).to include 'hub.mode=foo'
53
+ end
54
+
55
+ it 'appends the topic to the URI' do
56
+ verification = build(:verification, topic: 'http://topic.com')
57
+
58
+ expect(verification.uri.query).to include 'hub.topic=http%3A%2F%2Ftopic.com'
59
+ end
60
+
61
+ it 'appends the challenge token to the URI' do
62
+ verification = build(:verification)
63
+
64
+ expect(verification.uri.query).to match %r{hub.challenge=[0-9a-f]{32}}
65
+ end
66
+
67
+ it 'appends the verify token to the URI if it is passed in' do
68
+ verification = build(:verification, requester_token: 'foo')
69
+
70
+ expect(verification.uri.query).to include 'hub.verify_token=foo'
71
+ end
72
+
73
+ it 'does not append the verify token to the URI if it is not passed in' do
74
+ verification = build(:verification, requester_token: nil)
75
+
76
+ expect(verification.uri.query).not_to include 'hub.verify_token'
77
+ end
78
+
79
+ it 'appends the verification parameters to the URI even if they already exist in the subscription URI' do
80
+ verification = build(:verification, url: 'http://example.com?hub.mode=foo',
81
+ mode: 'mymode')
82
+
83
+ expect(verification.uri.to_s).to match %r{http://example.com\?hub.mode=foo&hub.mode=mymode.+}
84
+ end
85
+
86
+ it 'does not add an unnecessary ampersand to the URL if the :url has no query component' do
87
+ verification = build(:verification, url: 'http://example.com')
88
+
89
+ expect(verification.uri.to_s).to match %r{http://example.com\?[^&]}
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,55 @@
1
+ require 'rspectacular/spec_helpers/active_record_basic'
2
+ require 'hootenanny/publish_notification'
3
+
4
+ module Hootenanny
5
+ describe PublishNotification do
6
+ context 'when no notifications exist' do
7
+ before { expect(PublishNotification.count).to be_zero }
8
+
9
+ it 'can create a notification based on the topic' do
10
+ PublishNotification.notify('http://mytopic')
11
+
12
+ retrieved_notification = PublishNotification.for('http://mytopic').first
13
+
14
+ expect(PublishNotification.count).to eql 1
15
+ expect(retrieved_notification.topic).to eql 'http://mytopic'
16
+ end
17
+ end
18
+
19
+ context 'when a notification exists' do
20
+ let!(:existing_notification) { create :publish_notification,
21
+ :topic => 'http://mytopic' }
22
+
23
+ it 'can find the notification based on the topic' do
24
+ retrieved_notification = PublishNotification.for('http://mytopic').first
25
+
26
+ expect(retrieved_notification).to eql existing_notification
27
+ end
28
+
29
+ it 'can updates the existing notification', :time_mock => Time.utc(2012, 7, 26, 12, 0, 0) do
30
+ PublishNotification.notify('http://mytopic')
31
+
32
+ retrieved_notification = PublishNotification.for('http://mytopic').first
33
+
34
+ expect(PublishNotification.count).to eql 1
35
+ expect(retrieved_notification.updated_at).to eql Time.utc(2012, 7, 26, 12, 0, 0)
36
+ end
37
+ end
38
+
39
+ context 'when multiple notifications exist' do
40
+ let!(:existing_notifications) {[
41
+ create(:publish_notification, :topic => 'mytopic'),
42
+ create(:publish_notification, :topic => 'myothertopic')
43
+ ]}
44
+
45
+ it 'can find the notification based on the topic' do
46
+ retrieved_notifications = PublishNotification.for([
47
+ 'mytopic',
48
+ 'myothertopic'
49
+ ]).all
50
+
51
+ expect(retrieved_notifications).to eql existing_notifications
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,31 +1,46 @@
1
1
  require 'rspectacular/spec_helpers/active_record_basic'
2
2
  require 'hootenanny/subscription'
3
3
 
4
- Subscription ||= Hootenanny::Subscription
4
+ module Hootenanny
5
+ describe Subscription do
6
+ it 'can find itself based on its topic if it is active' do
7
+ create(:subscription, :active,
8
+ :topic => 'http://topic.com')
5
9
 
6
- describe Hootenanny::Subscription do
7
- it 'can find itself based on its topic' do
8
- existing_subscription = create(:subscription, :topic => 'my_topic')
9
-
10
- found_subscriptions = Subscription.to('my_topic')
10
+ found_subscriptions = Subscription.to('http://topic.com')
11
11
  found_subscription = found_subscriptions.first
12
12
 
13
13
  expect(found_subscriptions).to have(1).item
14
14
 
15
15
  expect(found_subscription).to be_a Subscription
16
- expect(found_subscription.topic).to eql 'my_topic'
16
+ expect(found_subscription.topic).to eql 'http://topic.com'
17
+ end
18
+
19
+ it 'cannot find itself based on its topic if it is inactive' do
20
+ create(:subscription, :inactive,
21
+ :topic => 'http://topic.com')
22
+
23
+ found_subscriptions = Subscription.to('http://topic.com')
24
+
25
+ expect(found_subscriptions).to be_empty
17
26
  end
18
27
 
19
28
  context 'when a subscription does not exist for a given subscriber and topic' do
20
29
  before { expect(Subscription.count).to be_zero }
21
30
 
22
- it 'can assign a subscription to a given subscriber and topic' do
23
- assigned_subscription = Subscription.assign( subscriber: 'http://example.com/my_callback',
24
- to: 'http://example.org/my_topic')
31
+ it 'can subscribe a subscription to a given subscriber and topic', :time_mock => Time.utc(2012, 7, 20, 12, 0, 0) do
32
+ subscribeed_subscription = Subscription.subscribe(
33
+ subscriber: 'http://example.com/my_callback',
34
+ to: 'http://example.org/my_topic',
35
+ lease_duration: 12,
36
+ digest_secret: 'secret')
25
37
 
26
- expect(assigned_subscription).to be_persisted
27
- expect(assigned_subscription.subscriber).to eql 'http://example.com/my_callback'
28
- expect(assigned_subscription.topic).to eql 'http://example.org/my_topic'
38
+ expect(subscribeed_subscription).to be_persisted
39
+ expect(subscribeed_subscription.subscriber).to eql URI.parse('http://example.com/my_callback')
40
+ expect(subscribeed_subscription.topic).to eql 'http://example.org/my_topic'
41
+ expect(subscribeed_subscription.lease_duration).to eql 12
42
+ expect(subscribeed_subscription.digest_secret).to eql 'secret'
43
+ expect(subscribeed_subscription.started_at).to eql Time.utc(2012, 7, 20, 12, 0, 0)
29
44
  end
30
45
  end
31
46
 
@@ -35,16 +50,40 @@ describe Hootenanny::Subscription do
35
50
  topic: 'http://example.org/my_topic')
36
51
  end
37
52
 
38
- it 'can does not create a new subscription but rather returns the current one' do
39
- assigned_subscription = Subscription.assign( subscriber: 'http://example.com/my_callback',
40
- to: 'http://example.org/my_topic')
53
+ it 'does not create a new subscription but rather returns the current one' do
54
+ subscribeed_subscription = Subscription.subscribe(
55
+ subscriber: 'http://example.com/my_callback',
56
+ to: 'http://example.org/my_topic',
57
+ lease_duration: 30)
41
58
 
42
- expect(assigned_subscription).to eql existing_subscription
59
+ expect(subscribeed_subscription).to eql existing_subscription
60
+ end
61
+
62
+ it 'updates the attributes of the current subscription to match the new subscription request' do
63
+ expect(existing_subscription.lease_duration).not_to eql 30
64
+
65
+ subscribeed_subscription = Subscription.subscribe(
66
+ subscriber: 'http://example.com/my_callback',
67
+ to: 'http://example.org/my_topic',
68
+ lease_duration: 30)
69
+
70
+ expect(subscribeed_subscription.lease_duration).to eql 30
71
+ end
72
+
73
+ it 'updates the starting date of the subscription to be the current time', :time_mock => Time.utc(2012, 6, 20, 12, 0, 0) do
74
+ subscribeed_subscription = Subscription.subscribe(
75
+ subscriber: 'http://example.com/my_callback',
76
+ to: 'http://example.org/my_topic',
77
+ lease_duration: 30)
78
+
79
+ expect(subscribeed_subscription.started_at).to eql Time.utc(2012, 6, 20, 12, 0, 0)
43
80
  end
44
81
  end
45
82
 
46
83
  it 'properly handles the error when the URIs are invalid' do
47
- expect { Subscription.assign( subscriber: 'http://iluvhamburgerz!!!',
48
- to: 'http://gimmeburger!!!') }.to raise_error Hootenanny::SubscriptionAssignmentError
84
+ expect { Subscription.subscribe( subscriber: 'http://iluvhamburgerz!!!',
85
+ to: 'http://gimmeburger!!!') }
86
+ .to raise_error Hootenanny::URI::InvalidError
49
87
  end
50
88
  end
89
+ end
@@ -0,0 +1,63 @@
1
+ def unconfirmed_subscription_verification(callback_url, topic_url)
2
+ unconfirmed_verification('subscribe', callback_url, topic_url)
3
+ end
4
+
5
+ def unverified_subscription_verification(callback_url, topic_url)
6
+ unverified_verification('subscribe', callback_url, topic_url)
7
+ end
8
+
9
+ def confirmed_subscription_verification(callback_url, topic_url)
10
+ confirmed_verification('subscribe', callback_url, topic_url)
11
+ end
12
+
13
+ def confirmed_verification(mode, callback_url, topic_url, options = {})
14
+ stub_request(:get, /#{callback_url}.*/)
15
+ .with do |request|
16
+ params = request.uri.query_values
17
+
18
+ params['hub.mode'] == mode &&
19
+ params['hub.topic'] == topic_url &&
20
+ params['hub.challenge'].match(/[0-9a-f]{32}/) &&
21
+ params['hub.verify_token'] == options[:requester_token]
22
+ end
23
+ .to_return do |request|
24
+ {
25
+ status: 200,
26
+ body: request.uri.query_values['hub.challenge'],
27
+ }
28
+ end
29
+ end
30
+
31
+ def unconfirmed_verification(mode, callback_url, topic_url)
32
+ stub_request(:get, /#{callback_url}.*/)
33
+ .with do |request|
34
+ params = request.uri.query_values
35
+
36
+ params['hub.mode'] == mode &&
37
+ params['hub.topic'] == topic_url &&
38
+ params['hub.challenge'].match(/[0-9a-f]{32}/)
39
+ end
40
+ .to_return do |request|
41
+ {
42
+ status: 404,
43
+ body: nil,
44
+ }
45
+ end
46
+ end
47
+
48
+ def unverified_verification(mode, callback_url, topic_url)
49
+ stub_request(:get, /#{callback_url}.*/)
50
+ .with do |request|
51
+ params = request.uri.query_values
52
+
53
+ params['hub.mode'] == mode &&
54
+ params['hub.topic'] == topic_url &&
55
+ params['hub.challenge'].match(/[0-9a-f]{32}/)
56
+ end
57
+ .to_return do |request|
58
+ {
59
+ status: 200,
60
+ body: 'aaaaaaaaaaaaaaaaaaaaa',
61
+ }
62
+ end
63
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hootenanny
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-23 00:00:00.000000000 Z
12
+ date: 2013-07-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -43,6 +43,38 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 0.2.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: faraday
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.7
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.7
62
+ - !ruby/object:Gem::Dependency
63
+ name: chronological
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.0beta10
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.0beta10
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: pg
48
80
  requirement: !ruby/object:Gem::Requirement
@@ -60,29 +92,29 @@ dependencies:
60
92
  - !ruby/object:Gem::Version
61
93
  version: '0'
62
94
  - !ruby/object:Gem::Dependency
63
- name: sqlite3
95
+ name: rspec-rails
64
96
  requirement: !ruby/object:Gem::Requirement
65
97
  none: false
66
98
  requirements:
67
- - - ! '>='
99
+ - - ~>
68
100
  - !ruby/object:Gem::Version
69
- version: '0'
101
+ version: 2.14.0.rc1
70
102
  type: :development
71
103
  prerelease: false
72
104
  version_requirements: !ruby/object:Gem::Requirement
73
105
  none: false
74
106
  requirements:
75
- - - ! '>='
107
+ - - ~>
76
108
  - !ruby/object:Gem::Version
77
- version: '0'
109
+ version: 2.14.0.rc1
78
110
  - !ruby/object:Gem::Dependency
79
- name: rspec-rails
111
+ name: rspec
80
112
  requirement: !ruby/object:Gem::Requirement
81
113
  none: false
82
114
  requirements:
83
115
  - - ~>
84
116
  - !ruby/object:Gem::Version
85
- version: '2.13'
117
+ version: 2.14.0.rc1
86
118
  type: :development
87
119
  prerelease: false
88
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +122,7 @@ dependencies:
90
122
  requirements:
91
123
  - - ~>
92
124
  - !ruby/object:Gem::Version
93
- version: '2.13'
125
+ version: 2.14.0.rc1
94
126
  - !ruby/object:Gem::Dependency
95
127
  name: database_cleaner
96
128
  requirement: !ruby/object:Gem::Requirement
@@ -139,6 +171,38 @@ dependencies:
139
171
  - - ~>
140
172
  - !ruby/object:Gem::Version
141
173
  version: '4.2'
174
+ - !ruby/object:Gem::Dependency
175
+ name: timecop
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ~>
180
+ - !ruby/object:Gem::Version
181
+ version: 0.6.1
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ~>
188
+ - !ruby/object:Gem::Version
189
+ version: 0.6.1
190
+ - !ruby/object:Gem::Dependency
191
+ name: webmock
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ~>
196
+ - !ruby/object:Gem::Version
197
+ version: '1.11'
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ~>
204
+ - !ruby/object:Gem::Version
205
+ version: '1.11'
142
206
  description: A drop-in PubSubHubBub-compliant Rails Engine for easy hubbubing.
143
207
  email: support@thekompanee.com
144
208
  executables: []
@@ -149,26 +213,62 @@ files:
149
213
  - .gitignore
150
214
  - .rspec
151
215
  - .ruby-version
216
+ - .travis.yml
152
217
  - Gemfile
153
218
  - Gemfile.lock
154
219
  - README.md
155
220
  - Rakefile
221
+ - app/controllers/hootenanny/notifications_controller.rb
222
+ - app/controllers/hootenanny/parameters.rb
156
223
  - app/controllers/hootenanny/subscriptions_controller.rb
224
+ - app/models/hootenanny/publish_notification.rb
157
225
  - app/models/hootenanny/subscription.rb
158
226
  - config/routes.rb
159
227
  - db/migrate/20130522014217_create_subscription_table.rb
160
228
  - db/migrate/20130522020623_rename_subscriptions_table.rb
161
229
  - db/migrate/20130522235837_add_topic_to_subscriptions.rb
162
230
  - db/migrate/20130523032940_add_subscriber_to_subscriptions.rb
231
+ - db/migrate/20130607182642_add_started_at_and_lease_duration_to_subscriptions.rb
232
+ - db/migrate/20130608225621_add_hmac_secret_to_subscription.rb
233
+ - db/migrate/20130611235218_add_publish_notifications.rb
234
+ - db/migrate/20130612153138_add_timestamps_to_publish_notification.rb
235
+ - db/migrate/20130705200729_add_processed_flag_to_publish_notifications.rb
236
+ - db/migrate/20130711061329_switch_publish_notification_process_state_from_boolean_to_string.rb
237
+ - db/migrate/20130711061558_add_index_to_notifications_state.rb
163
238
  - hootenanny.gemspec
164
239
  - lib/hootenanny.rb
240
+ - lib/hootenanny/configuration.rb
241
+ - lib/hootenanny/correspondent.rb
165
242
  - lib/hootenanny/engine.rb
166
243
  - lib/hootenanny/errors.rb
244
+ - lib/hootenanny/feed.rb
245
+ - lib/hootenanny/feed/atom_feed.rb
246
+ - lib/hootenanny/feed/atom_feed_item.rb
247
+ - lib/hootenanny/feed/digest_feed.rb
248
+ - lib/hootenanny/feed/digest_feed_item.rb
249
+ - lib/hootenanny/feed/feed_item.rb
250
+ - lib/hootenanny/feed/file.rb
251
+ - lib/hootenanny/feed/json_feed.rb
252
+ - lib/hootenanny/feed/json_feed_item.rb
253
+ - lib/hootenanny/feed/null_feed.rb
254
+ - lib/hootenanny/feed/rss_feed.rb
255
+ - lib/hootenanny/feed/rss_feed_item.rb
256
+ - lib/hootenanny/feed_store.rb
257
+ - lib/hootenanny/feed_store/file_feed_store.rb
258
+ - lib/hootenanny/feed_store/web_feed_store.rb
167
259
  - lib/hootenanny/hub.rb
260
+ - lib/hootenanny/publish_notification_expiration_policy.rb
261
+ - lib/hootenanny/request.rb
262
+ - lib/hootenanny/request/publish_notification.rb
263
+ - lib/hootenanny/request/subscription.rb
264
+ - lib/hootenanny/subscription_delivery.rb
265
+ - lib/hootenanny/topic.rb
266
+ - lib/hootenanny/topic_synchronizer.rb
267
+ - lib/hootenanny/uri.rb
268
+ - lib/hootenanny/verification.rb
168
269
  - lib/hootenanny/version.rb
169
270
  - lib/tasks/hootenanny_tasks.rake
170
271
  - script/rails
171
- - spec/controllers/hootenanny/hub_spec.rb
172
272
  - spec/dummy/README.rdoc
173
273
  - spec/dummy/Rakefile
174
274
  - spec/dummy/app/assets/javascripts/application.js
@@ -199,15 +299,74 @@ files:
199
299
  - spec/dummy/db/migrate/20130522020714_rename_subscriptions_table.hootenanny.rb
200
300
  - spec/dummy/db/migrate/20130523000104_add_topic_to_subscriptions.hootenanny.rb
201
301
  - spec/dummy/db/migrate/20130523053741_add_subscriber_to_subscriptions.hootenanny.rb
302
+ - spec/dummy/db/migrate/20130607183149_add_started_at_and_lease_duration_to_subscriptions.hootenanny.rb
303
+ - spec/dummy/db/migrate/20130608231253_add_hmac_secret_to_subscription.hootenanny.rb
304
+ - spec/dummy/db/migrate/20130611235546_add_publish_notifications.hootenanny.rb
305
+ - spec/dummy/db/migrate/20130612153353_add_timestamps_to_publish_notification.hootenanny.rb
306
+ - spec/dummy/db/migrate/20130705200832_add_processed_flag_to_publish_notifications.hootenanny.rb
307
+ - spec/dummy/db/migrate/20130711061518_switch_publish_notification_process_state_from_boolean_to_string.hootenanny.rb
308
+ - spec/dummy/db/migrate/20130711061629_add_index_to_notifications_state.hootenanny.rb
202
309
  - spec/dummy/lib/assets/.gitkeep
203
310
  - spec/dummy/public/404.html
204
311
  - spec/dummy/public/422.html
205
312
  - spec/dummy/public/500.html
206
313
  - spec/dummy/public/favicon.ico
207
314
  - spec/dummy/script/rails
315
+ - spec/factories/publish_notification.rb
316
+ - spec/factories/requests/publish_notification.rb
317
+ - spec/factories/requests/subscription.rb
208
318
  - spec/factories/subscription.rb
319
+ - spec/factories/verification.rb
320
+ - spec/features/publishers/can_notify_the_hub_of_content_updates_spec.rb
321
+ - spec/features/subscribers/are_protected_from_unwarranted_subscriptions_spec.rb
322
+ - spec/features/subscribers/can_receive_distributions_of_topic_content_spec.rb
209
323
  - spec/features/subscribers/can_subscribe_to_a_topic_spec.rb
324
+ - spec/fixtures/feeds/atom/97d79220f68b4bf27.atom
325
+ - spec/fixtures/feeds/atom/sample_feed.atom
326
+ - spec/fixtures/feeds/digest/97d79220f68b4bf27.digest
327
+ - spec/fixtures/feeds/digest/complete_broadcasted_items/5b187098da59f077f/97d79220f68b4bf27.digest
328
+ - spec/fixtures/feeds/digest/incomplete_broadcasted_items/5b187098da59f077f/97d79220f68b4bf27.digest
329
+ - spec/fixtures/feeds/digest/sample_feed.digest
330
+ - spec/fixtures/feeds/json/97d79220f68b4bf27.json
331
+ - spec/fixtures/feeds/json/feed_with_one_item.json
332
+ - spec/fixtures/feeds/json/sample_feed.json
333
+ - spec/fixtures/feeds/rss/5b187098da59f077f/97d79220f68b4bf27.rss
334
+ - spec/fixtures/feeds/rss/97d79220f68b4bf27.rss
335
+ - spec/fixtures/feeds/rss/feed_with_one_item.rss
336
+ - spec/fixtures/feeds/rss/minimal_feed.rss
337
+ - spec/fixtures/feeds/rss/sample_feed.rss
338
+ - spec/fixtures/feeds/rss/sample_feed_2.rss
339
+ - spec/lib/hootenanny/configuration_spec.rb
340
+ - spec/lib/hootenanny/correspondent_spec.rb
341
+ - spec/lib/hootenanny/errors_spec.rb
342
+ - spec/lib/hootenanny/feed/atom_feed_item_spec.rb
343
+ - spec/lib/hootenanny/feed/atom_feed_spec.rb
344
+ - spec/lib/hootenanny/feed/digest_feed_item_spec.rb
345
+ - spec/lib/hootenanny/feed/digest_feed_spec.rb
346
+ - spec/lib/hootenanny/feed/feed_item_spec.rb
347
+ - spec/lib/hootenanny/feed/file_spec.rb
348
+ - spec/lib/hootenanny/feed/json_feed_item_spec.rb
349
+ - spec/lib/hootenanny/feed/json_feed_spec.rb
350
+ - spec/lib/hootenanny/feed/null_feed_spec.rb
351
+ - spec/lib/hootenanny/feed/rss_feed_item_spec.rb
352
+ - spec/lib/hootenanny/feed/rss_feed_spec.rb
353
+ - spec/lib/hootenanny/feed_spec.rb
354
+ - spec/lib/hootenanny/feed_store/file_feed_store_spec.rb
355
+ - spec/lib/hootenanny/feed_store/web_feed_store_spec.rb
356
+ - spec/lib/hootenanny/feed_store_spec.rb
357
+ - spec/lib/hootenanny/hub_spec.rb
358
+ - spec/lib/hootenanny/publish_notification_expiration_policy_spec.rb
359
+ - spec/lib/hootenanny/request/publish_notification_spec.rb
360
+ - spec/lib/hootenanny/request/subscription_spec.rb
361
+ - spec/lib/hootenanny/request_spec.rb
362
+ - spec/lib/hootenanny/subscription_delivery_spec.rb
363
+ - spec/lib/hootenanny/topic_spec.rb
364
+ - spec/lib/hootenanny/topic_synchronizer_spec.rb
365
+ - spec/lib/hootenanny/uri_spec.rb
366
+ - spec/lib/hootenanny/verification_spec.rb
367
+ - spec/models/hootenanny/publish_notification_spec.rb
210
368
  - spec/models/hootenanny/subscription_spec.rb
369
+ - spec/support/verification.rb
211
370
  homepage: https://github.com/thekompanee/hootenanny
212
371
  licenses: []
213
372
  post_install_message:
@@ -223,7 +382,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
223
382
  version: '0'
224
383
  segments:
225
384
  - 0
226
- hash: 3205946143954146130
385
+ hash: 3624011435823886776
227
386
  required_rubygems_version: !ruby/object:Gem::Requirement
228
387
  none: false
229
388
  requirements:
@@ -232,7 +391,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
391
  version: '0'
233
392
  segments:
234
393
  - 0
235
- hash: 3205946143954146130
394
+ hash: 3624011435823886776
236
395
  requirements: []
237
396
  rubyforge_project: hootenanny
238
397
  rubygems_version: 1.8.23
@@ -240,7 +399,6 @@ signing_key:
240
399
  specification_version: 3
241
400
  summary: PubSubHubBub Engine for Rails
242
401
  test_files:
243
- - spec/controllers/hootenanny/hub_spec.rb
244
402
  - spec/dummy/README.rdoc
245
403
  - spec/dummy/Rakefile
246
404
  - spec/dummy/app/assets/javascripts/application.js
@@ -271,12 +429,71 @@ test_files:
271
429
  - spec/dummy/db/migrate/20130522020714_rename_subscriptions_table.hootenanny.rb
272
430
  - spec/dummy/db/migrate/20130523000104_add_topic_to_subscriptions.hootenanny.rb
273
431
  - spec/dummy/db/migrate/20130523053741_add_subscriber_to_subscriptions.hootenanny.rb
432
+ - spec/dummy/db/migrate/20130607183149_add_started_at_and_lease_duration_to_subscriptions.hootenanny.rb
433
+ - spec/dummy/db/migrate/20130608231253_add_hmac_secret_to_subscription.hootenanny.rb
434
+ - spec/dummy/db/migrate/20130611235546_add_publish_notifications.hootenanny.rb
435
+ - spec/dummy/db/migrate/20130612153353_add_timestamps_to_publish_notification.hootenanny.rb
436
+ - spec/dummy/db/migrate/20130705200832_add_processed_flag_to_publish_notifications.hootenanny.rb
437
+ - spec/dummy/db/migrate/20130711061518_switch_publish_notification_process_state_from_boolean_to_string.hootenanny.rb
438
+ - spec/dummy/db/migrate/20130711061629_add_index_to_notifications_state.hootenanny.rb
274
439
  - spec/dummy/lib/assets/.gitkeep
275
440
  - spec/dummy/public/404.html
276
441
  - spec/dummy/public/422.html
277
442
  - spec/dummy/public/500.html
278
443
  - spec/dummy/public/favicon.ico
279
444
  - spec/dummy/script/rails
445
+ - spec/factories/publish_notification.rb
446
+ - spec/factories/requests/publish_notification.rb
447
+ - spec/factories/requests/subscription.rb
280
448
  - spec/factories/subscription.rb
449
+ - spec/factories/verification.rb
450
+ - spec/features/publishers/can_notify_the_hub_of_content_updates_spec.rb
451
+ - spec/features/subscribers/are_protected_from_unwarranted_subscriptions_spec.rb
452
+ - spec/features/subscribers/can_receive_distributions_of_topic_content_spec.rb
281
453
  - spec/features/subscribers/can_subscribe_to_a_topic_spec.rb
454
+ - spec/fixtures/feeds/atom/97d79220f68b4bf27.atom
455
+ - spec/fixtures/feeds/atom/sample_feed.atom
456
+ - spec/fixtures/feeds/digest/97d79220f68b4bf27.digest
457
+ - spec/fixtures/feeds/digest/complete_broadcasted_items/5b187098da59f077f/97d79220f68b4bf27.digest
458
+ - spec/fixtures/feeds/digest/incomplete_broadcasted_items/5b187098da59f077f/97d79220f68b4bf27.digest
459
+ - spec/fixtures/feeds/digest/sample_feed.digest
460
+ - spec/fixtures/feeds/json/97d79220f68b4bf27.json
461
+ - spec/fixtures/feeds/json/feed_with_one_item.json
462
+ - spec/fixtures/feeds/json/sample_feed.json
463
+ - spec/fixtures/feeds/rss/5b187098da59f077f/97d79220f68b4bf27.rss
464
+ - spec/fixtures/feeds/rss/97d79220f68b4bf27.rss
465
+ - spec/fixtures/feeds/rss/feed_with_one_item.rss
466
+ - spec/fixtures/feeds/rss/minimal_feed.rss
467
+ - spec/fixtures/feeds/rss/sample_feed.rss
468
+ - spec/fixtures/feeds/rss/sample_feed_2.rss
469
+ - spec/lib/hootenanny/configuration_spec.rb
470
+ - spec/lib/hootenanny/correspondent_spec.rb
471
+ - spec/lib/hootenanny/errors_spec.rb
472
+ - spec/lib/hootenanny/feed/atom_feed_item_spec.rb
473
+ - spec/lib/hootenanny/feed/atom_feed_spec.rb
474
+ - spec/lib/hootenanny/feed/digest_feed_item_spec.rb
475
+ - spec/lib/hootenanny/feed/digest_feed_spec.rb
476
+ - spec/lib/hootenanny/feed/feed_item_spec.rb
477
+ - spec/lib/hootenanny/feed/file_spec.rb
478
+ - spec/lib/hootenanny/feed/json_feed_item_spec.rb
479
+ - spec/lib/hootenanny/feed/json_feed_spec.rb
480
+ - spec/lib/hootenanny/feed/null_feed_spec.rb
481
+ - spec/lib/hootenanny/feed/rss_feed_item_spec.rb
482
+ - spec/lib/hootenanny/feed/rss_feed_spec.rb
483
+ - spec/lib/hootenanny/feed_spec.rb
484
+ - spec/lib/hootenanny/feed_store/file_feed_store_spec.rb
485
+ - spec/lib/hootenanny/feed_store/web_feed_store_spec.rb
486
+ - spec/lib/hootenanny/feed_store_spec.rb
487
+ - spec/lib/hootenanny/hub_spec.rb
488
+ - spec/lib/hootenanny/publish_notification_expiration_policy_spec.rb
489
+ - spec/lib/hootenanny/request/publish_notification_spec.rb
490
+ - spec/lib/hootenanny/request/subscription_spec.rb
491
+ - spec/lib/hootenanny/request_spec.rb
492
+ - spec/lib/hootenanny/subscription_delivery_spec.rb
493
+ - spec/lib/hootenanny/topic_spec.rb
494
+ - spec/lib/hootenanny/topic_synchronizer_spec.rb
495
+ - spec/lib/hootenanny/uri_spec.rb
496
+ - spec/lib/hootenanny/verification_spec.rb
497
+ - spec/models/hootenanny/publish_notification_spec.rb
282
498
  - spec/models/hootenanny/subscription_spec.rb
499
+ - spec/support/verification.rb