149 lines
5.2 KiB
Ruby
149 lines
5.2 KiB
Ruby
module Carto
|
|
module Api
|
|
class WidgetsController < ::Api::ApplicationController
|
|
include Carto::ControllerHelper
|
|
|
|
ssl_required :show, :create, :update, :destroy, :update_many
|
|
|
|
before_filter :load_map
|
|
before_filter :load_layer, :load_widget_id, except: [:update_many]
|
|
before_filter :load_widget, only: [:show, :update, :destroy]
|
|
|
|
rescue_from Carto::LoadError, with: :rescue_from_carto_error
|
|
rescue_from Carto::UnauthorizedError, with: :rescue_from_carto_error
|
|
rescue_from Carto::UnprocesableEntityError, with: :rescue_from_carto_error
|
|
|
|
def show
|
|
render_jsonp(WidgetPresenter.new(@widget).to_poro)
|
|
end
|
|
|
|
def create
|
|
order_param = params[:order]
|
|
order = if order_param.present?
|
|
order_param
|
|
else
|
|
@map.visualization.widgets.count
|
|
end
|
|
widget = Carto::Widget.new(
|
|
layer_id: @layer_id,
|
|
order: order,
|
|
type: params[:type],
|
|
title: params[:title],
|
|
options: params[:options],
|
|
style: params[:style],
|
|
source_id: source_id_from_params)
|
|
widget.save!
|
|
|
|
Carto::Tracking::Events::CreatedWidget.new(current_viewer.id,
|
|
user_id: current_viewer.id,
|
|
visualization_id: @layer.visualization.id,
|
|
widget_id: widget.id).report
|
|
|
|
render_jsonp(WidgetPresenter.new(widget).to_poro, 201)
|
|
rescue ActiveRecord::RecordInvalid
|
|
render json: { errors: widget.errors }, status: 422
|
|
rescue => e
|
|
CartoDB::Logger.error(exception: e, message: "Error creating widget", widget: (widget ? widget : 'not created'))
|
|
render json: { errors: e.message }, status: 500
|
|
end
|
|
|
|
def update
|
|
update_widget!(@widget, params)
|
|
|
|
render_jsonp(WidgetPresenter.new(@widget).to_poro)
|
|
rescue => e
|
|
CartoDB::Logger.error(exception: e, message: "Error updating widget", widget: @widget)
|
|
render json: { errors: e.message }, status: 500
|
|
end
|
|
|
|
def update_many
|
|
entries = params[:_json].map do |json_widget|
|
|
{ widget: widget_with_validations(json_widget[:id]), json: json_widget }
|
|
end
|
|
result = ActiveRecord::Base.transaction do
|
|
entries.map { |entry| update_widget!(entry[:widget], entry[:json]) }
|
|
end
|
|
render_jsonp(result.map { |widget| WidgetPresenter.new(widget).to_poro })
|
|
end
|
|
|
|
def destroy
|
|
@widget.destroy
|
|
|
|
render_jsonp(WidgetPresenter.new(@widget).to_poro)
|
|
rescue => e
|
|
CartoDB::Logger.error(exception: e, message: "Error destroying widget", widget: @widget)
|
|
render json: { errors: e.message }, status: 500
|
|
end
|
|
|
|
private
|
|
|
|
def update_widget!(widget, json_params)
|
|
update_params = json_params.permit(:order, :type, :title)
|
|
update_params[:source_id] = source_id_from_params(json_params) if source_id_from_params(json_params)
|
|
widget.update_attributes(update_params)
|
|
widget.options = json_params[:options]
|
|
widget.style = json_params[:style]
|
|
widget.save!
|
|
widget
|
|
end
|
|
|
|
def load_map
|
|
@map_id = params[:map_id]
|
|
@map = Carto::Map.where(id: @map_id).first
|
|
raise LoadError.new("Map not found: #{@map_id}") unless @map
|
|
raise Carto::UnauthorizedError.new("Not authorized for map #{@map.id}") unless @map.writable_by_user?(current_user)
|
|
end
|
|
|
|
def load_layer
|
|
@layer_id = params[:map_layer_id]
|
|
payload_layer_id = params['layer_id']
|
|
|
|
if [payload_layer_id, @layer_id].compact.uniq.length >= 2
|
|
raise UnprocesableEntityError.new("URL layer id (#{@layer_id}) and payload layer id (#{payload_layer_id}) don't match")
|
|
end
|
|
|
|
@layer = Carto::Layer.where(id: @layer_id).first
|
|
raise LoadError.new("Layer not found: #{@layer_id}") unless @layer
|
|
|
|
raise UnprocesableEntityError.new("Layer #{@layer_id} doesn't belong to map #{@map_id}") unless @map.contains_layer?(@layer)
|
|
end
|
|
|
|
def load_widget_id
|
|
@widget_id = params[:id]
|
|
if [@widget_id, params[:id]].compact.uniq.length >= 2
|
|
raise UnprocesableEntityError.new("URL id (#{@widget_id}) and payload id (#{params[:id]}) don't match")
|
|
end
|
|
end
|
|
|
|
def source_id_from_params(parameters = params)
|
|
parameters[:source] ? parameters[:source][:id] : nil
|
|
end
|
|
|
|
def load_widget
|
|
@widget = widget_with_validations(@widget_id, @layer_id)
|
|
end
|
|
|
|
def widget_with_validations(widget_id, layer_id = nil)
|
|
widget = Carto::Widget.find(widget_id)
|
|
|
|
raise Carto::LoadError.new("Widget not found: #{@widget_id}") unless widget
|
|
|
|
if layer_id && widget.layer_id != layer_id
|
|
raise Carto::LoadError.new("Widget not found: #{@widget_id}")
|
|
end
|
|
|
|
unless widget.belongs_to_map?(@map_id)
|
|
raise Carto::LoadError.new("Widget not found: #{@widget_id} for that map (#{@map_id})")
|
|
end
|
|
|
|
unless widget.writable_by_user?(current_user)
|
|
raise Carto::UnauthorizedError.new("Not authorized for widget #{@widget_id}")
|
|
end
|
|
|
|
widget
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|