CartoDB/cartodb20

View on GitHub
app/controllers/carto/api/imports_controller.rb

Summary

Maintainability
A
40 mins
Test Coverage
module Carto
  module Api
    class ImportsController < ::Api::ApplicationController

      ssl_required :index, :show
      ssl_allowed :service_token_valid?, :list_files_for_service, :get_service_auth_url, :validate_service_oauth_code,
                  :service_oauth_callback

      def index
        imports = DataImportsService.new.process_recent_user_imports(current_user)
        render json: { imports: imports.map(&:id), success: true }
      end

      def show
        import = DataImportsService.new.process_by_id(params[:id])
        render_404 and return if import.nil?

        data = Carto::Api::DataImportPresenter.new(import).api_public_values
        if import.state == Carto::DataImport::STATE_COMPLETE
          data[:any_table_raster] = import.is_raster?

          decorate_twitter_import_data!(data, import)
          decorate_default_visualization_data!(data, import)
        end

        render json: data
      end

      def service_token_valid?
        valid = DataImportsService.new.validate_synchronization_oauth(uri_user, params[:id])
        render_jsonp({ oauth_valid: valid, success: true })
      rescue CartoDB::Datasources::TokenExpiredOrInvalidError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: e.message }, 401)
      rescue StandardError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: e.message }, 400)
      end

      def list_files_for_service
        filter = params[:filter].present? ? params[:filter] : []
        results = DataImportsService.new.get_service_files(uri_user, params[:id], filter)
        render_jsonp({ files: results, success: true })
      rescue CartoDB::Datasources::TokenExpiredOrInvalidError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: e.message }, 401)
      rescue StandardError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: { imports: e.message } }, 400)
      end

      def get_service_auth_url
        auth_url = DataImportsService.new.get_service_auth_url(uri_user, params[:id])
        render_jsonp({ url: auth_url, success: true})
      rescue CartoDB::Datasources::TokenExpiredOrInvalidError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: e.message }, 401)
      rescue StandardError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: { imports: e.message } }, 400)
      end

      def validate_service_oauth_code
        success = DataImportsService.new.validate_service_oauth_code(uri_user, params[:id], params[:code])
        render_jsonp({ success: success })
      rescue CartoDB::Datasources::TokenExpiredOrInvalidError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: e.message }, 401)
      rescue StandardError => e
        CartoDB.notify_exception(e, { user: uri_user, params: params })
        render_jsonp({ errors: { imports: e.message } }, 400)
      end

      def service_oauth_callback
        DataImportsService.new.validate_callback(uri_user, params[:id], params)
        request.format = 'html'
        respond_to do |format|
          format.all  { render text: '<script>window.close();</script>', content_type: 'text/html' }
        end
      rescue CartoDB::Datasources::AuthError => e
        log_warning(message: e.message, exception: e, current_user: uri_user, params: params)
        render text: "#{e.message}. Try reconnecting<script>setTimeout(function(){window.close()}, 1000);</script>",
               content_type: 'text/html', status: 400
      rescue CartoDB::Datasources::TokenExpiredOrInvalidError => e
        log_warning(message: "Expired oauth token", exception: e, current_user: uri_user, params: params)
        render text: 'Expired token. Try reconnecting<script>setTimeout(function(){window.close()}, 1000);</script>',
               content_type: 'text/html', status: 403
      rescue StandardError => e
        log_warning(message: "Error in oauth callback", exception: e, current_user: uri_user, params: params)
        render text: 'Connection failed<script>setTimeout(function(){window.close()}, 1000);</script>',
               content_type: 'text/html', status: 400
      end

      private

      # TODO: this should be moved upwards in the controller hierarchy, and make it a replacement for current_user
      def uri_user
        @uri_user ||= Carto::User.where(id: current_user.id).first
      end

      def decorate_twitter_import_data!(data, data_import)
        return if data_import.service_name != CartoDB::Datasources::Search::Twitter::DATASOURCE_NAME

        audit_entry = Carto::SearchTweet.find_by(data_import_id: data_import.id)
        data[:tweets_georeferenced] = audit_entry.retrieved_items
        data[:tweets_cost] = audit_entry.price
        data[:tweets_overquota] = audit_entry.user.remaining_twitter_quota == 0
      end

      def decorate_default_visualization_data!(data, data_import)
        derived_vis_id = nil

        if data_import.create_visualization && !data_import.visualization_id.nil?
          derived_vis_id = data_import.visualization_id
        end

        data[:derived_visualization_id] = derived_vis_id
      end

    end
  end
end