spina 2.10.0 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of spina might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/components/spina/pages/actions_component.html.erb +7 -0
- data/app/components/spina/pages/translations_component.rb +1 -1
- data/app/components/spina/user_interface/translations_component.rb +1 -1
- data/app/controllers/spina/admin/page_translations_controller.rb +14 -0
- data/app/models/concerns/spina/translated_content.rb +1 -1
- data/app/models/spina/account.rb +11 -1
- data/app/models/spina/page.rb +8 -8
- data/app/views/spina/sitemaps/show.xml.builder +1 -1
- data/config/initializers/yaml_column_permitted_classes.rb +16 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/nl.yml +4 -0
- data/config/routes.rb +3 -2
- data/lib/generators/spina/templates/app/assets/config/spina/tailwind.config.js.tt +2 -4
- data/lib/generators/spina/templates/app/views/demo/shared/_languages.html.erb +2 -2
- data/lib/generators/spina/templates/config/initializers/spina.rb +2 -1
- data/lib/spina/version.rb +1 -1
- data/lib/spina.rb +18 -15
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68c17b8a615a45c86dce79d2e4b32a5f7bc4fdbf8f71d94fbdc2f530a68baa48
|
4
|
+
data.tar.gz: a85f8e9b3a922c1b3de5866d37bab8bdae583c264e35894baa7871b95aa2eaf5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 %>
|
@@ -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.
|
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
|
data/app/models/spina/account.rb
CHANGED
@@ -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
|
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
|
data/app/models/spina/page.rb
CHANGED
@@ -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.
|
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
|
data/config/locales/en.yml
CHANGED
@@ -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:'
|
data/config/locales/nl.yml
CHANGED
@@ -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.
|
96
|
-
get '/:locale/' => 'pages#homepage', constraints: {locale: /#{Spina.
|
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('
|
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.
|
1
|
+
<% if Spina.locales.size > 1 %>
|
2
2
|
<div id="languages">
|
3
|
-
<%= Spina.
|
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 %>
|
data/lib/spina/version.rb
CHANGED
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.
|
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-
|
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.
|
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: []
|