solidus_backend 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_backend might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 02b974645362da82b2400967d919cf00ba57887c
4
- data.tar.gz: edf6dc31425526c2562e5120586525d6c5088f31
3
+ metadata.gz: de5973fabeefe021bc6172c76c6e1a1e02c49394
4
+ data.tar.gz: 05d29540a7e77b7821d80f2ce0511920dec88757
5
5
  SHA512:
6
- metadata.gz: 8e6464351c9e0ad0830445790b9126a0cd7ddf345fb8467971d7a4a90be3db3e19a0442ce4c18c264bb480d34e892b1a89591a5243f1a49fa95d44afe6c7e434
7
- data.tar.gz: 0c253286b3eef6125db0de099e2d64820de97a5194464c58d4d796231bd8f016f18271829489214528cb2e9b1cc4bf260d505069999ee49d9b4b8945097c8fa1
6
+ metadata.gz: 6d97bc9506580584a52f6627dbb70a33fed739686fa72da9ee321c0231a5521e49f79ff93a1b7ffc2cff5f9b42838e13fc93edd903e09344d62cc0a155f771ae
7
+ data.tar.gz: c214582ac6ba0bed1edc3b57a0f694e9342205c9b974574c225f7b6b0ad379949469841c4f7746ee8f5d0129c42270d936873b10a9ad5989823bc58d67ec72b2
@@ -26,7 +26,7 @@ $(document).ready(function() {
26
26
  }
27
27
  },
28
28
  results: function(data, page) {
29
- return { results: data }
29
+ return { results: data.users }
30
30
  }
31
31
  },
32
32
  dropdownCssClass: 'customer_search',
@@ -54,7 +54,7 @@ $(document).ready(function() {
54
54
  });
55
55
  });
56
56
  }
57
- return customer.email;
57
+ return Select2.util.escapeMarkup(customer.email);
58
58
  }
59
59
  })
60
60
  }
@@ -1,6 +1,10 @@
1
1
  $(document).ready(function () {
2
2
  'use strict';
3
3
 
4
+ function formatOptionType(option_type) {
5
+ return Select2.util.escapeMarkup(option_type.presentation + ' (' + option_type.name + ')');
6
+ }
7
+
4
8
  if ($('#product_option_type_ids').length > 0) {
5
9
  $('#product_option_type_ids').select2({
6
10
  placeholder: Spree.translations.option_type_placeholder,
@@ -31,12 +35,8 @@ $(document).ready(function () {
31
35
  };
32
36
  }
33
37
  },
34
- formatResult: function (option_type) {
35
- return option_type.presentation + ' (' + option_type.name + ')';
36
- },
37
- formatSelection: function (option_type) {
38
- return option_type.presentation + ' (' + option_type.name + ')';
39
- }
38
+ formatResult: formatOptionType,
39
+ formatSelection: formatOptionType
40
40
  });
41
41
  }
42
42
  });
@@ -5,6 +5,10 @@ $.fn.productAutocomplete = function (options) {
5
5
  options = options || {}
6
6
  var multiple = typeof(options['multiple']) !== 'undefined' ? options['multiple'] : true
7
7
 
8
+ function formatProduct(product) {
9
+ return Select2.util.escapeMarkup(product.name);
10
+ }
11
+
8
12
  this.select2({
9
13
  minimumInputLength: 3,
10
14
  multiple: multiple,
@@ -37,12 +41,8 @@ $.fn.productAutocomplete = function (options) {
37
41
  };
38
42
  }
39
43
  },
40
- formatResult: function (product) {
41
- return product.name;
42
- },
43
- formatSelection: function (product) {
44
- return product.name;
45
- }
44
+ formatResult: formatProduct,
45
+ formatSelection: formatProduct
46
46
  });
47
47
  };
48
48
 
@@ -17,5 +17,5 @@ jQuery ->
17
17
  return { results: data.stock_items, more: more }
18
18
  formatResult: (stock_item) ->
19
19
  variantTemplate({ variant: stock_item.variant })
20
- formatSelection: (stock_item) ->
21
- "#{stock_item.variant.name} (#{stock_item.variant.options_text})"
20
+ formatSelection: (stock_item, container, excapeMarkup) ->
21
+ Select2.util.escapeMarkup("#{stock_item.variant.name} (#{stock_item.variant.options_text})")
@@ -1,6 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var set_taxon_select = function(){
4
+ function formatTaxon(taxon) {
5
+ return Select2.util.escapeMarkup(taxon.pretty_name);
6
+ }
7
+
4
8
  if ($('#product_taxon_ids').length > 0) {
5
9
  $('#product_taxon_ids').select2({
6
10
  placeholder: Spree.translations.taxon_placeholder,
@@ -37,12 +41,8 @@ var set_taxon_select = function(){
37
41
  };
38
42
  }
39
43
  },
40
- formatResult: function (taxon) {
41
- return taxon.pretty_name;
42
- },
43
- formatSelection: function (taxon) {
44
- return taxon.pretty_name;
45
- }
44
+ formatResult: formatTaxon,
45
+ formatSelection: formatTaxon
46
46
  });
47
47
  }
48
48
  }
@@ -45,6 +45,9 @@ $(document).ready ->
45
45
  sortable.trigger('sortupdate', item: draggable)
46
46
  , 250
47
47
 
48
+ formatTaxon = (taxon) ->
49
+ Select2.util.escapeMarkup(taxon.pretty_name)
50
+
48
51
  $('#taxon_id').select2
49
52
  dropdownCssClass: "taxon_select_box",
50
53
  placeholder: Spree.translations.find_a_taxon,
@@ -59,10 +62,8 @@ $(document).ready ->
59
62
  results: (data) ->
60
63
  results: data['taxons'],
61
64
  more: data.current_page < data.pages
62
- formatResult: (taxon) ->
63
- taxon.pretty_name;
64
- formatSelection: (taxon) ->
65
- taxon.pretty_name;
65
+ formatResult: formatTaxon,
66
+ formatSelection: formatTaxon
66
67
 
67
68
  $('#taxon_id').on "change", (e) ->
68
69
  Spree.ajax
@@ -1,6 +1,10 @@
1
1
  $.fn.userAutocomplete = function () {
2
2
  'use strict';
3
3
 
4
+ function formatUser(user) {
5
+ return Select2.util.escapeMarkup(user.email);
6
+ }
7
+
4
8
  this.select2({
5
9
  minimumInputLength: 1,
6
10
  multiple: true,
@@ -8,7 +12,7 @@ $.fn.userAutocomplete = function () {
8
12
  $.get(Spree.routes.user_search, {
9
13
  ids: element.val()
10
14
  }, function (data) {
11
- callback(data);
15
+ callback(data.users);
12
16
  });
13
17
  },
14
18
  ajax: {
@@ -23,16 +27,12 @@ $.fn.userAutocomplete = function () {
23
27
  },
24
28
  results: function (data) {
25
29
  return {
26
- results: data
30
+ results: data.users
27
31
  };
28
32
  }
29
33
  },
30
- formatResult: function (user) {
31
- return user.email;
32
- },
33
- formatSelection: function (user) {
34
- return user.email;
35
- }
34
+ formatResult: formatUser,
35
+ formatSelection: formatUser
36
36
  });
37
37
  };
38
38
 
@@ -35,8 +35,8 @@ $.fn.variantAutocomplete = (searchOptions = {}) ->
35
35
  results: data["variants"]
36
36
 
37
37
  formatResult: formatVariantResult
38
- formatSelection: (variant) ->
38
+ formatSelection: (variant, container, escapeMarkup) ->
39
39
  if !!variant.options_text
40
- variant.name + " (#{variant.options_text})"
40
+ Select2.util.escapeMarkup("#{variant.name} (#{variant.options_text}")
41
41
  else
42
- variant.name
42
+ Select2.util.escapeMarkup(variant.name)
@@ -27,11 +27,15 @@ module Spree
27
27
  parts << variant.product.name
28
28
  parts << "(#{variant.options_text})" if variant.options_text.present?
29
29
  parts << line_item.display_total
30
- parts.join("<br>").html_safe
30
+ safe_join(parts, "<br />".html_safe)
31
31
  end
32
32
 
33
33
  def display_shipment(shipment)
34
- "#{Spree.t(:shipment)} ##{shipment.number}<br>#{shipment.display_cost}".html_safe
34
+ parts = [
35
+ "#{Spree.t(:shipment)} ##{shipment.number}",
36
+ shipment.display_cost
37
+ ]
38
+ safe_join(parts, "<br />".html_safe)
35
39
  end
36
40
 
37
41
  def display_order(order)
@@ -15,8 +15,8 @@ module Spree
15
15
  obj = object.respond_to?(:errors) ? object : instance_variable_get("@#{object}")
16
16
 
17
17
  if obj && obj.errors[method].present?
18
- errors = obj.errors[method].map { |err| h(err) }.join('<br />').html_safe
19
- content_tag(:span, errors, :class => 'formError')
18
+ errors = safe_join(obj.errors[method], "<br />".html_safe)
19
+ content_tag(:span, errors, class: 'formError')
20
20
  else
21
21
  ''
22
22
  end
@@ -132,12 +132,11 @@ module Spree
132
132
 
133
133
  def preference_fields(object, form)
134
134
  return unless object.respond_to?(:preferences)
135
- object.preferences.keys.map{ |key|
136
-
135
+ fields = object.preferences.keys.map { |key|
137
136
  form.label("preferred_#{key}", Spree.t(key) + ": ") +
138
- preference_field_for(form, "preferred_#{key}", :type => object.preference_type(key))
139
-
140
- }.join("<br />").html_safe
137
+ preference_field_for(form, "preferred_#{key}", type: object.preference_type(key))
138
+ }
139
+ safe_join(fields, "<br />".html_safe)
141
140
  end
142
141
 
143
142
  def link_to_add_fields(name, target, options = {})
@@ -74,7 +74,7 @@ module Spree
74
74
  options[:class] = (options[:class].to_s + " fa fa-#{icon_name} icon_link with-tip").strip
75
75
  options[:class] += ' no-text' if options[:no_text]
76
76
  options[:title] = text if options[:no_text]
77
- text = options[:no_text] ? '' : raw("<span class='text'>#{text}</span>")
77
+ text = options[:no_text] ? '' : content_tag(:span, text, class: 'text')
78
78
  options.delete(:no_text)
79
79
  link_to(text, url, options)
80
80
  end
@@ -107,16 +107,10 @@ module Spree
107
107
  if html_options[:icon]
108
108
  html_options[:class] += " fa fa-#{html_options[:icon]}"
109
109
  end
110
- link_to(text_for_button_link(text, html_options), url, html_options)
110
+ link_to(text, url, html_options)
111
111
  end
112
112
  end
113
113
 
114
- def text_for_button_link(text, html_options)
115
- s = ''
116
- s << text
117
- raw(s)
118
- end
119
-
120
114
  def configurations_menu_item(link_text, url, description = '')
121
115
  %(<tr>
122
116
  <td>#{link_to(link_text, url)}</td>
@@ -12,7 +12,7 @@ module Spree
12
12
  :data => { :confirm => Spree.t(:order_sure_want_to, :event => Spree.t(event)) })
13
13
  end
14
14
  end
15
- links.join('&nbsp;').html_safe
15
+ safe_join(links, '&nbsp;'.html_safe)
16
16
  end
17
17
 
18
18
  def line_item_shipment_price(line_item, quantity)
@@ -9,7 +9,8 @@ module Spree
9
9
  :selected => ('selected' if selected)) do
10
10
  (taxon.ancestors.pluck(:name) + [taxon.name]).join(" -> ")
11
11
  end
12
- end.join("").html_safe
12
+ end
13
+ safe_join(options)
13
14
  end
14
15
 
15
16
  def option_types_options_for(product)
@@ -20,7 +21,8 @@ module Spree
20
21
  :selected => ('selected' if selected)) do
21
22
  option_type.name
22
23
  end
23
- end.join("").html_safe
24
+ end
25
+ safe_join(options)
24
26
  end
25
27
  end
26
28
  end
@@ -15,9 +15,9 @@ module Spree
15
15
 
16
16
  def display_variant(stock_movement)
17
17
  variant = stock_movement.stock_item.variant
18
- output = variant.name
19
- output += "<br>(#{variant.options_text})" unless variant.options_text.blank?
20
- output.html_safe
18
+ output = [variant.name]
19
+ output << variant.options_text unless variant.options_text.blank?
20
+ safe_join(output, "<br />".html_safe)
21
21
  end
22
22
  end
23
23
  end
@@ -1,4 +1,4 @@
1
- collection(@users)
1
+ collection(@users => :users)
2
2
  attributes :email, :id
3
3
  address_fields = [:firstname, :lastname,
4
4
  :address1, :address2,
@@ -172,6 +172,18 @@ describe "New Order", :type => :feature do
172
172
  end
173
173
  end
174
174
 
175
+ context "customer with attempted XSS", js: true do
176
+ let(:xss_string) { %(<script>throw("XSS")</script>) }
177
+ before do
178
+ user.update!(email: xss_string)
179
+ end
180
+ it "displays the user's email escaped without executing" do
181
+ click_on "Customer Details"
182
+ targetted_select2_search user.email, from: "#s2id_customer_search"
183
+ expect(page).to have_field("Email", with: xss_string)
184
+ end
185
+ end
186
+
175
187
  def fill_in_address(kind = "bill")
176
188
  fill_in "First Name", with: "John 99"
177
189
  fill_in "Last Name", with: "Doe"
@@ -11,15 +11,16 @@ describe "Product Taxons", :type => :feature do
11
11
  Capybara.ignore_hidden_elements = false
12
12
  end
13
13
 
14
- context "managing taxons" do
14
+ context "managing taxons", js: true do
15
15
  def selected_taxons
16
16
  find("#product_taxon_ids").value.split(',').map(&:to_i).uniq
17
17
  end
18
18
 
19
- it "should allow an admin to manage taxons", :js => true do
19
+ let(:product) { create(:product) }
20
+
21
+ it "should allow an admin to manage taxons" do
20
22
  taxon_1 = create(:taxon)
21
- taxon_2 = create(:taxon, :name => 'Clothing')
22
- product = create(:product)
23
+ taxon_2 = create(:taxon, name: 'Clothing')
23
24
  product.taxons << taxon_1
24
25
 
25
26
  visit spree.admin_path
@@ -39,5 +40,17 @@ describe "Product Taxons", :type => :feature do
39
40
  expect(page).to have_css(".select2-search-choice", text: taxon_1.name)
40
41
  expect(page).to have_css(".select2-search-choice", text: taxon_2.name)
41
42
  end
43
+
44
+ context "with an XSS attempt" do
45
+ let(:taxon_name) { %(<script>throw("XSS")</script>) }
46
+ let!(:taxon) { create(:taxon, name: taxon_name) }
47
+ it "displays the escaped HTML without executing it" do
48
+ visit spree.edit_admin_product_path(product)
49
+
50
+ select2_search "<script>", from: "Taxons"
51
+
52
+ expect(page).to have_content(taxon_name)
53
+ end
54
+ end
42
55
  end
43
56
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Promotion with user rule', js: true do
4
+ stub_authorization!
5
+
6
+ given(:promotion) { create :promotion }
7
+
8
+ background do
9
+ visit spree.edit_admin_promotion_path(promotion)
10
+ end
11
+
12
+ context "with an attempted XSS" do
13
+ let(:xss_string) { %(<script>throw("XSS")</script>) }
14
+ given!(:user) { create(:user, email: xss_string) }
15
+
16
+ scenario "adding an option value rule" do
17
+ select2 "User", from: "Add rule of type"
18
+ within("#rules_container") { click_button "Add" }
19
+
20
+ select2_search "<script>", from: "Choose users"
21
+
22
+ expect(page).to have_content(xss_string)
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_backend
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Solidus Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-22 00:00:00.000000000 Z
11
+ date: 2016-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solidus_api
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.4
19
+ version: 1.0.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.4
26
+ version: 1.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: solidus_core
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.4
33
+ version: 1.0.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.4
40
+ version: 1.0.5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bourbon
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -639,6 +639,7 @@ files:
639
639
  - spec/features/admin/products/variant_spec.rb
640
640
  - spec/features/admin/promotion_adjustments_spec.rb
641
641
  - spec/features/admin/promotions/tiered_calculator_spec.rb
642
+ - spec/features/admin/promotions/user_rule_spec.rb
642
643
  - spec/features/admin/reports_spec.rb
643
644
  - spec/features/admin/stock_transfer_spec.rb
644
645
  - spec/features/admin/store_credits_spec.rb
@@ -712,3 +713,4 @@ signing_key:
712
713
  specification_version: 4
713
714
  summary: Admin interface for the Solidus e-commerce framework.
714
715
  test_files: []
716
+ has_rdoc: