FEATURE: New site setting, whitelisted_link_domains

If provided, users who normally couldn't post links (say, due to a
low trust level), can post links to those specific hosts.
This commit is contained in:
Robin Ward 2018-06-13 14:57:32 -04:00
parent debbb5be16
commit fd54c92a52
10 changed files with 96 additions and 21 deletions

View File

@ -47,6 +47,11 @@ export default Ember.Component.extend({
}
},
@computed
showLink() {
return this.currentUser && this.currentUser.get('link_posting_access') !== 'none';
},
@computed('composer.requiredCategoryMissing', 'composer.replyLength')
disableTextarea(requiredCategoryMissing, replyLength) {
return requiredCategoryMissing && replyLength === 0;

View File

@ -11,7 +11,7 @@
validation=validation
loading=composer.loading
forcePreview=forcePreview
showLink=currentUser.can_post_link
showLink=showLink
composerEvents=true
onExpandPopupMenuOptions="onExpandPopupMenuOptions"
onPopupMenuAction=onPopupMenuAction

View File

@ -6,11 +6,11 @@ class PostAnalyzer
def initialize(raw, topic_id)
@raw = raw
@topic_id = topic_id
@found_oneboxes = false
@onebox_urls = []
end
def found_oneboxes?
@found_oneboxes
@onebox_urls.present?
end
def has_oneboxes?
@ -32,7 +32,7 @@ class PostAnalyzer
end
result = Oneboxer.apply(cooked) do |url|
@found_oneboxes = true
@onebox_urls << url
Oneboxer.invalidate(url) if opts[:invalidate_oneboxes]
Oneboxer.cached_onebox(url)
end
@ -86,18 +86,20 @@ class PostAnalyzer
# Count how many hosts are linked in the post
def linked_hosts
return {} if raw_links.blank?
all_links = raw_links + @onebox_urls
return {} if all_links.blank?
return @linked_hosts if @linked_hosts.present?
@linked_hosts = {}
raw_links.each do |u|
all_links.each do |u|
begin
uri = self.class.parse_uri_rfc2396(u)
host = uri.host
@linked_hosts[host] ||= 1 unless host.nil?
rescue URI::InvalidURIError
# An invalid URI does not count as a raw link.
rescue URI::InvalidURIError, URI::InvalidComponentError
# An invalid URI does not count as a host
next
end
end

View File

@ -40,11 +40,11 @@ class CurrentUserSerializer < BasicUserSerializer
:primary_group_id,
:primary_group_name,
:can_create_topic,
:can_post_link,
:link_posting_access,
:external_id
def can_post_link
scope.can_post_link?
def link_posting_access
scope.link_posting_access
end
def can_create_topic

View File

@ -1394,6 +1394,8 @@ en:
min_trust_to_post_links: "The minimum trust level required to include links in posts"
min_trust_to_post_images: "The minimum trust level required to include images in a post"
whitelisted_link_domains: "Domains that users may link to even if they don't have the appropriate trust level to post links"
newuser_max_links: "How many links a new user can add to a post."
newuser_max_images: "How many images a new user can add to a post."
newuser_max_attachments: "How many attachments a new user can add to a post."

View File

@ -614,6 +614,9 @@ posting:
newuser_max_replies_per_topic: 3
newuser_max_mentions_per_post: 2
title_max_word_length: 30
whitelisted_link_domains:
default: ''
type: list
newuser_max_links: 2
newuser_max_images:
client: true

View File

@ -1,9 +1,25 @@
#mixin for all guardian methods dealing with post permissions
module PostGuardian
def can_post_link?
authenticated? &&
@user.has_trust_level?(TrustLevel[SiteSetting.min_trust_to_post_links])
def unrestricted_link_posting?
authenticated? && @user.has_trust_level?(TrustLevel[SiteSetting.min_trust_to_post_links])
end
def link_posting_access
if unrestricted_link_posting?
'full'
elsif SiteSetting.whitelisted_link_domains.present?
'limited'
else
'none'
end
end
def can_post_link?(host: nil)
return false if host.blank?
unrestricted_link_posting? ||
SiteSetting.whitelisted_link_domains.split('|').include?(host)
end
# Can the user act on the post in a particular way.

View File

@ -109,10 +109,12 @@ class Validators::PostValidator < ActiveModel::Validator
end
def can_post_links_validator(post)
if (post.link_count == 0 && !post.has_oneboxes?) ||
Guardian.new(post.acting_user).can_post_link? ||
private_message?(post)
if (post.link_count == 0 && !post.has_oneboxes?) || private_message?(post)
return newuser_links_validator(post)
end
guardian = Guardian.new(post.acting_user)
if post.linked_hosts.keys.all? { |h| guardian.can_post_link?(host: h) }
return newuser_links_validator(post)
end

View File

@ -26,21 +26,59 @@ describe Guardian do
expect { Guardian.new(user) }.not_to raise_error
end
describe "link_posting_access" do
it "is none for anonymous users" do
expect(Guardian.new.link_posting_access).to eq('none')
end
it "is full for regular users" do
expect(Guardian.new(user).link_posting_access).to eq('full')
end
it "is none for a user of a low trust level" do
user.trust_level = 0
SiteSetting.min_trust_to_post_links = 1
expect(Guardian.new(user).link_posting_access).to eq('none')
end
it "is limited for a user of a low trust level with a whitelist" do
SiteSetting.whitelisted_link_domains = 'example.com'
user.trust_level = 0
SiteSetting.min_trust_to_post_links = 1
expect(Guardian.new(user).link_posting_access).to eq('limited')
end
end
describe "can_post_link?" do
let(:host) { "discourse.org" }
it "returns false for anonymous users" do
expect(Guardian.new.can_post_link?).to eq(false)
expect(Guardian.new.can_post_link?(host: host)).to eq(false)
end
it "returns true for a regular user" do
expect(Guardian.new(user).can_post_link?).to eq(true)
expect(Guardian.new(user).can_post_link?(host: host)).to eq(true)
end
it "supports customization by site setting" do
user.trust_level = 0
SiteSetting.min_trust_to_post_links = 0
expect(Guardian.new(user).can_post_link?).to eq(true)
expect(Guardian.new(user).can_post_link?(host: host)).to eq(true)
SiteSetting.min_trust_to_post_links = 1
expect(Guardian.new(user).can_post_link?).to eq(false)
expect(Guardian.new(user).can_post_link?(host: host)).to eq(false)
end
describe "whitelisted host" do
before do
SiteSetting.whitelisted_link_domains = host
end
it "allows a new user to post the link to the host" do
user.trust_level = 0
SiteSetting.min_trust_to_post_links = 1
expect(Guardian.new(user).can_post_link?(host: host)).to eq(true)
expect(Guardian.new(user).can_post_link?(host: 'another-host.com')).to eq(false)
end
end
end

View File

@ -452,6 +452,13 @@ describe Post do
post_two_links.user.trust_level = TrustLevel[1]
expect(post_one_link).not_to be_valid
end
it "will skip the check for whitelisted domains" do
SiteSetting.whitelisted_link_domains = 'www.bbc.co.uk'
SiteSetting.min_trust_to_post_links = 2
post_two_links.user.trust_level = TrustLevel[1]
expect(post_one_link).to be_valid
end
end
end