spree_core 4.5.0 → 4.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/spree/countries/find.rb +1 -1
  3. data/app/finders/spree/option_values/find_available.rb +1 -1
  4. data/app/finders/spree/product_properties/find_available.rb +1 -1
  5. data/app/finders/spree/products/find.rb +21 -13
  6. data/app/finders/spree/taxons/find.rb +7 -10
  7. data/app/helpers/spree/base_helper.rb +3 -7
  8. data/app/helpers/spree/products_helper.rb +3 -3
  9. data/app/models/concerns/spree/metadata.rb +7 -2
  10. data/app/models/concerns/spree/named_type.rb +1 -1
  11. data/app/models/concerns/spree/product_scopes.rb +27 -23
  12. data/app/models/concerns/spree/translatable_resource.rb +25 -0
  13. data/app/models/concerns/spree/translatable_resource_scopes.rb +24 -0
  14. data/app/models/concerns/spree/translatable_resource_slug.rb +15 -0
  15. data/app/models/concerns/spree/user_roles.rb +3 -3
  16. data/app/models/spree/address.rb +6 -4
  17. data/app/models/spree/asset.rb +1 -1
  18. data/app/models/spree/base.rb +6 -1
  19. data/app/models/spree/calculator/default_tax.rb +1 -1
  20. data/app/models/spree/cms/sections/image_gallery.rb +1 -7
  21. data/app/models/spree/cms/sections/side_by_side_images.rb +1 -7
  22. data/app/models/spree/cms_page.rb +2 -2
  23. data/app/models/spree/cms_section.rb +1 -1
  24. data/app/models/spree/country.rb +2 -2
  25. data/app/models/spree/credit_card.rb +1 -1
  26. data/app/models/spree/customer_return.rb +2 -2
  27. data/app/models/spree/data_feed/google.rb +15 -0
  28. data/app/models/spree/data_feed.rb +40 -0
  29. data/app/models/spree/digital_link.rb +5 -1
  30. data/app/models/spree/image.rb +2 -2
  31. data/app/models/spree/legacy_user.rb +3 -3
  32. data/app/models/spree/line_item.rb +1 -1
  33. data/app/models/spree/log_entry.rb +5 -1
  34. data/app/models/spree/menu.rb +1 -1
  35. data/app/models/spree/option_type.rb +6 -2
  36. data/app/models/spree/option_value.rb +5 -1
  37. data/app/models/spree/order/store_credit.rb +8 -0
  38. data/app/models/spree/order.rb +9 -9
  39. data/app/models/spree/order_contents.rb +31 -0
  40. data/app/models/spree/payment.rb +7 -15
  41. data/app/models/spree/payment_method.rb +1 -1
  42. data/app/models/spree/payment_source.rb +1 -1
  43. data/app/models/spree/preference.rb +5 -1
  44. data/app/models/spree/price.rb +1 -1
  45. data/app/models/spree/product.rb +64 -25
  46. data/app/models/spree/product_property.rb +13 -4
  47. data/app/models/spree/promotion.rb +2 -2
  48. data/app/models/spree/property.rb +8 -2
  49. data/app/models/spree/prototype.rb +1 -1
  50. data/app/models/spree/refund.rb +1 -1
  51. data/app/models/spree/reimbursement.rb +1 -1
  52. data/app/models/spree/return_authorization.rb +1 -1
  53. data/app/models/spree/return_item.rb +5 -1
  54. data/app/models/spree/role.rb +1 -1
  55. data/app/models/spree/shipment.rb +5 -5
  56. data/app/models/spree/shipping_category.rb +1 -1
  57. data/app/models/spree/shipping_method.rb +1 -1
  58. data/app/models/spree/stock/estimator.rb +1 -1
  59. data/app/models/spree/stock/splitter/weight.rb +1 -1
  60. data/app/models/spree/stock_item.rb +1 -1
  61. data/app/models/spree/stock_location.rb +1 -1
  62. data/app/models/spree/stock_transfer.rb +3 -3
  63. data/app/models/spree/store.rb +22 -3
  64. data/app/models/spree/store_credit.rb +2 -2
  65. data/app/models/spree/taxon.rb +47 -7
  66. data/app/models/spree/taxon_image.rb +2 -2
  67. data/app/models/spree/taxonomy.rb +5 -1
  68. data/app/models/spree/variant.rb +6 -9
  69. data/app/models/spree/wishlist.rb +6 -2
  70. data/app/models/spree/zone.rb +2 -2
  71. data/app/services/spree/data_feeds/google/optional_attributes.rb +23 -0
  72. data/app/services/spree/data_feeds/google/optional_sub_attributes.rb +21 -0
  73. data/app/services/spree/data_feeds/google/products_list.rb +14 -0
  74. data/app/services/spree/data_feeds/google/required_attributes.rb +67 -0
  75. data/app/services/spree/data_feeds/google/rss.rb +107 -0
  76. data/app/services/spree/locales/set_fallback_locale_for_store.rb +16 -0
  77. data/app/services/spree/seeds/countries.rb +12 -27
  78. data/app/services/spree/seeds/states.rb +8 -17
  79. data/app/services/spree/stock_locations/stock_items/create.rb +12 -18
  80. data/app/sorters/spree/products/sort.rb +23 -0
  81. data/app/validators/db_maximum_length_validator.rb +2 -6
  82. data/brakeman.ignore +326 -18
  83. data/config/initializers/friendly_id.rb +2 -0
  84. data/config/initializers/mobility.rb +16 -0
  85. data/config/initializers/rails61_fixes.rb +1 -3
  86. data/config/locales/en.yml +7 -0
  87. data/db/migrate/20220706112554_create_product_name_and_description_translations_for_mobility_table_backend.rb +27 -0
  88. data/db/migrate/20220715083542_create_spree_product_translations_for_mobility.rb +7 -0
  89. data/db/migrate/20220715120222_change_product_name_null_to_true.rb +5 -0
  90. data/db/migrate/20220718100743_create_spree_taxon_name_and_description_translations_for_mobility_table_backend.rb +27 -0
  91. data/db/migrate/20220718100948_change_taxon_name_null_to_true.rb +5 -0
  92. data/db/migrate/20220802070609_add_locale_to_friendly_id_slugs.rb +11 -0
  93. data/db/migrate/20220802073225_create_spree_product_slug_translations_for_mobility_table_backend.rb +5 -0
  94. data/db/migrate/20220804073928_transfer_data_to_translatable_tables.rb +66 -0
  95. data/db/migrate/20221215151408_add_selected_locale_to_spree_users.rb +8 -0
  96. data/db/migrate/20221219123957_add_deleted_at_to_product_translations.rb +6 -0
  97. data/db/migrate/20221220133432_add_uniqueness_constraint_to_product_translations.rb +5 -0
  98. data/db/migrate/20221229132350_create_spree_data_feed_settings.rb +14 -0
  99. data/db/migrate/20230103144439_create_option_type_translations.rb +26 -0
  100. data/db/migrate/20230103151034_create_option_value_translations.rb +26 -0
  101. data/db/migrate/20230109084253_create_product_property_translations.rb +25 -0
  102. data/db/migrate/20230109094907_transfer_options_data_to_translatable_tables.rb +58 -0
  103. data/db/migrate/20230109105943_create_property_translations.rb +26 -0
  104. data/db/migrate/20230109110840_transfer_property_data_to_translatable_tables.rb +59 -0
  105. data/db/migrate/20230110142344_backfill_friendly_id_slug_locale.rb +15 -0
  106. data/db/migrate/20230111121534_add_additional_taxon_translation_fields.rb +8 -0
  107. data/db/migrate/20230111122511_transfer_product_and_taxon_data_to_translatable_tables.rb +82 -0
  108. data/db/migrate/20230117115531_create_taxonomy_translations.rb +24 -0
  109. data/db/migrate/20230117120430_allow_null_taxonomy_name.rb +5 -0
  110. data/db/migrate/20230117121303_transfer_taxonomy_data_to_translatable_tables.rb +11 -0
  111. data/db/migrate/20230210142732_create_store_translations.rb +50 -0
  112. data/db/migrate/20230210142849_transfer_store_data_to_translatable_tables.rb +11 -0
  113. data/db/migrate/20230210230434_add_deleted_at_to_store_translations.rb +6 -0
  114. data/db/migrate/20230415155958_rename_data_feed_settings_table.rb +5 -0
  115. data/db/migrate/20230415160828_rename_data_feed_table_columns.rb +7 -0
  116. data/db/migrate/20230415161226_add_indexes_to_data_feeds_table.rb +5 -0
  117. data/db/migrate/20230512094803_rename_data_feeds_column_provider_to_type.rb +5 -0
  118. data/db/migrate/20230514162157_add_index_on_locale_and_permalink_to_spree_taxons.rb +5 -0
  119. data/lib/mobility/plugins/store_based_fallbacks.rb +55 -0
  120. data/lib/spree/core/configuration.rb +2 -1
  121. data/lib/spree/core/controller_helpers/auth.rb +1 -1
  122. data/lib/spree/core/controller_helpers/common.rb +5 -5
  123. data/lib/spree/core/controller_helpers/locale.rb +33 -2
  124. data/lib/spree/core/dependencies.rb +70 -94
  125. data/lib/spree/core/dependencies_helper.rb +19 -0
  126. data/lib/spree/core/engine.rb +7 -1
  127. data/lib/spree/core/preferences/preferable_class_methods.rb +1 -1
  128. data/lib/spree/core/product_duplicator.rb +4 -1
  129. data/lib/spree/core/product_filters.rb +7 -4
  130. data/lib/spree/core/search/base.rb +1 -1
  131. data/lib/spree/core/version.rb +1 -1
  132. data/lib/spree/core.rb +2 -0
  133. data/lib/spree/permitted_attributes.rb +1 -1
  134. data/lib/spree/testing_support/controller_requests.rb +10 -10
  135. data/lib/spree/testing_support/factories/google_data_feed_factory.rb +8 -0
  136. data/lib/spree/testing_support/factories/product_factory.rb +6 -0
  137. data/lib/spree/testing_support/factories/product_translation_factory.rb +6 -0
  138. data/lib/spree/testing_support/factories/store_factory.rb +3 -0
  139. data/lib/spree/testing_support/factories/variant_factory.rb +4 -0
  140. data/lib/spree/translation_migrations.rb +40 -0
  141. data/lib/spree_core.rb +1 -0
  142. data/spree_core.gemspec +6 -3
  143. metadata +147 -14
@@ -11,6 +11,8 @@ module Spree
11
11
  products = by_price(products)
12
12
  products = by_sku(products)
13
13
 
14
+ products = select_translatable_fields(products)
15
+
14
16
  products.distinct
15
17
  end
16
18
 
@@ -46,6 +48,27 @@ module Spree
46
48
  def sort_by?(field)
47
49
  sort.detect { |s| s[0] == field }
48
50
  end
51
+
52
+ # Add translatable fields to SELECT statement to avoid InvalidColumnReference error (workaround for Mobility issue #596)
53
+ def select_translatable_fields(scope)
54
+ translatable_fields = translatable_sortable_fields
55
+ return scope if translatable_fields.empty?
56
+
57
+ # if sorting by 'sku' or 'price', spree_products.* is already included in SELECT statement
58
+ if sort_by?('sku') || sort_by?('price')
59
+ scope.i18n.select(*translatable_fields)
60
+ else
61
+ scope.i18n.select("#{Product.table_name}.*").select(*translatable_fields)
62
+ end
63
+ end
64
+
65
+ def translatable_sortable_fields
66
+ fields = []
67
+ Product.translatable_fields.each do |field|
68
+ fields << field if sort_by?(field.to_s)
69
+ end
70
+ fields
71
+ end
49
72
  end
50
73
  end
51
74
  end
@@ -2,16 +2,12 @@
2
2
  # Validates a field based on the maximum length of the underlying DB field, if there is one.
3
3
  class DbMaximumLengthValidator < ActiveModel::EachValidator
4
4
  def validate_each(record, attribute, value)
5
- ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
5
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
6
6
  `DbMaximumLengthValidator` is deprecated and will be removed in Spree 5.0.
7
7
  Please remove any `db_maximum_length: true` validations from your codebase
8
8
  DEPRECATION
9
9
 
10
- limit = if defined?(Globalize)
11
- record.class.translation_class.columns_hash[attribute.to_s].limit
12
- else
13
- record.class.columns_hash[attribute.to_s].limit
14
- end
10
+ limit = record.class.columns_hash[attribute.to_s].limit
15
11
  value = record[attribute.to_sym]
16
12
  if value && limit && value.to_s.length > limit
17
13
  record.errors.add(attribute.to_sym, :too_long, count: limit)
data/brakeman.ignore CHANGED
@@ -1,20 +1,328 @@
1
1
  {
2
- "ignored_warnings": [
3
- {
4
- "fingerprint": "011b2643940ba1112f7a737e403abe3616ad91764703c801cc35a48d36b721da",
5
- "note": "interpolating table name"
6
- },
7
- {
8
- "fingerprint": "965d3919f811ab63b7b8d62da528559a7f38dc122c57efea7136e7ec5ef1f062",
9
- "note": "interpolating table name"
10
- },
11
- {
12
- "fingerprint": "abd8e90e7a7dfbcdcd6d44fd3fb550598aee6d7a9ef2bb132ad1a18a3c50be30",
13
- "note": "interpolating table name"
14
- },
15
- {
16
- "fingerprint": "efcc57e1a5648d7db59d1beaf5e399d2278539a8667b19c520b305a6ca7e15e8",
17
- "note": "interpolating table name"
18
- }
19
- ]
2
+ "ignored_warnings": [
3
+ {
4
+ "warning_type": "SQL Injection",
5
+ "warning_code": 0,
6
+ "fingerprint": "011b2643940ba1112f7a737e403abe3616ad91764703c801cc35a48d36b721da",
7
+ "check_name": "SQL",
8
+ "message": "Possible SQL injection",
9
+ "file": "app/models/concerns/spree/product_scopes.rb",
10
+ "line": 64,
11
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
12
+ "code": "where(\"#{price_table_name}.amount <= ?\", price)",
13
+ "render_path": null,
14
+ "location": {
15
+ "type": "method",
16
+ "class": "Spree",
17
+ "method": null
18
+ },
19
+ "user_input": "price_table_name",
20
+ "confidence": "Medium",
21
+ "cwe_id": [
22
+ 89
23
+ ],
24
+ "note": "interpolating table name"
25
+ },
26
+ {
27
+ "warning_type": "Redirect",
28
+ "warning_code": 18,
29
+ "fingerprint": "05d3870f66d650510c859a8949d5686b05eb028825083b096d0f65fedf80b118",
30
+ "check_name": "Redirect",
31
+ "message": "Possible unprotected redirect",
32
+ "file": "lib/spree/core/controller_helpers/auth.rb",
33
+ "line": 25,
34
+ "link": "https://brakemanscanner.org/docs/warning_types/redirect/",
35
+ "code": "redirect_to((session[\"spree_user_return_to\"] or (request.env[\"HTTP_REFERER\"] or default)))",
36
+ "render_path": null,
37
+ "location": {
38
+ "type": "method",
39
+ "class": "Spree::Core::ControllerHelpers::Auth",
40
+ "method": "redirect_back_or_default"
41
+ },
42
+ "user_input": "request.env[\"HTTP_REFERER\"]",
43
+ "confidence": "High",
44
+ "cwe_id": [
45
+ 601
46
+ ],
47
+ "note": ""
48
+ },
49
+ {
50
+ "warning_type": "SQL Injection",
51
+ "warning_code": 0,
52
+ "fingerprint": "1c12fcb833b0ddffa07880acb7e604922c0d1d52de598316186241baf16551cd",
53
+ "check_name": "SQL",
54
+ "message": "Possible SQL injection",
55
+ "file": "app/finders/spree/taxons/find.rb",
56
+ "line": 75,
57
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
58
+ "code": "taxons.joins(\"INNER JOIN #{Spree::Taxon.table_name} AS parent_taxon ON parent_taxon.id = #{Spree::Taxon.table_name}.parent_id\").join_translation_table(Taxon, \"parent_taxon\").where([\"#{Taxon.translation_table_alias}.permalink = ?\", parent_permalink])",
59
+ "render_path": null,
60
+ "location": {
61
+ "type": "method",
62
+ "class": "Spree::Taxons::Find",
63
+ "method": "by_parent_permalink"
64
+ },
65
+ "user_input": "Taxon.translation_table_alias",
66
+ "confidence": "Weak",
67
+ "cwe_id": [
68
+ 89
69
+ ],
70
+ "note": ""
71
+ },
72
+ {
73
+ "warning_type": "SQL Injection",
74
+ "warning_code": 0,
75
+ "fingerprint": "1f02952550c2f54d044c9577a45e7ba7c7990c8b8a59d1dac83a96790237f507",
76
+ "check_name": "SQL",
77
+ "message": "Possible SQL injection",
78
+ "file": "app/models/concerns/spree/product_scopes.rb",
79
+ "line": 139,
80
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
81
+ "code": "joins(:properties).join_translation_table(Property).join_translation_table(ProductProperty).where(\"#{ProductProperty.translation_table_alias}.value = ?\", value)",
82
+ "render_path": null,
83
+ "location": {
84
+ "type": "method",
85
+ "class": "Spree::ProductScopes",
86
+ "method": null
87
+ },
88
+ "user_input": "ProductProperty.translation_table_alias",
89
+ "confidence": "Weak",
90
+ "cwe_id": [
91
+ 89
92
+ ],
93
+ "note": ""
94
+ },
95
+ {
96
+ "warning_type": "SQL Injection",
97
+ "warning_code": 0,
98
+ "fingerprint": "7928c0813a0bf084ead091b4554ef6abea9ae9c7167936f5c62da9e328b9f736",
99
+ "check_name": "SQL",
100
+ "message": "Possible SQL injection",
101
+ "file": "app/models/concerns/spree/product_scopes.rb",
102
+ "line": 139,
103
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
104
+ "code": "joins(:properties).join_translation_table(Property).join_translation_table(ProductProperty).where(\"#{ProductProperty.translation_table_alias}.value = ?\", value)",
105
+ "render_path": null,
106
+ "location": {
107
+ "type": "method",
108
+ "class": "Spree",
109
+ "method": null
110
+ },
111
+ "user_input": "ProductProperty.translation_table_alias",
112
+ "confidence": "Weak",
113
+ "cwe_id": [
114
+ 89
115
+ ],
116
+ "note": ""
117
+ },
118
+ {
119
+ "warning_type": "SQL Injection",
120
+ "warning_code": 0,
121
+ "fingerprint": "857c335935a00f584137f31dbcb1a4532af5c8bb5cf53a86058b4af98c6597dc",
122
+ "check_name": "SQL",
123
+ "message": "Possible SQL injection",
124
+ "file": "lib/spree/translation_migrations.rb",
125
+ "line": 21,
126
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
127
+ "code": "ActiveRecord::Base.connection.execute(\"\\n UPDATE #{resource_class.table_name}\\n SET #{resource_class.translatable_fields.map do\n \"#{f}=null\"\n end.join(\", \")};\\n \")",
128
+ "render_path": null,
129
+ "location": {
130
+ "type": "method",
131
+ "class": "Spree::TranslationMigrations",
132
+ "method": "transfer_translation_data"
133
+ },
134
+ "user_input": "resource_class.translatable_fields.map do\n \"#{f}=null\"\n end.join(\", \")",
135
+ "confidence": "Medium",
136
+ "cwe_id": [
137
+ 89
138
+ ],
139
+ "note": ""
140
+ },
141
+ {
142
+ "warning_type": "SQL Injection",
143
+ "warning_code": 0,
144
+ "fingerprint": "965d3919f811ab63b7b8d62da528559a7f38dc122c57efea7136e7ec5ef1f062",
145
+ "check_name": "SQL",
146
+ "message": "Possible SQL injection",
147
+ "file": "app/models/concerns/spree/product_scopes.rb",
148
+ "line": 68,
149
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
150
+ "code": "where(\"#{price_table_name}.amount >= ?\", price)",
151
+ "render_path": null,
152
+ "location": {
153
+ "type": "method",
154
+ "class": "Spree::ProductScopes",
155
+ "method": null
156
+ },
157
+ "user_input": "price_table_name",
158
+ "confidence": "Medium",
159
+ "cwe_id": [
160
+ 89
161
+ ],
162
+ "note": "interpolating table name"
163
+ },
164
+ {
165
+ "warning_type": "SQL Injection",
166
+ "warning_code": 0,
167
+ "fingerprint": "98607ecfb86c2d3c2567390f813861edbc42d6ffa9f482afb7c0b3464eaf6e73",
168
+ "check_name": "SQL",
169
+ "message": "Possible SQL injection",
170
+ "file": "app/models/concerns/spree/translatable_resource_scopes.rb",
171
+ "line": 18,
172
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
173
+ "code": "joins(\"LEFT OUTER JOIN #{translatable_class::Translation.table_name} #{translatable_class.translation_table_alias}\\n ON #{translatable_class.translation_table_alias}.#{\"#{translatable_class.table_name.singularize}_id\"} = #{(translatable_class.table_name or join_on_table_alias)}.id\\n AND #{translatable_class.translation_table_alias}.locale = '#{Mobility.locale}'\")",
174
+ "render_path": null,
175
+ "location": {
176
+ "type": "method",
177
+ "class": "Spree::TranslatableResourceScopes",
178
+ "method": "join_translation_table"
179
+ },
180
+ "user_input": "translatable_class.translation_table_alias",
181
+ "confidence": "Medium",
182
+ "cwe_id": [
183
+ 89
184
+ ],
185
+ "note": ""
186
+ },
187
+ {
188
+ "warning_type": "SQL Injection",
189
+ "warning_code": 0,
190
+ "fingerprint": "abd8e90e7a7dfbcdcd6d44fd3fb550598aee6d7a9ef2bb132ad1a18a3c50be30",
191
+ "check_name": "SQL",
192
+ "message": "Possible SQL injection",
193
+ "file": "app/models/concerns/spree/product_scopes.rb",
194
+ "line": 64,
195
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
196
+ "code": "where(\"#{price_table_name}.amount <= ?\", price)",
197
+ "render_path": null,
198
+ "location": {
199
+ "type": "method",
200
+ "class": "Spree::ProductScopes",
201
+ "method": null
202
+ },
203
+ "user_input": "price_table_name",
204
+ "confidence": "Medium",
205
+ "cwe_id": [
206
+ 89
207
+ ],
208
+ "note": "interpolating table name"
209
+ },
210
+ {
211
+ "warning_type": "SQL Injection",
212
+ "warning_code": 0,
213
+ "fingerprint": "c1c97347a2d74ea41d46519e3bfbd94c511a1bd9c285f3f2a1fa0cb7e624d232",
214
+ "check_name": "SQL",
215
+ "message": "Possible SQL injection",
216
+ "file": "lib/spree/translation_migrations.rb",
217
+ "line": 32,
218
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
219
+ "code": "ActiveRecord::Base.connection.execute(\"\\n UPDATE #{resource_class.table_name}\\n SET (#{resource_class.translatable_fields.join(\", \")}) = #{(\"ROW\" or \"\")}(#{resource_class.translatable_fields.map do\n \"#{resource_class::Translation.table_name}.#{f}\"\n end.join(\", \")})\\n FROM #{resource_class::Translation.table_name}\\n WHERE #{resource_class::Translation.table_name}.#{\"#{resource_class.table_name.singularize}_id\"} = #{resource_class.table_name}.id\\n \")",
220
+ "render_path": null,
221
+ "location": {
222
+ "type": "method",
223
+ "class": "Spree::TranslationMigrations",
224
+ "method": "revert_translation_data_transfer"
225
+ },
226
+ "user_input": "resource_class.translatable_fields.join(\", \")",
227
+ "confidence": "Medium",
228
+ "cwe_id": [
229
+ 89
230
+ ],
231
+ "note": ""
232
+ },
233
+ {
234
+ "warning_type": "SQL Injection",
235
+ "warning_code": 0,
236
+ "fingerprint": "c2bc48d98076b7c4fc3314c6a85f7bd1132efe5fcc346da4d28df7c25f93633f",
237
+ "check_name": "SQL",
238
+ "message": "Possible SQL injection",
239
+ "file": "app/models/spree/variant.rb",
240
+ "line": 126,
241
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
242
+ "code": "joins(:product).join_translation_table(Product).where(\"LOWER(#{Product.translation_table_alias}.name) LIKE LOWER(:query)\\n OR LOWER(sku) LIKE LOWER(:query)\", :query => (\"%#{query}%\"))",
243
+ "render_path": null,
244
+ "location": {
245
+ "type": "method",
246
+ "class": "Spree::Variant",
247
+ "method": "Spree::Variant.product_name_or_sku_cont"
248
+ },
249
+ "user_input": "Product.translation_table_alias",
250
+ "confidence": "Weak",
251
+ "cwe_id": [
252
+ 89
253
+ ],
254
+ "note": ""
255
+ },
256
+ {
257
+ "warning_type": "SQL Injection",
258
+ "warning_code": 0,
259
+ "fingerprint": "ed253ae6b1b4ea3fe3d87d3652380fecab80133319b1ed041d98d163fd16b815",
260
+ "check_name": "SQL",
261
+ "message": "Possible SQL injection",
262
+ "file": "app/finders/spree/taxons/find.rb",
263
+ "line": 71,
264
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
265
+ "code": "taxons.joins(:parent).join_translation_table(Taxon, \"parents_spree_taxons\").where([\"#{Taxon.translation_table_alias}.permalink = ?\", parent_permalink])",
266
+ "render_path": null,
267
+ "location": {
268
+ "type": "method",
269
+ "class": "Spree::Taxons::Find",
270
+ "method": "by_parent_permalink"
271
+ },
272
+ "user_input": "Taxon.translation_table_alias",
273
+ "confidence": "Weak",
274
+ "cwe_id": [
275
+ 89
276
+ ],
277
+ "note": ""
278
+ },
279
+ {
280
+ "warning_type": "SQL Injection",
281
+ "warning_code": 0,
282
+ "fingerprint": "efcc57e1a5648d7db59d1beaf5e399d2278539a8667b19c520b305a6ca7e15e8",
283
+ "check_name": "SQL",
284
+ "message": "Possible SQL injection",
285
+ "file": "app/models/concerns/spree/product_scopes.rb",
286
+ "line": 68,
287
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
288
+ "code": "where(\"#{price_table_name}.amount >= ?\", price)",
289
+ "render_path": null,
290
+ "location": {
291
+ "type": "method",
292
+ "class": "Spree",
293
+ "method": null
294
+ },
295
+ "user_input": "price_table_name",
296
+ "confidence": "Medium",
297
+ "cwe_id": [
298
+ 89
299
+ ],
300
+ "note": "interpolating table name"
301
+ },
302
+ {
303
+ "warning_type": "SQL Injection",
304
+ "warning_code": 0,
305
+ "fingerprint": "f14dd62fac0dd1e9d5532dd5efc770e2eb873a8db80faf366b6295378634754a",
306
+ "check_name": "SQL",
307
+ "message": "Possible SQL injection",
308
+ "file": "lib/spree/translation_migrations.rb",
309
+ "line": 16,
310
+ "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
311
+ "code": "ActiveRecord::Base.connection.execute(\"\\n INSERT INTO #{resource_class::Translation.table_name} (#{resource_class.translatable_fields.join(\", \")}, #{\"#{resource_class.table_name.singularize}_id\"}, locale, created_at, updated_at)\\n SELECT #{resource_class.translatable_fields.join(\", \")}, id, '#{default_locale}' as locale, created_at, updated_at FROM #{resource_class.table_name};\\n \")",
312
+ "render_path": null,
313
+ "location": {
314
+ "type": "method",
315
+ "class": "Spree::TranslationMigrations",
316
+ "method": "transfer_translation_data"
317
+ },
318
+ "user_input": "resource_class.translatable_fields.join(\", \")",
319
+ "confidence": "Medium",
320
+ "cwe_id": [
321
+ 89
322
+ ],
323
+ "note": ""
324
+ }
325
+ ],
326
+ "updated": "2023-03-22 20:11:32 +0100",
327
+ "brakeman_version": "5.4.1"
20
328
  }
@@ -1,3 +1,5 @@
1
+ require 'friendly_id/mobility'
2
+
1
3
  # To learn more, check out the guide:
2
4
  # http://norman.github.io/friendly_id/file.Guide.html
3
5
  FriendlyId.defaults do |config|
@@ -0,0 +1,16 @@
1
+ Mobility.configure do |config|
2
+ config.plugins do
3
+ ransack
4
+ backend :table
5
+ active_record
6
+ reader
7
+ writer
8
+ backend_reader
9
+ query
10
+ cache
11
+ store_based_fallbacks
12
+ locale_accessors
13
+ presence
14
+ dirty
15
+ end
16
+ end
@@ -1,3 +1 @@
1
- if Rails::VERSION::STRING >= '6.1'
2
- ActiveRecord::Base.has_many_inversing = false
3
- end
1
+ ActiveRecord::Base.has_many_inversing = false
@@ -1,6 +1,8 @@
1
1
  en:
2
2
  activemodel:
3
3
  errors:
4
+ messages:
5
+ blank: can't be blank
4
6
  models:
5
7
  spree/fulfilment_changer:
6
8
  attributes:
@@ -309,6 +311,8 @@ en:
309
311
  one: Zone
310
312
  other: Zones
311
313
  errors:
314
+ messages:
315
+ blank: can't be blank
312
316
  models:
313
317
  spree/calculator/tiered_flat_rate:
314
318
  attributes:
@@ -1112,6 +1116,7 @@ en:
1112
1116
  notice_messages:
1113
1117
  icon_removed: Image has been successfully removed
1114
1118
  prices_saved: Prices successfully saved
1119
+ translations_saved: Translations successfully saved
1115
1120
  product_cloned: Product has been cloned
1116
1121
  product_deleted: Product has been deleted
1117
1122
  product_not_cloned: "Product could not be cloned. Reason: %{error}"
@@ -1571,6 +1576,7 @@ en:
1571
1576
  starting_from: Starts at
1572
1577
  state: State
1573
1578
  state_based: State Based
1579
+ state_changes: State Changes
1574
1580
  states: States
1575
1581
  state_machine_states:
1576
1582
  accepted: Accepted
@@ -1749,6 +1755,7 @@ en:
1749
1755
  transfer_from_location: Transfer From
1750
1756
  transfer_stock: Transfer Stock
1751
1757
  transfer_to_location: Transfer To
1758
+ translations: Translations
1752
1759
  tree: Tree
1753
1760
  type: Type
1754
1761
  type_to_search: Type to search
@@ -0,0 +1,27 @@
1
+ class CreateProductNameAndDescriptionTranslationsForMobilityTableBackend < ActiveRecord::Migration[6.1]
2
+ def change
3
+ # create translation table only if spree_globalize has not already created it
4
+ if ActiveRecord::Base.connection.table_exists? 'spree_product_translations'
5
+ # manually check for index since Rails if_exists does not always work correctly
6
+ if ActiveRecord::Migration.connection.index_exists?(:spree_product_translations, :spree_product_id)
7
+ remove_index :spree_product_translations, name: "index_spree_product_translations_on_spree_product_id", if_exists: true
8
+ end
9
+ else
10
+ create_table :spree_product_translations do |t|
11
+
12
+ # Translated attribute(s)
13
+ t.string :name
14
+ t.text :description
15
+
16
+ t.string :locale, null: false
17
+ t.references :spree_product, null: false, foreign_key: true, index: false
18
+
19
+ t.timestamps null: false
20
+ end
21
+
22
+ add_index :spree_product_translations, :locale, name: :index_spree_product_translations_on_locale
23
+ end
24
+
25
+ add_index :spree_product_translations, [:spree_product_id, :locale], name: :unique_product_id_per_locale, unique: true
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ class CreateSpreeProductTranslationsForMobility < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :spree_product_translations, :meta_description, :text, if_not_exists: true
4
+ add_column :spree_product_translations, :meta_keywords, :string, if_not_exists: true
5
+ add_column :spree_product_translations, :meta_title, :string, if_not_exists: true
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeProductNameNullToTrue < ActiveRecord::Migration[6.1]
2
+ def change
3
+ change_column_null :spree_products, :name, true
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ class CreateSpreeTaxonNameAndDescriptionTranslationsForMobilityTableBackend < ActiveRecord::Migration[6.1]
2
+ def change
3
+ # create translation table only if spree_globalize has not already created it
4
+ if ActiveRecord::Base.connection.table_exists? 'spree_taxon_translations'
5
+ # manually check for index since Rails if_exists does not always work correctly
6
+ if ActiveRecord::Migration.connection.index_exists?(:spree_taxon_translations, :spree_taxon_id)
7
+ # replacing this with index on spree_taxon_id and locale
8
+ remove_index :spree_taxon_translations, name: "index_spree_taxon_translations_on_spree_taxon_id", if_exists: true
9
+ end
10
+ else
11
+ create_table :spree_taxon_translations do |t|
12
+ # Translated attribute(s)
13
+ t.string :name
14
+ t.text :description
15
+
16
+ t.string :locale, null: false
17
+ t.references :spree_taxon, null: false, foreign_key: true, index: false
18
+
19
+ t.timestamps null: false
20
+ end
21
+
22
+ add_index :spree_taxon_translations, :locale, name: :index_spree_taxon_translations_on_locale
23
+ end
24
+
25
+ add_index :spree_taxon_translations, [:spree_taxon_id, :locale], name: :index_spree_taxon_translations_on_spree_taxon_id_and_locale, unique: true
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeTaxonNameNullToTrue < ActiveRecord::Migration[6.1]
2
+ def change
3
+ change_column_null :spree_taxons, :name, true
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class AddLocaleToFriendlyIdSlugs < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :friendly_id_slugs, :locale, :string, null: :false, after: :scope
4
+
5
+ remove_index :friendly_id_slugs, [:slug, :sluggable_type]
6
+ add_index :friendly_id_slugs, [:slug, :sluggable_type, :locale], length: { slug: 140, sluggable_type: 50, locale: 2 }
7
+ remove_index :friendly_id_slugs, [:slug, :sluggable_type, :scope]
8
+ add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope, :locale], length: { slug: 70, sluggable_type: 50, scope: 70, locale: 2 }, unique: true, name: :index_friendly_id_slugs_unique
9
+ add_index :friendly_id_slugs, :locale
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class CreateSpreeProductSlugTranslationsForMobilityTableBackend < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :spree_product_translations, :slug, :string
4
+ end
5
+ end
@@ -0,0 +1,66 @@
1
+ class TransferDataToTranslatableTables < ActiveRecord::Migration[6.1]
2
+ DEFAULT_LOCALE = 'en'
3
+ PRODUCTS_TABLE = 'spree_products'
4
+ PRODUCT_TRANSLATIONS_TABLE = 'spree_product_translations'
5
+ TAXONS_TABLE = 'spree_taxons'
6
+ TAXON_TRANSLATIONS_TABLE = 'spree_taxon_translations'
7
+
8
+ def up
9
+ # Products
10
+ ActiveRecord::Base.connection.execute("
11
+ INSERT INTO #{PRODUCT_TRANSLATIONS_TABLE} (name, description, locale, spree_product_id, created_at, updated_at, meta_description, meta_keywords, meta_title, slug)
12
+ SELECT name, description, '#{DEFAULT_LOCALE}' as locale, id, created_at, updated_at, meta_description, meta_keywords, meta_title, slug FROM #{PRODUCTS_TABLE}
13
+ ")
14
+ ActiveRecord::Base.connection.execute("
15
+ UPDATE #{PRODUCTS_TABLE}
16
+ SET name=null, description=null, meta_description=null, meta_keywords=null, meta_title=null, slug=null;
17
+ ")
18
+ #Taxons
19
+ ActiveRecord::Base.connection.execute("
20
+ INSERT INTO #{TAXON_TRANSLATIONS_TABLE} (name, description, locale, spree_taxon_id, created_at, updated_at)
21
+ SELECT name, description, '#{DEFAULT_LOCALE}' as locale, id, created_at, updated_at FROM #{TAXONS_TABLE}
22
+ ")
23
+ ActiveRecord::Base.connection.execute("
24
+ UPDATE #{TAXONS_TABLE}
25
+ SET name=null, description=null
26
+ ")
27
+ end
28
+
29
+ def down
30
+ ActiveRecord::Base.connection.execute("
31
+ UPDATE #{PRODUCTS_TABLE} as products
32
+ SET (name,
33
+ description,
34
+ meta_description,
35
+ meta_keywords,
36
+ meta_title,
37
+ slug) =
38
+ (t_products.name,
39
+ t_products.description,
40
+ t_products.meta_description,
41
+ t_products.meta_keywords,
42
+ t_products.meta_title,
43
+ t_products.slug)
44
+ FROM #{PRODUCT_TRANSLATIONS_TABLE} AS t_products
45
+ WHERE t_products.spree_product_id = products.id
46
+ ")
47
+
48
+ ActiveRecord::Base.connection.execute("
49
+ TRUNCATE TABLE #{PRODUCT_TRANSLATIONS_TABLE}
50
+ ")
51
+
52
+ ActiveRecord::Base.connection.execute("
53
+ UPDATE #{TAXONS_TABLE} as taxons
54
+ SET (name,
55
+ description) =
56
+ (t_taxons.name,
57
+ t_taxons.description)
58
+ FROM #{TAXON_TRANSLATIONS_TABLE} AS t_taxons
59
+ WHERE t_taxons.spree_taxon_id = taxons.id
60
+ ")
61
+
62
+ ActiveRecord::Base.connection.execute("
63
+ TRUNCATE TABLE #{TAXON_TRANSLATIONS_TABLE}
64
+ ")
65
+ end
66
+ end
@@ -0,0 +1,8 @@
1
+ class AddSelectedLocaleToSpreeUsers < ActiveRecord::Migration[6.1]
2
+ def change
3
+ if Spree.user_class.present?
4
+ users_table_name = Spree.user_class.table_name
5
+ add_column users_table_name, :selected_locale, :string unless column_exists?(users_table_name, :selected_locale)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ class AddDeletedAtToProductTranslations < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :spree_product_translations, :deleted_at, :datetime
4
+ add_index :spree_product_translations, :deleted_at
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddUniquenessConstraintToProductTranslations < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_index :spree_product_translations, [:locale, :slug], unique: true, name: 'unique_slug_per_locale'
4
+ end
5
+ end