alchemy_cms 6.0.0.pre.rc2 → 6.0.0.pre.rc5

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.

Potentially problematic release.


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

Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +0 -7
  3. data/CHANGELOG.md +37 -0
  4. data/Gemfile +5 -0
  5. data/alchemy_cms.gemspec +2 -2
  6. data/app/assets/javascripts/alchemy/admin.js +0 -1
  7. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
  8. data/app/assets/stylesheets/alchemy/_extends.scss +4 -4
  9. data/app/assets/stylesheets/alchemy/flatpickr.scss +182 -232
  10. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +3 -3
  11. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +7 -7
  12. data/app/controllers/alchemy/admin/base_controller.rb +9 -3
  13. data/app/models/alchemy/attachment.rb +1 -1
  14. data/app/models/alchemy/element.rb +1 -1
  15. data/app/models/alchemy/node.rb +1 -1
  16. data/app/models/alchemy/page.rb +7 -2
  17. data/app/models/alchemy/picture.rb +1 -1
  18. data/app/services/alchemy/tag_validations.rb +21 -0
  19. data/app/views/alchemy/ingredients/_picture_editor.html.erb +2 -2
  20. data/config/brakeman.ignore +25 -5
  21. data/config/routes.rb +0 -1
  22. data/db/migrate/20200226213334_alchemy_four_point_four.rb +30 -30
  23. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +1 -1
  24. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +1 -1
  25. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +1 -1
  26. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +1 -1
  27. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +1 -1
  28. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +1 -1
  29. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +1 -1
  30. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +1 -1
  31. data/db/migrate/20201207131309_create_page_versions.rb +1 -1
  32. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +1 -1
  33. data/lib/alchemy/engine.rb +6 -5
  34. data/lib/alchemy/error_tracking.rb +14 -0
  35. data/lib/alchemy/taggable.rb +11 -4
  36. data/lib/alchemy/upgrader.rb +6 -0
  37. data/lib/alchemy/version.rb +1 -1
  38. data/lib/alchemy_cms.rb +1 -0
  39. data/lib/generators/alchemy/install/install_generator.rb +2 -1
  40. data/lib/tasks/alchemy/upgrade.rake +6 -0
  41. data/package/admin.js +3 -1
  42. data/package/src/datepicker.js +39 -0
  43. data/package.json +2 -1
  44. metadata +24 -22
  45. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +0 -29
@@ -30,7 +30,7 @@ td,th {
30
30
 
31
31
  .mce-object {
32
32
  border: 1px dotted #3a3a3a;
33
- background: #d5d5d5 url(img/object.gif) no-repeat center;
33
+ background: #d5d5d5 url('tinymce/skins/alchemy/fonts/img/object.gif') no-repeat center;
34
34
  }
35
35
 
36
36
  .mce-pagebreak {
@@ -55,7 +55,7 @@ td,th {
55
55
  width: 9px!important;
56
56
  height: 9px!important;
57
57
  border: 1px dotted #3a3a3a;
58
- background: #d5d5d5 url(img/anchor.gif) no-repeat center;
58
+ background: #d5d5d5 url('tinymce/skins/alchemy/fonts/img/anchor.gif') no-repeat center;
59
59
  }
60
60
 
61
61
  .mce-nbsp {
@@ -77,7 +77,7 @@ hr {
77
77
  }
78
78
 
79
79
  .mce-spellchecker-word {
80
- background: url(img/wline.gif) repeat-x bottom left;
80
+ background: url('tinymce/skins/alchemy/fonts/img/wline.gif') repeat-x bottom left;
81
81
  cursor: default;
82
82
  }
83
83
 
@@ -1561,23 +1561,23 @@ i.mce-i-resize {
1561
1561
  opacity: 0.6;
1562
1562
  filter: alpha(opacity=60);
1563
1563
  zoom: 1;
1564
- background: #fff url('img/loader.gif') no-repeat center center;
1564
+ background: #fff url('tinymce/skins/alchemy/fonts/img/loader.gif') no-repeat center center;
1565
1565
  }
1566
1566
 
1567
1567
  @font-face {
1568
1568
  font-family: 'tinymce';
1569
- src: url('fonts/tinymce.woff') format('woff'),
1570
- url('fonts/tinymce.ttf') format('truetype'),
1571
- url('fonts/tinymce.svg#tinymce') format('svg');
1569
+ src: url('tinymce/skins/alchemy/fonts/tinymce.woff') format('woff'),
1570
+ url('tinymce/skins/alchemy/fonts/tinymce.ttf') format('truetype'),
1571
+ url('tinymce/skins/alchemy/fonts/tinymce.svg#tinymce') format('svg');
1572
1572
  font-weight: normal;
1573
1573
  font-style: normal;
1574
1574
  }
1575
1575
 
1576
1576
  @font-face {
1577
1577
  font-family: 'tinymce-small';
1578
- src: url('fonts/tinymce-small.woff') format('woff'),
1579
- url('fonts/tinymce-small.ttf') format('truetype'),
1580
- url('fonts/tinymce-small.svg#tinymce') format('svg');
1578
+ src: url('tinymce/skins/alchemy/fonts/tinymce-small.woff') format('woff'),
1579
+ url('tinymce/skins/alchemy/fonts/tinymce-small.ttf') format('truetype'),
1580
+ url('tinymce/skins/alchemy/fonts/tinymce-small.svg#tinymce') format('svg');
1581
1581
  font-weight: normal;
1582
1582
  font-style: normal;
1583
1583
  }
@@ -40,9 +40,7 @@ module Alchemy
40
40
  def exception_handler(error)
41
41
  exception_logger(error)
42
42
  show_error_notice(error)
43
- if defined?(Airbrake)
44
- notify_airbrake(error) unless Rails.env.development? || Rails.env.test?
45
- end
43
+ notify_error_tracker(error)
46
44
  end
47
45
 
48
46
  # Displays an error notice in the Alchemy backend.
@@ -146,6 +144,14 @@ module Alchemy
146
144
  site
147
145
  end
148
146
  end
147
+
148
+ def notify_error_tracker(exception)
149
+ if ::Alchemy::ErrorTracking.notification_handler.respond_to?(:call)
150
+ ::Alchemy::ErrorTracking.notification_handler.call(exception)
151
+ else
152
+ Rails.logger.warn("To use the Alchemy::ErrorTracking.notification_handler, it must respond to #call.")
153
+ end
154
+ end
149
155
  end
150
156
  end
151
157
  end
@@ -28,7 +28,7 @@ module Alchemy
28
28
  after_assign { |f| write_attribute(:file_mime_type, f.mime_type) }
29
29
  end
30
30
 
31
- stampable stamper_class_name: Alchemy.user_class_name
31
+ stampable stamper_class_name: Alchemy.user_class.name
32
32
 
33
33
  has_many :essence_files, class_name: "Alchemy::EssenceFile", foreign_key: "attachment_id"
34
34
  has_many :contents, through: :essence_files
@@ -57,7 +57,7 @@ module Alchemy
57
57
  #
58
58
  acts_as_list scope: [:page_version_id, :fixed, :parent_element_id]
59
59
 
60
- stampable stamper_class_name: Alchemy.user_class_name
60
+ stampable stamper_class_name: Alchemy.user_class.name
61
61
 
62
62
  has_many :contents, dependent: :destroy, inverse_of: :element
63
63
 
@@ -7,7 +7,7 @@ module Alchemy
7
7
  before_destroy :check_if_related_essence_nodes_present
8
8
 
9
9
  acts_as_nested_set scope: "language_id", touch: true
10
- stampable stamper_class_name: Alchemy.user_class_name
10
+ stampable stamper_class_name: Alchemy.user_class.name
11
11
 
12
12
  belongs_to :language, class_name: "Alchemy::Language"
13
13
  belongs_to :page, class_name: "Alchemy::Page", optional: true, inverse_of: :nodes
@@ -88,7 +88,7 @@ module Alchemy
88
88
 
89
89
  acts_as_nested_set(dependent: :destroy, scope: [:layoutpage, :language_id])
90
90
 
91
- stampable stamper_class_name: Alchemy.user_class_name
91
+ stampable stamper_class_name: Alchemy.user_class.name
92
92
 
93
93
  belongs_to :language
94
94
 
@@ -144,7 +144,7 @@ module Alchemy
144
144
  after_update :create_legacy_url,
145
145
  if: :saved_change_to_urlname?
146
146
 
147
- after_update -> { nodes.update_all(updated_at: Time.current) }
147
+ after_update :touch_nodes
148
148
 
149
149
  # Concerns
150
150
  include PageScopes
@@ -603,5 +603,10 @@ module Alchemy
603
603
  def create_legacy_url
604
604
  legacy_urls.find_or_create_by(urlname: urlname_before_last_save)
605
605
  end
606
+
607
+ def touch_nodes
608
+ ids = node_ids + nodes.flat_map { |n| n.ancestors.pluck(:id) }
609
+ Node.where(id: ids).touch_all
610
+ end
606
611
  end
607
612
  end
@@ -110,7 +110,7 @@ module Alchemy
110
110
  case_sensitive: false,
111
111
  message: Alchemy.t("not a valid image")
112
112
 
113
- stampable stamper_class_name: Alchemy.user_class_name
113
+ stampable stamper_class_name: Alchemy.user_class.name
114
114
 
115
115
  scope :named, ->(name) { where("#{table_name}.name LIKE ?", "%#{name}%") }
116
116
  scope :recent, -> { where("#{table_name}.created_at > ?", Time.current - 24.hours).order(:created_at) }
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class TagValidations
5
+ def self.call(klass)
6
+ new(klass).call
7
+ end
8
+
9
+ def initialize(klass)
10
+ @klass = klass
11
+ end
12
+
13
+ def call
14
+ klass.validates :name, presence: true, uniqueness: { case_sensitive: true }
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :klass
20
+ end
21
+ end
@@ -54,7 +54,7 @@
54
54
  <%= f.hidden_field :link_title, data: { link_title: true }, id: nil %>
55
55
  <%= f.hidden_field :link_class_name, data: { link_class: true }, id: nil %>
56
56
  <%= f.hidden_field :link_target, data: { link_target: true }, id: nil %>
57
- <%= f.hidden_field :crop_from, data: { crop_from: true }, id: nil %>
58
- <%= f.hidden_field :crop_size, data: { crop_size: true }, id: nil %>
57
+ <%= f.hidden_field :crop_from, data: { crop_from: true }, id: picture_editor.form_field_id(:crop_from) %>
58
+ <%= f.hidden_field :crop_size, data: { crop_size: true }, id: picture_editor.form_field_id(:crop_size) %>
59
59
  <% end %>
60
60
  <% end %>
@@ -58,7 +58,7 @@
58
58
  "check_name": "MassAssignment",
59
59
  "message": "Specify exact keys allowed for mass assignment instead of using `permit!` which allows any keys",
60
60
  "file": "app/controllers/alchemy/admin/resources_controller.rb",
61
- "line": 136,
61
+ "line": 209,
62
62
  "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
63
63
  "code": "params.require(resource_handler.namespaced_resource_name).permit!",
64
64
  "render_path": null,
@@ -86,7 +86,7 @@
86
86
  "type": "controller",
87
87
  "class": "Alchemy::Admin::ElementsController",
88
88
  "method": "fold",
89
- "line": 97,
89
+ "line": 102,
90
90
  "file": "app/controllers/alchemy/admin/elements_controller.rb",
91
91
  "rendered": {
92
92
  "name": "alchemy/admin/elements/fold",
@@ -109,7 +109,7 @@
109
109
  "check_name": "MassAssignment",
110
110
  "message": "Specify exact keys allowed for mass assignment instead of using `permit!` which allows any keys",
111
111
  "file": "app/controllers/alchemy/admin/elements_controller.rb",
112
- "line": 150,
112
+ "line": 155,
113
113
  "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
114
114
  "code": "params.fetch(:contents, {}).permit!",
115
115
  "render_path": null,
@@ -122,6 +122,26 @@
122
122
  "confidence": "Medium",
123
123
  "note": "`Alchemy::Content` is a polymorphic association of any kind of model extending `Alchemy::Essence`. Since we can't know the attributes of all potential essences we need to permit all attributes. As this all happens inside the password protected /admin namespace this can be considered a false positive."
124
124
  },
125
+ {
126
+ "warning_type": "Command Injection",
127
+ "warning_code": 14,
128
+ "fingerprint": "6addfcb9d23d2d6f699f2f3542169744ff749dc4d0a97f8ac783ab92593e1d84",
129
+ "check_name": "Execute",
130
+ "message": "Possible command injection",
131
+ "file": "lib/alchemy/upgrader.rb",
132
+ "line": 30,
133
+ "link": "https://brakemanscanner.org/docs/warning_types/command_injection/",
134
+ "code": "`yarn add @alchemy_cms/admin@~#{Alchemy.version}`",
135
+ "render_path": null,
136
+ "location": {
137
+ "type": "method",
138
+ "class": "Alchemy::Upgrader",
139
+ "method": "update_npm_package"
140
+ },
141
+ "user_input": "Alchemy.version",
142
+ "confidence": "Medium",
143
+ "note": "The alchemy version is safe"
144
+ },
125
145
  {
126
146
  "warning_type": "Cross-Site Scripting",
127
147
  "warning_code": 4,
@@ -255,6 +275,6 @@
255
275
  "note": ""
256
276
  }
257
277
  ],
258
- "updated": "2021-06-29 20:56:10 +0200",
259
- "brakeman_version": "5.0.1"
278
+ "updated": "2021-10-26 21:44:59 +0200",
279
+ "brakeman_version": "5.1.1"
260
280
  }
data/config/routes.rb CHANGED
@@ -124,7 +124,6 @@ Alchemy::Engine.routes.draw do
124
124
 
125
125
  resources :messages, only: [:index, :new, :create]
126
126
  resources :elements, only: :show
127
- resources :contents, only: :show
128
127
 
129
128
  namespace :api, defaults: { format: "json" } do
130
129
  resources :contents, only: [:index, :show]
@@ -1,23 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
3
+ class AlchemyFourPointFour < ActiveRecord::Migration[6.0]
4
4
  def up
5
5
  unless table_exists?("alchemy_attachments")
6
- create_table "alchemy_attachments", force: :cascade do |t|
6
+ create_table "alchemy_attachments" do |t|
7
7
  t.string "name"
8
8
  t.string "file_name"
9
9
  t.string "file_mime_type"
10
10
  t.integer "file_size"
11
11
  t.references "creator"
12
12
  t.references "updater"
13
- t.timestamps null: false
13
+ t.timestamps
14
14
  t.string "file_uid"
15
15
  t.index ["file_uid"], name: "index_alchemy_attachments_on_file_uid"
16
16
  end
17
17
  end
18
18
 
19
19
  unless table_exists?("alchemy_contents")
20
- create_table "alchemy_contents", force: :cascade do |t|
20
+ create_table "alchemy_contents" do |t|
21
21
  t.string "name"
22
22
  t.references "essence", null: false, polymorphic: true, index: { unique: true }
23
23
  t.references "element", null: false
@@ -25,14 +25,14 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
25
25
  end
26
26
 
27
27
  unless table_exists?("alchemy_elements")
28
- create_table "alchemy_elements", force: :cascade do |t|
28
+ create_table "alchemy_elements" do |t|
29
29
  t.string "name"
30
30
  t.integer "position"
31
31
  t.references "page", null: false, index: false
32
32
  t.boolean "public", default: true
33
33
  t.boolean "folded", default: false
34
34
  t.boolean "unique", default: false
35
- t.timestamps null: false
35
+ t.timestamps
36
36
  t.references "creator"
37
37
  t.references "updater"
38
38
  t.references "parent_element", index: false
@@ -44,27 +44,27 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
44
44
  end
45
45
 
46
46
  unless table_exists?("alchemy_elements_alchemy_pages")
47
- create_table "alchemy_elements_alchemy_pages", id: false, force: :cascade do |t|
47
+ create_table "alchemy_elements_alchemy_pages", id: false do |t|
48
48
  t.references "element"
49
49
  t.references "page"
50
50
  end
51
51
  end
52
52
 
53
53
  unless table_exists?("alchemy_essence_booleans")
54
- create_table "alchemy_essence_booleans", force: :cascade do |t|
54
+ create_table "alchemy_essence_booleans" do |t|
55
55
  t.boolean "value"
56
56
  t.index ["value"], name: "index_alchemy_essence_booleans_on_value"
57
57
  end
58
58
  end
59
59
 
60
60
  unless table_exists?("alchemy_essence_dates")
61
- create_table "alchemy_essence_dates", force: :cascade do |t|
61
+ create_table "alchemy_essence_dates" do |t|
62
62
  t.datetime "date"
63
63
  end
64
64
  end
65
65
 
66
66
  unless table_exists?("alchemy_essence_files")
67
- create_table "alchemy_essence_files", force: :cascade do |t|
67
+ create_table "alchemy_essence_files" do |t|
68
68
  t.references "attachment"
69
69
  t.string "title"
70
70
  t.string "css_class"
@@ -73,13 +73,13 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
73
73
  end
74
74
 
75
75
  unless table_exists?("alchemy_essence_htmls")
76
- create_table "alchemy_essence_htmls", force: :cascade do |t|
76
+ create_table "alchemy_essence_htmls" do |t|
77
77
  t.text "source"
78
78
  end
79
79
  end
80
80
 
81
81
  unless table_exists?("alchemy_essence_links")
82
- create_table "alchemy_essence_links", force: :cascade do |t|
82
+ create_table "alchemy_essence_links" do |t|
83
83
  t.string "link"
84
84
  t.string "link_title"
85
85
  t.string "link_target"
@@ -88,13 +88,13 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
88
88
  end
89
89
 
90
90
  unless table_exists?("alchemy_essence_pages")
91
- create_table "alchemy_essence_pages", force: :cascade do |t|
91
+ create_table "alchemy_essence_pages" do |t|
92
92
  t.references "page"
93
93
  end
94
94
  end
95
95
 
96
96
  unless table_exists?("alchemy_essence_pictures")
97
- create_table "alchemy_essence_pictures", force: :cascade do |t|
97
+ create_table "alchemy_essence_pictures" do |t|
98
98
  t.references "picture"
99
99
  t.string "caption"
100
100
  t.string "title"
@@ -111,7 +111,7 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
111
111
  end
112
112
 
113
113
  unless table_exists?("alchemy_essence_richtexts")
114
- create_table "alchemy_essence_richtexts", force: :cascade do |t|
114
+ create_table "alchemy_essence_richtexts" do |t|
115
115
  t.text "body"
116
116
  t.text "stripped_body"
117
117
  t.boolean "public"
@@ -119,14 +119,14 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
119
119
  end
120
120
 
121
121
  unless table_exists?("alchemy_essence_selects")
122
- create_table "alchemy_essence_selects", force: :cascade do |t|
122
+ create_table "alchemy_essence_selects" do |t|
123
123
  t.string "value"
124
124
  t.index ["value"], name: "index_alchemy_essence_selects_on_value"
125
125
  end
126
126
  end
127
127
 
128
128
  unless table_exists?("alchemy_essence_texts")
129
- create_table "alchemy_essence_texts", force: :cascade do |t|
129
+ create_table "alchemy_essence_texts" do |t|
130
130
  t.text "body"
131
131
  t.string "link"
132
132
  t.string "link_title"
@@ -137,7 +137,7 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
137
137
  end
138
138
 
139
139
  unless table_exists?("alchemy_folded_pages")
140
- create_table "alchemy_folded_pages", force: :cascade do |t|
140
+ create_table "alchemy_folded_pages" do |t|
141
141
  t.references "page", null: false, index: false
142
142
  t.references "user", null: false, index: false
143
143
  t.boolean "folded", default: false
@@ -146,13 +146,13 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
146
146
  end
147
147
 
148
148
  unless table_exists?("alchemy_languages")
149
- create_table "alchemy_languages", force: :cascade do |t|
149
+ create_table "alchemy_languages" do |t|
150
150
  t.string "name"
151
151
  t.string "language_code"
152
152
  t.string "frontpage_name"
153
153
  t.string "page_layout", default: "intro"
154
154
  t.boolean "public", default: false
155
- t.timestamps null: false
155
+ t.timestamps
156
156
  t.references "creator"
157
157
  t.references "updater"
158
158
  t.boolean "default", default: false
@@ -165,16 +165,16 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
165
165
  end
166
166
 
167
167
  unless table_exists?("alchemy_legacy_page_urls")
168
- create_table "alchemy_legacy_page_urls", force: :cascade do |t|
168
+ create_table "alchemy_legacy_page_urls" do |t|
169
169
  t.string "urlname", null: false
170
170
  t.references "page", null: false
171
- t.timestamps null: false
171
+ t.timestamps
172
172
  t.index ["urlname"], name: "index_alchemy_legacy_page_urls_on_urlname"
173
173
  end
174
174
  end
175
175
 
176
176
  unless table_exists?("alchemy_nodes")
177
- create_table "alchemy_nodes", force: :cascade do |t|
177
+ create_table "alchemy_nodes" do |t|
178
178
  t.string "name"
179
179
  t.string "title"
180
180
  t.string "url"
@@ -189,7 +189,7 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
189
189
  t.references "language", null: false
190
190
  t.references "creator"
191
191
  t.references "updater"
192
- t.timestamps null: false
192
+ t.timestamps
193
193
  t.references "site", null: false
194
194
  t.index ["lft"], name: "index_alchemy_nodes_on_lft"
195
195
  t.index ["rgt"], name: "index_alchemy_nodes_on_rgt"
@@ -197,7 +197,7 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
197
197
  end
198
198
 
199
199
  unless table_exists?("alchemy_pages")
200
- create_table "alchemy_pages", force: :cascade do |t|
200
+ create_table "alchemy_pages" do |t|
201
201
  t.string "name"
202
202
  t.string "urlname"
203
203
  t.string "title"
@@ -217,7 +217,7 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
217
217
  t.boolean "robot_follow", default: true
218
218
  t.boolean "sitemap", default: true
219
219
  t.boolean "layoutpage", default: false
220
- t.timestamps null: false
220
+ t.timestamps
221
221
  t.references "creator"
222
222
  t.references "updater"
223
223
  t.references "language"
@@ -234,12 +234,12 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
234
234
  end
235
235
 
236
236
  unless table_exists?("alchemy_pictures")
237
- create_table "alchemy_pictures", force: :cascade do |t|
237
+ create_table "alchemy_pictures" do |t|
238
238
  t.string "name"
239
239
  t.string "image_file_name"
240
240
  t.integer "image_file_width"
241
241
  t.integer "image_file_height"
242
- t.timestamps null: false
242
+ t.timestamps
243
243
  t.references "creator"
244
244
  t.references "updater"
245
245
  t.string "upload_hash"
@@ -250,10 +250,10 @@ class AlchemyFourPointFour < ActiveRecord::Migration[5.2]
250
250
  end
251
251
 
252
252
  unless table_exists?("alchemy_sites")
253
- create_table "alchemy_sites", force: :cascade do |t|
253
+ create_table "alchemy_sites" do |t|
254
254
  t.string "host"
255
255
  t.string "name"
256
- t.timestamps null: false
256
+ t.timestamps
257
257
  t.boolean "public", default: false
258
258
  t.text "aliases"
259
259
  t.boolean "redirect_to_primary_host"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreateAlchemyEssenceNodes < ActiveRecord::Migration[5.2]
3
+ class CreateAlchemyEssenceNodes < ActiveRecord::Migration[6.0]
4
4
  def change
5
5
  create_table :alchemy_essence_nodes do |t|
6
6
  t.references "node"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- class RemoveSiteIdFromNodes < ActiveRecord::Migration[5.2]
2
+ class RemoveSiteIdFromNodes < ActiveRecord::Migration[6.0]
3
3
  def up
4
4
  remove_foreign_key :alchemy_nodes, :alchemy_sites
5
5
  remove_index :alchemy_nodes, :site_id
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddLanguageIdForeignKeyToAlchemyPages < ActiveRecord::Migration[5.2]
3
+ class AddLanguageIdForeignKeyToAlchemyPages < ActiveRecord::Migration[6.0]
4
4
  def change
5
5
  add_foreign_key :alchemy_pages, :alchemy_languages, column: :language_id
6
6
  change_column_null :alchemy_pages, :language_id, false, Alchemy::Language.default&.id
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- class AddMenuTypeToAlchemyNodes < ActiveRecord::Migration[5.2]
2
+ class AddMenuTypeToAlchemyNodes < ActiveRecord::Migration[6.0]
3
3
  class LocalNode < ActiveRecord::Base
4
4
  self.table_name = :alchemy_nodes
5
5
  acts_as_nested_set scope: :language_id
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- class MakePageLayoutpageNullFalse < ActiveRecord::Migration[5.2]
2
+ class MakePageLayoutpageNullFalse < ActiveRecord::Migration[6.0]
3
3
  def change
4
4
  change_column_null :alchemy_pages, :layoutpage, false, false
5
5
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- class RemoveVisibleFromAlchemyPages < ActiveRecord::Migration[5.2]
2
+ class RemoveVisibleFromAlchemyPages < ActiveRecord::Migration[6.0]
3
3
  class LocalPage < ActiveRecord::Base
4
4
  self.table_name = "alchemy_pages"
5
5
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreateAlchemyPictureThumbs < ActiveRecord::Migration[5.2]
3
+ class CreateAlchemyPictureThumbs < ActiveRecord::Migration[6.0]
4
4
  def up
5
5
  return if table_exists?(:alchemy_picture_thumbs)
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class RemoveTriStateBooleans < ActiveRecord::Migration[5.2]
3
+ class RemoveTriStateBooleans < ActiveRecord::Migration[6.0]
4
4
  def change
5
5
  change_column_null :alchemy_elements, :public, false, false
6
6
  change_column_default :alchemy_elements, :public, true
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreatePageVersions < ActiveRecord::Migration[5.2]
3
+ class CreatePageVersions < ActiveRecord::Migration[6.0]
4
4
  def change
5
5
  create_table :alchemy_page_versions do |t|
6
6
  t.references :page,
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddPageVersionIdToAlchemyElements < ActiveRecord::Migration[5.2]
3
+ class AddPageVersionIdToAlchemyElements < ActiveRecord::Migration[6.0]
4
4
  class LocalPage < ActiveRecord::Base
5
5
  self.table_name = :alchemy_pages
6
6
  has_many :elements, class_name: "LocalElement", inverse_of: :page
@@ -19,11 +19,12 @@ module Alchemy
19
19
  NonStupidDigestAssets.whitelist += [/^tinymce\//]
20
20
  end
21
21
 
22
- # Gutentag downcases all tgas before save.
23
- # We support having tags with uppercase characters.
24
- # The Gutentag search is case insensitive.
25
- initializer "alchemy.gutentag_normalizer" do
22
+ # Gutentag downcases all tags before save
23
+ # and Gutentag validations are not case sensitive.
24
+ # But we support having tags with uppercase characters.
25
+ config.to_prepare do
26
26
  Gutentag.normaliser = ->(value) { value.to_s }
27
+ Gutentag.tag_validations = Alchemy::TagValidations
27
28
  end
28
29
 
29
30
  # Custom Ransack sort arrows
@@ -40,7 +41,7 @@ module Alchemy
40
41
  if Alchemy.user_class
41
42
  ActiveSupport.on_load(:active_record) do
42
43
  Alchemy.user_class.model_stamper
43
- Alchemy.user_class.stampable(stamper_class_name: Alchemy.user_class_name)
44
+ Alchemy.user_class.stampable(stamper_class_name: Alchemy.user_class.name)
44
45
  end
45
46
  end
46
47
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ module ErrorTracking
5
+ class BaseHandler
6
+ def self.call(exception)
7
+ # implement your own notification method
8
+ end
9
+ end
10
+
11
+ mattr_accessor :notification_handler
12
+ @@notification_handler = BaseHandler
13
+ end
14
+ end
@@ -22,13 +22,20 @@ module Alchemy
22
22
  end
23
23
 
24
24
  module ClassMethods
25
- # Find all records matching all of the given tags.
26
- # Separate multiple tags by comma.
27
- def tagged_with(names)
25
+ def tagged_with(names = [], **args)
28
26
  if names.is_a? String
29
27
  names = names.split(/,\s*/)
30
28
  end
31
- super(names: names, match: :all)
29
+
30
+ unless args[:match]
31
+ args.merge!(match: :all)
32
+ end
33
+
34
+ if names.any?
35
+ args.merge!(names: names)
36
+ end
37
+
38
+ super(args)
32
39
  end
33
40
 
34
41
  # Returns all unique tags