diff --git a/app/models/post.rb b/app/models/post.rb index c20116d2a..579d0e098 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -32,7 +32,8 @@ class Post < ActiveRecord::Base validate :validate_parent_does_not_have_a_parent attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :as => [:member] - attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :is_rating_locked, :is_note_locked, :as => [:admin, :moderator] + attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :is_rating_locked, :is_note_locked, :as => [:moderator] + attr_accessible :source, :rating, :tag_string, :old_tag_string, :last_noted_at, :parent_id, :is_rating_locked, :is_note_locked, :is_status_locked, :as => [:admin] scope :pending, where(["is_pending = ?", true]) scope :pending_or_flagged, where(["(is_pending = ? OR is_flagged = ?)", true, true]) scope :undeleted, where(["is_deleted = ?", false]) @@ -271,10 +272,14 @@ class Post < ActiveRecord::Base module ApprovalMethods def is_approvable? - (is_pending? || is_flagged? || is_deleted?) && approver_id != CurrentUser.id + !is_status_locked? && (is_pending? || is_flagged? || is_deleted?) && approver_id != CurrentUser.id end def flag!(reason) + if is_status_locked? + raise PostFlag::Error.new("Post is locked and cannot be flagged") + end + flag = flags.create(:reason => reason) if flag.errors.any? @@ -285,6 +290,10 @@ class Post < ActiveRecord::Base end def appeal!(reason) + if is_status_locked? + raise PostAppeal::Error.new("Post is locked and cannot be appealed") + end + appeal = appeals.create(:reason => reason) if appeal.errors.any? @@ -293,6 +302,16 @@ class Post < ActiveRecord::Base end def approve! + if is_status_locked? + errors.add(:is_status_locked, "; post cannot be approved") + raise ApprovalError.new("Post is locked and cannot be approved") + end + + if uploader_id == CurrentUser.id + errors.add(:base, "You cannot approve a post you uploaded") + raise ApprovalError.new("You cannot approve a post you uploaded") + end + if approver_id == CurrentUser.id errors.add(:approver, "have already approved this post") raise ApprovalError.new("You have previously approved this post and cannot approve it again") @@ -922,11 +941,21 @@ class Post < ActiveRecord::Base module DeletionMethods def annihilate! + if is_status_locked? + self.errors.add(:is_status_locked, "; cannot delete post") + return false + end + delete! destroy end def delete! + if is_status_locked? + self.errors.add(:is_status_locked, "; cannot delete post") + return false + end + Post.transaction do give_favorites_to_parent update_children_on_destroy @@ -940,6 +969,11 @@ class Post < ActiveRecord::Base end def undelete! + if is_status_locked? + self.errors.add(:is_status_locked, "; cannot undelete post") + return false + end + update_column(:is_deleted, false) tag_array.each {|x| expire_cache(x)} update_parent_on_save diff --git a/app/views/posts/partials/show/_edit.html.erb b/app/views/posts/partials/show/_edit.html.erb index 706fda4e9..73b48dd76 100644 --- a/app/views/posts/partials/show/_edit.html.erb +++ b/app/views/posts/partials/show/_edit.html.erb @@ -26,7 +26,7 @@ <% end %> - <% if CurrentUser.user.is_privileged? %> + <% if CurrentUser.is_privileged? %>
<%= f.label :blank, "Lock" %> @@ -35,7 +35,12 @@ <%= f.label :is_note_locked, "Notes" %> <%= f.check_box :is_rating_locked %> - <%= f.label :is_rating_locked, "Rating" %> + <%= f.label :is_rating_locked, "Rating" %> + + <% if CurrentUser.is_admin? %> + <%= f.check_box :is_status_locked %> + <%= f.label :is_status_locked, "Status" %> + <% end %>
<% end %> diff --git a/db/development_structure.sql b/db/development_structure.sql index 83e5406d6..9a4750b3e 100644 --- a/db/development_structure.sql +++ b/db/development_structure.sql @@ -2319,6 +2319,7 @@ CREATE TABLE posts ( rating character(1) DEFAULT 'q'::bpchar NOT NULL, is_note_locked boolean DEFAULT false NOT NULL, is_rating_locked boolean DEFAULT false NOT NULL, + is_status_locked boolean DEFAULT false NOT NULL, is_pending boolean DEFAULT false NOT NULL, is_flagged boolean DEFAULT false NOT NULL, is_deleted boolean DEFAULT false NOT NULL, diff --git a/db/migrate/20100204214746_create_posts.rb b/db/migrate/20100204214746_create_posts.rb index e0b2b8208..6ad6c8cd4 100644 --- a/db/migrate/20100204214746_create_posts.rb +++ b/db/migrate/20100204214746_create_posts.rb @@ -13,6 +13,7 @@ class CreatePosts < ActiveRecord::Migration # Statuses t.column :is_note_locked, :boolean, :null => false, :default => false t.column :is_rating_locked, :boolean, :null => false, :default => false + t.column :is_status_locked, :boolean, :null => false, :default => false t.column :is_pending, :boolean, :null => false, :default => false t.column :is_flagged, :boolean, :null => false, :default => false t.column :is_deleted, :boolean, :null => false, :default => false diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index eac99a32f..84fb9537c 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -17,15 +17,40 @@ class PostTest < ActiveSupport::TestCase context "Annihilating a post" do setup do @post = Factory.create(:post) - @post.annihilate! + end + + context "that is status locked" do + setup do + @post.update_attributes({:is_status_locked => true}, :as => :admin) + end + + should "not destroy the record" do + @post.annihilate! + assert_equal(1, Post.where("id = ?", @post.id).count) + end end should "destroy the record" do + @post.annihilate! + assert_equal([], @post.errors.full_messages) assert_equal(0, Post.where("id = ?", @post.id).count) end end context "Deleting a post" do + context "that is status locked" do + setup do + @post = Factory.create(:post) + @post.update_attributes({:is_status_locked => true}, :as => :admin) + end + + should "fail" do + @post.delete! + assert_equal(["Is status locked ; cannot delete post"], @post.errors.full_messages) + assert_equal(1, Post.where("id = ?", @post.id).count) + end + end + should "update the fast count" do post = Factory.create(:post, :tag_string => "aaa") assert_equal(1, Post.fast_count) @@ -156,6 +181,24 @@ class PostTest < ActiveSupport::TestCase @post = Factory.create(:post, :is_deleted => true) end + context "that is status locked" do + setup do + @post.update_attributes({:is_status_locked => true}, :as => :admin) + end + + should "not allow undeletion" do + @post.undelete! + assert_equal(["Is status locked ; cannot undelete post"], @post.errors.full_messages) + assert_equal(true, @post.is_deleted?) + end + end + + should "be undeleted" do + @post.undelete! + @post.reload + assert_equal(false, @post.is_deleted?) + end + should "be appealed" do assert_difference("PostAppeal.count", 1) do @post.appeal!("xxx") @@ -192,14 +235,43 @@ class PostTest < ActiveSupport::TestCase assert_equal(post.approver_id, CurrentUser.id) end + context "that was uploaded by person X" do + setup do + @post = Factory.create(:post) + @post.flag!("reason") + end + + should "not allow person X to approve that post" do + assert_raises(Post::ApprovalError) do + CurrentUser.scoped(@post.uploader, "127.0.0.1") do + @post.approve! + end + end + + assert_equal(["You cannot approve a post you uploaded"], @post.errors.full_messages) + end + end + context "that was previously approved by person X" do + setup do + @user = Factory.create(:janitor_user, :name => "xxx") + @user2 = Factory.create(:janitor_user, :name => "yyy") + @post = Factory.create(:post, :approver_id => @user.id) + @post.flag!("bad") + end + should "not allow person X to reapprove that post" do - user = Factory.create(:janitor_user, :name => "xxx") - post = Factory.create(:post, :approver_id => user.id) - post.flag!("bad") - CurrentUser.scoped(user, "127.0.0.1") do + CurrentUser.scoped(@user, "127.0.0.1") do assert_raises(Post::ApprovalError) do - post.approve! + @post.approve! + end + end + end + + should "allow person Y to approve the post" do + CurrentUser.scoped(@user2, "127.0.0.1") do + assert_nothing_raised do + @post.approve! end end end @@ -217,6 +289,31 @@ class PostTest < ActiveSupport::TestCase end end end + + context "A status locked post" do + setup do + @post = Factory.create(:post) + @post.update_attributes({:is_status_locked => true}, :as => :admin) + end + + should "not allow new flags" do + assert_raises(PostFlag::Error) do + @post.flag!("wrong") + end + end + + should "not allow new appeals" do + assert_raises(PostAppeal::Error) do + @post.appeal!("wrong") + end + end + + should "not allow approval" do + assert_raises(Post::ApprovalError) do + @post.approve! + end + end + end end context "Tagging:" do @@ -670,7 +767,7 @@ class PostTest < ActiveSupport::TestCase post = Factory.create(:post) CurrentUser.scoped(user, "127.0.0.1") do assert_nothing_raised {post.vote!("up")} - assert_raise(PostVote::Error) {post.vote!("up")} + assert_raises(PostVote::Error) {post.vote!("up")} post.reload assert_equal(1, PostVote.count) assert_equal(1, post.score)