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)