Как пропустить аутентификацию при тестировании контроллеров rails в rspec? - PullRequest
0 голосов
/ 09 ноября 2019

У меня есть приложение rai backend api, интегрированное со службой auth0, которая проверяет только достоверность auth_token, полученного из приложения внешнего интерфейса. После защиты всех конечных точек API-интерфейса бэкэнда все мои тесты завершаются неудачно с результатом «Not Authenticated», как и должно быть. Однако я не могу понять, как пройти аутентификацию и не требовать ее для тестов rspec. Вот мои уроки:

projects_controller_spec.rb

require "rails_helper"

RSpec.describe Api::V1::ProjectsController, :type => :controller do
  describe 'GET /api/v1/organizations/1/projects' do
    let!(:organization) { create(:organization_with_projects) }
    before { get :index, params: { organization_id: organization } }

    context 'when authorized' do
      it 'should return JSON objects' do
        expect(json['projects'].count).to equal(3)
      end

      it { expect(response).to have_http_status(:ok) }
      it { expect(response.content_type).to include('application/json') }
    end

  describe 'POST /api/v1/organizations/1/projects' do
    let!(:organization) { create(:organization) }
    let(:project) { organization.projects.first }
    before { post :create, params: { organization_id: organization, project: attributes_for(:project) } }

    context 'when authorized' do
      it { expect(response).to have_http_status(:created) }
      it { expect(response.content_type).to include("application/json") }
      it { expect(json).to eq(serialized(project)) }
    end
  end
end

application_controller.rb

class ApplicationController < ActionController::API
  include Pundit
  include Secured

  rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found

  private
  def record_not_found(error)
    render json: { error: error.message }, status: :not_found
  end
end

беспокойства / secured.rb

module Secured
  extend ActiveSupport::Concern

  included do
    before_action :authenticate_request!
  end

  private

  def authenticate_request!
    # Create user if not existing
    pundit_user

    auth_token
  rescue JWT::VerificationError, JWT::DecodeError
    render json: { errors: ['Not Authenticated'] }, status: :unauthorized
  end

  def http_token
    if request.headers['Authorization'].present?
      request.headers['Authorization'].split(' ').last
    end
  end

  def auth_token
    JsonWebToken.verify(http_token)
  end

  def pundit_user
    User.create_from_token_payload({token: auth_token[0], organization_id: 
request.parameters['organization_id']})
  end

end

lib / json_web_token.rb

require 'net/http'
require 'uri'

class JsonWebToken
  def self.verify(token)
    JWT.decode(token, nil,
           true, # Verify the signature of this token
           algorithm: 'RS256',
           iss: 'https://xxx.auth0.com/',
           verify_iss: true,
           aud: Rails.application.secrets.auth0_api_audience,
           verify_aud: true) do |header|
      jwks_hash[header['kid']]
    end
  end

  def self.jwks_hash
    jwks_raw = Net::HTTP.get URI("https://xxx.auth0.com/.well-known/jwks.json")
     jwks_keys = Array(JSON.parse(jwks_raw)['keys'])
    Hash[
        jwks_keys
            .map do |k|
          [
              k['kid'],
              OpenSSL::X509::Certificate.new(
                  Base64.decode64(k['x5c'].first)
              ).public_key
          ]
        end
    ]
  end
end

1 Ответ

0 голосов
/ 09 ноября 2019

Похоже, я нашел решение, добавив следующую строку в каждый файл спецификации контроллера:

before { allow(controller).to receive(:authenticate_request!).and_return(true) }
...