radiant-comments-extension 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +1 -1
  2. data/CHANGELOG +6 -0
  3. data/Gemfile +4 -0
  4. data/README.rdoc +9 -0
  5. data/Rakefile +0 -16
  6. data/TODO +0 -1
  7. data/app/controllers/admin/comments_controller.rb +1 -5
  8. data/app/controllers/comments_controller.rb +46 -4
  9. data/app/models/akismet_spam_filter.rb +1 -1
  10. data/app/models/comment.rb +7 -1
  11. data/app/models/mollom_spam_filter.rb +17 -7
  12. data/app/models/spam_filter.rb +1 -0
  13. data/app/views/admin/comments/_comment.html.haml +26 -0
  14. data/app/views/admin/comments/_form.html.haml +37 -0
  15. data/app/views/admin/comments/edit.html.haml +4 -0
  16. data/app/views/admin/comments/index.html.haml +57 -0
  17. data/app/views/admin/pages/{_comments.rhtml → _comments.html.haml} +0 -0
  18. data/app/views/admin/pages/_edit_comments_enabled.html.haml +7 -0
  19. data/app/views/admin/pages/_index_head_view_comments.html.haml +1 -0
  20. data/app/views/admin/pages/_index_view_comments.html.haml +7 -0
  21. data/comments_extension.rb +11 -27
  22. data/config/locales/en.yml +26 -0
  23. data/config/locales/nl.yml +26 -0
  24. data/config/routes.rb +16 -0
  25. data/db/migrate/002_create_snippets.rb +4 -4
  26. data/lib/comment_page_extensions.rb +15 -2
  27. data/lib/comment_tags.rb +55 -0
  28. data/lib/radiant-comments-extension.rb +2 -0
  29. data/lib/radiant-comments-extension/version.rb +3 -0
  30. data/public/stylesheets/admin/comments.css +21 -29
  31. data/radiant-comments-extension.gemspec +8 -117
  32. data/spec/controllers/page_postback_spec.rb +2 -1
  33. data/spec/models/comment_spec.rb +7 -23
  34. data/spec/models/mollom_spam_filter_spec.rb +5 -0
  35. metadata +30 -32
  36. data/VERSION +0 -1
  37. data/app/views/admin/comments/_comment.rhtml +0 -34
  38. data/app/views/admin/comments/_form.rhtml +0 -36
  39. data/app/views/admin/comments/edit.rhtml +0 -5
  40. data/app/views/admin/comments/index.rhtml +0 -55
  41. data/app/views/admin/pages/_edit_comments_enabled.rhtml +0 -8
  42. data/app/views/admin/pages/_index_head_view_comments.rhtml +0 -1
  43. data/app/views/admin/pages/_index_view_comments.rhtml +0 -11
  44. data/app/views/comments/_comment.rhtml +0 -1
  45. data/app/views/comments/_form.rhtml +0 -23
  46. data/app/views/comments/_new.rhtml +0 -5
  47. data/lib/mollom.rb +0 -246
data/.gitignore CHANGED
@@ -1,3 +1,3 @@
1
1
  .DS_Store
2
2
  .svn
3
- pkg/*
3
+ *.gem
data/CHANGELOG CHANGED
@@ -1,5 +1,11 @@
1
1
  = Git
2
2
 
3
+ = 0.0.7
4
+
5
+ * Updated to use of the Mollom gem i.o. local copy [Benny Degezelle]
6
+ * Updated to use mollom to it's full potential (show CAPTCHA when unsure) [Benny Degezelle]
7
+ * Added r:comments:spam_message which only expands if a posted comment is thought to be spam [Benny Degezelle]
8
+
3
9
  = 0.0.6
4
10
 
5
11
  * Added spam_answer_tag for simple spam protection or CAPTCHA
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in comments-gem.gemspec
4
+ gemspec
data/README.rdoc CHANGED
@@ -15,6 +15,7 @@ If you want to contribute features or fixes please write your specs and code and
15
15
  * Requires will_paginate Rails plugin (http://github.com/mislav/will_paginate/tree/master)
16
16
  * Requires fastercsv 1.2.3 or greater.
17
17
  * Requires sanitize 1.0.8 or greater.
18
+ * Requires mollom 0.2.2 or greater.
18
19
 
19
20
  == Installation
20
21
 
@@ -24,6 +25,14 @@ To install Comments, run:
24
25
 
25
26
  This _WILL_ delete any snippets named 'comment', 'comments' and 'comment_form' if these exist.
26
27
 
28
+ If you are upgrading from a previous version with out the sanitizer run:
29
+
30
+ rake radiant:extensions:comments:initialize
31
+
32
+ or if you want to clean up your initializer for the sanitize gem run:
33
+
34
+ rake radiant:extensions:comments:forced_initialize
35
+
27
36
  == More Help
28
37
 
29
38
  See the included HELP docs here or read them in your Radiant interface with the Help extension installed.
data/Rakefile CHANGED
@@ -1,19 +1,3 @@
1
- begin
2
- require 'jeweler'
3
- Jeweler::Tasks.new do |gem|
4
- gem.name = "radiant-comments-extension"
5
- gem.summary = %Q{Comments Extension for Radiant CMS}
6
- gem.description = %Q{Adds blog-like comment functionality to Radiant.}
7
- gem.email = "jim@saturnflyer.com"
8
- gem.homepage = "http://github.com/saturnflyer/radiant-comments-extension"
9
- gem.authors = ['Jim Gay', 'Ryan Heneise', 'Sean Cribbs','John Muhl', 'Sven Schwyn', 'Gerrit Kaiser', 'Stephen Lombardo', 'Benny Degezelle', 'Frank Louwers', 'Michael Hale', 'Nathaniel Talbott', 'John Croisant', 'Jon Leighton', 'Witter Cheng', 'Keith Bingman']
10
- gem.add_development_dependency "radiant"
11
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
12
- end
13
- rescue LoadError
14
- puts "Jeweler (or a dependency) not available. This is only required if you plan to package dashboard as a gem."
15
- end
16
-
17
1
  # Determine where the RSpec plugin is by loading the boot
18
2
  unless defined? RADIANT_ROOT
19
3
  ENV["RAILS_ENV"] = "test"
data/TODO CHANGED
@@ -3,4 +3,3 @@
3
3
  * Write better specs.
4
4
  * Move tests to specs.
5
5
  * Add user notification message when a comment is posted.
6
- * captcha mollom implementation
@@ -114,11 +114,7 @@ class Admin::CommentsController < ApplicationController
114
114
  end
115
115
 
116
116
  def clear_cache
117
- if defined?(ResponseCache)
118
- ResponseCache.instance.clear
119
- else
120
- Radiant::Cache.clear
121
- end
117
+ Radiant::Cache.clear
122
118
  end
123
119
 
124
120
  def clear_single_page_cache(comment)
@@ -24,13 +24,42 @@ class CommentsController < ApplicationController
24
24
  end
25
25
  end
26
26
 
27
- flash[:selected_comment] = comment.id
28
- redirect_to "#{@page.url}comments#comment-#{comment.id}"
27
+ if comment.approved?
28
+ redirect_to "#{@page.url}comments#comment-#{comment.id}"
29
+ elsif Comment.spam_filter == MollomSpamFilter && MollomSpamFilter.mollom_response(comment).to_s == 'unsure'
30
+ set_up_page_with_captcha(comment)
31
+ render :text => @page.render and return
32
+ else
33
+ @page.posted_comment_is_spam = true
34
+ #comment.destroy
35
+ render :text => @page.render
36
+ end
29
37
  rescue ActiveRecord::RecordInvalid
38
+ if comment.errors.on(:spam_answer)
39
+ @page.posted_comment_is_spam = true
40
+ end
30
41
  @page.last_comment = comment
31
42
  render :text => @page.render
32
- # rescue Comments::MollomUnsure
33
- #flash, en render :text => @page.render
43
+ rescue SpamFilter::Spam
44
+ @page.posted_comment_is_spam = true
45
+ #comment.destroy
46
+ render :text => @page.render
47
+ end
48
+
49
+ def solve_captcha
50
+ comment = Comment.find_by_mollom_id(params[:comment_mollom_id])
51
+ answer = params[:captcha_answer]
52
+ mollom = Comment.spam_filter.mollom
53
+ if mollom.valid_captcha? :session_id => comment.mollom_id, :solution => answer
54
+ comment.approve!
55
+ redirect_to "#{@page.url}comments#comment-#{comment.id}"
56
+ else
57
+ set_up_page_with_captcha(comment)
58
+ render :text => @page.render
59
+ end
60
+ rescue Mollom::Error # when you don't provide 'correct' or 'incorrect' in mollom developer mode
61
+ set_up_page_with_captcha(comment)
62
+ render :text => @page.render
34
63
  end
35
64
 
36
65
  private
@@ -55,5 +84,18 @@ class CommentsController < ApplicationController
55
84
  end
56
85
  end
57
86
  end
87
+
88
+ def set_up_page_with_captcha(comment)
89
+ mollom = Comment.spam_filter.mollom
90
+ if comment.mollom_id.nil?
91
+ captcha = mollom.image_captcha
92
+ comment.update_attribute(:mollom_id, captcha['session_id'])
93
+ else
94
+ captcha = mollom.image_captcha(:session_id => comment.mollom_id)
95
+ end
96
+ @page.last_comment = comment
97
+ @page.captcha_url = captcha['url']
98
+ @page.comment_mollom_id = @page.captcha_url[/\/([a-z0-9]*).png/, 1]
99
+ end
58
100
 
59
101
  end
@@ -10,7 +10,7 @@ class AkismetSpamFilter < SpamFilter
10
10
 
11
11
  def approved?(comment)
12
12
  (akismet.valid? && ham?(comment)) || raise(SpamFilter::Spam)
13
- rescue
13
+ rescue StandardError, TimeoutError
14
14
  # Spam and anything raised by Net::HTTP, e.g. Errno, Timeout stuff
15
15
  false
16
16
  end
@@ -1,4 +1,5 @@
1
1
  require 'digest/md5'
2
+ require 'sanitize'
2
3
  class Comment < ActiveRecord::Base
3
4
  belongs_to :page, :counter_cache => true
4
5
 
@@ -35,8 +36,12 @@ class Comment < ActiveRecord::Base
35
36
  self.referrer = request.env['HTTP_REFERER']
36
37
  end
37
38
 
39
+ def is_ham?
40
+ spam_filter.valid?(self)
41
+ end
42
+
38
43
  def auto_approve?
39
- Radiant::Config['comments.auto_approve'] == "true" && spam_filter.approved?(self)
44
+ Radiant::Config['comments.auto_approve'] == "true" && is_ham?
40
45
  end
41
46
 
42
47
  def unapproved?
@@ -75,6 +80,7 @@ class Comment < ActiveRecord::Base
75
80
 
76
81
  def auto_approve
77
82
  self.approved_at = Time.now if auto_approve?
83
+ true
78
84
  end
79
85
 
80
86
  def apply_filter
@@ -8,9 +8,14 @@ class MollomSpamFilter < SpamFilter
8
8
  !Radiant::Config['comments.mollom_publickey'].blank?
9
9
  end
10
10
 
11
+ def valid?(comment)
12
+ approved?(comment)
13
+ rescue SpamFilter::Unsure
14
+ end
15
+
11
16
  def approved?(comment)
12
17
  (mollom.key_ok? && ham?(comment)) || raise(SpamFilter::Spam)
13
- rescue Mollom::Error, SpamFilter::Spam
18
+ rescue Mollom::Error, SpamFilter::Spam, TimeoutError
14
19
  false
15
20
  end
16
21
 
@@ -32,19 +37,24 @@ class MollomSpamFilter < SpamFilter
32
37
  end
33
38
  end
34
39
 
35
- private
36
- def ham?(comment)
37
- response = mollom.check_content(
40
+ def mollom_response(comment)
41
+ mollom.check_content(
38
42
  :author_name => comment.author, # author name
39
43
  :author_mail => comment.author_email, # author email
40
44
  :author_url => comment.author_url, # author url
41
- :post_body => comment.content # comment text
45
+ :post_body => comment.content, # comment text
46
+ :author_ip => comment.author_ip
42
47
  )
43
- comment.mollom_id = response.session_id
48
+ end
49
+
50
+ private
51
+
52
+ def ham?(comment)
53
+ response = mollom_response(comment)
44
54
  save_mollom_servers
45
55
  response.ham?
46
56
  end
47
-
57
+
48
58
  def save_mollom_servers
49
59
  Rails.cache.write('MOLLOM_SERVER_CACHE', mollom.server_list.to_yaml) if mollom.key_ok?
50
60
  rescue Mollom::Error #TODO: something with this error...
@@ -40,4 +40,5 @@ class SpamFilter
40
40
  end
41
41
 
42
42
  class Spam < ::StandardError; end
43
+ class Unsure < ::StandardError; end
43
44
  end
@@ -0,0 +1,26 @@
1
+ %tr{:id => dom_id(comment), :class => "comment comment-#{comment.ap_status}"}
2
+ %td.content{:title => comment.content.size >= 70 ? t('click_to_toggle') : "" }
3
+ %blockquote.short= escape_once(truncate(comment.content, :length => 70))
4
+ - if comment.content.size >= 70
5
+ %blockquote.expanded{:style => "display:none"}
6
+ = escape_once(comment.content)
7
+ %td.date-column
8
+ = comment.created_at.strftime("%b %e, %Y at %I:%M%p")
9
+ %td.author-column
10
+ = escape_once(comment.author)
11
+ - unless comment.author_email.blank?
12
+ = mail_to(comment.author_email, image_tag("admin/email.png"))
13
+ - unless comment.author_url.blank?
14
+ = link_to(image_tag("admin/link.png"), comment.author_url)
15
+ - unless @page
16
+ %td.page-column
17
+ = link_to truncate(comment.page.title, :length => 40), comment.page.url, :class => 'view-page'
18
+ = link_to image_tag("admin/page_white_edit.png"), edit_admin_page_path(comment.page), :title => t('edit_page')
19
+ %td.controls-column
20
+ - if comment.approved?
21
+ = link_to(image_tag('admin/error.png'), unapprove_admin_comment_path(comment), :method => :put, :title => t('unapprove_comment'))
22
+ - else
23
+ = link_to(image_tag('admin/accept.png'), approve_admin_comment_path(comment), :title => t('approve_comment'), :method => :put)
24
+
25
+ = link_to image_tag("admin/delete.png"), admin_comment_path(comment), :method => :delete, :confirm => t('are_you_sure_you_want_to_delete_this_comment'), :title => t('delete_comment')
26
+ = link_to image_tag("admin/comment_edit.png"), edit_admin_comment_path(comment), :title => t('edit_comment')
@@ -0,0 +1,37 @@
1
+ - if Comment.spam_filter == SimpleSpamFilter
2
+ %div{:style => "display:none"}
3
+ = f.hidden_field :spam_answer, :value => "hemidemisemiquaver"
4
+ = f.hidden_field :valid_spam_answer, :value => Digest::MD5.hexdigest("hemidemisemiquaver")
5
+
6
+ #comment_form_container.form-area
7
+ .set
8
+ %p.title
9
+ = f.label :author, t('author')
10
+ = f.text_field :author
11
+ %p
12
+ = f.label :author_url, t('url')
13
+ = f.text_field :author_url
14
+ %p
15
+ = f.label :author_email, t('email')
16
+ = f.text_field :author_email
17
+ %p
18
+ %label{:for => "comment_content"}= t('comment')
19
+ %br/
20
+ = f.text_area :content, :rows => 10, :cols => 72, :class => "textarea"
21
+ %p
22
+ %label{:for => "comment_filter_id"}= t('filter')
23
+ = f.select :filter_id, [['<none>', '']] + TextFilter.descendants.map { |s| s.filter_name }.sort
24
+ %p
25
+ Referred by:
26
+ = f.object.referrer
27
+ %p
28
+ Browser:
29
+ = f.object.user_agent
30
+ %p
31
+ Author's IP Address:
32
+ = f.object.author_ip
33
+
34
+ %p.buttons
35
+ = save_model_button(@comment)
36
+ = t('or')
37
+ = link_to t('cancel'), :back
@@ -0,0 +1,4 @@
1
+ %h1= "#{t('edit_comment_on')} #{escape_once(@comment.page.title)}"
2
+
3
+ - form_for [:admin, @comment] do |f|
4
+ = render :partial => "form", :locals => {:f => f}
@@ -0,0 +1,57 @@
1
+ - content_for :page_scripts do
2
+ :plain
3
+ document.observe('dom:loaded', function(){
4
+ Event.addBehavior({
5
+ 'tr.comment td.content': function(event){
6
+ $(this).observe('click', function(event){
7
+ if($(this).down('blockquote.expanded')){
8
+ $(this).down('blockquote.expanded').toggle();
9
+ $(this).down('blockquote.short').toggle();
10
+ }
11
+ event.stop();
12
+ });
13
+ }
14
+ });
15
+ });
16
+
17
+ - include_stylesheet 'admin/comments'
18
+
19
+ .outset
20
+ #filters
21
+ %ul.comment-nav
22
+ - if @page
23
+ %li
24
+ = "#{@page.comments.count.to_s} #{t("comment_states.#{params[:status]}")} " if params[:status]
25
+ = "#{pluralize(@page.comments.count, 'Comment')} on #{link_to @page.title, edit_admin_page_path(@page)}"
26
+ %li.all
27
+ = link_or_span_unless_current(t('comment_states.all'), :status => 'all', :page_id => params[:page_id])
28
+ %li.approved
29
+ = link_or_span_unless_current(t('comment_states.approved'), :status => "approved", :page_id => params[:page_id])
30
+ %li.unapproved
31
+ = link_or_span_unless_current(t('comment_states.unapproved'), :status => "unapproved", :page_id => params[:page_id])
32
+
33
+
34
+ #comments_table
35
+ %table#comments.index
36
+ %thead
37
+ %tr
38
+ %th= t('content')
39
+ %th= t('date_string')
40
+ %th= t('author')
41
+ - unless @page
42
+ %th= t('page')
43
+ %th= t('actions')
44
+ %tbody
45
+ = render(:partial => "comment", :collection => @comments) || %Q[<tr><td class="note" colspan="#{@page ? 4 : 5}">No comments</td></tr>]
46
+ %p
47
+ %small.notice
48
+ = Comment.spam_filter.message
49
+
50
+
51
+ #actions
52
+ = will_paginate @comments
53
+ %ul
54
+ %li
55
+ = link_to "#{image('table_save')} #{t('download_csv')}", :format => :csv
56
+ %li
57
+ = link_to "#{image('comments_delete')} #{t('delete_unapproved')}", destroy_unapproved_admin_comments_url, :class => 'delete-unapproved', :method => :delete, :confirm => 'Is it OK to delete ALL Unapproved Comments?'
@@ -0,0 +1,7 @@
1
+ %p{:style => "clear:left"}
2
+ %label{:for => "page_enable_comments"}
3
+ = check_box "page", "enable_comments"
4
+ = t('allow_comments_on_page')
5
+ - unless @page.new_record? or @page.comments_count < 1
6
+ %small
7
+ = link_to t('currently_x_view_comments', :count => @page.comments_count), admin_page_comments_path(:page_id => @page.id)
@@ -0,0 +1 @@
1
+ %th.comments= t('comments')
@@ -0,0 +1,7 @@
1
+ %td.comment_link
2
+ - if page.respond_to?('enable_comments')
3
+ %small
4
+ - if page.enable_comments
5
+ = link_to "#{page.comments_count} comments", admin_page_comments_path(:page_id => page.id)
6
+ - else
7
+ = link_to "Enable", admin_page_enable_comments_path(:page_id => page.id), :method => :put
@@ -1,28 +1,15 @@
1
+ require File.expand_path("../lib/radiant-comments-extension/version", __FILE__)
1
2
  class CommentsExtension < Radiant::Extension
2
- version "#{File.read(File.expand_path(File.dirname(__FILE__)) + '/VERSION')}"
3
+ version RadiantCommentsExtension::VERSION
3
4
  description "Adds blog-like comments and comment functionality to pages."
4
5
  url "http://github.com/saturnflyer/radiant-comments"
5
-
6
- define_routes do |map|
7
- map.namespace :admin do |admin|
8
- admin.connect 'comments/:status', :controller => 'comments', :status => 'unapproved', :conditions => { :method => :get }, :requirements => { :status => /all|unapproved|approved/ }
9
- admin.connect 'comments/:status.:format', :controller => 'comments', :status => /all|approved|unapproved/, :conditions => { :method => :get }
10
- admin.resources :comments, :member => { :remove => :get, :approve => :put, :unapprove => :put }, :collection => {:destroy_unapproved => :delete}
11
- admin.page_enable_comments '/pages/:page_id/comments/enable', :controller => 'comments', :action => 'enable', :conditions => {:method => :put}
12
- end
13
- map.with_options(:controller => 'admin/comments') do |comments|
14
- comments.connect 'admin/pages/:page_id/comments/:status', :status => /all|approved|unapproved/, :conditions => { :method => :get }
15
- comments.connect 'admin/pages/:page_id/comments/:status.:format', :status => /all|approved|unapproved/, :conditions => { :method => :get }
16
- comments.admin_page_comments 'admin/pages/:page_id/comments/:action'
17
- comments.admin_page_comment 'admin/pages/:page_id/comments/:id/:action'
18
- end
19
- # This needs to be last, otherwise it hoses the admin routes.
20
- map.resources :comments, :name_prefix => "page_", :path_prefix => "*url", :controller => "comments"
6
+
7
+ extension_config do |config|
8
+ config.gem 'sanitize'
9
+ config.gem 'mollom'
21
10
  end
22
11
 
23
12
  def activate
24
- require 'sanitize'
25
-
26
13
  Dir["#{File.dirname(__FILE__)}/app/models/*_filter.rb"].each do |file|
27
14
  require file
28
15
  end
@@ -37,14 +24,11 @@ class CommentsExtension < Radiant::Extension
37
24
  admin.page.index.add :sitemap_head, "index_head_view_comments"
38
25
  admin.page.index.add :node, "index_view_comments"
39
26
  end
40
-
41
- if self.respond_to? :tab
42
- tab "Content" do
43
- add_item('Comments', '/admin/comments')
44
- end
45
- else
46
- admin.tabs.add "Comments", "/admin/comments", :visibility => [:all]
47
- end
27
+
28
+ tab "Content" do
29
+ add_item("Comments", "/admin/comments")
30
+ end.
31
+
48
32
  require "fastercsv"
49
33
 
50
34
  ActiveRecord::Base.class_eval do