diff --git a/Makefile b/Makefile index 3881cf512a..e2cdc1cdad 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ WORKING_SPECS = \ services/synchronizer/spec/unit/ \ services/synchronizer/spec/acceptance/ \ services/geocoder/spec/geocoder_spec.rb \ + spec/models/synchronization/synchronization_oauth_spec.rb \ $(NULL) CDB_PATH=lib/assets/javascripts/cdb diff --git a/app/models/data_import.rb b/app/models/data_import.rb index cf5acb8633..ccaa114b65 100644 --- a/app/models/data_import.rb +++ b/app/models/data_import.rb @@ -301,14 +301,7 @@ class DataImport < Sequel::Model def new_importer(datasource_name=nil) log.append 'new_importer()' - begin - datasource_provider = DatasourcesFactory.get_datasource(datasource_name, current_user) - rescue ConfigurationError => exception - datasource_provider = nil - log.append "Exception: #{exception.to_s}" - log.append exception.backtrace - Rollbar.report_message('Import error', 'error', error_info: exception.to_s + exception.backtrace.join) - end + datasource_provider = get_datasource(datasource_name) tracker = lambda { |state| self.state = state; save } downloader = CartoDB::Importer2::Downloader.new(data_source) @@ -318,9 +311,7 @@ class DataImport < Sequel::Model registrar = CartoDB::TableRegistrar.new(current_user, Table) quota_checker = CartoDB::QuotaChecker.new(current_user) database = current_user.in_database - importer = CartoDB::Connector::Importer.new( - runner, registrar, quota_checker, database, id - ) + importer = CartoDB::Connector::Importer.new(runner, registrar, quota_checker, database, id) log.append 'Before run.' importer.run(tracker) @@ -330,6 +321,7 @@ class DataImport < Sequel::Model self.error_code = importer.error_code self.table_name = importer.table.name if importer.success? && importer.table self.table_id = importer.table.id if importer.success? && importer.table + if synchronization_id log.append "synchronization_id: #{synchronization_id}" synchronization = CartoDB::Synchronization::Member.new(id: synchronization_id).fetch @@ -348,6 +340,7 @@ class DataImport < Sequel::Model log.append "importer.success? #{synchronization.state}" synchronization.store end + importer.success? end @@ -382,6 +375,17 @@ class DataImport < Sequel::Model payload end + def get_datasource(datasource_name) + begin + DatasourcesFactory.get_datasource(datasource_name, current_user) + rescue ConfigurationError => exception + nil + log.append "Exception: #{exception.to_s}" + log.append exception.backtrace + Rollbar.report_message('Import error: ', 'error', error_info: exception.to_s + exception.backtrace.join) + end + end #get_datasource + def set_merge_error(error_code) log.append("going to set merge error with code #{error_code}") self.results = [CartoDB::Importer2::Result.new( diff --git a/app/models/synchronization/synchronization_oauth.rb b/app/models/synchronization/synchronization_oauth.rb new file mode 100644 index 0000000000..804c750a0d --- /dev/null +++ b/app/models/synchronization/synchronization_oauth.rb @@ -0,0 +1,46 @@ +# encoding: utf-8 + +# @see DB table 'synchronization_oauths' +class SynchronizationOauth < Sequel::Model + + many_to_one :user + + PUBLIC_ATTRIBUTES = [ + :id, + :user_id, + :service, + :token + ] + + def public_values + Hash[PUBLIC_ATTRIBUTES.map{ |k| [k, (self.send(k) rescue self[k].to_s)] }] + end #public_values + + def validate + super + + if new? + existing_oauth = SynchronizationOauth.filter( + user_id: user_id, + service: service + ).first + errors.add(:user_id, " already has an oauth token created for service #{:service}") unless existing_oauth.nil? + else + existing_oauth = SynchronizationOauth.filter( + id: id + ).first + errors.add(:id, ' cannot change user or service, only token') unless + (existing_oauth.service == service && existing_oauth.user_id == user_id) + end + end #validate + + def before_save + super + self.updated_at = Time.now + end #before_save + + def ==(oauth_object) + self.id == oauth_object.id + end #== + +end diff --git a/app/models/user.rb b/app/models/user.rb index 2f81507a83..a4fa9fdaa7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,7 +7,8 @@ class User < Sequel::Model self.strict_param_setting = false one_to_one :client_application - plugin :association_dependencies, :client_application => :destroy + # @param synchronization_oauths + one_to_many :synchronization_oauths one_to_many :tokens, :class => :OauthToken one_to_many :maps one_to_many :assets @@ -20,6 +21,7 @@ class User < Sequel::Model } # Sequel setup & plugins + plugin :association_dependencies, :client_application => :destroy, :synchronization_oauths => :destroy plugin :validation_helpers plugin :json_serializer plugin :dirty diff --git a/db/migrate/20140314101744_create_synchronization_oauths.rb b/db/migrate/20140314101744_create_synchronization_oauths.rb new file mode 100644 index 0000000000..3df3c76f78 --- /dev/null +++ b/db/migrate/20140314101744_create_synchronization_oauths.rb @@ -0,0 +1,16 @@ +Sequel.migration do + up do + create_table :synchronization_oauths do + primary_key :id + Uuid :user_id, index: true + Text :service, index: true + Text :token + DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP + DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP + end + end + + down do + drop_table :synchronization_oauths + end +end diff --git a/services/datasources/lib/datasources/url/dropbox.rb b/services/datasources/lib/datasources/url/dropbox.rb index 9f15074d86..df30f22e0d 100644 --- a/services/datasources/lib/datasources/url/dropbox.rb +++ b/services/datasources/lib/datasources/url/dropbox.rb @@ -41,9 +41,9 @@ module CartoDB @user = user self.filter=[] - @client = nil @auth_flow = nil + end #initialize # Factory method diff --git a/spec/models/synchronization/synchronization_oauth_spec.rb b/spec/models/synchronization/synchronization_oauth_spec.rb new file mode 100644 index 0000000000..c16decc859 --- /dev/null +++ b/spec/models/synchronization/synchronization_oauth_spec.rb @@ -0,0 +1,107 @@ +require 'spec_helper' + +describe SynchronizationOauth do + + before(:all) do + @user = create_user(:quota_in_bytes => 500.megabytes, :table_quota => 500) + end + + after(:all) do + @user.destroy + end + + before(:each) do + end + + after(:each) do + @user.synchronization_oauths.map &:destroy + @user.reload + end + + context '#creation_updating' do + it 'Tests basic creation operations' do + service_name = 'testtest' + token_value = 'qv2345q235erfaweerfdsdfsds' + token_value_2 = 'aaaaaaaaaaaaaaaaaaaaaaaa' + + SynchronizationOauth.all.size.should eq 0 + + oauth_entry = SynchronizationOauth.create( + user_id: @user.id, + service: service_name, + token: token_value + ).reload + + oauth_entry.nil?.should eq false + oauth_entry.user_id.should eq @user.id + oauth_entry.service.should eq service_name + oauth_entry.token.should eq token_value + + SynchronizationOauth.all.size.should eq 1 + + entry_second_handle = SynchronizationOauth.where(user_id: @user.id, service: service_name).first + entry_second_handle.nil?.should eq false + entry_second_handle.user_id.should eq @user.id + entry_second_handle.service.should eq service_name + entry_second_handle.token.should eq token_value + + entry_second_handle.should eq oauth_entry + + oauth_entry.token = token_value_2 + oauth_entry.save.reload + oauth_entry.token.should eq token_value_2 + + expect { + oauth_entry.service = 'another_service_name' + oauth_entry.save + }.to raise_exception Sequel::ValidationFailed + oauth_entry.service = service_name + + expect { + oauth_entry.user_id = UUIDTools::UUID.timestamp_create + oauth_entry.save + }.to raise_exception Sequel::ValidationFailed + + expect { + SynchronizationOauth.create( + user_id: @user.id, + service: service_name, + token: UUIDTools::UUID.timestamp_create + ) + }.to raise_exception Sequel::ValidationFailed + end + end + + context '#user_oauths' do + it 'tests the one to many association of user and sync oauths' do + service_name = 'testtest' + token_value = 'qv2345q235erfaweerfdsdfsds' + + @user.synchronization_oauths.size.should eq 0 + + SynchronizationOauth.create( + user_id: @user.id, + service: service_name, + token: token_value + ) + @user.reload + @user.synchronization_oauths.size.should eq 1 + + retrieved_entry = @user.synchronization_oauths.first + @user.synchronization_oauths.first.should eq retrieved_entry + + @user.synchronization_oauths.first.destroy + @user.reload + @user.synchronization_oauths.size.should eq 0 + + @user.add_synchronization_oauth(service: service_name, token: token_value) + @user.synchronization_oauths.size.should eq 1 + + expect { + @user.add_synchronization_oauth(service: service_name, token: token_value) + }.to raise_exception Sequel::ValidationFailed + + end + end + +end