about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorMatt Jankowski <mjankowski@thoughtbot.com>2017-05-10 18:19:37 -0400
committerEugen Rochko <eugen@zeonfederated.com>2017-05-11 00:19:37 +0200
commit08949cca413ae7df2a7b8e845e8c9a0e3c246b3a (patch)
tree5ac0992441727efed8851924f72c9401775d68ab /app
parenta231f915a0734d1089ca76dbd7f4593ef63e8764 (diff)
Pubsub confirmation worker spec (#2974)
* Add specs for valid challenge response from pubsub confirmation worker

* Refactor the pubsub confirmation worker
Diffstat (limited to 'app')
-rw-r--r--app/workers/pubsubhubbub/confirmation_worker.rb88
1 files changed, 71 insertions, 17 deletions
diff --git a/app/workers/pubsubhubbub/confirmation_worker.rb b/app/workers/pubsubhubbub/confirmation_worker.rb
index b02dd3f55..9186c5d7d 100644
--- a/app/workers/pubsubhubbub/confirmation_worker.rb
+++ b/app/workers/pubsubhubbub/confirmation_worker.rb
@@ -6,31 +6,85 @@ class Pubsubhubbub::ConfirmationWorker
 
   sidekiq_options queue: 'push', retry: false
 
+  attr_reader :subscription, :mode, :secret, :lease_seconds
+
   def perform(subscription_id, mode, secret = nil, lease_seconds = nil)
-    subscription = Subscription.find(subscription_id)
-    challenge    = SecureRandom.hex
+    @subscription = Subscription.find(subscription_id)
+    @mode = mode
+    @secret = secret
+    @lease_seconds = lease_seconds
+    process_confirmation
+  end
 
-    subscription.secret        = secret
-    subscription.lease_seconds = lease_seconds
-    subscription.confirmed     = true
+  private
 
-    response = HTTP.headers(user_agent: 'Mastodon/PubSubHubbub')
-                   .timeout(:per_operation, write: 20, connect: 20, read: 50)
-                   .get(subscription.callback_url, params: {
-                          'hub.topic' => account_url(subscription.account, format: :atom),
-                          'hub.mode'          => mode,
-                          'hub.challenge'     => challenge,
-                          'hub.lease_seconds' => subscription.lease_seconds,
-                        })
+  def process_confirmation
+    prepare_subscription
 
-    body = response.body.to_s
+    confirm_callback
+    logger.debug "Confirming PuSH subscription for #{subscription.callback_url} with challenge #{challenge}: #{callback_response_body}"
 
-    logger.debug "Confirming PuSH subscription for #{subscription.callback_url} with challenge #{challenge}: #{body}"
+    update_subscription
+  end
 
-    if mode == 'subscribe' && body == challenge
+  def update_subscription
+    if successful_subscribe?
       subscription.save!
-    elsif (mode == 'unsubscribe' && body == challenge) || !subscription.confirmed?
+    elsif successful_unsubscribe?
       subscription.destroy!
     end
   end
+
+  def successful_subscribe?
+    subscribing? && response_matches_challenge?
+  end
+
+  def successful_unsubscribe?
+    (unsubscribing? && response_matches_challenge?) || !subscription.confirmed?
+  end
+
+  def response_matches_challenge?
+    callback_response_body == challenge
+  end
+
+  def subscribing?
+    mode == 'subscribe'
+  end
+
+  def unsubscribing?
+    mode == 'unsubscribe'
+  end
+
+  def confirm_callback
+    @_confirm_callback ||= callback_get_with_params
+  end
+
+  def callback_get_with_params
+    HTTP.headers(user_agent: 'Mastodon/PubSubHubbub')
+        .timeout(:per_operation, write: 20, connect: 20, read: 50)
+        .get(subscription.callback_url, params: callback_params)
+  end
+
+  def callback_response_body
+    confirm_callback.body.to_s
+  end
+
+  def callback_params
+    {
+      'hub.topic' => account_url(subscription.account, format: :atom),
+      'hub.mode' => mode,
+      'hub.challenge' => challenge,
+      'hub.lease_seconds' => subscription.lease_seconds,
+    }
+  end
+
+  def prepare_subscription
+    subscription.secret = secret
+    subscription.lease_seconds = lease_seconds
+    subscription.confirmed = true
+  end
+
+  def challenge
+    @_challenge ||= SecureRandom.hex
+  end
 end