cartodb/app/controllers/carto/api/tables_controller.rb
2020-06-15 10:58:47 +08:00

101 lines
4.5 KiB
Ruby

require_relative '../../../models/carto/permission'
require_relative '../../../models/carto/user_table'
module Carto
module Api
class TablesController < ::Api::ApplicationController
ssl_required :show, :create, :update
before_filter :set_start_time
before_filter :load_user_table, only: [:show, :update]
before_filter :read_privileges?, only: [:show]
before_filter :write_privileges?, only: [:update]
def show
table = @user_table.service
render_jsonp(TablePresenter.new(table, current_user, self).to_poro.merge(schema: table.schema(reload: true)))
end
# Very basic controller method to simply make blank tables
# All other table creation things are controlled via the imports_controller#create
def create
table = ::Table.new
table.user_id = current_user.id
tables = Carto::Db::UserSchema.new(current_user).table_names
table.name = Carto::ValidTableNameProposer.new.propose_valid_table_name(params[:name], taken_names: tables)
table.description = params[:description] if params[:description]
table.the_geom_type = params[:the_geom_type] if params[:the_geom_type]
table.force_schema = params[:schema] if params[:schema]
table.tags = params[:tags] if params[:tags]
table.import_from_query = params[:from_query] if params[:from_query]
if table.valid? && table.save
render_jsonp(TablePresenter.new(table, current_user, self).to_poro, 200, location: "/tables/#{table.id}")
table_visualization = table.table_visualization
if table_visualization
current_viewer_id = current_viewer.id
Carto::Tracking::Events::CreatedDataset.new(current_viewer_id,
visualization_id: table_visualization.id,
user_id: current_viewer_id,
origin: 'blank').report
end
else
CartoDB::Logger.error(message: 'Error on tables#create', errors: table.errors.full_messages)
render_jsonp({ description: table.errors.full_messages, stack: table.errors.full_messages }, 400)
end
rescue CartoDB::QuotaExceeded
current_viewer_id = current_viewer.id
Carto::Tracking::Events::ExceededQuota.new(current_viewer_id,
user_id: current_viewer_id).report
render_jsonp({ errors: ['You have reached your table quota'] }, 400)
end
def update
# TODO This endpoint is only used to geocode from editor, passing `latitude_column` and `longitude_column`
# TODO It also supports attributes assignement, but this is not called from our frontend
table = @user_table.service
warnings = []
# TODO: this is bad, passing all params blindly to the table object
@user_table.assign_attributes(params.symbolize_keys.reject { |k, _| k == :name })
if params.keys.include?('latitude_column') && params.keys.include?('longitude_column')
latitude_column = params[:latitude_column] == 'nil' ? nil : params[:latitude_column].try(:to_sym)
longitude_column = params[:longitude_column] == 'nil' ? nil : params[:longitude_column].try(:to_sym)
table.georeference_from!(latitude_column: latitude_column, longitude_column: longitude_column)
table.update_bounding_box
render_jsonp(TablePresenter.new(table, current_user, self).to_poro.merge(warnings: warnings))
return
end
if @user_table.save
render_jsonp(TablePresenter.new(table, current_user, self).to_poro.merge(warnings: warnings))
else
render_jsonp({ errors: table.errors.full_messages }, 400)
end
rescue => e
CartoDB::Logger.error(message: 'Error updating table', exception: e)
render_jsonp({ errors: [translate_error(e.message.split("\n").first)] }, 400)
end
private
def load_user_table
@user_table = Carto::Helpers::TableLocator.new.get_by_id_or_name(params[:id], current_user)
raise RecordNotFound unless @user_table
end
def read_privileges?
head(403) unless current_user && @user_table.visualization.is_viewable_by_user?(current_user)
end
def write_privileges?
head(401) unless current_user && @user_table.visualization.writable_by?(current_user)
end
end
end
end