diff --git a/web/Gemfile b/web/Gemfile index eda57ee0a..e5c3f1583 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -65,7 +65,6 @@ gem 'postgres-copy' #end gem 'geokit-rails' gem 'postgres_ext' -gem 'recaptcha', '0.3.6' gem 'resque' gem 'resque-retry' gem 'resque-failed-job-mailer' diff --git a/web/app/controllers/api_recordings_controller.rb b/web/app/controllers/api_recordings_controller.rb index 695e3a4b4..6244e1e17 100644 --- a/web/app/controllers/api_recordings_controller.rb +++ b/web/app/controllers/api_recordings_controller.rb @@ -230,13 +230,13 @@ class ApiRecordingsController < ApiController # POST /api/recordings/:id/videos/:video_id/upload_sign def video_upload_sign length = params[:length] - @youtube_client.upload_sign(current_user, @recorded_video.url, length) + @youtube_client.sign_youtube_upload(current_user, @recorded_video.url, length) end # POST /api/recordings/:id/videos/:video_id/upload_complete def video_upload_start length = params[:length] - @youtube_client.get_upload_status(current_user, @recorded_video.url, length) + @youtube_client.youtube_upload_status(current_user, @recorded_video.url, length) end # POST /api/recordings/:id/videos/:video_id/upload_complete diff --git a/web/app/controllers/users_controller.rb b/web/app/controllers/users_controller.rb index 407b9a4c0..6cd34cabd 100644 --- a/web/app/controllers/users_controller.rb +++ b/web/app/controllers/users_controller.rb @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- require 'builder' -require 'recaptcha/rails' class Slide attr_accessor :img_url, :header, :vid_url @@ -142,10 +141,6 @@ class UsersController < ApplicationController terms_of_service = params[:jam_ruby_user][:terms_of_service].nil? || params[:jam_ruby_user][:terms_of_service] == "0"? false : true musician = params[:jam_ruby_user][:musician] - if Rails.application.config.recaptcha_enable - recaptcha_failed = verify_recaptcha(:private_key=>Rails.application.config.recaptcha_private_key, :timeout=>10) - end - @user = UserManager.new.signup(remote_ip: request.remote_ip, first_name: params[:jam_ruby_user][:first_name], last_name: params[:jam_ruby_user][:last_name], @@ -157,7 +152,7 @@ class UsersController < ApplicationController birth_date: birth_date, location: location, musician: musician, - recaptcha_failed: recaptcha_failed, + recaptcha_response: params['g-recaptcha-response'], invited_user: @invited_user, fb_signup: @fb_signup, signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm", diff --git a/web/lib/you_tube_client.rb b/web/lib/google_client.rb similarity index 88% rename from web/lib/you_tube_client.rb rename to web/lib/google_client.rb index cba813844..c622a6e5f 100644 --- a/web/lib/you_tube_client.rb +++ b/web/lib/google_client.rb @@ -9,7 +9,7 @@ require 'socket' # Youtube OAuth and API functionality: module JamRuby - class YouTubeClient + class GoogleClient attr_accessor :client attr_accessor :api attr_accessor :request @@ -27,7 +27,7 @@ module JamRuby :application_version => '1.0.0' ) - youtube = client.discovered_api('youtube', 'v3') + #youtube = client.discovered_api('youtube', 'v3') end # Return a login URL that will show a web page with @@ -52,7 +52,7 @@ module JamRuby # https://developers.google.com/youtube/v3/docs/videos/insert # https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol - def upload_sign(user, filename, length) + def sign_youtube_upload(user, filename, length) raise ArgumentError, "Length is required and should be > 0" if length.to_i.zero? # Something like this: @@ -140,7 +140,7 @@ module JamRuby end # https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol#Check_Upload_Status - def get_upload_status(user, upload_url, length) + def youtube_upload_status(user, upload_url, length) auth = UserAuthorization.google_auth(user).first if auth.nil? || auth.token.nil? raise SecurityError, "No current google token found for user #{user}" @@ -187,21 +187,50 @@ module JamRuby end # @return true if file specified by URL uploaded, false otherwise - def verify_upload(user, upload_url, length) - status_hash=get_upload_status(user, upload_url, length) + def verify_youtube_upload(user, upload_url, length) + status_hash=youtube_upload_status(user, upload_url, length) (status_hash['status']>=200 && status_hash['status']<300) end # Set fully_uploaded if the upload can be verified. # @return true if verified; false otherwise: def complete_upload(recorded_video) - if (verify_upload(recorded_video.user, recorded_video.url, recorded_video.length)) + if (verify_youtube_upload(recorded_video.user, recorded_video.url, recorded_video.length)) recorded_video.update_attribute(:fully_uploaded, true) else false end end + def verify_recaptcha(recaptcha_response) + success = false + if !Rails.application.config.recaptcha_enable + success = true + else + Rails.logger.info "Login with: #{recaptcha_response}" + RestClient.get("https://www.google.com/recaptcha/api/siteverify", + params: { + secret: Rails.application.config.recaptcha_private_key, + response: recaptcha_response + } + ) do |response, request, result| + Rails.logger.info "response: #{response.inspect}" + case(response.code) + when 200..207 + json = JSON.parse(response.to_str) + if json['success'] + success = true + else + Rails.logger.info("Error verifying recaptcha: #{json['error-codes'].inspect}") + end + else + Rails.logger.info("Unexpected status from google_recaptcha: [#{response.code}] with headers: #{response.headers.inspect}") + end #case + end #do + end # if + success + end #def + # This will also sign in and prompt for login as necessary; # currently requires the server to be running at localhost:3000 def signin_flow() diff --git a/web/lib/user_manager.rb b/web/lib/user_manager.rb index a694af94c..5c36c6974 100644 --- a/web/lib/user_manager.rb +++ b/web/lib/user_manager.rb @@ -1,8 +1,10 @@ +require 'google_client' class UserManager < BaseManager def initialize(options={}) super(options) @log = Logging.logger[self] + @google_client = GoogleClient.new() end # Note that almost everything can be nil here. This is because when users sign up via social media, @@ -24,7 +26,8 @@ class UserManager < BaseManager fb_signup = options[:fb_signup] signup_confirm_url = options[:signup_confirm_url] affiliate_referral_id = options[:affiliate_referral_id] - recaptcha_failed = Rails.application.config.recaptcha_enable && options[:recaptcha_failed] + recaptcha_failed=(fb_signup) ? false : !@google_client.verify_recaptcha(options[:recaptcha_response]) + user = User.new # check if we have disabled open signup for this site. open == invited users can still get in diff --git a/web/spec/features/oauth_spec.rb b/web/spec/features/oauth_spec.rb index 024418400..a24e6cfae 100644 --- a/web/spec/features/oauth_spec.rb +++ b/web/spec/features/oauth_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -require 'you_tube_client' +require 'google_client' describe "OAuth", :slow=>true, :js=>true, :type=>:feature, :capybara_feature=>true do @@ -15,7 +15,7 @@ describe "OAuth", :slow=>true, :js=>true, :type=>:feature, :capybara_feature=>tr end before(:each) do - @youtube_client = YouTubeClient.new() + @youtube_client = GoogleClient.new() end after(:each) do diff --git a/web/spec/features/youtube_spec.rb b/web/spec/features/youtube_spec.rb index 48d905df3..1fe81bf06 100644 --- a/web/spec/features/youtube_spec.rb +++ b/web/spec/features/youtube_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -require 'you_tube_client' +require 'google_client' require 'rest_client' describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature => true do @@ -12,7 +12,7 @@ describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature @previous_run_server = Capybara.run_server Capybara.run_server = false @user=FactoryGirl.create(:user, :email => "jamkazamtest@gmail.com") - @youtube_client = YouTubeClient.new() + @youtube_client = GoogleClient.new() authorize_google_user(@youtube_client, @user, "stinkyblueberryjam") google_auth = UserAuthorization.google_auth(@user).first # Consider returning this from above now that it is reliable end @@ -25,7 +25,7 @@ describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature it "should retrieve upload url" do length = 3276 - upload_hash=@youtube_client.upload_sign(@user, "test_video.mp4", length) + upload_hash=@youtube_client.sign_youtube_upload(@user, "test_video.mp4", length) upload_hash.should_not be_nil upload_hash.length.should be >=1 upload_hash['method'].should eq("PUT") @@ -35,13 +35,13 @@ describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature upload_hash['Content-Length'].should eq(length) upload_hash['Content-Type'].should_not be_nil - @youtube_client.verify_upload(@user, upload_hash['url'], length).should be_false + @youtube_client.verify_youtube_upload(@user, upload_hash['url'], length).should be_false end it "upload url should allow uploading" do vid_path = Rails.root.join('spec', 'files', 'test_video.mp4') length = File.size?(vid_path) - upload_hash=@youtube_client.upload_sign(@user, "test_video.mp4", length) + upload_hash=@youtube_client.sign_youtube_upload(@user, "test_video.mp4", length) #puts upload_hash.inspect upload_hash.should_not be_nil upload_hash.length.should be >=1 @@ -54,8 +54,8 @@ describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature # Upload this file as the client would: RestClient.put(upload_hash['url'], File.read(vid_path)) - @youtube_client.verify_upload(@user, upload_hash['url'], length).should be_true - #@youtube_client.get_upload_status(@user, upload_hash['url'], length) + @youtube_client.verify_youtube_upload(@user, upload_hash['url'], length).should be_true + #@youtube_client.youtube_upload_status(@user, upload_hash['url'], length) end it "sets upload flag when complete" do @@ -67,7 +67,7 @@ describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature vid_path = Rails.root.join('spec', 'files', 'test_video.mp4') length = File.size?(vid_path) - upload_hash=@youtube_client.upload_sign(@user, "test_video.mp4", length) + upload_hash=@youtube_client.sign_youtube_upload(@user, "test_video.mp4", length) upload_hash.should_not be_nil upload_hash['url'].should_not be_nil RestClient.put(upload_hash['url'], File.read(vid_path)) @@ -82,7 +82,7 @@ describe "YouTube", :slow=>true, :js=>true, :type => :feature, :capybara_feature @recording.recorded_videos << recorded_video - @youtube_client.verify_upload(@user, upload_hash['url'], length).should be_true + @youtube_client.verify_youtube_upload(@user, upload_hash['url'], length).should be_true @youtube_client.complete_upload(recorded_video).should be_true recorded_video.fully_uploaded.should be_true end diff --git a/web/spec/managers/user_manager_spec.rb b/web/spec/managers/user_manager_spec.rb index 23368a208..df30da27f 100644 --- a/web/spec/managers/user_manager_spec.rb +++ b/web/spec/managers/user_manager_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe UserManager do before(:each) do + Rails.application.config.recaptcha_enable=false @user_manager = UserManager.new(:conn => @conn) UserMailer.deliveries.clear @location = { :country => "US", :state => "Arkansas", :city => "Little Rock" } @@ -662,12 +663,12 @@ describe UserManager do end # describe "without nocaptcha" describe "with nocaptcha" do - before(:all) do + before(:each) do @old_recaptcha=Rails.application.config.recaptcha_enable Rails.application.config.recaptcha_enable=true end - after(:all) do + after(:each) do Rails.application.config.recaptcha_enable=@old_recaptcha end @@ -682,11 +683,13 @@ describe UserManager do instruments: @instruments, musician: true, location: @loca, - recaptcha_failed: true, + recaptcha_response: nil, signup_confirm_url: "http://localhost:3000/confirm") user.errors.any?.should be_true + end + it "passes when facebook signup" do user = @user_manager.signup(remote_ip: "1.2.3.4", first_name: "bob", last_name: "smith", @@ -694,13 +697,14 @@ describe UserManager do password: "foobar", password_confirmation: "foobar", terms_of_service: true, - recaptcha_failed: false, + fb_signup: FactoryGirl.create(:facebook_signup), + recaptcha_response: nil, instruments: @instruments, musician: true, location: @loca, signup_confirm_url: "http://localhost:3000/confirm") user.errors.any?.should be_false - end # it "fails when nocaptcha fails" + end # it "passes when facebook signup" end # describe "with nocaptcha" end # test diff --git a/web/spec/testing_oauth.txt b/web/spec/testing_oauth.txt index db139b81f..2a6ad3874 100644 --- a/web/spec/testing_oauth.txt +++ b/web/spec/testing_oauth.txt @@ -4,7 +4,7 @@ To obtain an access token, one must actually log into google using a browser run Getting an access token for the purposes of automated testing is tricky, but possible using Capybara with a javascript-enabled driver. (Note, web/spec/support/utilities.rb utilizes the JK youtube client to perform the intricate bits): -1) Obtain the login URL. It's ugly, but we can get it from the YouTubeClient. It contains the callback URL, as well as a "hint" that will fill in the username for us. +1) Obtain the login URL. It's ugly, but we can get it from the GoogleClient. It contains the callback URL, as well as a "hint" that will fill in the username for us. 2) Start a web server on an enabled callback server, such as localhost:3000 3) Obtain the URL using a known test user 4) Visit the URL in a capybara test @@ -12,7 +12,7 @@ Getting an access token for the purposes of automated testing is tricky, but pos 4b) Click the login button 4c) The approve page should load. Wait for the approve button to be enabled. This is usually a second or two after the page loads, but not immediately. 4d) Click the approve button -5) After google approves, some javascript will redirect to our test web server, which contains a code. This is not the access_token, but a one-time code that can be exchanged for an access_token, again POSTing to google's auth server. You can see it in gory detail in YouTubeClient.exchange_for_token. +5) After google approves, some javascript will redirect to our test web server, which contains a code. This is not the access_token, but a one-time code that can be exchanged for an access_token, again POSTing to google's auth server. You can see it in gory detail in GoogleClient.exchange_for_token. 6) If all goes well, the test web server will call back the invoker with a real access token. 7) For testing purposes, stick the access token in the user.user_authorizations table for the user for which we are testing.