summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2015-08-04 22:25:08 -0400
committerRobert Speicher <rspeicher@gmail.com>2015-09-01 17:00:29 -0400
commit7f75300573ff8f8e610bf4b0a3b4f2832552a1e9 (patch)
tree358bcb77d0e2910f4a8592959e6fa73b28322e57
parent454d227b45a563cb21ea8fa5091e687a2876380f (diff)
downloadgitlab-ce-7f75300573ff8f8e610bf4b0a3b4f2832552a1e9.tar.gz
Add RedactorFilter
-rw-r--r--lib/gitlab/markdown.rb1
-rw-r--r--lib/gitlab/markdown/redactor_filter.rb66
-rw-r--r--spec/lib/gitlab/markdown/redactor_filter_spec.rb76
3 files changed, 143 insertions, 0 deletions
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 097caf67a65..e07fdb702fc 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -41,6 +41,7 @@ module Gitlab
autoload :IssueReferenceFilter, 'gitlab/markdown/issue_reference_filter'
autoload :LabelReferenceFilter, 'gitlab/markdown/label_reference_filter'
autoload :MergeRequestReferenceFilter, 'gitlab/markdown/merge_request_reference_filter'
+ autoload :RedactorFilter, 'gitlab/markdown/redactor_filter'
autoload :RelativeLinkFilter, 'gitlab/markdown/relative_link_filter'
autoload :SanitizationFilter, 'gitlab/markdown/sanitization_filter'
autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter'
diff --git a/lib/gitlab/markdown/redactor_filter.rb b/lib/gitlab/markdown/redactor_filter.rb
new file mode 100644
index 00000000000..9faee4567ae
--- /dev/null
+++ b/lib/gitlab/markdown/redactor_filter.rb
@@ -0,0 +1,66 @@
+require 'gitlab/markdown'
+require 'html/pipeline/filter'
+
+module Gitlab
+ module Markdown
+ # HTML filter that removes references to records that the current user does
+ # not have permission to view.
+ #
+ # Expected to be run in its own post-processing pipeline.
+ #
+ class RedactorFilter < HTML::Pipeline::Filter
+ def call
+ doc.css('a.gfm').each do |node|
+ unless user_can_reference?(node)
+ node.replace(node.text)
+ end
+ end
+
+ doc
+ end
+
+ def user_can_reference?(node)
+ if node.has_attribute?('data-group-id')
+ user_can_reference_group?(node.attr('data-group-id'))
+ elsif node.has_attribute?('data-project-id')
+ user_can_reference_project?(node.attr('data-project-id'))
+ elsif node.has_attribute?('data-user-id')
+ user_can_reference_user?(node.attr('data-user-id'))
+ else
+ false
+ end
+ end
+
+ def user_can_reference_group?(id)
+ group = Group.find(id)
+
+ group && can?(:read_group, group)
+ end
+
+ def user_can_reference_project?(id)
+ project = Project.find(id)
+
+ project && can?(:read_project, project)
+ end
+
+ def user_can_reference_user?(id)
+ # Permit all user reference links
+ true
+ end
+
+ private
+
+ def abilities
+ Ability.abilities
+ end
+
+ def can?(ability, object)
+ abilities.allowed?(current_user, ability, object)
+ end
+
+ def current_user
+ context[:current_user]
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/markdown/redactor_filter_spec.rb b/spec/lib/gitlab/markdown/redactor_filter_spec.rb
new file mode 100644
index 00000000000..a6cf3c64236
--- /dev/null
+++ b/spec/lib/gitlab/markdown/redactor_filter_spec.rb
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+module Gitlab::Markdown
+ describe RedactorFilter do
+ include ActionView::Helpers::UrlHelper
+ include FilterSpecHelper
+
+ it 'ignores non-GFM links' do
+ html = %(See <a href="https://google.com/">Google</a>)
+ doc = filter(html, current_user: double)
+
+ expect(doc.css('a').length).to eq 1
+ end
+
+ def reference_link(data)
+ link_to('text', '', class: 'gfm', data: data)
+ end
+
+ context 'with data-group-id' do
+ it 'removes unpermitted Group references' do
+ user = create(:user)
+ group = create(:group)
+
+ link = reference_link(group_id: group.id)
+ doc = filter(link, current_user: user)
+
+ expect(doc.css('a').length).to eq 0
+ end
+
+ it 'allows permitted Group references' do
+ user = create(:user)
+ group = create(:group)
+ group.add_developer(user)
+
+ link = reference_link(group_id: group.id)
+ doc = filter(link, current_user: user)
+
+ expect(doc.css('a').length).to eq 1
+ end
+ end
+
+ context 'with data-project-id' do
+ it 'removes unpermitted Project references' do
+ user = create(:user)
+ project = create(:empty_project)
+
+ link = reference_link(project_id: project.id)
+ doc = filter(link, current_user: user)
+
+ expect(doc.css('a').length).to eq 0
+ end
+
+ it 'allows permitted Project references' do
+ user = create(:user)
+ project = create(:empty_project)
+ project.team << [user, :master]
+
+ link = reference_link(project_id: project.id)
+ doc = filter(link, current_user: user)
+
+ expect(doc.css('a').length).to eq 1
+ end
+ end
+
+ context 'with data-user-id' do
+ it 'allows any User reference' do
+ user = create(:user)
+
+ link = reference_link(user_id: user.id)
+ doc = filter(link)
+
+ expect(doc.css('a').length).to eq 1
+ end
+ end
+ end
+end