Specs for pubsub subscribe service (#2951)
* Add spec for pubsubhubbub/subscribe * Refactor pubsubhubbub/subscribe service
This commit is contained in:
		
							parent
							
								
									441d6dc734
								
							
						
					
					
						commit
						682507bc3c
					
				
					 2 changed files with 123 additions and 5 deletions
				
			
		|  | @ -1,14 +1,61 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Pubsubhubbub::SubscribeService < BaseService | ||||
|   URL_PATTERN = /\A#{URI.regexp(%w(http https))}\z/ | ||||
| 
 | ||||
|   attr_reader :account, :callback, :secret, :lease_seconds | ||||
| 
 | ||||
|   def call(account, callback, secret, lease_seconds) | ||||
|     return ['Invalid topic URL',        422] if account.nil? | ||||
|     return ['Invalid callback URL',     422] unless !callback.blank? && callback =~ /\A#{URI.regexp(%w(http https))}\z/ | ||||
|     return ['Callback URL not allowed', 403] if DomainBlock.blocked?(Addressable::URI.parse(callback).normalize.host) | ||||
|     @account = account | ||||
|     @callback = callback | ||||
|     @secret = secret | ||||
|     @lease_seconds = lease_seconds | ||||
| 
 | ||||
|     subscription = Subscription.where(account: account, callback_url: callback).first_or_create!(account: account, callback_url: callback) | ||||
|     Pubsubhubbub::ConfirmationWorker.perform_async(subscription.id, 'subscribe', secret, lease_seconds) | ||||
|     process_subscribe | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def process_subscribe | ||||
|     case subscribe_status | ||||
|     when :invalid_topic | ||||
|       ['Invalid topic URL', 422] | ||||
|     when :invalid_callback | ||||
|       ['Invalid callback URL', 422] | ||||
|     when :callback_not_allowed | ||||
|       ['Callback URL not allowed', 403] | ||||
|     when :valid | ||||
|       confirm_subscription | ||||
|       ['', 202] | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def subscribe_status | ||||
|     if account.nil? | ||||
|       :invalid_topic | ||||
|     elsif !valid_callback? | ||||
|       :invalid_callback | ||||
|     elsif blocked_domain? | ||||
|       :callback_not_allowed | ||||
|     else | ||||
|       :valid | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def confirm_subscription | ||||
|     subscription = locate_subscription | ||||
|     Pubsubhubbub::ConfirmationWorker.perform_async(subscription.id, 'subscribe', secret, lease_seconds) | ||||
|   end | ||||
| 
 | ||||
|   def valid_callback? | ||||
|     callback.present? && callback =~ URL_PATTERN | ||||
|   end | ||||
| 
 | ||||
|   def blocked_domain? | ||||
|     DomainBlock.blocked? Addressable::URI.parse(callback).normalize.host | ||||
|   end | ||||
| 
 | ||||
|   def locate_subscription | ||||
|     Subscription.where(account: account, callback_url: callback).first_or_create!(account: account, callback_url: callback) | ||||
|   end | ||||
| end | ||||
|  |  | |||
							
								
								
									
										71
									
								
								spec/services/pubsubhubbub/subscribe_service_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								spec/services/pubsubhubbub/subscribe_service_spec.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| require 'rails_helper' | ||||
| 
 | ||||
| describe Pubsubhubbub::SubscribeService do | ||||
|   describe '#call' do | ||||
|     subject { described_class.new } | ||||
|     let(:user_account) { Fabricate(:account) } | ||||
| 
 | ||||
|     context 'with a nil account' do | ||||
|       it 'returns the invalid topic status results' do | ||||
|         result = service_call(account: nil) | ||||
| 
 | ||||
|         expect(result).to eq invalid_topic_status | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'with an invalid callback url' do | ||||
|       it 'returns invalid callback status when callback is blank' do | ||||
|         result = service_call(callback: '') | ||||
| 
 | ||||
|         expect(result).to eq invalid_callback_status | ||||
|       end | ||||
|       it 'returns invalid callback status when callback is not a URI' do | ||||
|         result = service_call(callback: 'invalid-hostname') | ||||
| 
 | ||||
|         expect(result).to eq invalid_callback_status | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'with a blocked domain in the callback' do | ||||
|       it 'returns callback not allowed' do | ||||
|         Fabricate(:domain_block, domain: 'test.host', severity: :suspend) | ||||
|         result = service_call(callback: 'https://test.host/api') | ||||
| 
 | ||||
|         expect(result).to eq not_allowed_callback_status | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'with a valid account and callback' do | ||||
|       it 'returns success status and confirms subscription' do | ||||
|         allow(Pubsubhubbub::ConfirmationWorker).to receive(:perform_async).and_return(nil) | ||||
|         subscription = Fabricate(:subscription, account: user_account) | ||||
| 
 | ||||
|         result = service_call(callback: subscription.callback_url) | ||||
|         expect(result).to eq success_status | ||||
|         expect(Pubsubhubbub::ConfirmationWorker).to have_received(:perform_async).with(subscription.id, 'subscribe', 'asdf', 3600) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def service_call(account: user_account, callback: 'https://callback.host', secret: 'asdf', lease_seconds: 3600) | ||||
|     subject.call(account, callback, secret, lease_seconds) | ||||
|   end | ||||
| 
 | ||||
|   def invalid_topic_status | ||||
|     ['Invalid topic URL', 422] | ||||
|   end | ||||
| 
 | ||||
|   def invalid_callback_status | ||||
|     ['Invalid callback URL', 422] | ||||
|   end | ||||
| 
 | ||||
|   def not_allowed_callback_status | ||||
|     ['Callback URL not allowed', 403] | ||||
|   end | ||||
| 
 | ||||
|   def success_status | ||||
|     ['', 202] | ||||
|   end | ||||
| end | ||||
		Loading…
	
	Add table
		
		Reference in a new issue