spina 2.10.0 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd9893ef78c55c7d8a448cce6e8bc04fe22d3f48cde3f07bbef32c03d9aaf00e
4
- data.tar.gz: bc9fd36b1599b808d0313fabb1508506e4cf9e9e4f26908f645f906db3c5c79a
3
+ metadata.gz: 68c17b8a615a45c86dce79d2e4b32a5f7bc4fdbf8f71d94fbdc2f530a68baa48
4
+ data.tar.gz: a85f8e9b3a922c1b3de5866d37bab8bdae583c264e35894baa7871b95aa2eaf5
5
5
  SHA512:
6
- metadata.gz: 6c71bf70aa732fe118cdac86c234a99d88adfd0bf2669551a5f94c6847401ca87d0ebabc5afe522749d95d6c9e5f79c1abec95916080f735e5e29d36461c042c
7
- data.tar.gz: 8d2da67450bc5c70cfd73c61dadca688ccbacb6b971d465559cca95c9cc2969a02c6f8e84e7dd02e794329a08f94e7fcff31f48382ce93ad64ac84c75333e480
6
+ metadata.gz: be079dbe9d681c2d2912946c01127d40ffe84fd28c600be31be1a0a3d56aa0e7591f4ab8423943490aa52f5f70adc04d8eac73df8bd827397ea536e5fb53fce1
7
+ data.tar.gz: fdbb328aba58cbdc660869b2745d6469cbb10a9e40576a3b09205862e4deef8e6ca5f717bb7171039915010c4227e2998a2c1bb86907b194f5844e68a4925dd4
@@ -32,6 +32,13 @@
32
32
  <% if !@page.custom_page? %>
33
33
  <%= link_to t('spina.pages.change_view_template') + "...", helpers.spina.edit_template_admin_page_path(@page), class: "block px-4 py-2 text-sm font-medium leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900", data: {turbo_frame: "modal", action: "reveal#hide"} %>
34
34
  <% end %>
35
+
36
+ <% if @locale.to_sym != I18n.locale.to_sym %>
37
+ <% @page.translations.where(locale: @locale).each do |translation| %>
38
+ <%= button_to t("spina.page_translations.delete", translation: @locale.upcase), helpers.spina.admin_page_translation_path(translation), method: :delete, class: "block w-full text-left px-4 py-2 text-sm leading-5 font-medium text-red-500 cursor-pointer bg-white hover:bg-red-100 hover:bg-opacity-50 hover:text-red-500 focus:outline-none focus:bg-gray-100 focus:text-gray-900", form: {data: {controller: "confirm", confirm_message: t('spina.page_translations.delete_confirmation', subject: @locale.upcase)}} %>
39
+ <% end %>
40
+ <% end %>
41
+
35
42
  <% if @page.deletable? %>
36
43
  <%= button_to t('spina.pages.delete'), helpers.spina.admin_page_path(@page), method: :delete, class: "block w-full text-left px-4 py-2 text-sm leading-5 font-medium text-red-500 cursor-pointer bg-white hover:bg-red-100 hover:bg-opacity-50 hover:text-red-500 focus:outline-none focus:bg-gray-100 focus:text-gray-900", form: {data: {controller: "confirm", confirm_message: t('spina.pages.delete_confirmation', subject: @page.title)}} %>
37
44
  <% else %>
@@ -24,7 +24,7 @@ module Spina
24
24
  private
25
25
 
26
26
  def spina_locales
27
- Spina.config.locales.map(&:to_sym)
27
+ Spina.locales.map(&:to_sym)
28
28
  end
29
29
 
30
30
  end
@@ -18,7 +18,7 @@ module Spina
18
18
  private
19
19
 
20
20
  def spina_locales
21
- Spina.config.locales.map(&:to_sym)
21
+ Spina.locales.map(&:to_sym)
22
22
  end
23
23
 
24
24
  end
@@ -0,0 +1,14 @@
1
+ module Spina
2
+ module Admin
3
+ class PageTranslationsController < AdminController
4
+
5
+ def destroy
6
+ @translation = Spina::Page::Translation.find(params[:id])
7
+ @translation.destroy
8
+ flash[:info] = t("spina.page_translations.deleted")
9
+ redirect_to spina.edit_admin_page_path(@translation.translated_model), status: :see_other
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -6,7 +6,7 @@ module Spina
6
6
 
7
7
  included do
8
8
  # Store each locale's content in [locale]_content as an array of parts
9
- Spina.config.locales.each do |locale|
9
+ Spina.locales.each do |locale|
10
10
  attr_json "#{locale}_content".to_sym, AttrJson::Type::SpinaPartsModel.new, array: true, default: -> { [] }
11
11
  attr_json_setter_monkeypatch "#{locale}_content".to_sym
12
12
  attr_json_accepts_nested_attributes_for "#{locale}_content".to_sym
@@ -15,15 +15,25 @@ module Spina
15
15
  name
16
16
  end
17
17
 
18
+ # Spina previously stored account preferences with symbols as keys.
19
+ # Because of CVE-2022-32224 we're changing that to strings instead.
20
+ # This fallback ensures backwards compatibility, but in the long run this
21
+ # should be refactored to use a simple JSONB-column with Postgres.
18
22
  def self.serialized_attr_accessor(*args)
19
23
  args.each do |method_name|
20
24
  define_method method_name do
25
+ if self.preferences.try(:[], method_name.to_sym).present?
26
+ ActiveSupport::Deprecation.warn("#{method_name} is stored as a symbol. Please set and save it again using #{method_name}= on your Spina::Account model to store it as a string. You can do this from the UI by saving your account preferences.")
27
+ end
28
+
29
+ self.preferences.try(:[], method_name.to_s) ||
21
30
  self.preferences.try(:[], method_name.to_sym)
22
31
  end
23
32
 
24
33
  define_method "#{method_name}=" do |value|
25
34
  self.preferences ||= {}
26
- self.preferences[method_name.to_sym] = value
35
+ self.preferences.except!(method_name.to_sym)
36
+ self.preferences[method_name.to_s] = value
27
37
  end
28
38
  end
29
39
  end
@@ -17,16 +17,16 @@ module Spina
17
17
  has_many :navigations, through: :navigation_items
18
18
 
19
19
  # Pages can belong to a resource
20
- belongs_to :resource, optional: true
20
+ belongs_to :resource, optional: true, touch: true
21
21
 
22
- scope :main, -> { where(resource_id: nil) }
22
+ scope :main, -> { where(resource_id: nil) }
23
23
  scope :regular_pages, -> { main }
24
24
  scope :resource_pages, -> { where.not(resource: nil) }
25
25
  scope :active, -> { where(active: true) }
26
26
  scope :sorted, -> { order(:position) }
27
27
  scope :live, -> { active.where(draft: false) }
28
28
  scope :in_menu, -> { where(show_in_menu: true) }
29
-
29
+
30
30
  before_create :set_default_position
31
31
 
32
32
  # Copy resource from parent
@@ -57,7 +57,7 @@ module Spina
57
57
  def slug
58
58
  url_title.to_s.to_slug.transliterate(*Spina.config.transliterations).normalize.to_s
59
59
  end
60
-
60
+
61
61
  def homepage?
62
62
  name == 'homepage'
63
63
  end
@@ -81,11 +81,11 @@ module Spina
81
81
  def next_sibling
82
82
  siblings.where('position > ?', position).sorted.first
83
83
  end
84
-
84
+
85
85
  def set_materialized_path
86
86
  self.old_path = materialized_path
87
87
  self.materialized_path = localized_materialized_path
88
-
88
+
89
89
  # Append counter to duplicate materialized_path
90
90
  i = 0
91
91
  while duplicate_materialized_path?
@@ -104,7 +104,7 @@ module Spina
104
104
  end
105
105
 
106
106
  private
107
-
107
+
108
108
  def set_default_position
109
109
  self.position ||= self.class.maximum(:position).to_i.next
110
110
  end
@@ -136,7 +136,7 @@ module Spina
136
136
  path_fragments.append(slug) unless homepage?
137
137
  path_fragments.compact.map(&:parameterize).join('/')
138
138
  end
139
-
139
+
140
140
  def duplicate_materialized_path?
141
141
  self.class.where.not(id: id).i18n.where(materialized_path: materialized_path).exists?
142
142
  end
@@ -7,7 +7,7 @@ xml.urlset "xmlns" => "http://www.google.com/schemas/sitemap/0.9", "xmlns:xhtml"
7
7
 
8
8
  # Translations
9
9
  page.translations.each do |translation|
10
- if translation.locale.in? Spina.config.locales.map(&:to_s)
10
+ if translation.locale.in? Spina.locales.map(&:to_s)
11
11
  Mobility.with_locale(translation.locale) do
12
12
  xml.xhtml(:link, rel: "alternate", hreflang: translation.locale, href: "#{request.protocol}#{request.host}#{page.materialized_path}")
13
13
  end
@@ -0,0 +1,16 @@
1
+ # CVE-2022-32224 RAILS
2
+ #
3
+ # There was a bug in Rails allowing YAML-serialized data to be vulnerable to RCE.
4
+ # Spina uses the serialize method to store various preferences stored using symbols.
5
+ # We've now changed this so preferences are stored with strings as keys instead of
6
+ # symbols, but in order to not break existing projects we're adding 'Symbol' to the
7
+ # list of permitted classes.
8
+ # This can be removed in the future.
9
+ #
10
+ # More information:
11
+ # https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017
12
+
13
+ if ActiveRecord.respond_to?(:yaml_column_permitted_classes)
14
+ Rails.application.config.active_record.yaml_column_permitted_classes ||= []
15
+ Rails.application.config.active_record.yaml_column_permitted_classes += [Symbol]
16
+ end
@@ -281,6 +281,10 @@ en:
281
281
  show_in_menu: invisible
282
282
  skip_to_first_child: forward to first child page
283
283
  sorting_saved: Sorting saved
284
+ page_translations:
285
+ delete: Delete translation (%{translation})
286
+ delete_confirmation: Are you sure you want to delete this translation <strong>(%{subject})</strong>?
287
+ deleted: Translation deleted
284
288
  permanently_delete: Permanently delete
285
289
  photos:
286
290
  cannot_be_created: 'Image could not be processed:'
@@ -254,6 +254,10 @@ nl:
254
254
  show_in_menu: onzichtbaar
255
255
  skip_to_first_child: doorsturen naar 1<sup>e</sup> subpagina
256
256
  sorting_saved: Volgorde opgeslagen
257
+ page_translations:
258
+ delete: Verwijder vertaling (%{translation})
259
+ delete_confirmation: Weet je zeker dat je deze vertaling <strong>(%{subject})</strong> wilt verwijderen?
260
+ deleted: Vertaling verwijderd
257
261
  permanently_delete: Definitief verwijderen
258
262
  photos:
259
263
  cannot_be_created: 'Foto kon niet worden verwerkt:'
data/config/routes.rb CHANGED
@@ -53,6 +53,7 @@ Spina::Engine.routes.draw do
53
53
 
54
54
  post :sort, on: :collection
55
55
  end
56
+ resources :page_translations, only: [:destroy]
56
57
  resources :parent_pages
57
58
  resource :layout, controller: :layout, only: [:edit, :update]
58
59
 
@@ -92,8 +93,8 @@ Spina::Engine.routes.draw do
92
93
  root to: "pages#homepage"
93
94
 
94
95
  # Pages
95
- get '/:locale/*id' => 'pages#show', constraints: {locale: /#{Spina.config.locales.join('|')}/ }
96
- get '/:locale/' => 'pages#homepage', constraints: {locale: /#{Spina.config.locales.join('|')}/ }
96
+ get '/:locale/*id' => 'pages#show', constraints: {locale: /#{Spina.locales.join('|')}/ }
97
+ get '/:locale/' => 'pages#homepage', constraints: {locale: /#{Spina.locales.join('|')}/ }
97
98
  get '/*id' => 'pages#show', as: "page", controller: 'pages', constraints: -> (request) {
98
99
  request.path.exclude?(ActiveStorage.routes_prefix) &&
99
100
  !(Rails.env.development? && request.path.starts_with?('/rails/'))
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  content: [
3
3
  <%= Spina.config.tailwind_content.map{|path|"'#{path}'"}.join(",\n") %>
4
- ],
4
+ ],
5
5
  theme: {
6
6
  fontFamily: {
7
7
  body: ['Metropolis'],
@@ -18,8 +18,6 @@ module.exports = {
18
18
  }
19
19
  },
20
20
  plugins: [
21
- require('@tailwindcss/forms'),
22
- require('@tailwindcss/aspect-ratio'),
23
- require('@tailwindcss/typography'),
21
+ <%= Spina.config.tailwind_plugins.map {|plugin|"require('#{plugin}')"}.join(",\n\t") %>
24
22
  ]
25
23
  }
@@ -1,5 +1,5 @@
1
- <% if Spina.config.locales.size > 1 %>
1
+ <% if Spina.locales.size > 1 %>
2
2
  <div id="languages">
3
- <%= Spina.config.locales.map{|l| link_to_unless(l == I18n.locale, l.upcase, root_url(params: {locale: l}))}.join(' / ').html_safe %>
3
+ <%= Spina.locales.map{|l| link_to_unless(l == I18n.locale, l.upcase, root_url(params: {locale: l}))}.join(' / ').html_safe %>
4
4
  </div>
5
5
  <% end %>
@@ -2,7 +2,8 @@ Spina.configure do |config|
2
2
  # Locales
3
3
  # ===============
4
4
  # All locales your content should be available in.
5
- # config.locales = [I18n.default_locale]
5
+ # Defaults to I18n.default_locale
6
+ # config.locales = [:en, :nl]
6
7
 
7
8
  # Backend path
8
9
  # ===============
data/lib/spina/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Spina
2
- VERSION = "2.10.0"
2
+ VERSION = "2.11.0"
3
3
  end
data/lib/spina.rb CHANGED
@@ -22,17 +22,18 @@ module Spina
22
22
  config_accessor :api_key,
23
23
  :api_path,
24
24
  :authentication,
25
- :backend_path,
25
+ :backend_path,
26
26
  :importmap,
27
27
  :frontend_parent_controller,
28
28
  :disable_frontend_routes,
29
29
  :disable_decorator_load,
30
- :locales,
30
+ :locales,
31
31
  :embedded_image_size,
32
32
  :mailer_defaults,
33
33
  :thumbnail_image_size,
34
34
  :party_pooper,
35
35
  :tailwind_content,
36
+ :tailwind_plugins,
36
37
  :queues,
37
38
  :transliterations
38
39
 
@@ -50,17 +51,17 @@ module Spina
50
51
  self.locales = [I18n.default_locale]
51
52
  self.party_pooper = false
52
53
  self.transliterations = %i(latin)
53
-
54
+
54
55
  # Queues for background jobs
55
56
  # - config.queues.page_updates
56
57
  self.queues = ActiveSupport::InheritableOptions.new
57
-
58
+
58
59
  # An importmap specifically meant for Spina
59
60
  self.importmap = Importmap::Map.new
60
-
61
+
61
62
  # Tailwind content
62
- # In order for Tailwind to generate all of the CSS Spina needs,
63
- # it needs to know about every single file in your project
63
+ # In order for Tailwind to generate all of the CSS Spina needs,
64
+ # it needs to know about every single file in your project
64
65
  # that contains any Tailwind class names.
65
66
  # Make sure to add your own glob patterns if you're extending
66
67
  # Spina's UI.
@@ -70,39 +71,41 @@ module Spina
70
71
  "#{Spina::Engine.root}/app/assets/javascripts/**/*.js",
71
72
  "#{Spina::Engine.root}/app/**/application.tailwind.css"]
72
73
 
74
+ self.tailwind_plugins = %w[@tailwindcss/forms @tailwindcss/aspect-ratio @tailwindcss/typography]
75
+
73
76
  # Images that are embedded in the Trix editor are resized to fit
74
77
  # You can optimize this for your website and go for a smaller (or larger) size
75
78
  # Default: 2000x2000px
76
79
  class << self
77
80
  alias_method :config_original, :config
78
-
81
+
79
82
  def config
80
83
  config_obj = self.config_original
81
-
84
+
82
85
  def config_obj.tailwind_purge_content
83
86
  ActiveSupport::Deprecation.warn("config.tailwind_purge_content has been renamed to config.tailwind_content")
84
87
  tailwind_content
85
88
  end
86
-
89
+
87
90
  def config_obj.tailwind_purge_content=(paths)
88
91
  ActiveSupport::Deprecation.warn("config.tailwind_purge_content has been renamed to config.tailwind_content")
89
92
  tailwind_content = paths
90
93
  end
91
-
94
+
92
95
  def config_obj.embedded_image_size=(image_size)
93
96
  if image_size.is_a? String
94
97
  ActiveSupport::Deprecation.warn("Spina embedded_image_size should be set to an array of arguments to be passed to the :resize_to_limit ImageProcessing macro. https://github.com/janko/image_processing/blob/master/doc/minimagick.md#resize_to_limit")
95
98
  end
96
-
99
+
97
100
  self[:embedded_image_size] = image_size
98
101
  end
99
-
102
+
100
103
  config_obj
101
104
  end
102
-
105
+
103
106
  def mounted_at
104
107
  Spina::Engine.routes.find_script_name({})
105
108
  end
106
-
109
+
107
110
  end
108
111
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spina
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bram Jetten
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-06 00:00:00.000000000 Z
11
+ date: 2022-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -948,6 +948,7 @@ files:
948
948
  - app/controllers/spina/admin/move_pages_controller.rb
949
949
  - app/controllers/spina/admin/navigation_items_controller.rb
950
950
  - app/controllers/spina/admin/navigations_controller.rb
951
+ - app/controllers/spina/admin/page_translations_controller.rb
951
952
  - app/controllers/spina/admin/pages_controller.rb
952
953
  - app/controllers/spina/admin/parent_pages_controller.rb
953
954
  - app/controllers/spina/admin/password_resets_controller.rb
@@ -1096,6 +1097,7 @@ files:
1096
1097
  - app/views/spina/user_mailer/forgot_password.html.erb
1097
1098
  - app/views/spina/user_mailer/forgot_password.text.erb
1098
1099
  - config/initializers/importmap.rb
1100
+ - config/initializers/yaml_column_permitted_classes.rb
1099
1101
  - config/locales/TH.yml
1100
1102
  - config/locales/bg.yml
1101
1103
  - config/locales/de.yml
@@ -1177,7 +1179,7 @@ metadata:
1177
1179
  documentation_uri: https://www.spinacms.com/docs
1178
1180
  changelog_uri: https://github.com/SpinaCMS/Spina/blob/main/CHANGELOG.md
1179
1181
  source_code_uri: https://github.com/SpinaCMS/Spina
1180
- post_install_message:
1182
+ post_install_message:
1181
1183
  rdoc_options: []
1182
1184
  require_paths:
1183
1185
  - lib
@@ -1192,8 +1194,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1192
1194
  - !ruby/object:Gem::Version
1193
1195
  version: '0'
1194
1196
  requirements: []
1195
- rubygems_version: 3.3.7
1196
- signing_key:
1197
+ rubygems_version: 3.1.6
1198
+ signing_key:
1197
1199
  specification_version: 4
1198
1200
  summary: Spina
1199
1201
  test_files: []