Skip to content

Commit

Permalink
[itmammoth#30] Use message_verifier to prevent html from tampering
Browse files Browse the repository at this point in the history
  • Loading branch information
itmammoth committed Jul 24, 2019
1 parent 58eb04c commit e49052c
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 26 deletions.
17 changes: 12 additions & 5 deletions app/controllers/sortable_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
class SortableController < ApplicationController

VERIFIER = Rails.application.message_verifier(:rails_sortable_generate_sortable_id)

#
# post /sortable/reorder, rails_sortable: [{ klass: "Item", id: "3" }, { klass: "Item", id: "2" }, { klass: "Item", id: "1" }]
# post /sortable/reorder, rails_sortable: [
# "BAhJIhVjbGFzcz1JdGVtLGlkPTUwBjoGRVQ=--b48adfad6d6d7764e4106c44fc090fcad15d721e",
# "BAhJIhVjbGFzcz1JdGVtLGlkPTQxBjoGRVQ=--ac1c2d3b8eae8dd72e49fae302005e5ae4fc00a4", ...]
# Param `rails_sorable` is an array object containing encoded tokens,
# and each token must be able to be decoded with VERIFIER to a string formatted as "class={CLASS_NAME},id={ID}".
#
def reorder
ActiveRecord::Base.transaction do
params['rails_sortable'].each_with_index do |klass_to_id, new_sort|
model = find_model(klass_to_id)
params['rails_sortable'].each_with_index do |token, new_sort|
model = find_model(token)
current_sort = model.read_attribute(model.class.sort_attribute)
model.update_sort!(new_sort) if current_sort != new_sort
end
Expand All @@ -16,8 +23,8 @@ def reorder

private

def find_model(klass_to_id)
klass, id = klass_to_id.values_at('klass', 'id')
def find_model(token)
klass, id = VERIFIER.verify(token).match(/class=(.+),id=(.+)/)[1..2]
klass.constantize.find(id.to_i)
end
end
2 changes: 1 addition & 1 deletion app/models/rails_sortable/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def update_sort!(new_value)
end

def sortable_id
"#{self.class}_#{self.id}"
SortableController::VERIFIER.generate("class=#{self.class},id=#{self.id}")
end

protected
Expand Down
18 changes: 11 additions & 7 deletions spec/controllers/sortable_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
require 'spec_helper'

def create_token(klass, id)
return SortableController::VERIFIER.generate("class=#{klass},id=#{id}")
end

describe SortableController, type: :controller do
describe 'POST reorder' do
before do
Expand All @@ -9,9 +13,9 @@
end
it 'should reorder models' do
data = [
{ klass: 'Item', id: @item1.to_param },
{ klass: 'Item', id: @item3.to_param },
{ klass: 'Item', id: @item2.to_param },
create_token('Item', @item1.to_param),
create_token('Item', @item3.to_param),
create_token('Item', @item2.to_param),
]
if Gem::Version.new(Rails.version) < Gem::Version.new(5)
post :reorder, rails_sortable: data
Expand All @@ -34,10 +38,10 @@
end
it 'should reorder models' do
data = [
{ klass: 'SecondItem', id: @second_item2.to_param },
{ klass: 'FirstItem', id: @first_item2.to_param },
{ klass: 'FirstItem', id: @first_item1.to_param },
{ klass: 'SecondItem', id: @second_item1.to_param },
create_token('SecondItem', @second_item2.to_param),
create_token('FirstItem', @first_item2.to_param),
create_token('FirstItem', @first_item1.to_param),
create_token('SecondItem', @second_item1.to_param),
]
if Gem::Version.new(Rails.version) < Gem::Version.new(5)
post :reorder, rails_sortable: data
Expand Down
2 changes: 1 addition & 1 deletion spec/helpers/sortable_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
new_item = Item.create!
sortable_fetch([ new_item ]) do |item, id|
expect(item).to eq new_item
expect(id).to eq "Item_#{new_item.id}"
expect(id).to eq SortableController::VERIFIER.generate("class=Item,id=#{new_item.id}")
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions spec/models/rails_sortable/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@
describe "sortable_id" do
it "should return a correct sortable_id" do
item = Item.create!
expect(item.sortable_id).to eq("Item_#{item.id}")
expect(item.sortable_id).to eq(SortableController::VERIFIER.generate("class=Item,id=#{item.to_param}"))
end
end

describe "each_with_sortable_id" do
it "should make models iterable with sortable ids" do
items = 2.times.map { |i| Item.create! sort: i }
expect { |b| Item.order(:sort).each_with_sortable_id(&b) }.to yield_successive_args(
[items[0], "Item_#{items[0].id}"],
[items[1], "Item_#{items[1].id}"],
[items[0], SortableController::VERIFIER.generate("class=Item,id=#{items[0].to_param}")],
[items[1], SortableController::VERIFIER.generate("class=Item,id=#{items[1].to_param}")],
)
end
end
Expand Down
12 changes: 3 additions & 9 deletions vendor/assets/javascripts/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,12 @@
url: '/sortable/reorder',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(makePostData($(this))),
data: JSON.stringify({
rails_sortable: $(this).sortable('toArray'),
}),
});
}

this.sortable(settings);
};

var makePostData = function($sortable) {
var data = $.map($sortable.sortable('toArray'), function(sortableId) {
klassAndId = sortableId.split(/[-=_]/);
return { klass: klassAndId[0], id: klassAndId[1] };
});
return { rails_sortable: data };
};
})(jQuery);

0 comments on commit e49052c

Please sign in to comment.