# frozen_string_literal: true module Hoboken module AddOns # OmniAuth authentication (allows you to select a provider). # class OmniAuth < ::Hoboken::Group attr_reader :provider def add_gem @provider = ask('Specify a provider (i.e. twitter, facebook. etc.): ').downcase provider_version = ask('Specify provider version: ') gem gem_name, version: provider_version end def setup_middleware insert_into_file('app.rb', after: %r{require 'sinatra('|/base')}) do "\nrequire '#{gem_name}'\nrequire 'sinatra/json'\n" end snippet = <<~CODE use OmniAuth::Builder do provider :#{provider}, ENV['#{provider.upcase}_KEY'], ENV['#{provider.upcase}_SECRET'] end CODE indentation = classic? ? 2 : 6 location = /use Rack::Session::Cookie.+\n/ insert_into_file('config/environment.rb', after: location) do "\n#{indent(snippet, indentation)}\n" end end # rubocop:disable Metrics/MethodLength def add_routes routes = <<~CODE get '/login' do 'Login' end get '/auth/:provider/callback' do # TODO: Insert real authentication logic... json request.env['omniauth.auth'] end get '/auth/failure' do # TODO: Insert real error handling logic... halt 401, params[:message] end CODE if classic? append_file('app.rb', routes) else inject_into_class('app.rb', 'App') { indent(routes, 4) } end end # rubocop:enable Metrics/MethodLength # rubocop:disable Metrics/MethodLength def add_tests return if rspec? inject_into_class('test/unit/app_test.rb', 'AppTest') do <<-CODE setup do OmniAuth.config.test_mode = true end test 'GET /login' do get '/login' assert_equal('Login', last_response.body) end test 'GET /auth/#{provider}/callback' do auth_hash = { provider: '#{provider}', uid: '123545', info: { name: 'John Doe' } } OmniAuth.config.mock_auth[:#{provider}] = auth_hash get '/auth/#{provider}/callback' assert_equal(MultiJson.encode(auth_hash), last_response.body) end test 'GET /auth/failure' do OmniAuth.config.mock_auth[:#{provider}] = :invalid_credentials get '/auth/failure' assert_response :not_authorized end CODE end end # rubocop:enable Metrics/MethodLength # rubocop:disable Metrics/MethodLength def add_specs return unless rspec? append_file('spec/app_spec.rb') do <<~CODE # rubocop:disable Metrics/BlockLength RSpec.describe 'omniauth', rack: true do before { OmniAuth.config.test_mode = true } describe 'GET /login' do before { get '/login' } it { expect(last_response).to have_http_status(:ok) } it { expect(last_response).to have_content_type(:html) } it 'renders a template with a login link' do #{provider}_link = 'Login' expect(last_response.body).to include(#{provider}_link) end end describe 'GET /auth/#{provider}/callback' do let(:auth_hash) do { provider: '#{provider}', uid: '123545', info: { name: 'John Doe' } } end before do OmniAuth.config.mock_auth[:#{provider}] = auth_hash get '/auth/#{provider}/callback' end it { expect(last_response).to have_http_status(:ok) } it { expect(last_response).to have_content_type(:json) } it 'renders the auth hash result' do expect(last_response.body).to eq(JSON.generate(auth_hash)) end end describe 'GET /auth/failure' do before do OmniAuth.config.mock_auth[:#{provider}] = :invalid_credentials get '/auth/failure' end it { expect(last_response).to have_http_status(:not_authorized) } end end # rubocop:enable Metrics/BlockLength CODE end end # rubocop:enable Metrics/MethodLength def reminders say "\nGemfile updated... don't forget to 'bundle install'" end private def gem_name "omniauth-#{provider}" end end end end