mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 09:12:45 +08:00
FEATURE: Implement SiteSetting to Allow Anonymous Likes (#22131)
Allow anonymous users (logged-in, but set to anonymous posting) to like posts --------- Co-authored-by: Emmett Ling <eling@zendesk.com> Co-authored-by: Nat <natalie.tay@discourse.org>
This commit is contained in:
parent
8ffc274438
commit
978d52841a
|
@ -315,8 +315,14 @@ class PostSerializer < BasicPostSerializer
|
|||
summary.delete(:can_act)
|
||||
end
|
||||
|
||||
if actions.present? && SiteSetting.allow_anonymous_likes && sym == :like &&
|
||||
!scope.can_delete_post_action?(actions[id])
|
||||
summary.delete(:can_act)
|
||||
end
|
||||
|
||||
if actions.present? && actions.has_key?(id)
|
||||
summary[:acted] = true
|
||||
|
||||
summary[:can_undo] = true if scope.can_delete?(actions[id])
|
||||
end
|
||||
|
||||
|
|
|
@ -2164,6 +2164,7 @@ en:
|
|||
enable_category_group_moderation: "Allow groups to moderate content in specific categories"
|
||||
group_in_subject: "Set %%{optional_pm} in email subject to name of first group in PM, see: <a href='https://meta.discourse.org/t/customize-specific-email-templates/88323' target='_blank'>Customize subject format for standard emails</a>"
|
||||
allow_anonymous_posting: "Allow users to switch to anonymous mode"
|
||||
allow_anonymous_likes: "Allow anonymous users to like posts"
|
||||
anonymous_posting_min_trust_level: "Minimum trust level required to enable anonymous posting"
|
||||
anonymous_account_duration_minutes: "To protect anonymity create a new anonymous account every N minutes for each user. Example: if set to 600, as soon as 600 minutes elapse from last post AND user switches to anon, a new anonymous account is created."
|
||||
|
||||
|
|
|
@ -671,6 +671,9 @@ users:
|
|||
allow_anonymous_posting:
|
||||
default: false
|
||||
client: true
|
||||
allow_anonymous_likes:
|
||||
default: false
|
||||
client: true
|
||||
anonymous_posting_min_trust_level:
|
||||
default: 1
|
||||
enum: "TrustLevelSetting"
|
||||
|
|
|
@ -620,10 +620,14 @@ class Guardian
|
|||
private
|
||||
|
||||
def is_my_own?(obj)
|
||||
unless anonymous?
|
||||
return obj.user_id == @user.id if obj.respond_to?(:user_id) && obj.user_id && @user.id
|
||||
return obj.user == @user if obj.respond_to?(:user)
|
||||
if anonymous?
|
||||
return(
|
||||
SiteSetting.allow_anonymous_likes? && obj.class == PostAction && obj.is_like? &&
|
||||
obj.user_id == @user.id
|
||||
)
|
||||
end
|
||||
return obj.user_id == @user.id if obj.respond_to?(:user_id) && obj.user_id && @user.id
|
||||
return obj.user == @user if obj.respond_to?(:user)
|
||||
|
||||
false
|
||||
end
|
||||
|
|
|
@ -43,7 +43,10 @@ module PostGuardian
|
|||
already_did_flagging = taken.any? && (taken & PostActionType.notify_flag_types.values).any?
|
||||
|
||||
result =
|
||||
if authenticated? && post && !@user.anonymous?
|
||||
if authenticated? && post
|
||||
# Allow anonymous users to like if feature is enabled and short-circuit otherwise
|
||||
return SiteSetting.allow_anonymous_likes? && (action_key == :like) if @user.anonymous?
|
||||
|
||||
# Silenced users can't flag
|
||||
return false if is_flag && @user.silenced?
|
||||
|
||||
|
|
|
@ -98,6 +98,38 @@ RSpec.describe Guardian do
|
|||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:post) { Fabricate(:post) }
|
||||
|
||||
describe "an anonymous user" do
|
||||
before { SiteSetting.allow_anonymous_posting = true }
|
||||
|
||||
context "when allow_anonymous_likes is enabled" do
|
||||
before { SiteSetting.allow_anonymous_likes = true }
|
||||
|
||||
it "returns true when liking" do
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :like)).to be_truthy
|
||||
end
|
||||
|
||||
it "cannot perform any other action" do
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :flag)).to be_falsey
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :bookmark)).to be_falsey
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :notify_user)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context "when allow_anonymous_likes is disabled" do
|
||||
before { SiteSetting.allow_anonymous_likes = false }
|
||||
|
||||
it "returns false when liking" do
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :like)).to be_falsey
|
||||
end
|
||||
|
||||
it "cannot perform any other action" do
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :flag)).to be_falsey
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :bookmark)).to be_falsey
|
||||
expect(Guardian.new(anonymous_user).post_can_act?(post, :notify_user)).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "returns false when the user is nil" do
|
||||
expect(Guardian.new(nil).post_can_act?(post, :like)).to be_falsey
|
||||
end
|
||||
|
@ -2443,6 +2475,122 @@ RSpec.describe Guardian do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#can_delete_post_action" do
|
||||
before do
|
||||
SiteSetting.allow_anonymous_posting = true
|
||||
Guardian.any_instance.stubs(:anonymous?).returns(true)
|
||||
end
|
||||
|
||||
context "with allow_anonymous_likes enabled" do
|
||||
before { SiteSetting.allow_anonymous_likes = true }
|
||||
describe "an anonymous user" do
|
||||
let(:post_action) do
|
||||
user.id = anonymous_user.id
|
||||
post.id = 1
|
||||
|
||||
a =
|
||||
PostAction.new(
|
||||
user: anonymous_user,
|
||||
post: post,
|
||||
post_action_type_id: PostActionType.types[:like],
|
||||
)
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
end
|
||||
|
||||
let(:non_like_post_action) do
|
||||
user.id = anonymous_user.id
|
||||
post.id = 1
|
||||
|
||||
a =
|
||||
PostAction.new(
|
||||
user: anonymous_user,
|
||||
post: post,
|
||||
post_action_type_id: PostActionType.types[:reply],
|
||||
)
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
end
|
||||
|
||||
let(:other_users_post_action) do
|
||||
user.id = user.id
|
||||
post.id = 1
|
||||
|
||||
a =
|
||||
PostAction.new(user: user, post: post, post_action_type_id: PostActionType.types[:like])
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
end
|
||||
|
||||
it "returns true if the post belongs to the anonymous user" do
|
||||
expect(Guardian.new(anonymous_user).can_delete_post_action?(post_action)).to be_truthy
|
||||
end
|
||||
|
||||
it "return false if the post belongs to another user" do
|
||||
expect(
|
||||
Guardian.new(anonymous_user).can_delete_post_action?(other_users_post_action),
|
||||
).to be_falsey
|
||||
end
|
||||
|
||||
it "returns false for any other action" do
|
||||
expect(
|
||||
Guardian.new(anonymous_user).can_delete_post_action?(non_like_post_action),
|
||||
).to be_falsey
|
||||
end
|
||||
|
||||
it "returns false if the window has expired" do
|
||||
post_action.created_at = 20.minutes.ago
|
||||
SiteSetting.post_undo_action_window_mins = 10
|
||||
|
||||
expect(Guardian.new(anonymous_user).can_delete?(post_action)).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with allow_anonymous_likes disabled" do
|
||||
before do
|
||||
SiteSetting.allow_anonymous_likes = false
|
||||
SiteSetting.allow_anonymous_posting = true
|
||||
end
|
||||
describe "an anonymous user" do
|
||||
let(:post_action) do
|
||||
user.id = anonymous_user.id
|
||||
post.id = 1
|
||||
|
||||
a =
|
||||
PostAction.new(
|
||||
user: anonymous_user,
|
||||
post: post,
|
||||
post_action_type_id: PostActionType.types[:like],
|
||||
)
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
end
|
||||
|
||||
let(:non_like_post_action) do
|
||||
user.id = anonymous_user.id
|
||||
post.id = 1
|
||||
|
||||
a =
|
||||
PostAction.new(
|
||||
user: anonymous_user,
|
||||
post: post,
|
||||
post_action_type_id: PostActionType.types[:reply],
|
||||
)
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
end
|
||||
|
||||
it "any action returns false" do
|
||||
expect(Guardian.new(anonymous_user).can_delete_post_action?(post_action)).to be_falsey
|
||||
expect(
|
||||
Guardian.new(anonymous_user).can_delete_post_action?(non_like_post_action),
|
||||
).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#can_see_deleted_posts?" do
|
||||
it "returns true if the user is an admin" do
|
||||
expect(Guardian.new(admin).can_see_deleted_posts?(post.topic.category)).to be_truthy
|
||||
|
|
|
@ -310,6 +310,58 @@ RSpec.describe PostSerializer do
|
|||
end
|
||||
end
|
||||
|
||||
context "with allow_anonymous_likes enabled" do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:topic) { Fabricate(:topic, user: user) }
|
||||
fab!(:post) { Fabricate(:post, topic: topic, user: topic.user) }
|
||||
fab!(:anonymous_user) { Fabricate(:anonymous) }
|
||||
|
||||
let(:serializer) { PostSerializer.new(post, scope: Guardian.new(anonymous_user), root: false) }
|
||||
let(:post_action) do
|
||||
user.id = anonymous_user.id
|
||||
post.id = 1
|
||||
|
||||
a =
|
||||
PostAction.new(
|
||||
user: anonymous_user,
|
||||
post: post,
|
||||
post_action_type_id: PostActionType.types[:like],
|
||||
)
|
||||
a.created_at = 1.minute.ago
|
||||
a
|
||||
end
|
||||
|
||||
before do
|
||||
SiteSetting.allow_anonymous_posting = true
|
||||
SiteSetting.allow_anonymous_likes = true
|
||||
SiteSetting.post_undo_action_window_mins = 10
|
||||
PostSerializer.any_instance.stubs(:post_actions).returns({ 2 => post_action })
|
||||
end
|
||||
|
||||
context "when post_undo_action_window_mins has not passed" do
|
||||
before { post_action.created_at = 5.minutes.ago }
|
||||
|
||||
it "allows anonymous users to unlike posts" do
|
||||
like_actions_summary =
|
||||
serializer.actions_summary.find { |a| a[:id] == PostActionType.types[:like] }
|
||||
|
||||
#When :can_act is present, the JavaScript allows the user to click the unlike button
|
||||
expect(like_actions_summary[:can_act]).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "when post_undo_action_window_mins has passed" do
|
||||
before { post_action.created_at = 20.minutes.ago }
|
||||
|
||||
it "disallows anonymous users from unliking posts" do
|
||||
# There are no other post actions available to anonymous users so the action_summary will be an empty array
|
||||
expect(serializer.actions_summary.find { |a| a[:id] == PostActionType.types[:like] }).to eq(
|
||||
nil,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#user_status" do
|
||||
fab!(:user_status) { Fabricate(:user_status) }
|
||||
fab!(:user) { Fabricate(:user, user_status: user_status) }
|
||||
|
|
Loading…
Reference in New Issue
Block a user