keep track of post approvals to prevent approval cycles

This commit is contained in:
Albert Yi
2016-10-31 17:51:44 -07:00
parent 03fd48c989
commit 2dbb869188
7 changed files with 159 additions and 4 deletions

View File

@@ -15,6 +15,7 @@ class DailyMaintenance
TagAlias.update_cached_post_counts_for_all TagAlias.update_cached_post_counts_for_all
PostDisapproval.dmail_messages! PostDisapproval.dmail_messages!
Tag.clean_up_negative_post_counts! Tag.clean_up_negative_post_counts!
PostApproval.prune!
SuperVoter.init! SuperVoter.init!
AntiVoter.init! AntiVoter.init!
end end

View File

@@ -274,7 +274,7 @@ class Post < ActiveRecord::Base
module ApprovalMethods module ApprovalMethods
def is_approvable? def is_approvable?
!is_status_locked? && (is_pending? || is_flagged? || is_deleted?) && approver_id != CurrentUser.id !is_status_locked? && (is_pending? || is_flagged? || is_deleted?) && !PostApproval.approved?(CurrentUser.id, id)
end end
def flag!(reason, options = {}) def flag!(reason, options = {})
@@ -314,7 +314,7 @@ class Post < ActiveRecord::Base
raise ApprovalError.new("You cannot approve a post you uploaded") raise ApprovalError.new("You cannot approve a post you uploaded")
end end
if approver_id == CurrentUser.id if approver_id == CurrentUser.id || PostApproval.approved?(CurrentUser.id, id)
errors.add(:approver, "have already approved this post") errors.add(:approver, "have already approved this post")
raise ApprovalError.new("You have previously approved this post and cannot approve it again") raise ApprovalError.new("You have previously approved this post and cannot approve it again")
end end
@@ -324,6 +324,9 @@ class Post < ActiveRecord::Base
self.is_pending = false self.is_pending = false
self.is_deleted = false self.is_deleted = false
self.approver_id = CurrentUser.id self.approver_id = CurrentUser.id
PostApproval.create(user_id: CurrentUser.id, post_id: id)
save! save!
end end
@@ -1362,7 +1365,7 @@ class Post < ActiveRecord::Base
end end
if !CurrentUser.is_admin? if !CurrentUser.is_admin?
if approver_id == CurrentUser.id if approver_id == CurrentUser.id || PostApproval.approved?(CurrentUser.id, id)
raise ApprovalError.new("You have previously approved this post and cannot undelete it") raise ApprovalError.new("You have previously approved this post and cannot undelete it")
elsif uploader_id == CurrentUser.id elsif uploader_id == CurrentUser.id
raise ApprovalError.new("You cannot undelete a post you uploaded") raise ApprovalError.new("You cannot undelete a post you uploaded")

View File

@@ -0,0 +1,12 @@
class PostApproval < ActiveRecord::Base
belongs_to :user
belongs_to :post
def self.prune!
where("created_at < ?", 1.month.ago).delete_all
end
def self.approved?(user_id, post_id)
where(user_id: user_id, post_id: post_id).exists?
end
end

View File

@@ -148,7 +148,9 @@
<meta name="favorites" content="<%= @post.fav_string %>"> <meta name="favorites" content="<%= @post.fav_string %>">
<meta name="pools" content="<%= @post.pool_string %>"> <meta name="pools" content="<%= @post.pool_string %>">
<meta name="post-id" content="<%= @post.id %>"> <meta name="post-id" content="<%= @post.id %>">
<meta name="post-is-approvable" content="<%= @post.is_approvable? %>"> <% if CurrentUser.can_approve_posts? %>
<meta name="post-is-approvable" content="<%= @post.is_approvable? %>">
<% end %>
<meta name="post-is-deleted" content="<%= @post.is_deleted? %>"> <meta name="post-is-deleted" content="<%= @post.is_deleted? %>">
<meta name="post-is-flagged" content="<%= @post.is_flagged? %>"> <meta name="post-is-flagged" content="<%= @post.is_flagged? %>">
<meta name="config-large-width" content="<%= Danbooru.config.large_image_width %>"> <meta name="config-large-width" content="<%= Danbooru.config.large_image_width %>">

View File

@@ -0,0 +1,12 @@
class CreatePostApprovals < ActiveRecord::Migration
def change
create_table :post_approvals do |t|
t.integer :user_id, null: false
t.integer :post_id, null: false
t.timestamps null: false
end
add_index :post_approvals, :user_id
add_index :post_approvals, :post_id
end
end

View File

@@ -2617,6 +2617,38 @@ CREATE SEQUENCE post_appeals_id_seq
ALTER SEQUENCE post_appeals_id_seq OWNED BY post_appeals.id; ALTER SEQUENCE post_appeals_id_seq OWNED BY post_appeals.id;
--
-- Name: post_approvals; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE post_approvals (
id integer NOT NULL,
user_id integer NOT NULL,
post_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
--
-- Name: post_approvals_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE post_approvals_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: post_approvals_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE post_approvals_id_seq OWNED BY post_approvals.id;
-- --
-- Name: post_disapprovals; Type: TABLE; Schema: public; Owner: - -- Name: post_disapprovals; Type: TABLE; Schema: public; Owner: -
-- --
@@ -4307,6 +4339,13 @@ ALTER TABLE ONLY pools ALTER COLUMN id SET DEFAULT nextval('pools_id_seq'::regcl
ALTER TABLE ONLY post_appeals ALTER COLUMN id SET DEFAULT nextval('post_appeals_id_seq'::regclass); ALTER TABLE ONLY post_appeals ALTER COLUMN id SET DEFAULT nextval('post_appeals_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY post_approvals ALTER COLUMN id SET DEFAULT nextval('post_approvals_id_seq'::regclass);
-- --
-- Name: id; Type: DEFAULT; Schema: public; Owner: - -- Name: id; Type: DEFAULT; Schema: public; Owner: -
-- --
@@ -4712,6 +4751,14 @@ ALTER TABLE ONLY post_appeals
ADD CONSTRAINT post_appeals_pkey PRIMARY KEY (id); ADD CONSTRAINT post_appeals_pkey PRIMARY KEY (id);
--
-- Name: post_approvals_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY post_approvals
ADD CONSTRAINT post_approvals_pkey PRIMARY KEY (id);
-- --
-- Name: post_disapprovals_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: post_disapprovals_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@@ -6768,6 +6815,20 @@ CREATE INDEX index_post_appeals_on_creator_ip_addr ON post_appeals USING btree (
CREATE INDEX index_post_appeals_on_post_id ON post_appeals USING btree (post_id); CREATE INDEX index_post_appeals_on_post_id ON post_appeals USING btree (post_id);
--
-- Name: index_post_approvals_on_post_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_post_approvals_on_post_id ON post_approvals USING btree (post_id);
--
-- Name: index_post_approvals_on_user_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_post_approvals_on_user_id ON post_approvals USING btree (user_id);
-- --
-- Name: index_post_disapprovals_on_post_id; Type: INDEX; Schema: public; Owner: - -- Name: index_post_disapprovals_on_post_id; Type: INDEX; Schema: public; Owner: -
-- --
@@ -7459,3 +7520,5 @@ INSERT INTO schema_migrations (version) VALUES ('20161018221128');
INSERT INTO schema_migrations (version) VALUES ('20161024220345'); INSERT INTO schema_migrations (version) VALUES ('20161024220345');
INSERT INTO schema_migrations (version) VALUES ('20161101003139');

View File

@@ -0,0 +1,62 @@
require 'test_helper'
class PostApprovalTest < ActiveSupport::TestCase
context "a pending post" do
setup do
@user = FactoryGirl.create(:user)
CurrentUser.user = @user
CurrentUser.ip_addr = "127.0.0.1"
@post = FactoryGirl.create(:post, uploader_id: @user.id, is_pending: true)
@approver = FactoryGirl.create(:user)
@approver.can_approve_posts = true
@approver.save
CurrentUser.user = @approver
CurrentUser.stubs(:can_approve_posts?).returns(true)
end
teardown do
CurrentUser.user = nil
end
should "allow approval" do
assert_equal(false, PostApproval.approved?(@approver.id, @post.id))
end
context "That is approved" do
should "create a postapproval record" do
assert_difference("PostApproval.count") do
@post.approve!
end
end
context "that is then flagged" do
setup do
@user2 = FactoryGirl.create(:user)
@user3 = FactoryGirl.create(:user)
@approver2 = FactoryGirl.create(:user)
@approver2.can_approve_posts = true
@approver2.save
end
should "prevent the first approver from approving again" do
@post.approve!
CurrentUser.user = @user2
@post.flag!("blah")
CurrentUser.user = @approver2
@post.approve!
assert_not_equal(@approver.id, @post.approver_id)
CurrentUser.user = @user3
@post.flag!("blah blah")
CurrentUser.user = @approver
assert_raises(Post::ApprovalError) do
@post.approve!
end
end
end
end
end
end