From 2c2525ce1f0ed0833a7adedba2ffb15303da1189 Mon Sep 17 00:00:00 2001 From: Swift Date: Wed, 31 May 2017 16:31:18 -0400 Subject: [PATCH] Added MyMLH login to play !Light (#12) * Require users to login with MyMLH before using !Light * Updated README --- .gitignore | 5 +- Gemfile | 3 +- Gemfile.lock | 101 ++++++++++-------- Procfile | 1 + README.md | 6 +- Rakefile | 1 + no_light_sinatra.rb | 45 +++++++- spec/acceptance_helper.rb | 1 + spec/spec_helper.rb | 21 +++- .../visitor_can_authorize_with_my_mlh_spec.rb | 50 +++++++++ 10 files changed, 175 insertions(+), 59 deletions(-) create mode 100644 Procfile create mode 100644 spec/visitor_can_authorize_with_my_mlh_spec.rb diff --git a/.gitignore b/.gitignore index 205d353..addf156 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,7 @@ # DS_Store .DS_Store -# Coveralls -.coveralls.yml - # Testing vendor/code_statistics.rb .env -coverage/ \ No newline at end of file +coverage/ diff --git a/Gemfile b/Gemfile index e4b22cc..dff2bf4 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,8 @@ gem 'skylight' gem 'sinatra' gem 'sinatra-contrib' gem 'zippy' +gem 'omniauth' +gem 'omniauth-mlh' group :development do gem 'sinatra-reloader' @@ -23,7 +25,6 @@ group :test do gem 'capybara' gem 'capybara-webkit' gem 'capybara_minitest_spec' - gem 'coveralls', require: false gem 'database_cleaner' gem 'faker' gem 'minitest' diff --git a/Gemfile.lock b/Gemfile.lock index 9d01dbc..88cc58c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,29 @@ GEM remote: https://rubygems.org/ specs: - activemodel (5.0.2) - activesupport (= 5.0.2) + activemodel (5.1.1) + activesupport (= 5.1.1) activemodel-serializers-xml (1.0.1) activemodel (> 5.x) activerecord (> 5.x) activesupport (> 5.x) builder (~> 3.1) - activerecord (5.0.2) - activemodel (= 5.0.2) - activesupport (= 5.0.2) - arel (~> 7.0) - activesupport (5.0.2) + activerecord (5.1.1) + activemodel (= 5.1.1) + activesupport (= 5.1.1) + arel (~> 8.0) + activesupport (5.1.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.5.1) public_suffix (~> 2.0, >= 2.0.2) - airbrake (6.0.0) - airbrake-ruby (~> 2.0) - airbrake-ruby (2.0.0) - arel (7.1.4) - backports (3.7.0) + airbrake (6.1.1) + airbrake-ruby (~> 2.2, >= 2.2.5) + airbrake-ruby (2.2.5) + arel (8.0.0) + backports (3.8.0) bson (1.12.5) bson_ext (1.12.5) bson (~> 1.12.5) @@ -43,24 +43,21 @@ GEM minitest (>= 4) coderay (1.1.1) concurrent-ruby (1.0.5) - coveralls (0.8.20) - json (>= 1.8, < 3) - simplecov (~> 0.14.1) - term-ansicolor (~> 1.3) - thor (~> 0.19.4) - tins (~> 1.6) - database_cleaner (1.5.3) - docile (1.1.5) + database_cleaner (1.6.1) faker (1.7.3) i18n (~> 0.5) - i18n (0.8.1) - json (2.0.4) + faraday (0.11.0) + multipart-post (>= 1.2, < 3) + hashie (3.5.5) + i18n (0.8.4) + json (2.1.0) + jwt (1.5.6) method_source (0.8.2) mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_portile2 (2.1.0) - minitest (5.10.1) + minitest (5.10.2) mongo (1.12.5) bson (= 1.12.5) mongo_mapper (0.14.0) @@ -69,8 +66,27 @@ GEM mongo (~> 1.8) plucky (~> 0.7.0) multi_json (1.12.1) - nokogiri (1.7.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + mustermann (1.0.0) + nokogiri (1.7.2) mini_portile2 (~> 2.1.0) + oauth2 (1.3.1) + faraday (>= 0.8, < 0.12) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.6.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-mlh (0.3.1) + activesupport + omniauth (~> 1.0) + omniauth-oauth2 (~> 1.3.1) + omniauth-oauth2 (1.3.1) + oauth2 (~> 1.0) + omniauth (~> 1.2) plucky (0.7.0) mongo (~> 1.5) pry (0.10.4) @@ -78,43 +94,35 @@ GEM method_source (~> 0.8.1) slop (~> 3.4) public_suffix (2.0.5) - rack (1.6.5) - rack-protection (1.5.3) + rack (2.0.3) + rack-protection (2.0.0) rack rack-test (0.6.3) rack (>= 1.0) rake (12.0.0) rubyzip (1.2.1) - simplecov (0.14.1) - docile (~> 1.1.0) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.0) - sinatra (1.4.8) - rack (~> 1.5) - rack-protection (~> 1.4) - tilt (>= 1.3, < 3) - sinatra-contrib (1.4.7) + sinatra (2.0.0) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.0) + tilt (~> 2.0) + sinatra-contrib (2.0.0) backports (>= 2.0) multi_json - rack-protection - rack-test - sinatra (~> 1.4.0) + mustermann (~> 1.0) + rack-protection (= 2.0.0) + sinatra (= 2.0.0) tilt (>= 1.3, < 3) sinatra-reloader (1.0) sinatra-contrib - skylight (1.2.0) + skylight (1.3.1) activesupport (>= 3.0.0) slop (3.6.0) - term-ansicolor (1.5.0) - tins (~> 1.0) - thor (0.19.4) thread_safe (0.3.6) tilt (2.0.7) - tins (1.13.2) tzinfo (1.2.3) thread_safe (~> 0.1) - xpath (2.0.0) + xpath (2.1.0) nokogiri (~> 1.3) zippy (0.2.3) rubyzip (>= 1.0.0) @@ -129,11 +137,12 @@ DEPENDENCIES capybara capybara-webkit capybara_minitest_spec - coveralls database_cleaner faker minitest mongo_mapper + omniauth + omniauth-mlh pry rack-test rake diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..81a0871 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: rackup config.ru diff --git a/README.md b/README.md index 9e2cc78..c3d4dd1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-[![Circle CI](https://circleci.com/gh/MLH/no-light/tree/master.svg?style=svg)](https://circleci.com/gh/MLH/no-light/tree/master) [![Coverage Status](https://coveralls.io/repos/MLH/no-light/badge.svg?branch=master&service=github)](https://coveralls.io/github/MLH/no-light?branch=master) +[![Circle CI](https://circleci.com/gh/MLH/no-light/tree/master.svg?style=svg)](https://circleci.com/gh/MLH/no-light/tree/master)
This is a **micro service** that allows participants of the No Light mini-event to quickly submit their entries (see below for more info). The organizer of the mini-event can then conveniently download a ZIP file of all the entries. @@ -39,6 +39,10 @@ $ cd no-light $ mkdir data && mkdir data/db $ mongod --dbpath data/db +Set ENV variable (on Mac OS X): +$ export MY_MLH_KEY=... +$ export MY_MLH_SECRET=... + Launch server locally (on Mac OS X): $ rackup ``` diff --git a/Rakefile b/Rakefile index ce4f93c..eb016b0 100644 --- a/Rakefile +++ b/Rakefile @@ -8,6 +8,7 @@ require './no_light_sinatra' task default: :spec Rake::TestTask.new(:spec) do |t| + t.ruby_opts = ['-W1'] t.test_files = FileList['spec/*_spec.rb'] end diff --git a/no_light_sinatra.rb b/no_light_sinatra.rb index 705a1e6..1650c17 100644 --- a/no_light_sinatra.rb +++ b/no_light_sinatra.rb @@ -11,6 +11,12 @@ class NoLightSinatra < Sinatra::Base use Airbrake::Rack::Middleware unless ENV['RACK_ENV'] == 'test' + enable :sessions + + use OmniAuth::Builder do + provider :mlh, ENV['MY_MLH_KEY'], ENV['MY_MLH_SECRET'], scope: 'default' + end + set public_folder: 'public', static: true configure do @@ -20,7 +26,7 @@ class NoLightSinatra < Sinatra::Base 'test' => { 'uri' => 'mongodb://localhost/no_light_test' }, 'production' => { 'uri' => ENV['MONGODB_URI'] } } - + MongoMapper.setup(ENVIRONMENTS, ENV['RACK_ENV']) end @@ -33,6 +39,24 @@ class NoLightSinatra < Sinatra::Base erb :default_page end + get '/auth/mlh/callback' do + auth = request.env["omniauth.auth"] + session[:user_id] = auth["uid"] + next_page = session[:redirect] + + if next_page + session[:redirect] = nil + redirect '%s' % next_page + else + redirect '/' + end + end + + get '/logout' do + session.clear + redirect '/' + end + post '/submit' do @submission = Submission.new(get_submit_params) @@ -53,15 +77,28 @@ class NoLightSinatra < Sinatra::Base end get '/:hackathon' do - show_editor(DEFAULT_BRANDING) + authorize do + show_editor(DEFAULT_BRANDING) + end end get '/:hackathon/:branding?' do - show_editor(params[:branding]) + authorize do + show_editor(params[:branding]) + end end private + def authorize + if session[:user_id] + yield + else + session[:redirect] = request.fullpath + redirect '/auth/mlh' + end + end + def show_editor(custom_branding) @body_class = ['editor', custom_branding].join(' ') erb :editor @@ -110,4 +147,4 @@ def set_response_headers response.headers['Content-Transfer-Encoding'] = 'binary' response.headers['Content-Length'] = create_tempfile.size end -end \ No newline at end of file +end diff --git a/spec/acceptance_helper.rb b/spec/acceptance_helper.rb index fba0859..2ca5105 100644 --- a/spec/acceptance_helper.rb +++ b/spec/acceptance_helper.rb @@ -11,6 +11,7 @@ Capybara.app = NoLightSinatra Capybara.default_driver = :webkit + class MiniTest::Spec include Capybara::DSL end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2e5a63b..8af1dc7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,14 +1,11 @@ # encoding: UTF-8 require 'bundler' -require 'coveralls' require 'pry' Bundler.setup Bundler.require -Coveralls.wear! - ENV['RACK_ENV'] = 'test' set :environment, :test @@ -36,6 +33,24 @@ class MiniTest::Spec end after(:each) do + visit '/logout' DatabaseCleaner[:mongo_mapper].clean end end + +OmniAuth.config.test_mode = true + +def mock_with_valid_mlh_credentials! + OmniAuth.config.mock_auth[:mlh] = OmniAuth::AuthHash.new({ + provider: :mlh, + uid: "1", + info: OmniAuth::AuthHash::InfoHash.new({ + email: 'grace.hopper@mlh.io', + created_at: Time.now, + updated_at: Time.now, + first_name: 'Grace', + last_name: 'Hopper', + scopes: ['default'] + }) + }) +end diff --git a/spec/visitor_can_authorize_with_my_mlh_spec.rb b/spec/visitor_can_authorize_with_my_mlh_spec.rb new file mode 100644 index 0000000..7f22841 --- /dev/null +++ b/spec/visitor_can_authorize_with_my_mlh_spec.rb @@ -0,0 +1,50 @@ +require_relative "spec_helper" +require_relative "acceptance_helper" +require 'pry' + +def app + NoLightSinatra +end + +describe NoLightSinatra do + + before do + mock_with_valid_mlh_credentials! + end + + it 'the un-branded editor redirects visitors to MyMLH' do + get '/hacktheplanet' + + last_response.status.must_equal(302) + last_response.location.must_include("/auth/mlh") + end + + it 'the branded editor redirects visitors to MyMLH' do + get '/hacktheplanet/dell' + + last_response.status.must_equal(302) + last_response.location.must_include("/auth/mlh") + end + + it 'displays the editor to signed in users' do + sign_in! + + get '/hacktheplanet' + + last_response.status.must_equal(200) + last_request.path.must_equal("/hacktheplanet") + end + + it 'redirects authorized users to the previous page' do + visit '/hacktheplanet-test' + + current_path.must_equal('/hacktheplanet-test') + end + + private + + def sign_in! + get '/auth/mlh' + follow_redirect! + end +end