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 +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: []
|