bring snapshot codebase from snapshots original branch

pull/10937/head
Guido Fioravantti 8 years ago
parent f880f9a1c7
commit 7a35796d9e

@ -83,7 +83,6 @@ WORKING_SPECS_1 = \
spec/models/carto/widget_spec.rb \
spec/models/carto/ldap/configuration_spec.rb \
spec/requests/sessions_controller_spec.rb \
spec/services/carto/user_authenticator_spec.rb \
spec/services/carto/visualizations_export_service_spec.rb \
spec/services/carto/visualizations_export_service_2_spec.rb \
$(NULL)
@ -291,6 +290,8 @@ SPEC_HELPER_MIN_SPECS = \
spec/requests/carto/api/legends_controller_spec.rb \
spec/lib/carto/legend_definition_validator_spec.rb \
spec/lib/carto/legend_migrator_spec.rb \
spec/requests/carto/api/snapshots_controller_specs.rb \
spec/models/carto/snapshot_spec.rb \
$(NULL)
# This class must be tested isolated as pollutes namespace

@ -0,0 +1,19 @@
module Carto
module Api
class SnapshotPresenter
def initialize(snapshot)
@snapshot = snapshot
end
def to_hash
{
id: @snapshot.id,
created_at: @snapshot.created_at,
updated_at: @snapshot.updated_at,
state: @snapshot.state,
user: Carto::Api::UserPresenter.new(@snapshot.user).to_public_poro
}
end
end
end
end

@ -0,0 +1,86 @@
# encoding utf-8
module Carto
module Api
class SnapshotsController < ::Api::ApplicationController
include ControllerHelper
ssl_required :index, :show, :create, :update, :destroy
before_filter :load_visualization,
:check_visualization_viewable
before_filter :load_snapshot,
:owners_only, only: [:show, :update, :destroy]
rescue_from LoadError,
UnauthorizedError,
UnprocesableEntityError, with: :rescue_from_carto_error
def index
snapshots = @visualization.snapshots.where(user_id: current_viewer.id)
presentation = snapshots.map do |snapshot|
SnapshotPresenter.new(snapshot).to_hash
end
render json: presentation
end
def show
render json: SnapshotPresenter.new(@snapshot).to_hash
end
def create
snapshot = Snapshot.create!(user_id: current_viewer.id,
visualization_id: @visualization.id,
state: params[:state])
render json: SnapshotPresenter.new(snapshot).to_hash, status: :created
rescue ActiveRecord::RecordInvalid => exception
message = exception.record.errors.full_messages.join(', ')
raise UnprocesableEntityError.new(message)
end
def update
@snapshot.update_attributes!(state: params[:state])
render json: SnapshotPresenter.new(@snapshot).to_hash
rescue ActiveRecord::RecordInvalid => exception
message = exception.record.errors.full_messages.join(', ')
raise UnprocesableEntityError.new(message)
end
def destroy
@snapshot.destroy
render json: Hash.new, status: :no_content
end
private
def load_visualization
@visualization = Visualization.find(params[:visualization_id])
rescue ActiveRecord::RecordNotFound
raise LoadError.new('Visualization not found')
end
def check_visualization_viewable
unless @visualization.is_viewable_by_user?(current_viewer)
raise UnauthorizedError.new
end
end
def load_snapshot
@snapshot = Snapshot.find(params[:id])
rescue ActiveRecord::RecordNotFound
raise LoadError.new('Snapshot not found')
end
def owners_only
unless @snapshot.user_id == current_viewer.id
raise UnauthorizedError.new
end
end
end
end
end

@ -0,0 +1,17 @@
# encoding utf-8
require 'json'
require_relative './carto_json_serializer'
module Carto
class Snapshot < ActiveRecord::Base
belongs_to :visualization, class_name: Carto::Visualization
belongs_to :user, class_name: Carto::User
default_scope order('created_at DESC')
serialize :state, ::Carto::CartoJsonSymbolizerSerializer
validates :state, carto_json_symbolizer: true
validates :visualization, :user, presence: true
end
end

@ -65,6 +65,8 @@ class Carto::Visualization < ActiveRecord::Base
belongs_to :state, class_name: Carto::State
after_save :save_state_if_needed
has_many :snapshots, class_name: Carto::Snapshot, dependent: :destroy
validates :version, presence: true
before_validation :set_default_version

@ -584,6 +584,10 @@ CartoDB::Application.routes.draw do
resources :mapcaps, only: [:index, :show, :create, :destroy], constraints: { id: /[^\/]+/ }
resource :state, only: [:update]
resources :snapshots,
only: [:index, :show, :create, :update, :destroy],
constraints: { id: UUID_REGEXP }
scope '/layer/:layer_id', constraints: { layer_id: /[^\/]+/ } do
resources :legends,
only: [:index, :show, :create, :update, :destroy],

@ -0,0 +1,32 @@
# encoding: utf-8
require 'spec_helper_min'
require 'factories/carto_visualizations'
describe Carto::Snapshot do
include Carto::Factories::Visualizations
before(:all) do
@user = FactoryGirl.create(:carto_user)
@_m, @_t, @_tv, @visualization = create_full_visualization(@user)
end
after(:all) do
destroy_full_visualization(@_m, @_t, @_tv, @visualization)
@user.destroy
end
describe('#validation') do
it 'rejects nil visualization' do
snapshot = Carto::Snapshot.new(user_id: @user.id)
snapshot.save.should be_false
snapshot.errors[:visualization].should_not be_empty
end
it 'rejects nil user' do
snapshot = Carto::Snapshot.new(visualization_id: @visualization.id)
snapshot.save.should be_false
snapshot.errors[:user].should_not be_empty
end
end
end

@ -0,0 +1,414 @@
# encoding utf-8
require 'spec_helper_min'
require 'support/helpers'
require 'factories/carto_visualizations'
describe Carto::Api::SnapshotsController do
include Carto::Factories::Visualizations
include HelperMethods
let(:fake_state) { { manolo: 'escobar' } }
before(:all) do
@user = FactoryGirl.create(:carto_user)
@intruder = FactoryGirl.create(:carto_user)
@_m, @_t, @_tv, @visualization = create_full_visualization(@user)
@_om, @_ot, @_otv, @other_visualization = create_full_visualization(@user)
end
after(:all) do
destroy_full_visualzation(@_m, @_t, @_tv, @visualization)
destroy_full_visualzation(@_om, @_ot, @_otv, @other_visualization)
@intruder.destroy
@user.destroy
end
describe('#index') do
def snapshots_index_url(user_domain: @user.subdomain,
visualization_id: @visualization.id,
api_key: @user.api_key)
snapshots_url(user_domain: user_domain,
visualization_id: visualization_id,
api_key: api_key)
end
before(:all) do
5.times do
Carto::Snapshot.create!(user_id: @user.id,
visualization_id: @visualization.id,
state: fake_state)
end
@buddy = FactoryGirl.create(:carto_user)
5.times do
Carto::Snapshot.create!(user_id: @buddy.id,
visualization_id: @visualization.id,
state: fake_state)
end
5.times do
Carto::Snapshot.create!(user_id: @buddy.id,
visualization_id: @other_visualization.id,
state: fake_state)
end
end
after(:all) do
Carto::Snapshot.where(user_id: @user.id).map(&:destroy)
Carto::Snapshot.where(user_id: @buddy.id).map(&:destroy)
@buddy.destroy
end
it 'rejects unauthenticated access' do
Carto::Visualization.any_instance
.stubs(:is_publically_accesible?)
.returns(false)
get_json(snapshots_index_url(api_key: nil), Hash.new) do |response|
response.status.should eq 401
end
end
it 'rejects users with no read access' do
Carto::Visualization.any_instance
.stubs(:is_viewable_by_user?)
.returns(false)
intruder_url = snapshots_index_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
get_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'returns 404 for non existent visualizations' do
not_found_url = snapshots_index_url(visualization_id: random_uuid)
get_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'should not list visualization state for owner' do
get_json(snapshots_index_url, Hash.new) do |response|
response.status.should eq 200
response_ids = response.body
.map { |snapshot| snapshot['id'] }
.compact
.sort
response_ids.should_not be_empty
response_ids.should_not include(@visualization.id)
end
end
it 'lists only snapshots for user and visualization' do
buddy_url = snapshots_index_url(user_domain: @buddy.subdomain,
api_key: @buddy.api_key)
buddy_snaps = Carto::Snapshot.where(user_id: @buddy.id,
visualization_id: @visualization.id)
.map(&:id)
.sort
get_json(buddy_url, Hash.new) do |response|
response.status.should eq 200
response_ids = response.body
.map { |snapshot| snapshot['id'] }
.compact
.sort
response_ids.should_not be_empty
response_ids.should eq buddy_snaps
end
end
end
describe('#show') do
def snapshots_show_url(user_domain: @user.subdomain,
visualization_id: @visualization.id,
snapshot_id: @snapshot.id,
api_key: @user.api_key)
snapshot_url(user_domain: user_domain,
visualization_id: visualization_id,
id: snapshot_id,
api_key: api_key)
end
before(:all) do
@snapshot = Carto::Snapshot.create!(user_id: @user.id,
visualization_id: @visualization.id,
state: fake_state)
end
after(:all) do
@snapshot.destroy
end
it 'rejects unauthenticated access' do
Carto::Visualization.any_instance
.stubs(:is_publically_accesible?)
.returns(false)
get_json(snapshots_show_url(api_key: nil), Hash.new) do |response|
response.status.should eq 401
end
end
it 'rejects users with no read access' do
Carto::Visualization.any_instance
.stubs(:is_viewable_by_user?)
.returns(false)
intruder_url = snapshots_show_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
get_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'returns 404 for non existent visualizations' do
not_found_url = snapshots_show_url(visualization_id: random_uuid)
get_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'returns 404 for inexistent snapshots' do
not_found_url = snapshots_show_url(snapshot_id: random_uuid)
get_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'only accepts owners of snapshots' do
intruder_url = snapshots_show_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
get_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'shows a snapshot' do
get_json(snapshots_show_url, Hash.new) do |response|
response.status.should eq 200
response.body[:id].should eq @snapshot.id
end
end
end
describe('#create') do
def snapshots_create_url(user_domain: @user.subdomain,
visualization_id: @visualization.id,
api_key: @user.api_key)
snapshots_url(user_domain: user_domain,
visualization_id: visualization_id,
api_key: api_key)
end
before(:each) do
@user.visualizations.map(&:snapshots).flatten.map(&:destroy)
end
after(:all) do
@user.visualizations.map(&:snapshots).flatten.map(&:destroy)
end
it 'rejects unauthenticated access' do
Carto::Visualization.any_instance
.stubs(:is_publically_accesible?)
.returns(false)
nil_api_key_url = snapshots_create_url(api_key: nil)
post_json(nil_api_key_url, state: fake_state) do |response|
response.status.should eq 401
end
end
it 'rejects users with no read access' do
Carto::Visualization.any_instance
.stubs(:is_viewable_by_user?)
.returns(false)
intruder_url = snapshots_create_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
post_json(intruder_url, state: fake_state) do |response|
response.status.should eq 403
end
end
it 'returns 404 for non existent visualizations' do
not_found_url = snapshots_create_url(visualization_id: random_uuid)
post_json(not_found_url, state: fake_state) do |response|
response.status.should eq 404
end
end
it 'creates a snapshot' do
@visualization.snapshots.count.should eq 0
post_json(snapshots_create_url, state: fake_state) do |response|
response.status.should eq 201
@visualization.reload
@visualization.snapshots.count.should eq 1
@visualization.snapshots.first.id.should eq response.body[:id]
end
end
end
describe('#update') do
def snapshots_update_url(user_domain: @user.subdomain,
visualization_id: @visualization.id,
snapshot_id: @snapshot.id,
api_key: @user.api_key)
snapshot_url(user_domain: user_domain,
visualization_id: visualization_id,
id: snapshot_id,
api_key: api_key)
end
before(:all) do
@snapshot = Carto::Snapshot.create!(user_id: @user.id,
visualization_id: @visualization.id,
state: fake_state)
end
after(:all) do
@snapshot.destroy
end
it 'rejects unauthenticated access' do
Carto::Visualization.any_instance
.stubs(:is_publically_accesible?)
.returns(false)
put_json(snapshots_update_url(api_key: nil), Hash.new) do |response|
response.status.should eq 401
end
end
it 'rejects users with no read access' do
Carto::Visualization.any_instance
.stubs(:is_viewable_by_user?)
.returns(false)
intruder_url = snapshots_update_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
put_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'returns 404 for non existent visualizations' do
not_found_url = snapshots_update_url(visualization_id: random_uuid)
put_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'returns 404 for inexistent snapshots' do
not_found_url = snapshots_update_url(snapshot_id: random_uuid)
put_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'only accepts owners of snapshots' do
intruder_url = snapshots_update_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
put_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'updates a snapshot' do
new_state = { minili: 'iscibir' }
put_json(snapshots_update_url, state: new_state) do |response|
response.status.should eq 200
end
@snapshot.reload.state.should eq new_state
end
end
describe('#destroy') do
def snapshots_update_url(user_domain: @user.subdomain,
visualization_id: @visualization.id,
snapshot_id: @snapshot.id,
api_key: @user.api_key)
snapshot_url(user_domain: user_domain,
visualization_id: visualization_id,
id: snapshot_id,
api_key: api_key)
end
before(:each) do
@snapshot = Carto::Snapshot.create!(user_id: @user.id,
visualization_id: @visualization.id,
state: fake_state)
end
after(:each) do
@snapshot.destroy
end
it 'rejects unauthenticated access' do
Carto::Visualization.any_instance
.stubs(:is_publically_accesible?)
.returns(false)
delete_json(snapshots_update_url(api_key: nil), Hash.new) do |response|
response.status.should eq 401
end
end
it 'rejects users with no read access' do
Carto::Visualization.any_instance
.stubs(:is_viewable_by_user?)
.returns(false)
intruder_url = snapshots_update_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
delete_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'returns 404 for non existent visualizations' do
not_found_url = snapshots_update_url(visualization_id: random_uuid)
delete_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'returns 404 for inexistent snapshots' do
not_found_url = snapshots_update_url(snapshot_id: random_uuid)
delete_json(not_found_url, Hash.new) do |response|
response.status.should eq 404
end
end
it 'only accepts owners of snapshots' do
intruder_url = snapshots_update_url(user_domain: @intruder.subdomain,
api_key: @intruder.api_key)
delete_json(intruder_url, Hash.new) do |response|
response.status.should eq 403
end
end
it 'destroys a snapshot' do
delete_json(snapshots_update_url, Hash.new) do |response|
response.status.should eq 204
end
end
end
end
Loading…
Cancel
Save