Dropbox API v2

pull/12099/head
Juan Ignacio Sánchez Lara 7 years ago
parent cfa9b5ced6
commit 7d1848b4b6

@ -55,7 +55,7 @@ gem 'dbf', '2.0.6'
gem 'faraday', '0.9.0'
gem 'retriable', '1.4.1' # google-api-client needs this
gem 'google-api-client', '0.7.0'
gem 'dropbox-sdk', '1.6.3'
gem 'dropbox_api', '0.1.6'
gem 'instagram', '1.1.6'
gem 'gibbon', '1.1.4'

@ -106,8 +106,9 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.1.3)
docile (1.1.5)
dropbox-sdk (1.6.3)
json
dropbox_api (0.1.6)
faraday (~> 0.9, ~> 0.8)
oauth2 (~> 1.1)
ejs (1.1.1)
em-pg-client (0.2.1)
eventmachine (>= 0.12.10)
@ -192,6 +193,12 @@ GEM
oauth (0.4.5)
oauth-plugin (0.4.0.pre4)
oauth (>= 0.4.4)
oauth2 (1.3.1)
faraday (>= 0.8, < 0.12)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
pg (0.15.0)
poltergeist (1.0.3)
capybara (~> 1.1)
@ -373,7 +380,7 @@ DEPENDENCIES
db-query-matchers (= 0.4.0)
dbf (= 2.0.6)
delorean
dropbox-sdk (= 1.6.3)
dropbox_api (= 0.1.6)
ejs (~> 1.1.1)
em-pg-client (= 0.2.1)
eventmachine (= 1.0.4)

@ -0,0 +1,30 @@
require 'dropbox_api'
# These classes add toking revoking features to dropbox_api gem. They should be eventually sent there.
module DropboxApi::Metadata
class Revoke < Base
def initialize(_response_data)
# response_data is empty
end
end
end
module DropboxApi::Endpoints
module Auth
module Token
class Revoke < DropboxApi::Endpoints::Rpc
Method = :post
Path = "/2/auth/token/revoke".freeze
ResultType = DropboxApi::Metadata::Revoke
ErrorType = DropboxApi::Errors::BasicError
# Revoke token
#
# @return [Revoke] Empty response
add_endpoint :revoke do
perform_request nil
end
end
end
end
end

@ -1,7 +1,8 @@
# encoding: utf-8
require 'dropbox_sdk'
require 'dropbox_api'
require_relative '../base_oauth'
require_relative '../../../../../lib/dropbox_api/endpoints/auth/token/revoke'
module CartoDB
module Datasources
@ -62,46 +63,24 @@ module CartoDB
end
# Return the url to be displayed or sent the user to to authenticate and get authorization code
# @param use_callback_flow : bool
# Older implementations had a use_callback_flow parameter that became deprecated. Not implemented.
# @throws AuthError
def get_auth_url(use_callback_flow=true)
if use_callback_flow
@auth_flow = DropboxOAuth2Flow.new(@app_key, @app_secret, @callback_url, {}, :csrf_token)
else
@auth_flow = DropboxOAuth2FlowNoRedirect.new(@app_key, @app_secret)
end
service_name = service_name_for_user(DATASOURCE_NAME, @user)
@auth_flow.start(CALLBACK_STATE_DATA_PLACEHOLDER.sub('user', @user.username).sub('service', service_name))
rescue DropboxError, ArgumentError => ex
def get_auth_url
authenticator.authorize_url redirect_uri: @callback_url, state: state
rescue => ex
raise AuthError.new("get_auth_url(#{use_callback_flow}): #{ex.message}", DATASOURCE_NAME)
end
# Validate authorization code and store token
# @param auth_code : string
# @return string : Access token
# @throws AuthError
def validate_auth_code(auth_code)
@auth_flow = DropboxOAuth2FlowNoRedirect.new(@app_key, @app_secret)
data = @auth_flow.finish(auth_code)
@access_token = data[0] # Only keep the access token
@auth_flow = nil
@client = DropboxClient.new(@access_token)
@access_token
rescue DropboxError, ArgumentError => ex
raise AuthError.new("validate_auth_code(): #{ex.message}", DATASOURCE_NAME)
end
# Validates the authorization callback
# @param params : mixed
def validate_callback(params)
session = {csrf_token: params[:state].split('|').first.presence }
@auth_flow = DropboxOAuth2Flow.new(@app_key, @app_secret, @callback_url, session, :csrf_token)
data = @auth_flow.finish(params)
@access_token = data[0] # Only keep the access token
@auth_flow = nil
@client = DropboxClient.new(@access_token)
raise "state doesn't match" unless params[:state] == state
auth_bearer = authenticator.get_token(params[:code], redirect_uri: @callback_url)
@access_token = auth_bearer.token
@client = DropboxApi::Client.new(@access_token)
@access_token
rescue DropboxError, ArgumentError => ex
rescue => ex
raise AuthError.new("validate_callback(#{params.inspect}): #{ex.message}", DATASOURCE_NAME)
end
@ -111,7 +90,7 @@ module CartoDB
# @throws AuthError
def token=(token)
@access_token = token
@client = DropboxClient.new(@access_token)
@client = DropboxApi::Client.new(@access_token)
rescue => ex
handle_error(ex, "token= : #{ex.message}")
end
@ -133,9 +112,9 @@ module CartoDB
self.filter = filter
@formats.each do |search_query|
response = @client.search('/', search_query)
response.each do |item|
all_results.push(format_item_data(item))
response = @client.search(search_query, '')
response.matches.each do |item|
all_results.push(format_item_data(item.resource))
end
end
all_results
@ -150,8 +129,11 @@ module CartoDB
# @throws AuthError
# @throws DataDownloadError
def get_resource(id)
contents, = @client.get_file_and_metadata(id)
contents
file_contents = ''
@client.download(id) do |chunk|
file_contents << chunk
end
file_contents
rescue => ex
handle_error(ex, "get_resource() #{id}: #{ex.message}")
end
@ -164,7 +146,7 @@ module CartoDB
def get_resource_metadata(id)
raise DropboxPermissionError.new('No Dropbox client', DATASOURCE_NAME) unless @client.present?
response = @client.metadata(id)
response = @client.get_metadata(id)
item_data = format_item_data(response)
item_data.to_hash
@ -214,17 +196,13 @@ module CartoDB
# @throws AuthError
def token_valid?
# Any call would do, we just want to see if communicates or refuses the token
@client.account_info
raise "Current account not found" unless @client.get_current_account
true
rescue DropboxError => ex
error_code = ex.http_response.code.to_i
raise AuthError.new("token_valid? : #{ex.message}") unless (error_code == 401 || error_code == 403)
false
end
# Revokes current set token
def revoke_token
@client.disable_access_token
@client.revoke
true
rescue => ex
raise AuthError.new("revoke_token: #{ex.message}", DATASOURCE_NAME)
@ -239,7 +217,7 @@ module CartoDB
# @throws AuthError
# @throws mixed
def handle_error(original_exception, message)
if original_exception.kind_of? DropboxError
if original_exception.kind_of? DropboxApi::Errors::BasicError
error_code = original_exception.http_response.code.to_i
if error_code == 401 || error_code == 403
raise TokenExpiredOrInvalidError.new(message, DATASOURCE_NAME)
@ -256,19 +234,28 @@ module CartoDB
# Formats all data to comply with our desired format
# @param item_data Hash : Single item returned from Dropbox API
# @return { :id, :title, :url, :service, :size }
def format_item_data(item_data)
filename = item_data.fetch('path').split('/').last
def format_item_data(resource)
path = resource.path_display
filename = path.split('/').last
{
id: item_data.fetch('path'),
id: path,
title: filename,
filename: filename,
service: DATASOURCE_NAME,
checksum: checksum_of(item_data.fetch('rev')),
size: item_data.fetch('bytes').to_i
checksum: checksum_of(resource.rev),
size: resource.size
}
end
def authenticator
@authenticator ||= DropboxApi::Authenticator.new(@app_key, @app_secret)
end
def state
service_name = service_name_for_user(DATASOURCE_NAME, @user)
CALLBACK_STATE_DATA_PLACEHOLDER.sub('user', @user.username).sub('service', service_name)
end
end
end
end

Loading…
Cancel
Save