publify_core 9.2.6 → 9.2.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of publify_core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/app/assets/javascripts/check_password.js +9 -0
- data/app/assets/javascripts/publify.js +1 -0
- data/app/controllers/admin/content_controller.rb +5 -5
- data/app/controllers/articles_controller.rb +4 -1
- data/app/controllers/comments_controller.rb +2 -7
- data/app/models/article.rb +2 -2
- data/app/models/comment.rb +9 -1
- data/app/models/feedback.rb +8 -7
- data/app/models/trackback.rb +5 -1
- data/app/uploaders/resource_uploader.rb +14 -16
- data/app/views/admin/feedback/article.html.erb +5 -4
- data/app/views/admin/feedback/index.html.erb +1 -0
- data/app/views/articles/_password_form.html.erb +2 -4
- data/app/views/articles/search.html.erb +3 -1
- data/app/views/devise/mailer/reset_password_instructions.html.erb +2 -2
- data/app/views/devise/passwords/edit.html.erb +1 -1
- data/app/views/devise/passwords/new.html.erb +1 -1
- data/config/routes.rb +2 -1
- data/lib/publify_core/version.rb +1 -1
- data/lib/spam_protection.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72e8560336bbbbfd2c517840b744e34509782d0f4d6db7cde5ee607230770b65
|
4
|
+
data.tar.gz: 886335b6900c26cfc579bf4197304b0e30cb8eedbe4c362a5394d153cb746487
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
+
});
|
@@ -58,9 +58,9 @@ class Admin::ContentController < Admin::BaseController
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def update
|
61
|
-
|
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
|
-
|
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
|
-
@
|
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
|
-
|
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:
|
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
|
data/app/models/article.rb
CHANGED
@@ -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
|
data/app/models/comment.rb
CHANGED
@@ -38,7 +38,7 @@ class Comment < Feedback
|
|
38
38
|
really_send_notifications
|
39
39
|
end
|
40
40
|
|
41
|
-
|
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
|
data/app/models/feedback.rb
CHANGED
@@ -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
|
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
|
-
|
204
|
+
check_article_closed_for_feedback
|
204
205
|
end
|
205
206
|
|
206
207
|
def send_notifications
|
data/app/models/trackback.rb
CHANGED
@@ -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(:
|
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, :
|
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
|
41
|
-
if image?
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
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
|
-
|
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
|
-
<%=
|
9
|
+
<%= hidden_field_tag 'article_id', @article.id %>
|
10
|
+
|
10
11
|
<%= render 'button', position: 'top' %>
|
11
12
|
|
12
13
|
<br class='clear' />
|
@@ -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
|
-
<%=
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
<%=
|
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
|
-
<%=
|
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
|
data/lib/publify_core/version.rb
CHANGED
data/lib/spam_protection.rb
CHANGED
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.
|
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-
|
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
|