publify_core 9.2.6 → 9.2.9

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 publify_core might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da6da95f7716a807eb81fc3c6684945b4afeb75dae12256d6e8e0341dacc8108
4
- data.tar.gz: 16590e78cb4f249017cad7df86fb72fb6ebfc90eb3c9a55d9fdac017a708c203
3
+ metadata.gz: 72e8560336bbbbfd2c517840b744e34509782d0f4d6db7cde5ee607230770b65
4
+ data.tar.gz: 886335b6900c26cfc579bf4197304b0e30cb8eedbe4c362a5394d153cb746487
5
5
  SHA512:
6
- metadata.gz: 9ba6b4fb3315f76bb3ffba8f2c423fe4d0a2a57fda992a1bf0ce92df49dad52f78e0d72955a75dfcac58ab2a693ecc46f419dbb1c59678ceb86ed8f0c280140d
7
- data.tar.gz: 4704c65615d660a2a10f8827970710baeb5438917adeb8d37e7a10a1534626b08b1a45049486398163739c23929d5629d71a41198d28dd46572e5aa3d6260f4d
6
+ metadata.gz: 695ae9d70e7cb24e7b10b4c2efaaff9d13e32bdcde17e5fcc4be6aab288f5d8d1a0b74465b54f79dd28cf1fbc55a3c7f0e80d02074e8706e863bbba15ddd0368
7
+ data.tar.gz: 3044549f33cfe4db50562be0d0441e3fc952b433181eefc861768cbeb3072b11be25780c40b2977572ce69d38df945af520c09343d294920eccdf17198b9d143
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.2.9 / 2022-05-22
4
+
5
+ * Fix admin article access control [#1065](https://github.com/publify/publify/pull/1065)
6
+ * Refuse html files as resources even if declared to be plain text [#1066](https://github.com/publify/publify/pull/1066)
7
+
8
+ ## 9.2.8 / 2022-05-14
9
+
10
+ * Fix password protected article reveal [#1049](https://github.com/publify/publify/pull/1049)
11
+ * Disallow comments on draft articles [#1048](https://github.com/publify/publify/pull/1048)
12
+ * Clean up Feedback validation [#1051](https://github.com/publify/publify/pull/1051)
13
+ * Disallow images in comments [#1054](https://github.com/publify/publify/pull/1054)
14
+ * Fix password reset process [#1055](https://github.com/publify/publify/pull/1055)
15
+ * Hide bodies of password-protected articles in search results [#1057](https://github.com/publify/publify/pull/1057)
16
+ * Provide correct `article_id` input in bulkops form [#1058](https://github.com/publify/publify/pull/1058)
17
+ * Do not create article meta description for password-protected articles [#1061](https://github.com/publify/publify/pull/1061)
18
+
19
+ ## 9.2.7 / 2022-02-07
20
+
21
+ * Fix setting the article password from the Admin [#1044](https://github.com/publify/publify/pull/1044)
22
+
3
23
  ## 9.2.6 / 2022-01-07
4
24
 
5
25
  * Add documentation about use of the media library
@@ -0,0 +1,9 @@
1
+ // Show and hide spinners on Ajax requests.
2
+ $(document).ready(function() {
3
+ $('form.check_password').on('ajax:complete',
4
+ function(evt, xhr, stat) {
5
+ var form = evt.currentTarget;
6
+ var elem = document.getElementById(form.dataset["update"]);
7
+ elem.outerHTML = xhr.responseText;
8
+ })
9
+ });
@@ -7,5 +7,6 @@
7
7
  //= require jquery_ujs
8
8
  //= require lightbox
9
9
  //= require observe
10
+ //= require check_password
10
11
  //
11
12
  //= require_self
@@ -58,9 +58,9 @@ class Admin::ContentController < Admin::BaseController
58
58
  end
59
59
 
60
60
  def update
61
- return unless access_granted?(params[:id])
61
+ id = params[:id]
62
+ return unless access_granted?(id)
62
63
 
63
- id = params[:article][:id] || params[:id]
64
64
  @article = Article.find(id)
65
65
 
66
66
  if params[:article][:draft]
@@ -101,6 +101,7 @@ class Admin::ContentController < Admin::BaseController
101
101
  return false unless request.xhr?
102
102
 
103
103
  id = params[:article][:id] || params[:id]
104
+ return if id && !access_granted?(id)
104
105
 
105
106
  article_factory = Article::Factory.new(this_blog, current_user)
106
107
  @article = article_factory.get_or_build_from(id)
@@ -131,7 +132,7 @@ class Admin::ContentController < Admin::BaseController
131
132
  end
132
133
  end
133
134
 
134
- protected
135
+ private
135
136
 
136
137
  def fetch_fresh_or_existing_draft_for_article
137
138
  return unless @article.published? && @article.id
@@ -146,8 +147,6 @@ class Admin::ContentController < Admin::BaseController
146
147
 
147
148
  attr_accessor :resources, :resource
148
149
 
149
- private
150
-
151
150
  def load_resources
152
151
  @post_types = PostType.all
153
152
  @macros = TextFilterPlugin.macro_filters
@@ -180,6 +179,7 @@ class Admin::ContentController < Admin::BaseController
180
179
  :body_and_extended,
181
180
  :draft,
182
181
  :extended,
182
+ :password,
183
183
  :permalink,
184
184
  :published_at,
185
185
  :text_filter_name,
@@ -166,7 +166,10 @@ class ArticlesController < ContentController
166
166
  format.html do
167
167
  @comment = Comment.new
168
168
  @page_title = this_blog.article_title_template.to_title(@article, this_blog, params)
169
- @description = this_blog.article_desc_template.to_title(@article, this_blog, params)
169
+ if @article.password.blank?
170
+ @description = this_blog.article_desc_template.
171
+ to_title(@article, this_blog, params)
172
+ end
170
173
 
171
174
  @keywords = @article.tags.map(&:name).join(", ")
172
175
  render "articles/#{@article.post_type}"
@@ -7,11 +7,6 @@ class CommentsController < BaseController
7
7
  options = new_comment_defaults.merge comment_params.to_h
8
8
  @comment = @article.add_comment(options)
9
9
 
10
- unless current_user.nil? || session[:user_id].nil?
11
- # maybe useless, but who knows ?
12
- @comment.user_id = current_user.id if current_user.id == session[:user_id]
13
- end
14
-
15
10
  remember_author_info_for @comment
16
11
 
17
12
  partial = "/articles/comment_failed"
@@ -33,7 +28,7 @@ class CommentsController < BaseController
33
28
  @comment = @article.comments.build(comment_params)
34
29
  end
35
30
 
36
- protected
31
+ private
37
32
 
38
33
  def recaptcha_ok_for?(comment)
39
34
  use_recaptcha = comment.blog.use_recaptcha
@@ -43,7 +38,7 @@ class CommentsController < BaseController
43
38
  def new_comment_defaults
44
39
  { ip: request.remote_ip,
45
40
  author: "Anonymous",
46
- user: @current_user,
41
+ user: current_user,
47
42
  user_agent: request.env["HTTP_USER_AGENT"],
48
43
  referrer: request.env["HTTP_REFERER"],
49
44
  permalink: @article.permalink_url }.stringify_keys
@@ -204,7 +204,7 @@ class Article < Content
204
204
  end
205
205
 
206
206
  def comments_closed?
207
- !(allow_comments? && in_feedback_window?)
207
+ !(allow_comments? && published? && in_feedback_window?)
208
208
  end
209
209
 
210
210
  def html_urls
@@ -216,7 +216,7 @@ class Article < Content
216
216
  end
217
217
 
218
218
  def pings_closed?
219
- !(allow_pings? && in_feedback_window?)
219
+ !(allow_pings? && published? && in_feedback_window?)
220
220
  end
221
221
 
222
222
  # check if time to comment is open or not
@@ -38,7 +38,7 @@ class Comment < Feedback
38
38
  really_send_notifications
39
39
  end
40
40
 
41
- protected
41
+ private
42
42
 
43
43
  def article_allows_feedback?
44
44
  return true if article.allow_comments?
@@ -47,6 +47,14 @@ class Comment < Feedback
47
47
  false
48
48
  end
49
49
 
50
+ def blog_allows_feedback?
51
+ true
52
+ end
53
+
54
+ def check_article_closed_for_feedback
55
+ errors.add(:article, "Comment are closed") if article.comments_closed?
56
+ end
57
+
50
58
  def originator
51
59
  author
52
60
  end
@@ -11,11 +11,12 @@ class Feedback < ApplicationRecord
11
11
  include PublifyGuid
12
12
  include ContentBase
13
13
 
14
+ validate :article_allows_this_feedback, on: :create
14
15
  validate :feedback_not_closed, on: :create
15
16
  validates :article, presence: true
16
17
 
17
18
  before_save :correct_url, :classify_content
18
- before_create :create_guid, :article_allows_this_feedback
19
+ before_create :create_guid
19
20
 
20
21
  # TODO: Rename so it doesn't sound like only approved ham
21
22
  scope :ham, -> { where(state: %w(presumed_ham ham)) }
@@ -66,6 +67,10 @@ class Feedback < ApplicationRecord
66
67
  page(page).per(per_page)
67
68
  end
68
69
 
70
+ def self.allowed_tags
71
+ @allowed_tags ||= Rails::Html::SafeListSanitizer.allowed_tags - ["img"]
72
+ end
73
+
69
74
  def parent
70
75
  article
71
76
  end
@@ -85,7 +90,7 @@ class Feedback < ApplicationRecord
85
90
 
86
91
  def html_postprocess(_field, html)
87
92
  helper = ContentTextHelpers.new
88
- helper.sanitize(helper.auto_link(html))
93
+ helper.sanitize(helper.auto_link(html), tags: self.class.allowed_tags)
89
94
  end
90
95
 
91
96
  def correct_url
@@ -98,10 +103,6 @@ class Feedback < ApplicationRecord
98
103
  article && blog_allows_feedback? && article_allows_feedback?
99
104
  end
100
105
 
101
- def blog_allows_feedback?
102
- true
103
- end
104
-
105
106
  def akismet_options
106
107
  { type: self.class.to_s.downcase,
107
108
  author: originator,
@@ -200,7 +201,7 @@ class Feedback < ApplicationRecord
200
201
  end
201
202
 
202
203
  def feedback_not_closed
203
- errors.add(:article_id, "Comment are closed") if article.comments_closed?
204
+ check_article_closed_for_feedback
204
205
  end
205
206
 
206
207
  def send_notifications
@@ -24,10 +24,14 @@ class Trackback < Feedback
24
24
  def blog_allows_feedback?
25
25
  return true unless blog.global_pings_disable
26
26
 
27
- errors.add(:article, "Pings are disabled")
27
+ errors.add(:base, "Pings are disabled")
28
28
  false
29
29
  end
30
30
 
31
+ def check_article_closed_for_feedback
32
+ errors.add(:article, "Pings are closed") if article.pings_closed?
33
+ end
34
+
31
35
  def originator
32
36
  blog_name
33
37
  end
@@ -4,7 +4,7 @@ require "marcel"
4
4
 
5
5
  class ResourceUploader < CarrierWave::Uploader::Base
6
6
  include CarrierWave::MiniMagick
7
- before :cache, :check_image_content_type!
7
+ before :cache, :check_content_type!
8
8
 
9
9
  def content_type_allowlist
10
10
  [%r{image/}, %r{audio/}, %r{video/}, "text/plain"]
@@ -37,26 +37,24 @@ class ResourceUploader < CarrierWave::Uploader::Base
37
37
  content_type&.include?("image")
38
38
  end
39
39
 
40
- def check_image_content_type!(new_file)
41
- if image?(new_file)
42
- magic_type = mime_magic_content_type(new_file)
43
- if magic_type != new_file.content_type
44
- raise CarrierWave::IntegrityError, "has MIME type mismatch"
45
- end
40
+ def check_content_type!(new_file)
41
+ detected_type = if image? new_file
42
+ file_content_content_type(new_file)
43
+ else
44
+ file_content_type(new_file)
45
+ end
46
+ if detected_type != new_file.content_type
47
+ raise CarrierWave::IntegrityError, "has MIME type mismatch"
46
48
  end
47
49
  end
48
50
 
49
51
  private
50
52
 
51
- # NOTE: This method was adapted from MagicMimeBlacklist#extract_content_type
52
- # from CarrierWave 1.0.0 and SanitizedFile#mime_magic_content_type from CarrierWave 0.11.2
53
- def mime_magic_content_type(new_file)
54
- content_type = nil
55
-
56
- File.open(new_file.path) do |fd|
57
- content_type = Marcel::MimeType.for(fd)
58
- end
53
+ def file_content_content_type(new_file)
54
+ Marcel::MimeType.for Pathname.new(new_file.path)
55
+ end
59
56
 
60
- content_type
57
+ def file_content_type(new_file)
58
+ Marcel::MimeType.for Pathname.new(new_file.path), name: new_file.filename
61
59
  end
62
60
  end
@@ -1,12 +1,13 @@
1
1
  <% content_for :page_heading do %>
2
- <h2 class="page-title">
3
- <%= t('.comments_for_html', title: @article.title) %>
4
- </h2>
2
+ <h2 class="page-title">
3
+ <%= t('.comments_for_html', title: @article.title) %>
4
+ </h2>
5
5
  <% end %>
6
6
 
7
7
  <%= form_tag({ action: 'bulkops' }, { class: 'form-inline' }) do %>
8
8
 
9
- <%= hidden_field 'article_id', @article.id %>
9
+ <%= hidden_field_tag 'article_id', @article.id %>
10
+
10
11
  <%= render 'button', position: 'top' %>
11
12
 
12
13
  <br class='clear' />
@@ -40,6 +40,7 @@
40
40
  </td>
41
41
  </tr>
42
42
  <% end %>
43
+
43
44
  <% @feedback.each do |comment| %>
44
45
  <%= render 'feedback', comment: comment %>
45
46
  <% end %>
@@ -1,10 +1,8 @@
1
1
  <div id='content-<%= article.id %>'>
2
2
  <p>This post is password protected. Please fill in your password or login to view the content</p>
3
- <%= form_for(article, remote: true,
4
- url: { controller: 'articles', action: 'check_password' },
5
- update: "content-#{article.id}") do |f| %>
3
+ <%= form_tag(check_password_url, remote: true, class: "check_password", data: { update: "content-#{article.id}" }) do %>
6
4
  <%= password_field(:article, :password) %>
7
- <input type='hidden' name='article[id]' value='<%= article.id %>' />
5
+ <%= hidden_field(:article, :id) %>
8
6
  <%= submit_tag(t('.submit') + '!', name: 'check_password') %>
9
7
  <% end %>
10
8
  </div>
@@ -1,7 +1,9 @@
1
1
  <% for article in @articles %>
2
2
  <div class="post">
3
3
  <h2><%= link_to_permalink article, article.title %></h2>
4
- <%= article.html(:body).gsub(%r{</?[^>]*>}, '').slice(0..300) %>...
4
+ <% if article.password.blank? %>
5
+ <%= article.html(:body).gsub(%r{</?[^>]*>}, '').slice(0..300) %>...
6
+ <% end %>
5
7
  </div>
6
8
  <% end %>
7
9
 
@@ -1,6 +1,6 @@
1
1
  <% require 'devise/version' %>
2
- <%# TODO: Link user to blog so we can do @resource.blog
3
- blog = Blog.first %>
2
+ <%# TODO: Link user to blog so we can do @resource.blog %>
3
+ <% blog = Blog.first %>
4
4
  <p><%= t('.greeting', recipient: @resource.login, default: "Hello #{@resource.login}!") %></p>
5
5
 
6
6
  <p><%= t('.instruction', default: 'Someone has requested a link to change your password, and you can do this through the link below.') %></p>
@@ -3,7 +3,7 @@
3
3
  <% end %>
4
4
 
5
5
  <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
6
- <%= devise_error_messages! %>
6
+ <%= render "devise/shared/error_messages", resource: resource %>
7
7
  <fieldset>
8
8
  <%= f.hidden_field :reset_password_token %>
9
9
 
@@ -3,7 +3,7 @@
3
3
  <% end %>
4
4
 
5
5
  <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
6
- <%= devise_error_messages! %>
6
+ <%= render "devise/shared/error_messages", resource: resource %>
7
7
  <fieldset>
8
8
 
9
9
  <div class='form-group'>
data/config/routes.rb CHANGED
@@ -36,10 +36,11 @@ Rails.application.routes.draw do
36
36
  get "/pages/*name", to: "articles#view_page", format: false
37
37
  get "previews(/:id)", to: "articles#preview", format: false
38
38
  get "previews_pages(/:id)", to: "articles#preview_page", format: false
39
- get "check_password", to: "articles#check_password", format: false
40
39
  get "articles/markup_help/:id", to: "articles#markup_help", format: false
41
40
  get "articles/tag", to: "articles#tag", format: false
42
41
 
42
+ post "check_password", to: "articles#check_password", format: false
43
+
43
44
  # SetupController
44
45
  get "/setup", to: "setup#index", format: false
45
46
  post "/setup", to: "setup#create", format: false
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PublifyCore
4
- VERSION = "9.2.6"
4
+ VERSION = "9.2.9"
5
5
  end
@@ -31,7 +31,7 @@ class SpamProtection
31
31
  end
32
32
  end
33
33
 
34
- protected
34
+ private
35
35
 
36
36
  def scan_ip(ip_address)
37
37
  logger.info("[SP] Scanning IP #{ip_address}")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: publify_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.2.6
4
+ version: 9.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matijs van Zuijlen
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2022-01-07 00:00:00.000000000 Z
14
+ date: 2022-05-22 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: aasm
@@ -579,6 +579,7 @@ files:
579
579
  - app/assets/javascripts/bootstrap/modal.js
580
580
  - app/assets/javascripts/bootstrap/tab.js
581
581
  - app/assets/javascripts/bootstrap/transition.js
582
+ - app/assets/javascripts/check_password.js
582
583
  - app/assets/javascripts/cookies.js
583
584
  - app/assets/javascripts/datetimepicker.js
584
585
  - app/assets/javascripts/lang/da_DK.js