mirror of
https://github.com/discourse/discourse.git
synced 2024-12-15 09:03:40 +08:00
d9a02d1336
This reverts commit20780a1eee
. * SECURITY: re-adds accidentally reverted commit: 03d26cd6: ensure embed_url contains valid http(s) uri * when the merge commite62a85cf
was reverted, git chose the2660c2e2
parent to land on instead of the03d26cd6
parent (which contains security fixes)
414 lines
13 KiB
Ruby
414 lines
13 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
describe UserGuardian do
|
|
|
|
let :user do
|
|
Fabricate(:user)
|
|
end
|
|
|
|
let :moderator do
|
|
Fabricate(:moderator)
|
|
end
|
|
|
|
let :admin do
|
|
Fabricate(:admin)
|
|
end
|
|
|
|
let(:user_avatar) do
|
|
Fabricate(:user_avatar, user: user)
|
|
end
|
|
|
|
let :users_upload do
|
|
Upload.new(user_id: user_avatar.user_id, id: 1)
|
|
end
|
|
|
|
let :already_uploaded do
|
|
u = Upload.new(user_id: 9999, id: 2)
|
|
user_avatar.custom_upload_id = u.id
|
|
u
|
|
end
|
|
|
|
let :not_my_upload do
|
|
Upload.new(user_id: 9999, id: 3)
|
|
end
|
|
|
|
let(:moderator_upload) do
|
|
Upload.new(user_id: moderator.id, id: 4)
|
|
end
|
|
|
|
describe '#can_pick_avatar?' do
|
|
|
|
let :guardian do
|
|
Guardian.new(user)
|
|
end
|
|
|
|
context 'anon user' do
|
|
let(:guardian) { Guardian.new }
|
|
|
|
it "should return the right value" do
|
|
expect(guardian.can_pick_avatar?(user_avatar, users_upload)).to eq(false)
|
|
end
|
|
end
|
|
|
|
context 'current user' do
|
|
it "can not set uploads not owned by current user" do
|
|
expect(guardian.can_pick_avatar?(user_avatar, users_upload)).to eq(true)
|
|
expect(guardian.can_pick_avatar?(user_avatar, already_uploaded)).to eq(true)
|
|
|
|
UserUpload.create!(
|
|
upload_id: not_my_upload.id,
|
|
user_id: not_my_upload.user_id
|
|
)
|
|
|
|
expect(guardian.can_pick_avatar?(user_avatar, not_my_upload)).to eq(false)
|
|
expect(guardian.can_pick_avatar?(user_avatar, nil)).to eq(true)
|
|
end
|
|
|
|
it "can handle uploads that are associated but not directly owned" do
|
|
UserUpload.create!(
|
|
upload_id: not_my_upload.id,
|
|
user_id: user_avatar.user_id
|
|
)
|
|
|
|
expect(guardian.can_pick_avatar?(user_avatar, not_my_upload))
|
|
.to eq(true)
|
|
end
|
|
end
|
|
|
|
context 'moderator' do
|
|
|
|
let :guardian do
|
|
Guardian.new(moderator)
|
|
end
|
|
|
|
it "is secure" do
|
|
expect(guardian.can_pick_avatar?(user_avatar, moderator_upload)).to eq(true)
|
|
expect(guardian.can_pick_avatar?(user_avatar, users_upload)).to eq(true)
|
|
expect(guardian.can_pick_avatar?(user_avatar, already_uploaded)).to eq(true)
|
|
expect(guardian.can_pick_avatar?(user_avatar, not_my_upload)).to eq(false)
|
|
expect(guardian.can_pick_avatar?(user_avatar, nil)).to eq(true)
|
|
end
|
|
end
|
|
|
|
context 'admin' do
|
|
let :guardian do
|
|
Guardian.new(admin)
|
|
end
|
|
|
|
it "is secure" do
|
|
expect(guardian.can_pick_avatar?(user_avatar, not_my_upload)).to eq(true)
|
|
expect(guardian.can_pick_avatar?(user_avatar, nil)).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#can_see_profile?" do
|
|
|
|
it "is false for no user" do
|
|
expect(Guardian.new.can_see_profile?(nil)).to eq(false)
|
|
end
|
|
|
|
it "is true for a user whose profile is public" do
|
|
expect(Guardian.new.can_see_profile?(user)).to eq(true)
|
|
end
|
|
|
|
context "hidden profile" do
|
|
# Mixing Fabricate.build() and Fabricate() could cause ID clashes, so override :user
|
|
fab!(:user) { Fabricate(:user) }
|
|
|
|
let(:hidden_user) do
|
|
result = Fabricate(:user)
|
|
result.user_option.update_column(:hide_profile_and_presence, true)
|
|
result
|
|
end
|
|
|
|
it "is false for another user" do
|
|
expect(Guardian.new(user).can_see_profile?(hidden_user)).to eq(false)
|
|
end
|
|
|
|
it "is false for an anonymous user" do
|
|
expect(Guardian.new.can_see_profile?(hidden_user)).to eq(false)
|
|
end
|
|
|
|
it "is true for the user themselves" do
|
|
expect(Guardian.new(hidden_user).can_see_profile?(hidden_user)).to eq(true)
|
|
end
|
|
|
|
it "is true for a staff user" do
|
|
expect(Guardian.new(admin).can_see_profile?(hidden_user)).to eq(true)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
describe "#allowed_user_field_ids" do
|
|
let! :fields do
|
|
[
|
|
Fabricate(:user_field),
|
|
Fabricate(:user_field),
|
|
Fabricate(:user_field, show_on_profile: true),
|
|
Fabricate(:user_field, show_on_user_card: true),
|
|
Fabricate(:user_field, show_on_user_card: true, show_on_profile: true)
|
|
]
|
|
end
|
|
|
|
let :user2 do
|
|
Fabricate(:user)
|
|
end
|
|
|
|
it "returns all fields for staff" do
|
|
guardian = Guardian.new(admin)
|
|
expect(guardian.allowed_user_field_ids(user)).to contain_exactly(*fields.map(&:id))
|
|
end
|
|
|
|
it "returns all fields for self" do
|
|
guardian = Guardian.new(user)
|
|
expect(guardian.allowed_user_field_ids(user)).to contain_exactly(*fields.map(&:id))
|
|
end
|
|
|
|
it "returns only public fields for others" do
|
|
guardian = Guardian.new(user)
|
|
expect(guardian.allowed_user_field_ids(user2)).to contain_exactly(*fields[2..5].map(&:id))
|
|
end
|
|
|
|
it "has a different cache per user" do
|
|
guardian = Guardian.new(user)
|
|
expect(guardian.allowed_user_field_ids(user2)).to contain_exactly(*fields[2..5].map(&:id))
|
|
expect(guardian.allowed_user_field_ids(user)).to contain_exactly(*fields.map(&:id))
|
|
end
|
|
end
|
|
|
|
describe "#can_delete_user?" do
|
|
shared_examples "can_delete_user examples" do
|
|
it "isn't allowed if user is an admin" do
|
|
another_admin = Fabricate(:admin)
|
|
expect(guardian.can_delete_user?(another_admin)).to eq(false)
|
|
end
|
|
end
|
|
|
|
shared_examples "can_delete_user staff examples" do
|
|
it "is allowed when user didn't create a post yet" do
|
|
expect(user.first_post_created_at).to be_nil
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
end
|
|
|
|
context "when user created too many posts" do
|
|
before do
|
|
(User::MAX_STAFF_DELETE_POST_COUNT + 1).times { Fabricate(:post, user: user) }
|
|
end
|
|
|
|
it "is allowed when user created the first post within delete_user_max_post_age days" do
|
|
SiteSetting.delete_user_max_post_age = 2
|
|
|
|
user.user_stat = UserStat.new(new_since: 3.days.ago, first_post_created_at: 1.day.ago)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
user.user_stat = UserStat.new(new_since: 3.days.ago, first_post_created_at: 3.day.ago)
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
end
|
|
|
|
context "when user didn't create many posts" do
|
|
before do
|
|
(User::MAX_STAFF_DELETE_POST_COUNT - 1).times { Fabricate(:post, user: user) }
|
|
end
|
|
|
|
it "is allowed when even when user created the first post before delete_user_max_post_age days" do
|
|
SiteSetting.delete_user_max_post_age = 2
|
|
|
|
user.user_stat = UserStat.new(new_since: 3.days.ago, first_post_created_at: 3.day.ago)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "delete myself" do
|
|
let(:guardian) { Guardian.new(user) }
|
|
|
|
include_examples "can_delete_user examples"
|
|
|
|
it "isn't allowed when SSO is enabled" do
|
|
SiteSetting.sso_url = "https://www.example.com/sso"
|
|
SiteSetting.enable_sso = true
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
|
|
it "isn't allowed when user created too many posts" do
|
|
Fabricate(:post, user: user)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user)
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
|
|
it "isn't allowed when user created too many posts in PM" do
|
|
topic = Fabricate(:private_message_topic, user: user)
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
|
|
it "is allowed when user responded to PM from system user" do
|
|
topic = Fabricate(:private_message_topic, user: Discourse.system_user, topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: Discourse.system_user),
|
|
Fabricate.build(:topic_allowed_user, user: user)
|
|
])
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
end
|
|
|
|
it "is allowed when user created multiple posts in PMs to themself" do
|
|
topic = Fabricate(:private_message_topic, user: user, topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: user)
|
|
])
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
end
|
|
|
|
it "isn't allowed when user created multiple posts in PMs sent to other users" do
|
|
topic = Fabricate(:private_message_topic, user: user, topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: user),
|
|
Fabricate.build(:topic_allowed_user, user: Fabricate(:user))
|
|
])
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
|
|
it "isn't allowed when user created multiple posts in PMs sent to groups" do
|
|
topic = Fabricate(:private_message_topic, user: user, topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: user)
|
|
], topic_allowed_groups: [
|
|
Fabricate.build(:topic_allowed_group, group: Fabricate(:group)),
|
|
Fabricate.build(:topic_allowed_group, group: Fabricate(:group))
|
|
])
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user, topic: topic)
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
|
|
it "isn't allowed when site admin blocked self deletion" do
|
|
expect(user.first_post_created_at).to be_nil
|
|
|
|
SiteSetting.delete_user_self_max_post_count = -1
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
end
|
|
|
|
it "correctly respects the delete_user_self_max_post_count setting" do
|
|
SiteSetting.delete_user_self_max_post_count = 0
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user)
|
|
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
SiteSetting.delete_user_self_max_post_count = 1
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
|
|
Fabricate(:post, user: user)
|
|
|
|
expect(guardian.can_delete_user?(user)).to eq(false)
|
|
SiteSetting.delete_user_self_max_post_count = 2
|
|
expect(guardian.can_delete_user?(user)).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "for moderators" do
|
|
let(:guardian) { Guardian.new(moderator) }
|
|
include_examples "can_delete_user examples"
|
|
include_examples "can_delete_user staff examples"
|
|
end
|
|
|
|
context "for admins" do
|
|
let(:guardian) { Guardian.new(admin) }
|
|
include_examples "can_delete_user examples"
|
|
include_examples "can_delete_user staff examples"
|
|
end
|
|
end
|
|
|
|
describe "#can_merge_user?" do
|
|
shared_examples "can_merge_user examples" do
|
|
it "isn't allowed if user is a staff" do
|
|
staff = Fabricate(:moderator)
|
|
expect(guardian.can_merge_user?(staff)).to eq(false)
|
|
end
|
|
end
|
|
|
|
context "for moderators" do
|
|
let(:guardian) { Guardian.new(moderator) }
|
|
include_examples "can_merge_user examples"
|
|
|
|
it "isn't allowed if current_user is not an admin" do
|
|
expect(guardian.can_merge_user?(user)).to eq(false)
|
|
end
|
|
end
|
|
|
|
context "for admins" do
|
|
let(:guardian) { Guardian.new(admin) }
|
|
include_examples "can_merge_user examples"
|
|
end
|
|
end
|
|
|
|
describe "#can_see_review_queue?" do
|
|
it 'returns true when the user is a staff member' do
|
|
guardian = Guardian.new(moderator)
|
|
expect(guardian.can_see_review_queue?).to eq(true)
|
|
end
|
|
|
|
it 'returns false for a regular user' do
|
|
guardian = Guardian.new(user)
|
|
expect(guardian.can_see_review_queue?).to eq(false)
|
|
end
|
|
|
|
it "returns true when the user's group can review an item in the queue" do
|
|
group = Fabricate(:group)
|
|
group.add(user)
|
|
guardian = Guardian.new(user)
|
|
SiteSetting.enable_category_group_review = true
|
|
|
|
Fabricate(:reviewable_flagged_post, reviewable_by_group: group, category: nil)
|
|
|
|
expect(guardian.can_see_review_queue?).to eq(true)
|
|
end
|
|
|
|
it 'returns false if category group review is disabled' do
|
|
group = Fabricate(:group)
|
|
group.add(user)
|
|
guardian = Guardian.new(user)
|
|
SiteSetting.enable_category_group_review = false
|
|
|
|
Fabricate(:reviewable_flagged_post, reviewable_by_group: group, category: nil)
|
|
|
|
expect(guardian.can_see_review_queue?).to eq(false)
|
|
end
|
|
|
|
it 'returns false if the reviewable is under a read restricted category' do
|
|
group = Fabricate(:group)
|
|
group.add(user)
|
|
guardian = Guardian.new(user)
|
|
SiteSetting.enable_category_group_review = true
|
|
category = Fabricate(:category, read_restricted: true)
|
|
|
|
Fabricate(:reviewable_flagged_post, reviewable_by_group: group, category: category)
|
|
|
|
expect(guardian.can_see_review_queue?).to eq(false)
|
|
end
|
|
end
|
|
end
|