From 137100dcf38c0da0fe7044a4c92aa06eae02c420 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 13 Apr 2017 07:09:07 -0400 Subject: [PATCH] Clean up well-known routes/controllers (#1649) * Add request spec for host meta route returning xml * Add routing spec for xrd routes * Update well-known routes * Move webfinger and host-meta actions to their own controllers --- .../well_known/host_meta_controller.rb | 13 +++++ .../well_known/webfinger_controller.rb | 43 +++++++++++++++ app/controllers/xrd_controller.rb | 55 ------------------- .../host_meta/show.xml.ruby} | 0 .../webfinger/show.json.rabl} | 0 .../webfinger/show.xml.ruby} | 0 config/routes.rb | 4 +- .../well_known/host_meta_controller_spec.rb | 13 +++++ .../well_known/webfinger_controller_spec.rb | 21 +++++++ spec/controllers/xrd_controller_spec.rb | 26 --------- spec/requests/host_meta_request_spec.rb | 12 ++++ spec/routing/well_known_routes_spec.rb | 15 +++++ 12 files changed, 119 insertions(+), 83 deletions(-) create mode 100644 app/controllers/well_known/host_meta_controller.rb create mode 100644 app/controllers/well_known/webfinger_controller.rb delete mode 100644 app/controllers/xrd_controller.rb rename app/views/{xrd/host_meta.xml.ruby => well_known/host_meta/show.xml.ruby} (100%) rename app/views/{xrd/webfinger.json.rabl => well_known/webfinger/show.json.rabl} (100%) rename app/views/{xrd/webfinger.xml.ruby => well_known/webfinger/show.xml.ruby} (100%) create mode 100644 spec/controllers/well_known/host_meta_controller_spec.rb create mode 100644 spec/controllers/well_known/webfinger_controller_spec.rb delete mode 100644 spec/controllers/xrd_controller_spec.rb create mode 100644 spec/requests/host_meta_request_spec.rb create mode 100644 spec/routing/well_known_routes_spec.rb diff --git a/app/controllers/well_known/host_meta_controller.rb b/app/controllers/well_known/host_meta_controller.rb new file mode 100644 index 000000000..2f0960acd --- /dev/null +++ b/app/controllers/well_known/host_meta_controller.rb @@ -0,0 +1,13 @@ + # frozen_string_literal: true + +module WellKnown + class HostMetaController < ApplicationController + def show + @webfinger_template = "#{webfinger_url}?resource={uri}" + + respond_to do |format| + format.xml { render content_type: 'application/xrd+xml' } + end + end + end +end diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb new file mode 100644 index 000000000..1a8ef5f90 --- /dev/null +++ b/app/controllers/well_known/webfinger_controller.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module WellKnown + class WebfingerController < ApplicationController + def show + @account = Account.find_local!(username_from_resource) + @canonical_account_uri = @account.to_webfinger_s + @magic_key = pem_to_magic_key(@account.keypair.public_key) + + respond_to do |format| + format.xml { render content_type: 'application/xrd+xml' } + format.json { render content_type: 'application/jrd+json' } + end + rescue ActiveRecord::RecordNotFound + head 404 + end + + private + + def username_from_resource + WebfingerResource.new(resource_param).username + end + + def pem_to_magic_key(public_key) + modulus, exponent = [public_key.n, public_key.e].map do |component| + result = [] + + until component.zero? + result << [component % 256].pack('C') + component >>= 8 + end + + result.reverse.join + end + + (['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.') + end + + def resource_param + params.require(:resource) + end + end +end diff --git a/app/controllers/xrd_controller.rb b/app/controllers/xrd_controller.rb deleted file mode 100644 index 2886315ac..000000000 --- a/app/controllers/xrd_controller.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true - -class XrdController < ApplicationController - before_action :set_default_format_xml, only: :host_meta - - def host_meta - @webfinger_template = "#{webfinger_url}?resource={uri}" - - respond_to do |format| - format.xml { render content_type: 'application/xrd+xml' } - end - end - - def webfinger - @account = Account.find_local!(username_from_resource) - @canonical_account_uri = @account.to_webfinger_s - @magic_key = pem_to_magic_key(@account.keypair.public_key) - - respond_to do |format| - format.xml { render content_type: 'application/xrd+xml' } - format.json { render content_type: 'application/jrd+json' } - end - rescue ActiveRecord::RecordNotFound - head 404 - end - - private - - def set_default_format_xml - request.format = 'xml' if request.headers['HTTP_ACCEPT'].nil? && params[:format].nil? - end - - def username_from_resource - WebfingerResource.new(resource_param).username - end - - def pem_to_magic_key(public_key) - modulus, exponent = [public_key.n, public_key.e].map do |component| - result = [] - - until component.zero? - result << [component % 256].pack('C') - component >>= 8 - end - - result.reverse.join - end - - (['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.') - end - - def resource_param - params.require(:resource) - end -end diff --git a/app/views/xrd/host_meta.xml.ruby b/app/views/well_known/host_meta/show.xml.ruby similarity index 100% rename from app/views/xrd/host_meta.xml.ruby rename to app/views/well_known/host_meta/show.xml.ruby diff --git a/app/views/xrd/webfinger.json.rabl b/app/views/well_known/webfinger/show.json.rabl similarity index 100% rename from app/views/xrd/webfinger.json.rabl rename to app/views/well_known/webfinger/show.json.rabl diff --git a/app/views/xrd/webfinger.xml.ruby b/app/views/well_known/webfinger/show.xml.ruby similarity index 100% rename from app/views/xrd/webfinger.xml.ruby rename to app/views/well_known/webfinger/show.xml.ruby diff --git a/config/routes.rb b/config/routes.rb index ca3f31055..6e48d3b92 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,8 +15,8 @@ Rails.application.routes.draw do controllers authorizations: 'oauth/authorizations', authorized_applications: 'oauth/authorized_applications' end - get '.well-known/host-meta', to: 'xrd#host_meta', as: :host_meta - get '.well-known/webfinger', to: 'xrd#webfinger', as: :webfinger, defaults: { format: 'json' } + get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' } + get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger, defaults: { format: 'json' } devise_for :users, path: 'auth', controllers: { sessions: 'auth/sessions', diff --git a/spec/controllers/well_known/host_meta_controller_spec.rb b/spec/controllers/well_known/host_meta_controller_spec.rb new file mode 100644 index 000000000..8a040021a --- /dev/null +++ b/spec/controllers/well_known/host_meta_controller_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +describe WellKnown::HostMetaController, type: :controller do + render_views + + describe 'GET #show' do + it 'returns http success' do + get :show, format: :xml + + expect(response).to have_http_status(:success) + end + end +end diff --git a/spec/controllers/well_known/webfinger_controller_spec.rb b/spec/controllers/well_known/webfinger_controller_spec.rb new file mode 100644 index 000000000..6e493b037 --- /dev/null +++ b/spec/controllers/well_known/webfinger_controller_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +describe WellKnown::WebfingerController, type: :controller do + render_views + + describe 'GET #show' do + let(:alice) { Fabricate(:account, username: 'alice') } + + it 'returns http success when account can be found' do + get :show, params: { resource: alice.to_webfinger_s }, format: :json + + expect(response).to have_http_status(:success) + end + + it 'returns http not found when account cannot be found' do + get :show, params: { resource: 'acct:not@existing.com' }, format: :json + + expect(response).to have_http_status(:not_found) + end + end +end diff --git a/spec/controllers/xrd_controller_spec.rb b/spec/controllers/xrd_controller_spec.rb deleted file mode 100644 index 33b17f152..000000000 --- a/spec/controllers/xrd_controller_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'rails_helper' - -RSpec.describe XrdController, type: :controller do - render_views - - describe 'GET #host_meta' do - it 'returns http success' do - get :host_meta - expect(response).to have_http_status(:success) - end - end - - describe 'GET #webfinger' do - let(:alice) { Fabricate(:account, username: 'alice') } - - it 'returns http success when account can be found' do - get :webfinger, params: { resource: alice.to_webfinger_s }, format: :json - expect(response).to have_http_status(:success) - end - - it 'returns http not found when account cannot be found' do - get :webfinger, params: { resource: 'acct:not@existing.com' }, format: :json - expect(response).to have_http_status(:not_found) - end - end -end diff --git a/spec/requests/host_meta_request_spec.rb b/spec/requests/host_meta_request_spec.rb new file mode 100644 index 000000000..0c51b5f48 --- /dev/null +++ b/spec/requests/host_meta_request_spec.rb @@ -0,0 +1,12 @@ +require "rails_helper" + +describe "The host_meta route" do + describe "requested without accepts headers" do + it "returns an xml response" do + get host_meta_url + + expect(response).to have_http_status(:success) + expect(response.content_type).to eq "application/xrd+xml" + end + end +end diff --git a/spec/routing/well_known_routes_spec.rb b/spec/routing/well_known_routes_spec.rb new file mode 100644 index 000000000..9540c3de3 --- /dev/null +++ b/spec/routing/well_known_routes_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +describe 'the host-meta route' do + it 'routes to correct place with xml format' do + expect(get('/.well-known/host-meta')). + to route_to('well_known/host_meta#show', format: 'xml') + end +end + +describe 'the webfinger route' do + it 'routes to correct place with json format' do + expect(get('/.well-known/webfinger')). + to route_to('well_known/webfinger#show', format: 'json') + end +end