Further decoupling of google_docs from models and controllers.
fixes: CNVS-12328 test plan: - as admin enable the google_doc plugin - as student visit `/profile/settings` - click 'Google Docs' under the 'Other Services' section - click 'Authorize Google Doc Access' in modal - when redirect to google, click 'Allow access' - verify success banner displays Change-Id: I2b45ffa38ac0d1d810fb988335f4cd39154ae2a6 Reviewed-on: https://gerrit.instructure.com/32949 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Simon Williams <simon@instructure.com> QA-Review: Trevor deHaan <tdehaan@instructure.com> Product-Review: Simon Williams <simon@instructure.com>
This commit is contained in:
parent
4e90438d25
commit
c8d7b9f915
|
@ -1737,4 +1737,22 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
js_env hash
|
||||
end
|
||||
|
||||
def google_docs_connection
|
||||
## @real_current_user first ensures that a masquerading user never sees the
|
||||
## masqueradee's files, but in general you may want to block access to google
|
||||
## docs for masqueraders earlier in the request
|
||||
user = @real_current_user || @current_user
|
||||
if user
|
||||
service_token, service_secret = Rails.cache.fetch(['google_docs_tokens', user].cache_key) do
|
||||
service = user.user_services.find_by_service("google_docs")
|
||||
service && [service.token, service.secret]
|
||||
end
|
||||
raise GoogleDocs::NoTokenError unless service_token && service_secret
|
||||
google_docs = GoogleDocs.new(service_token, service_secret)
|
||||
else
|
||||
google_docs = GoogleDocs.new(session[:oauth_gdocs_access_token_token], session[:oauth_gdocs_access_token_secret])
|
||||
end
|
||||
google_docs
|
||||
end
|
||||
end
|
||||
|
|
|
@ -133,7 +133,7 @@ class AssignmentsController < ApplicationController
|
|||
end
|
||||
|
||||
begin
|
||||
google_docs = GoogleDocs.new(logged_in_user, session)
|
||||
google_docs = google_docs_connection
|
||||
@google_docs_token = google_docs.retrieve_access_token
|
||||
rescue GoogleDocs::NoTokenError
|
||||
#do nothing
|
||||
|
@ -165,9 +165,9 @@ class AssignmentsController < ApplicationController
|
|||
if assignment.allow_google_docs_submission? && @real_current_user.blank?
|
||||
docs = {}
|
||||
begin
|
||||
google_docs = GoogleDocs.new(logged_in_user, session)
|
||||
google_docs = google_docs_connection
|
||||
docs = google_docs.list_with_extension_filter(assignment.allowed_extensions)
|
||||
rescue NoTokenError
|
||||
rescue GoogleDocs::NoTokenError
|
||||
#do nothing
|
||||
rescue => e
|
||||
ErrorReport.log_exception(:oauth, e)
|
||||
|
|
|
@ -64,7 +64,7 @@ class CollaborationsController < ApplicationController
|
|||
@collaborations = @context.collaborations.active
|
||||
log_asset_access("collaborations:#{@context.asset_string}", "collaborations", "other")
|
||||
|
||||
google_docs = GoogleDocs.new(logged_in_user, session)
|
||||
google_docs = google_docs_connection
|
||||
@google_docs_authorized = google_docs.verify_access_token rescue false
|
||||
js_env :TITLE_MAX_LEN => Collaboration::TITLE_MAX_LENGTH,
|
||||
:collaboration_types => Collaboration.collaboration_types
|
||||
|
|
|
@ -498,7 +498,7 @@ class SubmissionsController < ApplicationController
|
|||
# Internal: Submit a Google Doc.
|
||||
def submit_google_doc(document_id)
|
||||
# fetch document from google
|
||||
google_docs = GoogleDocs.new(logged_in_user, session)
|
||||
google_docs = google_docs_connection
|
||||
document_response, display_name, file_extension = google_docs.download(document_id)
|
||||
|
||||
# error handling
|
||||
|
|
|
@ -143,7 +143,17 @@ class UsersController < ApplicationController
|
|||
end
|
||||
return_to_url = params[:return_to] || user_profile_url(@current_user)
|
||||
if params[:service] == "google_docs"
|
||||
redirect_to GoogleDocs.request_token_url(return_to_url, session, logged_in_user, request.host_with_port, oauth_success_url(:service => 'google_docs'))
|
||||
request_token = GoogleDocs.request_token(oauth_success_url(:service => 'google_docs'))
|
||||
OauthRequest.create(
|
||||
:service => 'google_docs',
|
||||
:token => request_token.token,
|
||||
:secret => request_token.secret,
|
||||
:user_secret => CanvasUuid::Uuid.generate(nil, 16),
|
||||
:return_url => return_to_url,
|
||||
:user => @real_current_user || @current_user,
|
||||
:original_host_with_port => request.host_with_port
|
||||
)
|
||||
redirect_to request_token.authorize_url
|
||||
elsif params[:service] == "twitter"
|
||||
redirect_to twitter_request_token_url(return_to_url)
|
||||
elsif params[:service] == "linked_in"
|
||||
|
@ -199,7 +209,24 @@ class UsersController < ApplicationController
|
|||
end
|
||||
elsif params[:service] == "google_docs"
|
||||
begin
|
||||
GoogleDocs.get_access_token(oauth_request, params[:oauth_verifier], session, logged_in_user)
|
||||
access_token = GoogleDocs.get_access_token(oauth_request.token, oauth_request.secret, params[:oauth_verifier])
|
||||
google_docs = GoogleDocs.new(oauth_request.token, oauth_request.secret)
|
||||
service_user_id, service_user_name = google_docs.get_service_user_info access_token
|
||||
if oauth_request.user
|
||||
UserService.register(
|
||||
:service => "google_docs",
|
||||
:access_token => access_token,
|
||||
:user => oauth_request.user,
|
||||
:service_domain => "google.com",
|
||||
:service_user_id => service_user_id,
|
||||
:service_user_name => service_user_name
|
||||
)
|
||||
oauth_request.destroy
|
||||
else
|
||||
session[:oauth_gdocs_access_token_token] = access_token.token
|
||||
session[:oauth_gdocs_access_token_secret] = access_token.secret
|
||||
end
|
||||
|
||||
flash[:notice] = t('google_docs_added', "Google Docs access authorized!")
|
||||
rescue => e
|
||||
ErrorReport.log_exception(:oauth, e)
|
||||
|
|
|
@ -27,7 +27,7 @@ class GoogleDocsCollaboration < Collaboration
|
|||
|
||||
def delete_document
|
||||
if !self.document_id && self.user
|
||||
google_docs = GoogleDocs.new(user, {})
|
||||
google_docs = google_docs_for_user
|
||||
google_docs.delete_doc(GoogleDocEntry.new(self.data))
|
||||
end
|
||||
end
|
||||
|
@ -39,8 +39,8 @@ class GoogleDocsCollaboration < Collaboration
|
|||
name = nil if name && name.empty?
|
||||
name ||= I18n.t('lib.google_docs.default_document_name', "Instructure Doc")
|
||||
|
||||
google_docs = GoogleDocs.new(user, {})
|
||||
file = google_docs.create_doc(name)
|
||||
google_docs = google_docs_for_user
|
||||
file = google_docs.create_doc(name, google_docs.retrieve_access_token)
|
||||
self.document_id = file.document_id
|
||||
self.data = file.entry.to_xml
|
||||
self.url = file.alternate_url.to_s
|
||||
|
@ -62,7 +62,7 @@ class GoogleDocsCollaboration < Collaboration
|
|||
service_user_id = google_services.find{|s| s.service_user_id}.service_user_id rescue nil
|
||||
collaborator = self.collaborators.find_by_user_id(user.id)
|
||||
if collaborator && collaborator.authorized_service_user_id != service_user_id
|
||||
google_docs = GoogleDocs.new(user, {})
|
||||
google_docs = google_docs_for_user
|
||||
google_docs.acl_remove(self.document_id, [collaborator.authorized_service_user_id]) if collaborator.authorized_service_user_id
|
||||
google_docs.acl_add(self.document_id, [user])
|
||||
collaborator.update_attributes(:authorized_service_user_id => service_user_id)
|
||||
|
@ -70,7 +70,7 @@ class GoogleDocsCollaboration < Collaboration
|
|||
end
|
||||
|
||||
def remove_users_from_document(users_to_remove)
|
||||
google_docs = GoogleDocs.new(user, {})
|
||||
google_docs = google_docs_for_user
|
||||
google_docs.acl_remove(self.document_id, users_to_remove) if self.document_id
|
||||
end
|
||||
|
||||
|
@ -81,7 +81,7 @@ class GoogleDocsCollaboration < Collaboration
|
|||
nil
|
||||
end
|
||||
if document_id
|
||||
google_docs = GoogleDocs.new(user, {})
|
||||
google_docs = google_docs_for_user
|
||||
google_docs.acl_add(self.document_id, new_users, domain)
|
||||
end
|
||||
end
|
||||
|
@ -93,4 +93,14 @@ class GoogleDocsCollaboration < Collaboration
|
|||
def self.config
|
||||
GoogleDocs.config
|
||||
end
|
||||
|
||||
private
|
||||
def google_docs_for_user
|
||||
service_token, service_secret = Rails.cache.fetch(['google_docs_tokens', self.user].cache_key) do
|
||||
service = self.user.user_services.find_by_service("google_docs")
|
||||
service && [service.token, service.secret]
|
||||
end
|
||||
raise GoogleDocs::NoTokenError unless service_token && service_secret
|
||||
GoogleDocs.new(service_token, service_secret)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,28 +26,18 @@ class GoogleDocs
|
|||
end
|
||||
end
|
||||
|
||||
def initialize(user, session)
|
||||
@user = user
|
||||
@session = session
|
||||
def initialize(oauth_gdocs_access_token, oauth_gdocs_access_token_secret)
|
||||
@oauth_gdocs_access_token = oauth_gdocs_access_token
|
||||
@oauth_gdocs_access_token_secret = oauth_gdocs_access_token_secret
|
||||
end
|
||||
|
||||
def retrieve_access_token
|
||||
consumer = GoogleDocs.consumer
|
||||
return nil unless consumer
|
||||
if @user
|
||||
service_token, service_secret = Rails.cache.fetch(['google_docs_tokens', @user].cache_key) do
|
||||
service = @user.user_services.find_by_service("google_docs")
|
||||
service && [service.token, service.secret]
|
||||
end
|
||||
raise NoTokenError unless service_token && service_secret
|
||||
access_token = OAuth::AccessToken.new(consumer, service_token, service_secret)
|
||||
else
|
||||
access_token = OAuth::AccessToken.new(consumer, @session[:oauth_gdocs_access_token_token], @session[:oauth_gdocs_access_token_secret])
|
||||
end
|
||||
access_token
|
||||
@access_token ||= OAuth::AccessToken.new(consumer, @oauth_gdocs_access_token, @oauth_gdocs_access_token_secret)
|
||||
end
|
||||
|
||||
def get_service_user(access_token)
|
||||
def get_service_user_info(access_token)
|
||||
doc = create_doc("Temp Doc: #{Time.now.strftime("%d %b %Y, %I:%M %p")}", access_token)
|
||||
delete_doc(doc, access_token)
|
||||
service_user_id = doc.entry.authors[0].email rescue nil
|
||||
|
@ -55,47 +45,17 @@ class GoogleDocs
|
|||
return service_user_id, service_user_name
|
||||
end
|
||||
|
||||
def self.get_access_token(oauth_request, oauth_verifier, session, user)
|
||||
def self.get_access_token(token, secret, oauth_verifier)
|
||||
consumer = GoogleDocs.consumer
|
||||
request_token = OAuth::RequestToken.new(consumer,
|
||||
session.delete(:oauth_google_docs_request_token_token),
|
||||
session.delete(:oauth_google_docs_request_token_secret))
|
||||
access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
|
||||
google_docs = GoogleDocs.new(user, session)
|
||||
service_user_id, service_user_name = google_docs.get_service_user(access_token)
|
||||
session[:oauth_gdocs_access_token_token] = access_token.token
|
||||
session[:oauth_gdocs_access_token_secret] = access_token.secret
|
||||
if oauth_request.user
|
||||
UserService.register(
|
||||
:service => "google_docs",
|
||||
:access_token => access_token,
|
||||
:user => oauth_request.user,
|
||||
:service_domain => "google.com",
|
||||
:service_user_id => service_user_id,
|
||||
:service_user_name => service_user_name
|
||||
)
|
||||
oauth_request.destroy
|
||||
session.delete(:oauth_gdocs_access_token_token)
|
||||
session.delete(:oauth_gdocs_access_token_secret)
|
||||
end
|
||||
access_token
|
||||
token,
|
||||
secret)
|
||||
request_token.get_access_token(:oauth_verifier => oauth_verifier)
|
||||
end
|
||||
|
||||
def self.request_token_url(return_to, session, user, host_with_port, oauth_callback)
|
||||
def self.request_token(oauth_callback)
|
||||
consumer = GoogleDocs.consumer
|
||||
request_token = consumer.get_request_token({ :oauth_callback => oauth_callback}, {:scope => "https://docs.google.com/feeds/ https://spreadsheets.google.com/feeds/"})
|
||||
session[:oauth_google_docs_request_token_token] = request_token.token
|
||||
session[:oauth_google_docs_request_token_secret] = request_token.secret
|
||||
OauthRequest.create(
|
||||
:service => 'google_docs',
|
||||
:token => request_token.token,
|
||||
:secret => request_token.secret,
|
||||
:user_secret => CanvasUuid::Uuid.generate(nil, 16),
|
||||
:return_url => return_to,
|
||||
:user => user,
|
||||
:original_host_with_port => host_with_port
|
||||
)
|
||||
request_token.authorize_url
|
||||
consumer.get_request_token({ :oauth_callback => oauth_callback}, {:scope => "https://docs.google.com/feeds/ https://spreadsheets.google.com/feeds/"})
|
||||
end
|
||||
|
||||
|
||||
|
@ -276,8 +236,7 @@ class GoogleDocs
|
|||
add_extension_namespace :gAcl, 'http://schemas.google.com/acl/2007'
|
||||
end
|
||||
|
||||
def create_doc(name, access_token=nil)
|
||||
access_token ||= retrieve_access_token
|
||||
def create_doc(name, access_token)
|
||||
url = "https://docs.google.com/feeds/documents/private/full"
|
||||
entry = Atom::Entry.new do |entry|
|
||||
entry.title = name
|
||||
|
|
|
@ -25,6 +25,80 @@ describe ApplicationController do
|
|||
controller.stubs(:request).returns(stub(:host_with_port => "www.example.com"))
|
||||
end
|
||||
|
||||
describe "#google_docs_connection" do
|
||||
it "uses @real_current_user first" do
|
||||
mock_real_current_user = mock()
|
||||
mock_current_user = mock()
|
||||
controller.instance_variable_set(:@real_current_user, mock_real_current_user)
|
||||
controller.instance_variable_set(:@current_user, mock_current_user)
|
||||
session[:oauth_gdocs_access_token_token] = "session_token"
|
||||
session[:oauth_gdocs_access_token_secret] = "sesion_secret"
|
||||
|
||||
Rails.cache.expects(:fetch).with(['google_docs_tokens', mock_real_current_user].cache_key).returns(["real_current_user_token", "real_current_user_secret"])
|
||||
|
||||
GoogleDocs.expects(:new).with("real_current_user_token", "real_current_user_secret")
|
||||
|
||||
controller.send(:google_docs_connection)
|
||||
end
|
||||
|
||||
it "uses @current_user second" do
|
||||
mock_current_user = mock()
|
||||
controller.instance_variable_set(:@real_current_user, nil)
|
||||
controller.instance_variable_set(:@current_user, mock_current_user)
|
||||
session[:oauth_gdocs_access_token_token] = "session_token"
|
||||
session[:oauth_gdocs_access_token_secret] = "sesion_secret"
|
||||
|
||||
Rails.cache.expects(:fetch).with(['google_docs_tokens', mock_current_user].cache_key).returns(["current_user_token", "current_user_secret"])
|
||||
|
||||
GoogleDocs.expects(:new).with("current_user_token", "current_user_secret")
|
||||
|
||||
controller.send(:google_docs_connection)
|
||||
end
|
||||
|
||||
it "queries user services if token isn't in the cache" do
|
||||
mock_current_user = mock()
|
||||
controller.instance_variable_set(:@real_current_user, nil)
|
||||
controller.instance_variable_set(:@current_user, mock_current_user)
|
||||
session[:oauth_gdocs_access_token_token] = "session_token"
|
||||
session[:oauth_gdocs_access_token_secret] = "sesion_secret"
|
||||
|
||||
mock_user_services = mock("mock_user_services")
|
||||
mock_current_user.expects(:user_services).returns(mock_user_services)
|
||||
mock_user_services.expects(:find_by_service).with("google_docs").returns(mock(token: "user_service_token", secret: "user_service_secret"))
|
||||
|
||||
GoogleDocs.expects(:new).with("user_service_token", "user_service_secret")
|
||||
|
||||
controller.send(:google_docs_connection)
|
||||
end
|
||||
|
||||
it "uses the session values if no users are set" do
|
||||
controller.instance_variable_set(:@real_current_user, nil)
|
||||
controller.instance_variable_set(:@current_user, nil)
|
||||
session[:oauth_gdocs_access_token_token] = "session_token"
|
||||
session[:oauth_gdocs_access_token_secret] = "sesion_secret"
|
||||
|
||||
GoogleDocs.expects(:new).with("session_token", "sesion_secret")
|
||||
|
||||
controller.send(:google_docs_connection)
|
||||
end
|
||||
|
||||
it "raises a NoTokenError when the user exists but does not have a user service" do
|
||||
mock_current_user = mock()
|
||||
controller.instance_variable_set(:@real_current_user, nil)
|
||||
controller.instance_variable_set(:@current_user, mock_current_user)
|
||||
session[:oauth_gdocs_access_token_token] = "session_token"
|
||||
session[:oauth_gdocs_access_token_secret] = "sesion_secret"
|
||||
|
||||
mock_user_services = mock("mock_user_services")
|
||||
mock_current_user.expects(:user_services).returns(mock_user_services)
|
||||
mock_user_services.expects(:find_by_service).with("google_docs").returns(nil)
|
||||
|
||||
expect {
|
||||
controller.send(:google_docs_connection)
|
||||
}.to raise_error(GoogleDocs::NoTokenError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "js_env" do
|
||||
it "should set items" do
|
||||
HostUrl.expects(:file_host).with(Account.default, "www.example.com").returns("files.example.com")
|
||||
|
@ -165,7 +239,7 @@ describe ApplicationController do
|
|||
@pseudonym.update_attribute(:sis_user_id, 'test1')
|
||||
controller.instance_variable_set(:@domain_root_account, Account.default)
|
||||
controller.stubs(:named_context_url).with(@user, :context_url).returns('')
|
||||
controller.stubs(:params).returns({ :user_id => 'sis_user_id:test1' })
|
||||
controller.stubs(:params).returns({:user_id => 'sis_user_id:test1'})
|
||||
controller.stubs(:api_request?).returns(true)
|
||||
controller.send(:get_context)
|
||||
controller.instance_variable_get(:@context).should == @user
|
||||
|
@ -177,7 +251,7 @@ describe ApplicationController do
|
|||
@section.update_attribute(:sis_source_id, 'test1')
|
||||
controller.instance_variable_set(:@domain_root_account, Account.default)
|
||||
controller.stubs(:named_context_url).with(@section, :context_url).returns('')
|
||||
controller.stubs(:params).returns({ :course_section_id => 'sis_section_id:test1' })
|
||||
controller.stubs(:params).returns({:course_section_id => 'sis_section_id:test1'})
|
||||
controller.stubs(:api_request?).returns(true)
|
||||
controller.send(:get_context)
|
||||
controller.instance_variable_get(:@context).should == @section
|
||||
|
@ -191,7 +265,7 @@ describe ApplicationController do
|
|||
acct = Account.default
|
||||
acct.default_locale = "es"
|
||||
acct.save!
|
||||
controller.instance_variable_set(:@domain_root_account, acct)
|
||||
controller.instance_variable_set(:@domain_root_account, acct)
|
||||
req = mock()
|
||||
req.stubs(:headers).returns({})
|
||||
controller.stubs(:request).returns(req)
|
||||
|
@ -200,7 +274,7 @@ describe ApplicationController do
|
|||
I18n.locale.to_s.should == "es"
|
||||
course_model(:locale => "ru")
|
||||
controller.stubs(:named_context_url).with(@course, :context_url).returns('')
|
||||
controller.stubs(:params).returns({ :course_id => @course.id })
|
||||
controller.stubs(:params).returns({:course_id => @course.id})
|
||||
controller.stubs(:api_request?).returns(false)
|
||||
controller.stubs(:session).returns({})
|
||||
controller.stubs(:js_env).returns({})
|
||||
|
@ -219,7 +293,6 @@ describe ApplicationController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe WikiPagesController do
|
||||
|
@ -233,7 +306,7 @@ describe WikiPagesController do
|
|||
get 'pages_index', :course_id => @course.id
|
||||
|
||||
controller.js_env.should include(:WIKI_RIGHTS)
|
||||
controller.js_env[:WIKI_RIGHTS].should == Hash[@course.wiki.check_policy(@teacher).map {|right| [right, true]}]
|
||||
controller.js_env[:WIKI_RIGHTS].should == Hash[@course.wiki.check_policy(@teacher).map { |right| [right, true] }]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,8 +41,28 @@ describe CollaborationsController do
|
|||
|
||||
it "should assign variables" do
|
||||
course_with_student_logged_in(:active_all => true)
|
||||
mock_user_service = mock()
|
||||
@user.expects(:user_services).returns(mock_user_service)
|
||||
mock_user_service.expects(:find_by_service).with("google_docs").returns(mock(token: "token", secret: "secret"))
|
||||
GoogleDocs.any_instance.expects(:verify_access_token).returns(true)
|
||||
|
||||
get 'index', :course_id => @course.id
|
||||
|
||||
response.should be_success
|
||||
assigns(:google_docs_authorized).should == true
|
||||
end
|
||||
|
||||
it "should assign variables when verify raises" do
|
||||
course_with_student_logged_in(:active_all => true)
|
||||
mock_user_service = mock()
|
||||
@user.expects(:user_services).returns(mock_user_service)
|
||||
mock_user_service.expects(:find_by_service).with("google_docs").returns(mock(token: "token", secret: "secret"))
|
||||
GoogleDocs.any_instance.expects(:verify_access_token).raises("Error")
|
||||
|
||||
get 'index', :course_id => @course.id
|
||||
|
||||
response.should be_success
|
||||
assigns(:google_docs_authorized).should == false
|
||||
end
|
||||
|
||||
it "should not allow the student view student to access collaborations" do
|
||||
|
@ -61,6 +81,10 @@ describe CollaborationsController do
|
|||
group = gc.groups.create!(:context => @course)
|
||||
group.add_user(@student, 'accepted')
|
||||
|
||||
mock_user_service = mock()
|
||||
@user.expects(:user_services).returns(mock_user_service)
|
||||
mock_user_service.expects(:find_by_service).with("google_docs").returns(mock(token: "token", secret: "secret"))
|
||||
|
||||
get 'index', :group_id => group.id
|
||||
response.should be_success
|
||||
end
|
||||
|
|
|
@ -184,6 +184,9 @@ describe SubmissionsController do
|
|||
flag.feature = 'google_docs_domain_restriction'
|
||||
flag.state = 'on'
|
||||
flag.save!
|
||||
mock_user_service = mock()
|
||||
@user.expects(:user_services).returns(mock_user_service)
|
||||
mock_user_service.expects(:find_by_service).with("google_docs").returns(mock(token: "token", secret: "secret"))
|
||||
end
|
||||
|
||||
it "should not save if domain restriction prevents it" do
|
||||
|
|
|
@ -794,4 +794,25 @@ describe UsersController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "oauth_success" do
|
||||
it "should use the access token to get user info" do
|
||||
|
||||
user_with_pseudonym
|
||||
admin = @user
|
||||
user_session(admin)
|
||||
|
||||
mock_oauth_request = stub(token: 'token', secret: 'secret', original_host_with_port: 'test.host', user: @user, return_url: '/')
|
||||
OauthRequest.expects(:find_by_token_and_service).with('token', 'google_docs').returns(mock_oauth_request)
|
||||
|
||||
mock_access_token = stub(token: '123', secret: 'abc')
|
||||
GoogleDocs.expects(:get_access_token).with('token', 'secret', 'oauth_verifier').returns(mock_access_token)
|
||||
mock_google_docs = stub()
|
||||
GoogleDocs.expects(:new).with('token', 'secret').returns(mock_google_docs)
|
||||
mock_google_docs.expects(:get_service_user_info).with(mock_access_token)
|
||||
|
||||
get 'oauth_success', {oauth_token: 'token', service: 'google_docs', oauth_verifier: 'oauth_verifier'}, {host_with_port: 'test.host'}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entry xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Temp Doc: 07 Apr 2014, 08:32 AM</title>
|
||||
<category label="document" scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#document"/>
|
||||
</entry>
|
|
@ -23,6 +23,17 @@ describe CollaborationsController, type: :request do
|
|||
it 'should properly link to the user who posted the collaboration' do
|
||||
PluginSetting.create!(:name => 'etherpad', :settings => {})
|
||||
course_with_teacher_logged_in :active_all => true, :name => "teacher 1"
|
||||
|
||||
UserService.register(
|
||||
:service => "google_docs",
|
||||
:token => "token",
|
||||
:secret => "secret",
|
||||
:user => @user,
|
||||
:service_domain => "google.com",
|
||||
:service_user_id => "service_user_id",
|
||||
:service_user_name => "service_user_name"
|
||||
)
|
||||
|
||||
get "/courses/#{@course.id}/collaborations/"
|
||||
response.should be_success
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ describe integration do
|
|||
# mock up the response from the 3rd party service, so we don't actually contact it
|
||||
OAuth::Consumer.any_instance.expects(:token_request).with(anything, anything, anything, has_entry(:oauth_verifier, "test_verifier"), anything).returns({:oauth_token => "test_token", :oauth_token_secret => "test_secret"})
|
||||
if integration == "GoogleDocs"
|
||||
GoogleDocs.any_instance.expects(:get_service_user).with(instance_of(OAuth::AccessToken)).returns(["test_user_id", "test_user_name"])
|
||||
GoogleDocs.any_instance.expects(:get_service_user_info).returns(["test_user_id", "test_user_name"])
|
||||
elsif integration == "LinkedIn"
|
||||
LinkedIn::Connection.any_instance.expects(:get_service_user_info).with(instance_of(OAuth::AccessToken)).returns(["test_user_id", "test_user_name"])
|
||||
else
|
||||
|
@ -121,7 +121,7 @@ describe integration do
|
|||
|
||||
# pretend that somehow we think we got a valid auth token, but we actually didn't
|
||||
if integration == "GoogleDocs"
|
||||
GoogleDocs.any_instance.expects(:get_service_user).with(instance_of(OAuth::AccessToken)).raises(RuntimeError, "Third-party service totally like, failed")
|
||||
GoogleDocs.any_instance.expects(:get_service_user_info).raises(RuntimeError, "Third-party service totally like, failed")
|
||||
elsif integration == "LinkedIn"
|
||||
LinkedIn::Connection.any_instance.expects(:get_service_user_info).with(instance_of(OAuth::AccessToken)).raises(RuntimeError, "Third-party service totally like, failed")
|
||||
else
|
||||
|
|
|
@ -31,69 +31,78 @@ describe GoogleDocs do
|
|||
let(:xml_doc_list_one) { load_fixture("doc_list_one.xml") }
|
||||
let(:xml_doc_list_many) { load_fixture("doc_list_many.xml") }
|
||||
let(:xml_create_doc_request) { load_fixture("create_doc_request.xml") }
|
||||
let(:xml_create_temp_doc_request) { load_fixture("create_temp_doc_request.xml") }
|
||||
let(:xml_create_doc_response) { load_fixture("create_doc_response.xml") }
|
||||
let(:xml_remove_doc_request) { load_fixture("remove_doc_request.xml") }
|
||||
let(:xml_remove_doc_response) { load_fixture("remove_doc_response.xml") }
|
||||
let(:xml_add_user_acl) { load_fixture("add_user_acl.xml") }
|
||||
let(:token) { "token" }
|
||||
let(:secret) { "secret" }
|
||||
|
||||
before do
|
||||
@user = User.create!
|
||||
GoogleDocs.stubs(:config).returns(google_doc_settings)
|
||||
UserService.register(
|
||||
:service => "google_docs",
|
||||
:token => GoogleDocs.config["test_user_token"],
|
||||
:secret => GoogleDocs.config["test_user_secret"],
|
||||
:user => @user,
|
||||
:service_domain => "google.com",
|
||||
:service_user_id => GoogleDocs.config["test_user_id"],
|
||||
:service_user_name => GoogleDocs.config["test_user_name"]
|
||||
)
|
||||
config = {
|
||||
"api_key" => "key",
|
||||
"secret_key" => "secret",
|
||||
}
|
||||
Setting.stubs(:from_config).returns(config)
|
||||
Canvas::Plugin.stubs(:find).returns(nil)
|
||||
end
|
||||
|
||||
describe "#retrieve_access_token" do
|
||||
it "should not error out if the google plugin is not configured" do
|
||||
GoogleDocs.stubs(:config).returns nil
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
Canvas::Plugin.stubs(:find).returns(nil)
|
||||
Setting.stubs(:from_config).returns(nil)
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
google_docs.retrieve_access_token.should be_nil
|
||||
end
|
||||
|
||||
it "should use the current_user" do
|
||||
user_service = mock
|
||||
google_docs_service = mock(token: 'u_token_from_service', secret: 'u_secret_from_service')
|
||||
user_service.expects(:find_by_service).with("google_docs").returns(google_docs_service)
|
||||
@user.expects(:user_services).returns(user_service)
|
||||
it "news up an OAuth::AccessToken" do
|
||||
access_token = mock_access_token
|
||||
|
||||
consumer = new_mock_consumer('key', 'secret')
|
||||
access_token = new_mock_access_token(consumer, 'u_token_from_service', 'u_secret_from_service')
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs.retrieve_access_token.should eql access_token
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
google_docs.retrieve_access_token.should == access_token
|
||||
end
|
||||
end
|
||||
|
||||
it "should use the session data if no user" do
|
||||
consumer = new_mock_consumer('key', 'secret')
|
||||
access_token = new_mock_access_token(consumer, 'u_token_from_session', 'u_secret_from_session')
|
||||
session = {
|
||||
:oauth_gdocs_access_token_token => 'u_token_from_session',
|
||||
:oauth_gdocs_access_token_secret => 'u_secret_from_session'
|
||||
}
|
||||
@google_docs = GoogleDocs.new(nil, session)
|
||||
@google_docs.retrieve_access_token.should == access_token
|
||||
describe "#get_service_user_info" do
|
||||
it "returns service user id and name" do
|
||||
known_time = Time.new(2014, 4, 7, 8, 32)
|
||||
|
||||
Timecop.freeze(known_time) do
|
||||
prepare_mock_post(xml_schema_id, xml_create_temp_doc_request, xml_create_doc_response)
|
||||
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
|
||||
prepare_mock_delete("#{xml_schema_id}/document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA")
|
||||
|
||||
user_service_id, user_service_name = google_docs.get_service_user_info google_docs.retrieve_access_token
|
||||
user_service_id.should == "instructure.test.2011@gmail.com"
|
||||
user_service_name.should == "instructure.test.2011@gmail.com"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "raises NoTokenError if user does not have google_docs service" do
|
||||
Rails.cache.delete(['google_docs_tokens', @user].cache_key)
|
||||
describe ".get_access_token" do
|
||||
it "returns the access token" do
|
||||
mock_consumer = mock_consumer()
|
||||
mock_request_token = mock()
|
||||
OAuth::RequestToken.expects(:new).with(mock_consumer, token, secret).returns(mock_request_token)
|
||||
mock_access_token = mock()
|
||||
mock_request_token.expects(:get_access_token).with(oauth_verifier: "oauth-verifier").returns(mock_access_token)
|
||||
|
||||
user_service = mock
|
||||
user_service.expects(:find_by_service).with("google_docs").returns(nil)
|
||||
@user.expects(:user_services).returns(user_service)
|
||||
access_token = GoogleDocs.get_access_token(token, secret, "oauth-verifier")
|
||||
|
||||
new_mock_consumer('key', 'secret')
|
||||
access_token.should == mock_access_token
|
||||
end
|
||||
end
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
expect do
|
||||
google_docs.retrieve_access_token
|
||||
end.to raise_error(GoogleDocs::NoTokenError)
|
||||
describe ".request_token" do
|
||||
it "returns a request token" do
|
||||
consumer = mock_consumer
|
||||
mock_request_token = mock()
|
||||
consumer.expects(:get_request_token).with({:oauth_callback => "http://callback.example.com"}, {:scope => "https://docs.google.com/feeds/ https://spreadsheets.google.com/feeds/"}).returns(mock_request_token)
|
||||
request_token = GoogleDocs.request_token("http://callback.example.com")
|
||||
request_token.should == mock_request_token
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -101,7 +110,7 @@ describe GoogleDocs do
|
|||
context "with an empty list" do
|
||||
before do
|
||||
prepare_mock_get xml_doc_list_empty
|
||||
@google_docs = GoogleDocs.new(@user, {})
|
||||
@google_docs = GoogleDocs.new(token, secret)
|
||||
end
|
||||
it "handles an empty list" do
|
||||
document_id_list = @google_docs.list_with_extension_filter(nil).files.map(&:document_id)
|
||||
|
@ -115,7 +124,7 @@ describe GoogleDocs do
|
|||
|
||||
context "with a single document" do
|
||||
before do
|
||||
@google_docs = GoogleDocs.new(@user, {})
|
||||
@google_docs = GoogleDocs.new(token, secret)
|
||||
end
|
||||
it "and nil filter" do
|
||||
prepare_mock_get xml_doc_list_one
|
||||
|
@ -148,7 +157,7 @@ describe GoogleDocs do
|
|||
|
||||
context "with multiple documents" do
|
||||
before do
|
||||
@google_docs = GoogleDocs.new(@user, {})
|
||||
@google_docs = GoogleDocs.new(token, secret)
|
||||
end
|
||||
it "returns filesystem view of results" do
|
||||
prepare_mock_get xml_doc_list_many
|
||||
|
@ -179,18 +188,17 @@ describe GoogleDocs do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
describe "#download" do
|
||||
it "pulls the document out that matches the provided id" do
|
||||
doc_id = 'spreadsheet:0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c'
|
||||
token = mock_access_token
|
||||
access_token = mock_access_token
|
||||
document_response = mock()
|
||||
token.expects(:get).with('https://docs.google.com/feeds/download/spreadsheets/Export?key=0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c').returns(document_response)
|
||||
access_token.expects(:get).with('https://docs.google.com/feeds/download/spreadsheets/Export?key=0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c').returns(document_response)
|
||||
response = mock()
|
||||
response.expects(:body).returns(xml_doc_list_many)
|
||||
token.expects(:get).with(xml_schema_id).returns(response)
|
||||
access_token.expects(:get).with(xml_schema_id).returns(response)
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
doc_array = google_docs.download(doc_id)
|
||||
doc_array[0].should == document_response
|
||||
doc_array[1].should == 'Sprint Teams'
|
||||
|
@ -199,19 +207,19 @@ describe GoogleDocs do
|
|||
|
||||
it "follows redirects" do
|
||||
doc_id = 'spreadsheet:0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c'
|
||||
token = mock_access_token
|
||||
access_token = mock_access_token
|
||||
document_response = mock()
|
||||
|
||||
redirect = Net::HTTPFound.new(1.0, 302, "FOUND")
|
||||
redirect['Location'] = 'http://example.com/1234'
|
||||
token.expects(:get).with('https://docs.google.com/feeds/download/spreadsheets/Export?key=0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c').returns(redirect)
|
||||
token.expects(:get).with('http://example.com/1234').returns(document_response)
|
||||
access_token.expects(:get).with('https://docs.google.com/feeds/download/spreadsheets/Export?key=0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c').returns(redirect)
|
||||
access_token.expects(:get).with('http://example.com/1234').returns(document_response)
|
||||
|
||||
response = mock()
|
||||
response.expects(:body).returns(xml_doc_list_many)
|
||||
token.expects(:get).with(xml_schema_id).returns(response)
|
||||
access_token.expects(:get).with(xml_schema_id).returns(response)
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
doc_array = google_docs.download(doc_id)
|
||||
doc_array[0].should == document_response
|
||||
doc_array[1].should == 'Sprint Teams'
|
||||
|
@ -220,25 +228,24 @@ describe GoogleDocs do
|
|||
|
||||
it "handles nonexistant entry" do
|
||||
doc_id = 'spreadsheet:WRONG'
|
||||
token = mock_access_token
|
||||
#token.expects(:get).with('https://docs.google.com/feeds/download/spreadsheets/Export?key=0AiN8C_VHrPxkdEF6YmQyc3p2Qm02ODhJWGJnUmJYY2c').returns(mock())
|
||||
access_token = mock_access_token
|
||||
response = mock()
|
||||
response.expects(:body).returns(xml_doc_list_many)
|
||||
token.expects(:get).with(xml_schema_id).returns(response)
|
||||
access_token.expects(:get).with(xml_schema_id).returns(response)
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
doc_array = google_docs.download(doc_id)
|
||||
doc_array.should == [nil, nil, nil]
|
||||
end
|
||||
end
|
||||
|
||||
describe "documents" do
|
||||
describe "#create_doc" do
|
||||
it "can be created" do
|
||||
prepare_mock_post(xml_schema_id, xml_create_doc_request, xml_create_doc_response)
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
|
||||
new_document = google_docs.create_doc "test document"
|
||||
new_document = google_docs.create_doc "test document", google_docs.retrieve_access_token
|
||||
new_document.document_id.should == 'document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA'
|
||||
new_document.extension.should == 'doc'
|
||||
new_document.display_name.should == 'test document'
|
||||
|
@ -246,26 +253,30 @@ describe GoogleDocs do
|
|||
new_document.alternate_url.should be_a(Atom::Link)
|
||||
new_document.alternate_url.href.should == 'https://docs.google.com/document/d/1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA/edit?hl=en_US'
|
||||
end
|
||||
end
|
||||
|
||||
it "can be removed" do
|
||||
prepare_mock_post('https://docs.google.com/feeds/acl/private/full/document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA/batch', xml_remove_doc_request, xml_remove_doc_response)
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
result = google_docs.acl_remove 'document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA', ['user@example.com']
|
||||
result.should == []
|
||||
end
|
||||
|
||||
describe "#delete_doc" do
|
||||
it "can be deleted" do
|
||||
prepare_mock_post(xml_schema_id, xml_create_doc_request, xml_create_doc_response)
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
new_document = google_docs.create_doc "test document"
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
new_document = google_docs.create_doc("test document", google_docs.retrieve_access_token)
|
||||
|
||||
prepare_mock_delete "#{xml_schema_id}/document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA"
|
||||
google_docs.delete_doc new_document
|
||||
end
|
||||
end
|
||||
|
||||
describe "#acl_remove" do
|
||||
it "can be removed" do
|
||||
prepare_mock_post('https://docs.google.com/feeds/acl/private/full/document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA/batch', xml_remove_doc_request, xml_remove_doc_response)
|
||||
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
result = google_docs.acl_remove 'document:1HJoN38KHlnu32B5z_THgchnTMUbj7dgs8P-Twrm38cA', ['user@example.com']
|
||||
result.should == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "#acl_add" do
|
||||
let(:doc_response) { mock }
|
||||
let(:doc_id) { "12345" }
|
||||
|
@ -274,7 +285,7 @@ describe GoogleDocs do
|
|||
it "should add users to a document" do
|
||||
prepare_mock_post(url, xml_add_user_acl, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\"/>\n")
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
mock_user = mock()
|
||||
mock_user.stubs(:id).returns(192)
|
||||
mock_user.stubs(:google_docs_address).returns('u_id')
|
||||
|
@ -286,7 +297,7 @@ describe GoogleDocs do
|
|||
access_token = mock_access_token
|
||||
access_token.expects(:post).never
|
||||
|
||||
google_docs = GoogleDocs.new(@user, {})
|
||||
google_docs = GoogleDocs.new(token, secret)
|
||||
mock_user = mock()
|
||||
mock_user.stubs(:id).returns(192)
|
||||
mock_user.stubs(:google_docs_address).returns('u_id')
|
||||
|
@ -314,7 +325,7 @@ describe GoogleDocs do
|
|||
|
||||
def mock_consumer
|
||||
consumer = mock()
|
||||
OAuth::Consumer.expects(:new).with(
|
||||
OAuth::Consumer.expects(:new).at_least_once.with(
|
||||
GoogleDocs.config["api_key"],
|
||||
GoogleDocs.config["secret_key"], {
|
||||
:signature_method => 'HMAC-SHA1',
|
||||
|
@ -325,33 +336,13 @@ describe GoogleDocs do
|
|||
return consumer
|
||||
end
|
||||
|
||||
def new_mock_consumer(api_key, secret_key)
|
||||
consumer = mock()
|
||||
OAuth::Consumer.expects(:new).with(
|
||||
api_key,
|
||||
secret_key, {
|
||||
:signature_method => 'HMAC-SHA1',
|
||||
:request_token_path => '/accounts/OAuthGetRequestToken',
|
||||
:site => 'https://www.google.com',
|
||||
:authorize_path => '/accounts/OAuthAuthorizeToken',
|
||||
:access_token_path => '/accounts/OAuthGetAccessToken'}).returns(consumer)
|
||||
return consumer
|
||||
end
|
||||
|
||||
def mock_access_token
|
||||
access_token = mock()
|
||||
OAuth::AccessToken.expects(:new).with(mock_consumer(),
|
||||
GoogleDocs.config["test_user_token"],
|
||||
GoogleDocs.config["test_user_secret"]).returns(access_token)
|
||||
return access_token
|
||||
end
|
||||
|
||||
def new_mock_access_token(consumer, user_token, user_secret)
|
||||
access_token = mock()
|
||||
OAuth::AccessToken.expects(:new).with(consumer,
|
||||
user_token,
|
||||
user_secret).returns(access_token)
|
||||
return access_token
|
||||
return @access_token if @access_token
|
||||
@access_token = mock()
|
||||
OAuth::AccessToken.expects(:new).at_least_once.with(mock_consumer(),
|
||||
"token",
|
||||
"secret").returns(@access_token)
|
||||
return @access_token
|
||||
end
|
||||
|
||||
def prepare_mock_get(response_xml)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Copyright (C) 2014 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe GoogleDocsCollaboration do
|
||||
describe "#initialize_document" do
|
||||
let(:user) { User.new }
|
||||
it "creates a google doc" do
|
||||
google_docs_collaboration = GoogleDocsCollaboration.new
|
||||
google_docs_collaboration.title = "title"
|
||||
google_docs_collaboration.user = user
|
||||
google_doc_connection = stub(retrieve_access_token: "asdf123")
|
||||
GoogleDocs.expects(:new).returns(google_doc_connection)
|
||||
file = stub(document_id: 1, entry: stub(to_xml: "<xml></xml>"), alternate_url: "http://google.com")
|
||||
google_doc_connection.expects(:create_doc).with("title", "asdf123").returns(file)
|
||||
Rails.cache.expects(:fetch).returns(["token", "secret"])
|
||||
|
||||
google_docs_collaboration.initialize_document
|
||||
end
|
||||
end
|
||||
end
|
|
@ -84,6 +84,17 @@ describe "collaborations" do
|
|||
before(:each) do
|
||||
course_with_teacher_logged_in
|
||||
|
||||
UserService.register(
|
||||
:service => "google_docs",
|
||||
:token => "token",
|
||||
:secret => "secret",
|
||||
:user => @user,
|
||||
:service_domain => "google.com",
|
||||
:service_user_id => "service_user_id",
|
||||
:service_user_name => "service_user_name"
|
||||
)
|
||||
|
||||
|
||||
if type == 'google_docs'
|
||||
GoogleDocs.any_instance.
|
||||
stubs(:verify_access_token).
|
||||
|
|
Loading…
Reference in New Issue