From 334f4a8d115dd6aa1e90990fa38fe83d6a104439 Mon Sep 17 00:00:00 2001 From: Jeremy Prevost Date: Fri, 31 Mar 2017 10:16:20 -0400 Subject: [PATCH] Adds access control to flipflop controller What: * adds shared secret key access to flipflop controller in all environments (dev / test were previously always accessible) * travis defaults to running `rake`, new way is `bin/rails test` Why: * the ability to easily toggle features for staff in PR and staging builds where they can confirm their current settings requires some form of dashboard and flipflop comes with one so why not use it How: * setting `ENV['FLIPFLOP_KEY']` and passing that value like `/flipflop?flipflop_key=thatthingyouset` will provide access to the dashboard where you can see all possible toggles and easily toggle features for your session * if you don't set `ENV['FLIPFLOP_KEY']` all access is denied to the dashboard but you can still toggle features via the `/toggle?feature=yourfeature` route --- .travis.yml | 1 + app.json | 3 +++ app/controllers/application_controller.rb | 13 ++++++++++++ config/application.rb | 2 +- config/environments/development.rb | 4 ---- config/environments/test.rb | 5 +---- test/features/flipflop_dashboard_test.rb | 24 +++++++++++++++++++++++ test/integration/flipflop_test.rb | 18 +++++++++++++++++ 8 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 test/features/flipflop_dashboard_test.rb create mode 100644 test/integration/flipflop_test.rb diff --git a/.travis.yml b/.travis.yml index c0f3c553..f06f60d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,3 +2,4 @@ language: ruby rvm: - 2.3.1 sudo: false +script: bin/rails test diff --git a/app.json b/app.json index 872f5faa..490619a3 100644 --- a/app.json +++ b/app.json @@ -35,6 +35,9 @@ "FEEDBACK_MAIL_TO": { "required": true }, + "FLIPFLOP_KEY": { + "required": true + }, "GLOBAL_ALERT": { "required": true }, diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1eeeef40..f4fb4de1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,7 +3,20 @@ class ApplicationController < ActionController::Base # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + def flipflop_access_control + return if session[:flipflop_user] + head :forbidden unless valid_flipflop_key? + session[:flipflop_user] = true + end + def new_session_path(_scope) root_path end + + private + + def valid_flipflop_key? + return if params[:flipflop_key].blank? + params[:flipflop_key] == ENV['FLIPFLOP_KEY'] + end end diff --git a/config/application.rb b/config/application.rb index 4939464d..ad5619cf 100644 --- a/config/application.rb +++ b/config/application.rb @@ -10,7 +10,7 @@ module MitBento class Application < Rails::Application # Replace with a lambda or method name defined in ApplicationController # to implement access control for the Flipflop dashboard. - config.flipflop.dashboard_access_filter = -> { head :forbidden } + config.flipflop.dashboard_access_filter = :flipflop_access_control # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers diff --git a/config/environments/development.rb b/config/environments/development.rb index 28499f6d..cecdbb8e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,8 +1,4 @@ Rails.application.configure do - # Replace with a lambda or method name defined in ApplicationController - # to implement access control for the Flipflop dashboard. - config.flipflop.dashboard_access_filter = nil - # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on diff --git a/config/environments/test.rb b/config/environments/test.rb index ace0841c..1b2311bf 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,8 +1,4 @@ Rails.application.configure do - # Replace with a lambda or method name defined in ApplicationController - # to implement access control for the Flipflop dashboard. - config.flipflop.dashboard_access_filter = nil - # Settings specified here will take precedence over those in config/application.rb. ENV['EDS_URL'] = 'https://eds-api.ebscohost.com' @@ -22,6 +18,7 @@ ENV['ALEPH_API_URI'] = 'https://fake_server.example.com/rest-dlf/' ENV['ALEPH_KEY'] = 'FAKE_KEY' ENV['PER_PAGE'] = '10' + ENV['FLIPFLOP_KEY'] = 'yoyo' # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that diff --git a/test/features/flipflop_dashboard_test.rb b/test/features/flipflop_dashboard_test.rb new file mode 100644 index 00000000..0c132a96 --- /dev/null +++ b/test/features/flipflop_dashboard_test.rb @@ -0,0 +1,24 @@ +require 'test_helper' + +feature 'FlipflopDashboard' do + before do + Capybara.current_session.driver.browser.clear_cookies + end + + after do + Capybara.current_session.driver.browser.clear_cookies + end + + test 'can toggle a feature from the dashboard' do + visit "/flipflop?flipflop_key=#{ENV['FLIPFLOP_KEY']}" + + within('tr[data-feature=debug] td[data-strategy=session]') do + click_on 'on' + end + + within('tr[data-feature=debug]') do + assert_equal('on', first('td.status').text) + assert_equal('on', first('td[data-strategy=session] button.active').text) + end + end +end diff --git a/test/integration/flipflop_test.rb b/test/integration/flipflop_test.rb new file mode 100644 index 00000000..ec3bb99b --- /dev/null +++ b/test/integration/flipflop_test.rb @@ -0,0 +1,18 @@ +require 'test_helper' + +class FlipflopTest < ActionDispatch::IntegrationTest + test 'can access dashboard with secret key' do + get '/flipflop', params: { flipflop_key: ENV['FLIPFLOP_KEY'] } + assert_response :success + end + + test 'cannot acess dashboard without secret key' do + get '/flipflop' + assert_response :forbidden + end + + test 'cannot access dashboard with wrong secret key' do + get '/flipflop', params: { flipflop_key: 'not_the_key' } + assert_response :forbidden + end +end