From af9b27358c7869c27e7a2d9f5d9b8317fafa939f Mon Sep 17 00:00:00 2001
From: Robin Ward <robin.ward@gmail.com>
Date: Fri, 5 Apr 2013 13:59:00 -0400
Subject: [PATCH] If an admin or moderator edits a visitor's post, the
 restrictions should be based on the *editors* access rights, not the original
 poster.

---
 app/models/post.rb                   | 17 +++++++++++++---
 app/models/site_content.rb           |  3 ++-
 lib/post_revisor.rb                  |  2 ++
 spec/components/post_revisor_spec.rb | 30 ++++++++++++++++++++++++++--
 spec/fabricators/user_fabricator.rb  |  6 ++++++
 5 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/app/models/post.rb b/app/models/post.rb
index 0ba7ffb74..3ada5aef1 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -123,8 +123,19 @@ class Post < ActiveRecord::Base
     total
   end
 
+  # Sometimes the post is being edited by someone else, for example, a mod.
+  # If that's the case, they should not be bound by the original poster's
+  # restrictions, for example on not posting images.
+  def acting_user
+    @acting_user || user
+  end
+
+  def acting_user=(pu)
+    @acting_user = pu
+  end
+
   def max_mention_validator
-    if user.present? && user.has_trust_level?(:basic)
+    if acting_user.present? && acting_user.has_trust_level?(:basic)
       errors.add(:base, I18n.t(:too_many_mentions, count: SiteSetting.max_mentions_per_post)) if raw_mentions.size > SiteSetting.max_mentions_per_post
     else
       errors.add(:base, I18n.t(:too_many_mentions_visitor, count: SiteSetting.visitor_max_mentions_per_post)) if raw_mentions.size > SiteSetting.visitor_max_mentions_per_post
@@ -132,12 +143,12 @@ class Post < ActiveRecord::Base
   end
 
   def max_images_validator
-    return if user.present? && user.has_trust_level?(:basic)
+    return if acting_user.present? && acting_user.has_trust_level?(:basic)
     errors.add(:base, I18n.t(:too_many_images, count: SiteSetting.visitor_max_images)) if image_count > SiteSetting.visitor_max_images
   end
 
   def max_links_validator
-    return if user.present? && user.has_trust_level?(:basic)
+    return if acting_user.present? && acting_user.has_trust_level?(:basic)
     errors.add(:base, I18n.t(:too_many_links, count: SiteSetting.visitor_max_links)) if link_count > SiteSetting.visitor_max_links
   end
 
diff --git a/app/models/site_content.rb b/app/models/site_content.rb
index 5eea42d34..47dd86c88 100644
--- a/app/models/site_content.rb
+++ b/app/models/site_content.rb
@@ -4,7 +4,8 @@ require_dependency 'site_content_class_methods'
 class SiteContent < ActiveRecord::Base
   extend SiteContentClassMethods
 
-  set_primary_key :content_type
+  self.primary_key = 'content_type'
+
   validates_presence_of :content
 
   def self.formats
diff --git a/lib/post_revisor.rb b/lib/post_revisor.rb
index 862daaa3a..aed1a9dda 100644
--- a/lib/post_revisor.rb
+++ b/lib/post_revisor.rb
@@ -10,6 +10,8 @@ class PostRevisor
   def revise!(user, new_raw, opts = {})
     @user, @new_raw, @opts = user, new_raw, opts
     return false if not should_revise?
+
+    @post.acting_user = @user
     revise_post
     update_category_description
     post_process_post
diff --git a/spec/components/post_revisor_spec.rb b/spec/components/post_revisor_spec.rb
index 4430e3e9c..b3994865f 100644
--- a/spec/components/post_revisor_spec.rb
+++ b/spec/components/post_revisor_spec.rb
@@ -4,10 +4,10 @@ require 'post_revisor'
 describe PostRevisor do
 
   let(:topic) { Fabricate(:topic) }
-  let(:post_args) { {user: topic.user, topic: topic} }
+  let(:visitor) { Fabricate(:visitor) }
+  let(:post_args) { {user: visitor, topic: topic} }
 
   context 'revise' do
-
     let(:post) { Fabricate(:post, post_args) }
     let(:first_version_at) { post.last_version_at }
 
@@ -186,6 +186,32 @@ describe PostRevisor do
       end
     end
 
+    describe "admin editing a visitor's post" do
+      let(:changed_by) { Fabricate(:admin) }
+
+      before do
+        SiteSetting.stubs(:too_many_images).returns(0)
+        subject.revise!(changed_by, "So, post them here!\nhttp://i.imgur.com/FGg7Vzu.gif")
+      end
+
+      it "allows an admin to insert images into a visitor's post" do
+        post.errors.should be_blank
+      end
+    end
+
+    describe "visitor editing their own post" do
+      before do
+        SiteSetting.stubs(:too_many_images).returns(0)
+        subject.revise!(post.user, "So, post them here!\nhttp://i.imgur.com/FGg7Vzu.gif")
+      end
+
+      it "allows an admin to insert images into a visitor's post" do
+        post.errors.should be_present
+      end
+
+    end
+
+
     describe 'with a new body' do
       let(:changed_by) { Fabricate(:coding_horror) }
       let!(:result) { subject.revise!(changed_by, 'updated body') }
diff --git a/spec/fabricators/user_fabricator.rb b/spec/fabricators/user_fabricator.rb
index 323b6c7b9..7951f9617 100644
--- a/spec/fabricators/user_fabricator.rb
+++ b/spec/fabricators/user_fabricator.rb
@@ -49,3 +49,9 @@ Fabricator(:another_admin, from: :user) do
   admin true
 end
 
+Fabricator(:visitor, from: :user) do
+  name 'Newbie Newperson'
+  username 'newbie'
+  email 'newbie@new.com'
+  trust_level TrustLevel.levels[:visitor]
+end