diff --git a/app/models/post.rb b/app/models/post.rb index 64f02929a..21620e6cd 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -679,8 +679,8 @@ class Post < ActiveRecord::Base end def filter_metatags(tags) - @pre_metatags, tags = tags.partition {|x| x =~ /\A(?:rating|parent|-parent|source):/i} - @post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|newpool|fav|-fav|child|-favgroup|favgroup):/i} + @pre_metatags, tags = tags.partition {|x| x =~ /\A(?:rating|parent|-parent|source|-?locked):/i} + @post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|newpool|fav|-fav|child|-favgroup|favgroup|upvote|downvote):/i} apply_pre_metatags return tags end @@ -719,6 +719,9 @@ class Post < ActiveRecord::Base when /^-fav:(.+)$/i remove_favorite!(CurrentUser.user) + when /^(up|down)vote:(.+)$/i + vote!($1) + when /^child:(.+)$/i child = Post.find($1) child.parent_id = id @@ -773,6 +776,15 @@ class Post < ActiveRecord::Base when /^rating:([qse])/i self.rating = $1.downcase + + when /^(-?)locked:notes?$/i + assign_attributes({ is_note_locked: $1 != "-" }, as: CurrentUser.role) + + when /^(-?)locked:rating$/i + assign_attributes({ is_rating_locked: $1 != "-" }, as: CurrentUser.role) + + when /^(-?)locked:status$/i + assign_attributes({ is_status_locked: $1 != "-" }, as: CurrentUser.role) end end end @@ -1021,12 +1033,16 @@ class Post < ActiveRecord::Base end def vote!(score) - if can_be_voted_by?(CurrentUser.user) - vote = PostVote.create(:post_id => id, :score => score) - self.score += vote.score - else + unless CurrentUser.is_voter? + raise PostVote::Error.new("You do not have permission to vote") + end + + unless can_be_voted_by?(CurrentUser.user) raise PostVote::Error.new("You have already voted for this post") end + + PostVote.create(:post_id => id, :score => score) + reload # PostVote.create modifies our score. Reload to get the new score. end def unvote! diff --git a/test/factories/user.rb b/test/factories/user.rb index 186318fa4..0bfa09fd5 100644 --- a/test/factories/user.rb +++ b/test/factories/user.rb @@ -7,6 +7,7 @@ FactoryGirl.define do default_image_size "large" base_upload_limit 10 level 20 + created_at {Time.now} last_logged_in_at {Time.now} favorite_count 0 bit_prefs 0 diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index 79ead2b17..994bd563f 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -731,6 +731,119 @@ class PostTest < ActiveSupport::TestCase assert_equal(14901720, @post.pixiv_id) end end + + context "of" do + setup do + @builder = FactoryGirl.build(:builder_user) + end + + context "locked:notes" do + context "by a member" do + should "not lock the notes" do + @post.update(:tag_string => "locked:notes") + assert_equal(false, @post.is_note_locked) + end + end + + context "by a builder" do + should "lock/unlock the notes" do + CurrentUser.scoped(@builder) do + @post.update(:tag_string => "locked:notes") + assert_equal(true, @post.is_note_locked) + + @post.update(:tag_string => "-locked:notes") + assert_equal(false, @post.is_note_locked) + end + end + end + end + + context "locked:rating" do + context "by a member" do + should "not lock the rating" do + @post.update(:tag_string => "locked:rating") + assert_equal(false, @post.is_rating_locked) + end + end + + context "by a builder" do + should "lock/unlock the rating" do + CurrentUser.scoped(@builder) do + @post.update(:tag_string => "locked:rating") + assert_equal(true, @post.is_rating_locked) + + @post.update(:tag_string => "-locked:rating") + assert_equal(false, @post.is_rating_locked) + end + end + end + end + + context "locked:status" do + context "by a member" do + should "not lock the status" do + @post.update(:tag_string => "locked:status") + assert_equal(false, @post.is_status_locked) + end + end + + context "by an admin" do + should "lock/unlock the status" do + CurrentUser.scoped(FactoryGirl.build(:admin_user)) do + @post.update(:tag_string => "locked:status") + assert_equal(true, @post.is_status_locked) + + @post.update(:tag_string => "-locked:status") + assert_equal(false, @post.is_status_locked) + end + end + end + end + end + + context "of" do + setup do + @gold = FactoryGirl.build(:gold_user) + end + + context "upvote:self or downvote:self" do + context "by a member" do + should "not upvote the post" do + assert_raises PostVote::Error do + @post.update(:tag_string => "upvote:self") + end + + assert_equal(0, @post.score) + end + + should "not downvote the post" do + assert_raises PostVote::Error do + @post.update(:tag_string => "downvote:self") + end + + assert_equal(0, @post.score) + end + end + + context "by a gold user" do + should "upvote the post" do + CurrentUser.scoped(FactoryGirl.create(:gold_user)) do + @post.update(:tag_string => "tag1 tag2 upvote:self") + assert_equal(false, @post.errors.any?) + assert_equal(1, @post.score) + end + end + + should "downvote the post" do + CurrentUser.scoped(FactoryGirl.create(:gold_user)) do + @post.update(:tag_string => "tag1 tag2 downvote:self") + assert_equal(false, @post.errors.any?) + assert_equal(-1, @post.score) + end + end + end + end + end end context "tagged with a negated tag" do @@ -1664,8 +1777,16 @@ class PostTest < ActiveSupport::TestCase end end + should "not allow members to vote" do + @user = FactoryGirl.create(:user) + @post = FactoryGirl.create(:post) + CurrentUser.scoped(@user) do + assert_raises(PostVote::Error) { @post.vote!("up") } + end + end + should "not allow duplicate votes" do - user = FactoryGirl.create(:user) + user = FactoryGirl.create(:gold_user) post = FactoryGirl.create(:post) CurrentUser.scoped(user, "127.0.0.1") do assert_nothing_raised {post.vote!("up")} @@ -1677,7 +1798,7 @@ class PostTest < ActiveSupport::TestCase end should "allow undoing of votes" do - user = FactoryGirl.create(:user) + user = FactoryGirl.create(:gold_user) post = FactoryGirl.create(:post) # We deliberately don't call post.reload until the end to verify that