forked from cybrespace/mastodon
		
	Specs for API push controller, with refactor (#2926)
* Coverage for api push controller * Refactor the api/push controller
This commit is contained in:
		
							parent
							
								
									fed585e3f4
								
							
						
					
					
						commit
						04166c4a35
					
				
					 2 changed files with 100 additions and 25 deletions
				
			
		| 
						 | 
					@ -2,36 +2,66 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Api::PushController < ApiController
 | 
					class Api::PushController < ApiController
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
    mode          = params['hub.mode']
 | 
					    response, status = process_push_request
 | 
				
			||||||
    topic         = params['hub.topic']
 | 
					 | 
				
			||||||
    callback      = params['hub.callback']
 | 
					 | 
				
			||||||
    lease_seconds = params['hub.lease_seconds']
 | 
					 | 
				
			||||||
    secret        = params['hub.secret']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case mode
 | 
					 | 
				
			||||||
    when 'subscribe'
 | 
					 | 
				
			||||||
      response, status = Pubsubhubbub::SubscribeService.new.call(topic_to_account(topic), callback, secret, lease_seconds)
 | 
					 | 
				
			||||||
    when 'unsubscribe'
 | 
					 | 
				
			||||||
      response, status = Pubsubhubbub::UnsubscribeService.new.call(topic_to_account(topic), callback)
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      response = "Unknown mode: #{mode}"
 | 
					 | 
				
			||||||
      status   = 422
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render plain: response, status: status
 | 
					    render plain: response, status: status
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def topic_to_account(topic_url)
 | 
					  def process_push_request
 | 
				
			||||||
    return if topic_url.blank?
 | 
					    case hub_mode
 | 
				
			||||||
 | 
					    when 'subscribe'
 | 
				
			||||||
 | 
					      Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds)
 | 
				
			||||||
 | 
					    when 'unsubscribe'
 | 
				
			||||||
 | 
					      Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback)
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      ["Unknown mode: #{hub_mode}", 422]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uri    = Addressable::URI.parse(topic_url).normalize
 | 
					  def hub_mode
 | 
				
			||||||
    params = Rails.application.routes.recognize_path(uri.path)
 | 
					    params['hub.mode']
 | 
				
			||||||
    domain = uri.host + (uri.port ? ":#{uri.port}" : '')
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return unless TagManager.instance.web_domain?(domain) && params[:controller] == 'accounts' && params[:action] == 'show' && params[:format] == 'atom'
 | 
					  def hub_topic
 | 
				
			||||||
 | 
					    params['hub.topic']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Account.find_local(params[:username])
 | 
					  def hub_callback
 | 
				
			||||||
 | 
					    params['hub.callback']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hub_lease_seconds
 | 
				
			||||||
 | 
					    params['hub.lease_seconds']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hub_secret
 | 
				
			||||||
 | 
					    params['hub.secret']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def account_from_topic
 | 
				
			||||||
 | 
					    if hub_topic.present? && local_domain? && account_feed_path?
 | 
				
			||||||
 | 
					      Account.find_local(hub_topic_params[:username])
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hub_topic_params
 | 
				
			||||||
 | 
					    @_hub_topic_params ||= Rails.application.routes.recognize_path(hub_topic_uri.path)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hub_topic_uri
 | 
				
			||||||
 | 
					    @_hub_topic_uri ||= Addressable::URI.parse(hub_topic).normalize
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def local_domain?
 | 
				
			||||||
 | 
					    TagManager.instance.web_domain?(hub_topic_domain)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def hub_topic_domain
 | 
				
			||||||
 | 
					    hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def account_feed_path?
 | 
				
			||||||
 | 
					    hub_topic_params[:controller] == 'accounts' && hub_topic_params[:action] == 'show' && hub_topic_params[:format] == 'atom'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,56 @@ require 'rails_helper'
 | 
				
			||||||
RSpec.describe Api::PushController, type: :controller do
 | 
					RSpec.describe Api::PushController, type: :controller do
 | 
				
			||||||
  describe 'POST #update' do
 | 
					  describe 'POST #update' do
 | 
				
			||||||
    context 'with hub.mode=subscribe' do
 | 
					    context 'with hub.mode=subscribe' do
 | 
				
			||||||
      pending
 | 
					      it 'creates a subscription' do
 | 
				
			||||||
 | 
					        service = double(call: ['', 202])
 | 
				
			||||||
 | 
					        allow(Pubsubhubbub::SubscribeService).to receive(:new).and_return(service)
 | 
				
			||||||
 | 
					        account = Fabricate(:account)
 | 
				
			||||||
 | 
					        account_topic_url = "https://#{Rails.configuration.x.local_domain}/users/#{account.username}.atom"
 | 
				
			||||||
 | 
					        post :update, params: {
 | 
				
			||||||
 | 
					          'hub.mode' => 'subscribe',
 | 
				
			||||||
 | 
					          'hub.topic' => account_topic_url,
 | 
				
			||||||
 | 
					          'hub.callback' => 'https://callback.host/api',
 | 
				
			||||||
 | 
					          'hub.lease_seconds' => '3600',
 | 
				
			||||||
 | 
					          'hub.secret' => 'as1234df',
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(service).to have_received(:call).with(
 | 
				
			||||||
 | 
					          account,
 | 
				
			||||||
 | 
					          'https://callback.host/api',
 | 
				
			||||||
 | 
					          'as1234df',
 | 
				
			||||||
 | 
					          '3600',
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:success)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context 'with hub.mode=unsubscribe' do
 | 
					    context 'with hub.mode=unsubscribe' do
 | 
				
			||||||
      pending
 | 
					      it 'unsubscribes the account' do
 | 
				
			||||||
 | 
					        service = double(call: ['', 202])
 | 
				
			||||||
 | 
					        allow(Pubsubhubbub::UnsubscribeService).to receive(:new).and_return(service)
 | 
				
			||||||
 | 
					        account = Fabricate(:account)
 | 
				
			||||||
 | 
					        account_topic_url = "https://#{Rails.configuration.x.local_domain}/users/#{account.username}.atom"
 | 
				
			||||||
 | 
					        post :update, params: {
 | 
				
			||||||
 | 
					          'hub.mode' => 'unsubscribe',
 | 
				
			||||||
 | 
					          'hub.topic' => account_topic_url,
 | 
				
			||||||
 | 
					          'hub.callback' => 'https://callback.host/api',
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(service).to have_received(:call).with(
 | 
				
			||||||
 | 
					          account,
 | 
				
			||||||
 | 
					          'https://callback.host/api',
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:success)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context 'with unknown mode' do
 | 
				
			||||||
 | 
					      it 'returns an unknown mode error' do
 | 
				
			||||||
 | 
					        post :update, params: { 'hub.mode' => 'fake' }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(422)
 | 
				
			||||||
 | 
					        expect(response.body).to match(/Unknown mode/)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue