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
 | 
			
		||||
  def update
 | 
			
		||||
    mode          = params['hub.mode']
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    response, status = process_push_request
 | 
			
		||||
    render plain: response, status: status
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def topic_to_account(topic_url)
 | 
			
		||||
    return if topic_url.blank?
 | 
			
		||||
 | 
			
		||||
    uri    = Addressable::URI.parse(topic_url).normalize
 | 
			
		||||
    params = Rails.application.routes.recognize_path(uri.path)
 | 
			
		||||
    domain = uri.host + (uri.port ? ":#{uri.port}" : '')
 | 
			
		||||
 | 
			
		||||
    return unless TagManager.instance.web_domain?(domain) && params[:controller] == 'accounts' && params[:action] == 'show' && params[:format] == 'atom'
 | 
			
		||||
 | 
			
		||||
    Account.find_local(params[:username])
 | 
			
		||||
  def process_push_request
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
  def hub_mode
 | 
			
		||||
    params['hub.mode']
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def hub_topic
 | 
			
		||||
    params['hub.topic']
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,56 @@ require 'rails_helper'
 | 
			
		|||
RSpec.describe Api::PushController, type: :controller do
 | 
			
		||||
  describe 'POST #update' 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
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue