VRFS-2540 : Fix. Remove usage of recaptcha; refactor nocaptcha check in google_client (was youtube_client). Fix and add tests.

This commit is contained in:
Steven Miers 2015-01-11 17:04:16 -06:00
parent d139966445
commit a900087d87
9 changed files with 65 additions and 35 deletions

View File

@ -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'

View File

@ -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

View File

@ -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",

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.