From d597a0a21ab7a589eb8c959e3062632f472ee099 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 11 Dec 2015 16:42:40 +0100 Subject: Pass all requests from NGINX to gitlab-workhorse --- lib/support/nginx/gitlab | 146 +----------------------------------------- lib/support/nginx/gitlab-ssl | 147 +------------------------------------------ 2 files changed, 3 insertions(+), 290 deletions(-) (limited to 'lib') diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab index 2a79fbdcf93..fc5475c4eef 100644 --- a/lib/support/nginx/gitlab +++ b/lib/support/nginx/gitlab @@ -10,34 +10,12 @@ ## If you change this file in a Merge Request, please also create ## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests ## -################################## -## CHUNKED TRANSFER ## -################################## -## -## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] -## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object -## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get -## around this by tweaking this configuration file and either: -## - installing an old version of Nginx with the chunkin module [2] compiled in, or -## - using a newer version of Nginx. -## -## At the time of writing we do not know if either of these theoretical solutions works. -## As a workaround users can use Git over SSH to push large files. -## -## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99 -## [1] https://github.com/agentzh/chunkin-nginx-module#status -## [2] https://github.com/agentzh/chunkin-nginx-module -## ################################### ## configuration ## ################################### ## ## See installation.md#using-https for additional HTTPS configuration details. -upstream gitlab { - server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0; -} - upstream gitlab-workhorse { server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0; } @@ -54,10 +32,6 @@ server { server_tokens off; ## Don't show the nginx version number, a security best practice root /home/git/gitlab/public; - ## Increase this if you want to upload large attachments - ## Or if you want to accept large git objects over http - client_max_body_size 20m; - ## See app/controllers/application_controller.rb for headers set ## Individual nginx logs for this GitLab vhost @@ -65,103 +39,8 @@ server { error_log /var/log/nginx/gitlab_error.log; location / { - ## Serve static files from defined root folder. - ## @gitlab is a named location for the upstream fallback, see below. - try_files $uri /index.html $uri.html @gitlab; - } - - ## We route uploads through GitLab to prevent XSS and enforce access control. - location /uploads/ { - ## If you use HTTPS make sure you disable gzip compression - ## to be safe against BREACH attack. - # gzip off; - - ## https://github.com/gitlabhq/gitlabhq/issues/694 - ## Some requests take more than 30 seconds. - proxy_read_timeout 300; - proxy_connect_timeout 300; - proxy_redirect off; - - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Frame-Options SAMEORIGIN; - - proxy_pass http://gitlab; - } - - ## If a file, which is not found in the root folder is requested, - ## then the proxy passes the request to the upsteam (gitlab unicorn). - location @gitlab { - ## If you use HTTPS make sure you disable gzip compression - ## to be safe against BREACH attack. - # gzip off; - - ## https://github.com/gitlabhq/gitlabhq/issues/694 - ## Some requests take more than 30 seconds. - proxy_read_timeout 300; - proxy_connect_timeout 300; - proxy_redirect off; - - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Frame-Options SAMEORIGIN; - - proxy_pass http://gitlab; - } - - location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location ~ ^/api/v3/projects/.*/repository/archive { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - # Build artifacts should be submitted to this location - location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - # Build artifacts should be submitted to this location - location ~ /ci/api/v1/builds/[0-9]+/artifacts { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location @gitlab-workhorse { - client_max_body_size 0; - ## If you use HTTPS make sure you disable gzip compression - ## to be safe against BREACH attack. - # gzip off; + gzip off; ## https://github.com/gitlabhq/gitlabhq/issues/694 ## Some requests take more than 30 seconds. @@ -169,14 +48,7 @@ server { proxy_connect_timeout 300; proxy_redirect off; - # Do not buffer Git HTTP responses - proxy_buffering off; - - # The following settings only work with NGINX 1.7.11 or newer - # - # # Pass chunked request bodies to gitlab-workhorse as-is - # proxy_request_buffering off; - # proxy_http_version 1.1; + proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; @@ -185,18 +57,4 @@ server { proxy_pass http://gitlab-workhorse; } - - ## Enable gzip compression as per rails guide: - ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression - ## WARNING: If you are using relative urls remove the block below - ## See config/application.rb under "Relative url support" for the list of - ## other files that need to be changed for relative url support - location ~ ^/(assets)/ { - root /home/git/gitlab/public; - gzip_static on; # to serve pre-gzipped version - expires max; - add_header Cache-Control public; - } - - error_page 502 /502.html; } diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 79fe1474821..1e5f85413ec 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -14,34 +14,12 @@ ## If you change this file in a Merge Request, please also create ## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests ## -################################## -## CHUNKED TRANSFER ## -################################## -## -## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] -## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object -## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get -## around this by tweaking this configuration file and either: -## - installing an old version of Nginx with the chunkin module [2] compiled in, or -## - using a newer version of Nginx. -## -## At the time of writing we do not know if either of these theoretical solutions works. -## As a workaround users can use Git over SSH to push large files. -## -## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99 -## [1] https://github.com/agentzh/chunkin-nginx-module#status -## [2] https://github.com/agentzh/chunkin-nginx-module -## ################################### ## configuration ## ################################### ## ## See installation.md#using-https for additional HTTPS configuration details. -upstream gitlab { - server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0; -} - upstream gitlab-workhorse { server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0; } @@ -61,7 +39,6 @@ server { error_log /var/log/nginx/gitlab_error.log; } - ## HTTPS host server { listen 0.0.0.0:443 ssl; @@ -70,10 +47,6 @@ server { server_tokens off; ## Don't show the nginx version number, a security best practice root /home/git/gitlab/public; - ## Increase this if you want to upload large attachments - ## Or if you want to accept large git objects over http - client_max_body_size 20m; - ## Strong SSL Security ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/ ssl on; @@ -110,104 +83,7 @@ server { error_log /var/log/nginx/gitlab_error.log; location / { - ## Serve static files from defined root folder. - ## @gitlab is a named location for the upstream fallback, see below. - try_files $uri /index.html $uri.html @gitlab; - } - - ## We route uploads through GitLab to prevent XSS and enforce access control. - location /uploads/ { - ## If you use HTTPS make sure you disable gzip compression - ## to be safe against BREACH attack. - gzip off; - - ## https://github.com/gitlabhq/gitlabhq/issues/694 - ## Some requests take more than 30 seconds. - proxy_read_timeout 300; - proxy_connect_timeout 300; - proxy_redirect off; - - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Ssl on; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Frame-Options SAMEORIGIN; - - proxy_pass http://gitlab; - } - - ## If a file, which is not found in the root folder is requested, - ## then the proxy passes the request to the upsteam (gitlab unicorn). - location @gitlab { - ## If you use HTTPS make sure you disable gzip compression - ## to be safe against BREACH attack. - gzip off; - - ## https://github.com/gitlabhq/gitlabhq/issues/694 - ## Some requests take more than 30 seconds. - proxy_read_timeout 300; - proxy_connect_timeout 300; - proxy_redirect off; - - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Ssl on; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Frame-Options SAMEORIGIN; - - proxy_pass http://gitlab; - } - - location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive { client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location ~ ^/api/v3/projects/.*/repository/archive { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - # Build artifacts should be submitted to this location - location ~ ^/[\w\.-]+/[\w\.-]+/builds/download { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - # Build artifacts should be submitted to this location - location ~ /ci/api/v1/builds/[0-9]+/artifacts { - client_max_body_size 0; - # 'Error' 418 is a hack to re-use the @gitlab-workhorse block - error_page 418 = @gitlab-workhorse; - return 418; - } - - location @gitlab-workhorse { - client_max_body_size 0; - ## If you use HTTPS make sure you disable gzip compression - ## to be safe against BREACH attack. gzip off; ## https://github.com/gitlabhq/gitlabhq/issues/694 @@ -216,14 +92,7 @@ server { proxy_connect_timeout 300; proxy_redirect off; - # Do not buffer Git HTTP responses - proxy_buffering off; - - # The following settings only work with NGINX 1.7.11 or newer - # - # # Pass chunked request bodies to gitlab-workhorse as-is - # proxy_request_buffering off; - # proxy_http_version 1.1; + proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; @@ -232,18 +101,4 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://gitlab-workhorse; } - - ## Enable gzip compression as per rails guide: - ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression - ## WARNING: If you are using relative urls remove the block below - ## See config/application.rb under "Relative url support" for the list of - ## other files that need to be changed for relative url support - location ~ ^/(assets)/ { - root /home/git/gitlab/public; - gzip_static on; # to serve pre-gzipped version - expires max; - add_header Cache-Control public; - } - - error_page 502 /502.html; } -- cgit v1.2.1 From 3efae53bd79db118463bfaeceb209bc91f63bd0b Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 11 Dec 2015 23:17:36 -0800 Subject: Add open_issues_count to project API This is needed to support Huboard and a generally useful value. --- lib/api/entities.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 81bf7a8222b..014116ef130 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -68,6 +68,7 @@ module API expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } expose :avatar_url expose :star_count, :forks_count + expose :open_issues_count, if: lambda { | project, options | project.issues_enabled? && project.default_issues_tracker? } end class ProjectMember < UserBasic -- cgit v1.2.1 From f8bf6c4b2c5fb41ae92df09b9f968d5d5d61bb2b Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Fri, 11 Dec 2015 17:27:20 -0600 Subject: [ci skip] Add user repository integrity check rake task --- lib/tasks/gitlab/check.rake | 56 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index a25fac62cfc..167b0112666 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -822,10 +822,27 @@ namespace :gitlab do namespace_dirs.each do |namespace_dir| repo_dirs = Dir.glob(File.join(namespace_dir, '*')) - repo_dirs.each do |dir| - puts "\nChecking repo at #{dir}" - system(*%W(#{Gitlab.config.git.bin_path} fsck), chdir: dir) - end + repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) } + end + end + end + + namespace :user do + desc "GitLab | Check the integrity of a specific user's repositories" + task :check_repos, [:username] => :environment do |t, args| + username = args[:username] || prompt("Check repository integrity for which username? ".blue) + user = User.find_by(username: username) + if user + repo_dirs = user.authorized_projects.map do |p| + File.join( + Gitlab.config.gitlab_shell.repos_path, + "#{p.path_with_namespace}.git" + ) + end + + repo_dirs.each { |repo_dir| check_repo_integrity(repo_dir) } + else + puts "\nUser '#{username}' not found".red end end end @@ -952,4 +969,35 @@ namespace :gitlab do false end end + + def check_repo_integrity(repo_dir) + puts "\nChecking repo at #{repo_dir.yellow}" + + git_fsck(repo_dir) + check_config_lock(repo_dir) + check_ref_locks(repo_dir) + end + + def git_fsck(repo_dir) + puts "Running `git fsck`".yellow + system(*%W(#{Gitlab.config.git.bin_path} fsck), chdir: repo_dir) + end + + def check_config_lock(repo_dir) + config_exists = File.exist?(File.join(repo_dir,'config.lock')) + config_output = config_exists ? 'yes'.red : 'no'.green + puts "'config.lock' file exists?".yellow + " ... #{config_output}" + end + + def check_ref_locks(repo_dir) + lock_files = Dir.glob(File.join(repo_dir,'refs/heads/*.lock')) + if lock_files.present? + puts "Ref lock files exist:".red + lock_files.each do |lock_file| + puts " #{lock_file}" + end + else + puts "No ref lock files exist".green + end + end end -- cgit v1.2.1 From b5291f95996743067bbec5a32f9c6cf0d34b36c7 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Tue, 15 Dec 2015 00:53:52 -0200 Subject: Fixed Rubocop offenses --- lib/api/entities.rb | 2 +- lib/gitlab/backend/shell.rb | 2 +- lib/gitlab/bitbucket_import/project_creator.rb | 3 ++- lib/gitlab/diff/file.rb | 4 ++-- lib/gitlab/fogbugz_import/importer.rb | 2 +- lib/gitlab/fogbugz_import/project_creator.rb | 3 ++- lib/gitlab/gitlab_import/project_creator.rb | 3 ++- lib/gitlab/gitorious_import/project_creator.rb | 3 ++- lib/gitlab/google_code_import/importer.rb | 6 +++--- lib/gitlab/google_code_import/project_creator.rb | 3 ++- lib/gitlab/markdown/filter/markdown_filter.rb | 2 +- lib/gitlab/markdown/filter/table_of_contents_filter.rb | 2 +- lib/rouge/formatters/html_gitlab.rb | 2 +- 13 files changed, 21 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b1cd80bdf65..a5daa45faf0 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -67,7 +67,7 @@ module API expose :shared_runners_enabled expose :creator_id expose :namespace - expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } + expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ |project, options| project.forked? } expose :avatar_url expose :star_count, :forks_count end diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 87ac30b5ffe..459e3d6bcdb 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -2,7 +2,7 @@ module Gitlab class Shell class Error < StandardError; end - class KeyAdder < Struct.new(:io) + KeyAdder = Struct.new(:io) do def add_key(id, key) key.gsub!(/[[:space:]]+/, ' ').strip! io.puts("#{id}\t#{key}") diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb index 35e34d033e0..03aac1a025a 100644 --- a/lib/gitlab/bitbucket_import/project_creator.rb +++ b/lib/gitlab/bitbucket_import/project_creator.rb @@ -11,7 +11,8 @@ module Gitlab end def execute - project = ::Projects::CreateService.new(current_user, + project = ::Projects::CreateService.new( + current_user, name: repo["name"], path: repo["slug"], description: repo["description"], diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index 142058aa69d..79061cd0141 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -46,11 +46,11 @@ module Gitlab end def added_lines - diff_lines.select(&:added?).size + diff_lines.count(&:added?) end def removed_lines - diff_lines.select(&:removed?).size + diff_lines.count(&:removed?) end end end diff --git a/lib/gitlab/fogbugz_import/importer.rb b/lib/gitlab/fogbugz_import/importer.rb index 496256700b8..403ebeec474 100644 --- a/lib/gitlab/fogbugz_import/importer.rb +++ b/lib/gitlab/fogbugz_import/importer.rb @@ -199,7 +199,7 @@ module Gitlab s = s.gsub(/^#/, "\\#") s = s.gsub(/^-/, "\\-") s = s.gsub("`", "\\~") - s = s.gsub("\r", "") + s = s.delete("\r") s = s.gsub("\n", " \n") s end diff --git a/lib/gitlab/fogbugz_import/project_creator.rb b/lib/gitlab/fogbugz_import/project_creator.rb index 8b1b6f48ed5..e0163499e30 100644 --- a/lib/gitlab/fogbugz_import/project_creator.rb +++ b/lib/gitlab/fogbugz_import/project_creator.rb @@ -12,7 +12,8 @@ module Gitlab end def execute - project = ::Projects::CreateService.new(current_user, + project = ::Projects::CreateService.new( + current_user, name: repo.safe_name, path: repo.path, namespace: namespace, diff --git a/lib/gitlab/gitlab_import/project_creator.rb b/lib/gitlab/gitlab_import/project_creator.rb index d9452de6a50..7baaadb813c 100644 --- a/lib/gitlab/gitlab_import/project_creator.rb +++ b/lib/gitlab/gitlab_import/project_creator.rb @@ -11,7 +11,8 @@ module Gitlab end def execute - project = ::Projects::CreateService.new(current_user, + project = ::Projects::CreateService.new( + current_user, name: repo["name"], path: repo["path"], description: repo["description"], diff --git a/lib/gitlab/gitorious_import/project_creator.rb b/lib/gitlab/gitorious_import/project_creator.rb index cc9a91c91f4..8e22aa9286d 100644 --- a/lib/gitlab/gitorious_import/project_creator.rb +++ b/lib/gitlab/gitorious_import/project_creator.rb @@ -10,7 +10,8 @@ module Gitlab end def execute - ::Projects::CreateService.new(current_user, + ::Projects::CreateService.new( + current_user, name: repo.name, path: repo.path, description: repo.description, diff --git a/lib/gitlab/google_code_import/importer.rb b/lib/gitlab/google_code_import/importer.rb index 87fee28dc01..62da327931f 100644 --- a/lib/gitlab/google_code_import/importer.rb +++ b/lib/gitlab/google_code_import/importer.rb @@ -171,8 +171,6 @@ module Gitlab when /\AMilestone:/ "#fee3ff" - when *@closed_statuses.map { |s| nice_status_name(s) } - "#cfcfcf" when "Status: New" "#428bca" when "Status: Accepted" @@ -199,6 +197,8 @@ module Gitlab "#8e44ad" when "Type: Other" "#7f8c8d" + when *@closed_statuses.map { |s| nice_status_name(s) } + "#cfcfcf" else "#e2e2e2" end @@ -227,7 +227,7 @@ module Gitlab s = s.gsub("`", "\\`") # Carriage returns make me sad - s = s.gsub("\r", "") + s = s.delete("\r") # Markdown ignores single newlines, but we need them as
. s = s.gsub("\n", " \n") diff --git a/lib/gitlab/google_code_import/project_creator.rb b/lib/gitlab/google_code_import/project_creator.rb index 1cb7d16aeb3..87821c23460 100644 --- a/lib/gitlab/google_code_import/project_creator.rb +++ b/lib/gitlab/google_code_import/project_creator.rb @@ -11,7 +11,8 @@ module Gitlab end def execute - project = ::Projects::CreateService.new(current_user, + project = ::Projects::CreateService.new( + current_user, name: repo.name, path: repo.name, description: repo.summary, diff --git a/lib/gitlab/markdown/filter/markdown_filter.rb b/lib/gitlab/markdown/filter/markdown_filter.rb index 921e2a0794e..b1b974fcc70 100644 --- a/lib/gitlab/markdown/filter/markdown_filter.rb +++ b/lib/gitlab/markdown/filter/markdown_filter.rb @@ -3,7 +3,7 @@ module Gitlab class MarkdownFilter < HTML::Pipeline::TextFilter def initialize(text, context = nil, result = nil) super text, context, result - @text = @text.gsub "\r", '' + @text = @text.delete "\r" end def call diff --git a/lib/gitlab/markdown/filter/table_of_contents_filter.rb b/lib/gitlab/markdown/filter/table_of_contents_filter.rb index bbb3bf7fc8b..6be644b0f67 100644 --- a/lib/gitlab/markdown/filter/table_of_contents_filter.rb +++ b/lib/gitlab/markdown/filter/table_of_contents_filter.rb @@ -31,7 +31,7 @@ module Gitlab id = text.downcase id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation - id.gsub!(' ', '-') # replace spaces with dash + id.tr!(' ', '-') # replace spaces with dash id.squeeze!('-') # replace multiple dashes with one uniq = (headers[id] > 0) ? "-#{headers[id]}" : '' diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb index 6762ca47c32..8c309efc7b8 100644 --- a/lib/rouge/formatters/html_gitlab.rb +++ b/lib/rouge/formatters/html_gitlab.rb @@ -39,7 +39,7 @@ module Rouge lineanchorsid: 'L', anchorlinenos: false, inline_theme: nil - ) + ) @nowrap = nowrap @cssclass = cssclass @linenos = linenos -- cgit v1.2.1 From 8e3f1fa629a61741282214b293c1bc9438aada59 Mon Sep 17 00:00:00 2001 From: tduehr Date: Wed, 11 Nov 2015 22:25:31 -0600 Subject: add CAS authentication support --- lib/gitlab/o_auth/session.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/gitlab/o_auth/session.rb (limited to 'lib') diff --git a/lib/gitlab/o_auth/session.rb b/lib/gitlab/o_auth/session.rb new file mode 100644 index 00000000000..f33bfd0bd0e --- /dev/null +++ b/lib/gitlab/o_auth/session.rb @@ -0,0 +1,17 @@ +module Gitlab + module OAuth + module Session + def self.create(provider, ticket) + Rails.cache.write("gitlab:#{provider}:#{ticket}", ticket, expires_in: Gitlab.config.omniauth.cas3.session_duration) + end + + def self.destroy(provider, ticket) + Rails.cache.delete("gitlab:#{provider}:#{ticket}") + end + + def self.valid?(provider, ticket) + Rails.cache.read("gitlab:#{provider}:#{ticket}").present? + end + end + end +end -- cgit v1.2.1 From 7781bda9bd82997f4a03de4cf911b1156ceb2cde Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 15 Dec 2015 15:51:16 +0100 Subject: Move Markdown/reference logic from Gitlab::Markdown to Banzai --- lib/banzai.rb | 13 ++ lib/banzai/cross_project_reference.rb | 22 +++ lib/banzai/filter.rb | 10 + lib/banzai/filter/abstract_reference_filter.rb | 145 ++++++++++++++ lib/banzai/filter/autolink_filter.rb | 107 +++++++++++ lib/banzai/filter/commit_range_reference_filter.rb | 58 ++++++ lib/banzai/filter/commit_reference_filter.rb | 63 ++++++ lib/banzai/filter/emoji_filter.rb | 80 ++++++++ .../filter/external_issue_reference_filter.rb | 69 +++++++ lib/banzai/filter/external_link_filter.rb | 34 ++++ lib/banzai/filter/issue_reference_filter.rb | 23 +++ lib/banzai/filter/label_reference_filter.rb | 96 ++++++++++ lib/banzai/filter/markdown_filter.rb | 42 ++++ .../filter/merge_request_reference_filter.rb | 41 ++++ lib/banzai/filter/redactor_filter.rb | 43 +++++ lib/banzai/filter/reference_filter.rb | 190 +++++++++++++++++++ lib/banzai/filter/reference_gatherer_filter.rb | 62 ++++++ lib/banzai/filter/relative_link_filter.rb | 157 +++++++++++++++ lib/banzai/filter/sanitization_filter.rb | 99 ++++++++++ lib/banzai/filter/snippet_reference_filter.rb | 25 +++ lib/banzai/filter/syntax_highlight_filter.rb | 45 +++++ lib/banzai/filter/table_of_contents_filter.rb | 63 ++++++ lib/banzai/filter/task_list_filter.rb | 24 +++ lib/banzai/filter/upload_link_filter.rb | 47 +++++ lib/banzai/filter/user_reference_filter.rb | 129 +++++++++++++ lib/banzai/lazy_reference.rb | 27 +++ lib/banzai/pipeline.rb | 10 + lib/banzai/pipeline/asciidoc_pipeline.rb | 13 ++ lib/banzai/pipeline/atom_pipeline.rb | 14 ++ lib/banzai/pipeline/base_pipeline.rb | 30 +++ lib/banzai/pipeline/combined_pipeline.rb | 27 +++ lib/banzai/pipeline/description_pipeline.rb | 14 ++ lib/banzai/pipeline/email_pipeline.rb | 13 ++ lib/banzai/pipeline/full_pipeline.rb | 9 + lib/banzai/pipeline/gfm_pipeline.rb | 41 ++++ lib/banzai/pipeline/note_pipeline.rb | 14 ++ lib/banzai/pipeline/plain_markdown_pipeline.rb | 13 ++ lib/banzai/pipeline/post_process_pipeline.rb | 20 ++ .../pipeline/reference_extraction_pipeline.rb | 13 ++ lib/banzai/pipeline/single_line_pipeline.rb | 9 + lib/banzai/reference_extractor.rb | 55 ++++++ lib/banzai/renderer.rb | 76 ++++++++ lib/gitlab/asciidoc.rb | 2 +- lib/gitlab/markdown.rb | 115 ----------- lib/gitlab/markdown/abstract_reference_filter.rb | 145 -------------- lib/gitlab/markdown/combined_pipeline.rb | 27 --- lib/gitlab/markdown/cross_project_reference.rb | 24 --- lib/gitlab/markdown/filter/autolink_filter.rb | 107 ----------- .../filter/commit_range_reference_filter.rb | 58 ------ .../markdown/filter/commit_reference_filter.rb | 63 ------ lib/gitlab/markdown/filter/emoji_filter.rb | 80 -------- .../filter/external_issue_reference_filter.rb | 69 ------- lib/gitlab/markdown/filter/external_link_filter.rb | 34 ---- .../markdown/filter/issue_reference_filter.rb | 23 --- .../markdown/filter/label_reference_filter.rb | 96 ---------- lib/gitlab/markdown/filter/markdown_filter.rb | 39 ---- .../filter/merge_request_reference_filter.rb | 41 ---- lib/gitlab/markdown/filter/redactor_filter.rb | 43 ----- .../markdown/filter/reference_gatherer_filter.rb | 63 ------ lib/gitlab/markdown/filter/relative_link_filter.rb | 157 --------------- lib/gitlab/markdown/filter/sanitization_filter.rb | 99 ---------- .../markdown/filter/snippet_reference_filter.rb | 25 --- .../markdown/filter/syntax_highlight_filter.rb | 45 ----- .../markdown/filter/table_of_contents_filter.rb | 63 ------ lib/gitlab/markdown/filter/task_list_filter.rb | 24 --- lib/gitlab/markdown/filter/upload_link_filter.rb | 47 ----- .../markdown/filter/user_reference_filter.rb | 129 ------------- lib/gitlab/markdown/pipeline.rb | 4 +- lib/gitlab/markdown/pipeline/asciidoc_pipeline.rb | 13 -- lib/gitlab/markdown/pipeline/atom_pipeline.rb | 14 -- .../markdown/pipeline/description_pipeline.rb | 14 -- lib/gitlab/markdown/pipeline/email_pipeline.rb | 13 -- lib/gitlab/markdown/pipeline/full_pipeline.rb | 9 - lib/gitlab/markdown/pipeline/gfm_pipeline.rb | 41 ---- lib/gitlab/markdown/pipeline/note_pipeline.rb | 14 -- .../markdown/pipeline/plain_markdown_pipeline.rb | 13 -- .../markdown/pipeline/post_process_pipeline.rb | 20 -- .../pipeline/reference_extraction_pipeline.rb | 13 -- .../markdown/pipeline/single_line_pipeline.rb | 9 - lib/gitlab/markdown/reference_filter.rb | 211 --------------------- lib/gitlab/reference_extractor.rb | 53 +----- 81 files changed, 2097 insertions(+), 2047 deletions(-) create mode 100644 lib/banzai.rb create mode 100644 lib/banzai/cross_project_reference.rb create mode 100644 lib/banzai/filter.rb create mode 100644 lib/banzai/filter/abstract_reference_filter.rb create mode 100644 lib/banzai/filter/autolink_filter.rb create mode 100644 lib/banzai/filter/commit_range_reference_filter.rb create mode 100644 lib/banzai/filter/commit_reference_filter.rb create mode 100644 lib/banzai/filter/emoji_filter.rb create mode 100644 lib/banzai/filter/external_issue_reference_filter.rb create mode 100644 lib/banzai/filter/external_link_filter.rb create mode 100644 lib/banzai/filter/issue_reference_filter.rb create mode 100644 lib/banzai/filter/label_reference_filter.rb create mode 100644 lib/banzai/filter/markdown_filter.rb create mode 100644 lib/banzai/filter/merge_request_reference_filter.rb create mode 100644 lib/banzai/filter/redactor_filter.rb create mode 100644 lib/banzai/filter/reference_filter.rb create mode 100644 lib/banzai/filter/reference_gatherer_filter.rb create mode 100644 lib/banzai/filter/relative_link_filter.rb create mode 100644 lib/banzai/filter/sanitization_filter.rb create mode 100644 lib/banzai/filter/snippet_reference_filter.rb create mode 100644 lib/banzai/filter/syntax_highlight_filter.rb create mode 100644 lib/banzai/filter/table_of_contents_filter.rb create mode 100644 lib/banzai/filter/task_list_filter.rb create mode 100644 lib/banzai/filter/upload_link_filter.rb create mode 100644 lib/banzai/filter/user_reference_filter.rb create mode 100644 lib/banzai/lazy_reference.rb create mode 100644 lib/banzai/pipeline.rb create mode 100644 lib/banzai/pipeline/asciidoc_pipeline.rb create mode 100644 lib/banzai/pipeline/atom_pipeline.rb create mode 100644 lib/banzai/pipeline/base_pipeline.rb create mode 100644 lib/banzai/pipeline/combined_pipeline.rb create mode 100644 lib/banzai/pipeline/description_pipeline.rb create mode 100644 lib/banzai/pipeline/email_pipeline.rb create mode 100644 lib/banzai/pipeline/full_pipeline.rb create mode 100644 lib/banzai/pipeline/gfm_pipeline.rb create mode 100644 lib/banzai/pipeline/note_pipeline.rb create mode 100644 lib/banzai/pipeline/plain_markdown_pipeline.rb create mode 100644 lib/banzai/pipeline/post_process_pipeline.rb create mode 100644 lib/banzai/pipeline/reference_extraction_pipeline.rb create mode 100644 lib/banzai/pipeline/single_line_pipeline.rb create mode 100644 lib/banzai/reference_extractor.rb create mode 100644 lib/banzai/renderer.rb delete mode 100644 lib/gitlab/markdown.rb delete mode 100644 lib/gitlab/markdown/abstract_reference_filter.rb delete mode 100644 lib/gitlab/markdown/combined_pipeline.rb delete mode 100644 lib/gitlab/markdown/cross_project_reference.rb delete mode 100644 lib/gitlab/markdown/filter/autolink_filter.rb delete mode 100644 lib/gitlab/markdown/filter/commit_range_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/commit_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/emoji_filter.rb delete mode 100644 lib/gitlab/markdown/filter/external_issue_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/external_link_filter.rb delete mode 100644 lib/gitlab/markdown/filter/issue_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/label_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/markdown_filter.rb delete mode 100644 lib/gitlab/markdown/filter/merge_request_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/redactor_filter.rb delete mode 100644 lib/gitlab/markdown/filter/reference_gatherer_filter.rb delete mode 100644 lib/gitlab/markdown/filter/relative_link_filter.rb delete mode 100644 lib/gitlab/markdown/filter/sanitization_filter.rb delete mode 100644 lib/gitlab/markdown/filter/snippet_reference_filter.rb delete mode 100644 lib/gitlab/markdown/filter/syntax_highlight_filter.rb delete mode 100644 lib/gitlab/markdown/filter/table_of_contents_filter.rb delete mode 100644 lib/gitlab/markdown/filter/task_list_filter.rb delete mode 100644 lib/gitlab/markdown/filter/upload_link_filter.rb delete mode 100644 lib/gitlab/markdown/filter/user_reference_filter.rb delete mode 100644 lib/gitlab/markdown/pipeline/asciidoc_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/atom_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/description_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/email_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/full_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/gfm_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/note_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/plain_markdown_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/post_process_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/reference_extraction_pipeline.rb delete mode 100644 lib/gitlab/markdown/pipeline/single_line_pipeline.rb delete mode 100644 lib/gitlab/markdown/reference_filter.rb (limited to 'lib') diff --git a/lib/banzai.rb b/lib/banzai.rb new file mode 100644 index 00000000000..093382261ae --- /dev/null +++ b/lib/banzai.rb @@ -0,0 +1,13 @@ +module Banzai + def self.render(text, context = {}) + Renderer.render(text, context) + end + + def self.render_result(text, context = {}) + Renderer.render_result(text, context) + end + + def self.post_process(html, context) + Renderer.post_process(html, context) + end +end diff --git a/lib/banzai/cross_project_reference.rb b/lib/banzai/cross_project_reference.rb new file mode 100644 index 00000000000..ba2866e1efa --- /dev/null +++ b/lib/banzai/cross_project_reference.rb @@ -0,0 +1,22 @@ +require 'banzai' + +module Banzai + # Common methods for ReferenceFilters that support an optional cross-project + # reference. + module CrossProjectReference + # Given a cross-project reference string, get the Project record + # + # Defaults to value of `context[:project]` if: + # * No reference is given OR + # * Reference given doesn't exist + # + # ref - String reference. + # + # Returns a Project, or nil if the reference can't be found + def project_from_ref(ref) + return context[:project] unless ref + + Project.find_with_namespace(ref) + end + end +end diff --git a/lib/banzai/filter.rb b/lib/banzai/filter.rb new file mode 100644 index 00000000000..fd4fe024252 --- /dev/null +++ b/lib/banzai/filter.rb @@ -0,0 +1,10 @@ +require 'active_support/core_ext/string/output_safety' +require 'banzai' + +module Banzai + module Filter + def self.[](name) + const_get("#{name.to_s.camelize}Filter") + end + end +end diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb new file mode 100644 index 00000000000..bdaa4721b4b --- /dev/null +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -0,0 +1,145 @@ +require 'banzai' + +module Banzai + module Filter + # Issues, Merge Requests, Snippets, Commits and Commit Ranges share + # similar functionality in reference filtering. + class AbstractReferenceFilter < ReferenceFilter + include CrossProjectReference + + def self.object_class + # Implement in child class + # Example: MergeRequest + end + + def self.object_name + object_class.name.underscore + end + + def self.object_sym + object_name.to_sym + end + + def self.data_reference + "data-#{object_name.dasherize}" + end + + # Public: Find references in text (like `!123` for merge requests) + # + # AnyReferenceFilter.references_in(text) do |match, id, project_ref, matches| + # object = find_object(project_ref, id) + # "#{object.to_reference}" + # end + # + # text - String text to search. + # + # Yields the String match, the Integer referenced object ID, an optional String + # of the external project reference, and all of the matchdata. + # + # Returns a String replaced with the return of the block. + def self.references_in(text, pattern = object_class.reference_pattern) + text.gsub(pattern) do |match| + yield match, $~[object_sym].to_i, $~[:project], $~ + end + end + + def self.referenced_by(node) + { object_sym => LazyReference.new(object_class, node.attr(data_reference)) } + end + + delegate :object_class, :object_sym, :references_in, to: :class + + def find_object(project, id) + # Implement in child class + # Example: project.merge_requests.find + end + + def url_for_object(object, project) + # Implement in child class + # Example: project_merge_request_url + end + + def call + # `#123` + replace_text_nodes_matching(object_class.reference_pattern) do |content| + object_link_filter(content, object_class.reference_pattern) + end + + # `[Issue](#123)`, which is turned into + # `Issue` + replace_link_nodes_with_href(object_class.reference_pattern) do |link, text| + object_link_filter(link, object_class.reference_pattern, link_text: text) + end + + # `http://gitlab.example.com/namespace/project/issues/123`, which is turned into + # `http://gitlab.example.com/namespace/project/issues/123` + replace_link_nodes_with_text(object_class.link_reference_pattern) do |text| + object_link_filter(text, object_class.link_reference_pattern) + end + + # `[Issue](http://gitlab.example.com/namespace/project/issues/123)`, which is turned into + # `Issue` + replace_link_nodes_with_href(object_class.link_reference_pattern) do |link, text| + object_link_filter(link, object_class.link_reference_pattern, link_text: text) + end + end + + # Replace references (like `!123` for merge requests) in text with links + # to the referenced object's details page. + # + # text - String text to replace references in. + # pattern - Reference pattern to match against. + # link_text - Original content of the link being replaced. + # + # Returns a String with references replaced with links. All links + # have `gfm` and `gfm-OBJECT_NAME` class names attached for styling. + def object_link_filter(text, pattern, link_text: nil) + references_in(text, pattern) do |match, id, project_ref, matches| + project = project_from_ref(project_ref) + + if project && object = find_object(project, id) + title = escape_once(object_link_title(object)) + klass = reference_class(object_sym) + + data = data_attribute( + original: link_text || match, + project: project.id, + object_sym => object.id + ) + + url = matches[:url] if matches.names.include?("url") + url ||= url_for_object(object, project) + + text = link_text + unless text + text = object.reference_link_text(context[:project]) + + extras = object_link_text_extras(object, matches) + text += " (#{extras.join(", ")})" if extras.any? + end + + %(#{text}) + else + match + end + end + end + + def object_link_text_extras(object, matches) + extras = [] + + if matches.names.include?("anchor") && matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/ + extras << "comment #{$1}" + end + + extras + end + + def object_link_title(object) + "#{object_class.name.titleize}: #{object.title}" + end + end + end +end diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb new file mode 100644 index 00000000000..da4ee80c1b5 --- /dev/null +++ b/lib/banzai/filter/autolink_filter.rb @@ -0,0 +1,107 @@ +require 'banzai' +require 'html/pipeline/filter' +require 'uri' + +module Banzai + module Filter + # HTML Filter for auto-linking URLs in HTML. + # + # Based on HTML::Pipeline::AutolinkFilter + # + # Context options: + # :autolink - Boolean, skips all processing done by this filter when false + # :link_attr - Hash of attributes for the generated links + # + class AutolinkFilter < HTML::Pipeline::Filter + include ActionView::Helpers::TagHelper + + # Pattern to match text that should be autolinked. + # + # A URI scheme begins with a letter and may contain letters, numbers, + # plus, period and hyphen. Schemes are case-insensitive but we're being + # picky here and allowing only lowercase for autolinks. + # + # See http://en.wikipedia.org/wiki/URI_scheme + # + # The negative lookbehind ensures that users can paste a URL followed by a + # period or comma for punctuation without those characters being included + # in the generated link. + # + # Rubular: http://rubular.com/r/cxjPyZc7Sb + LINK_PATTERN = %r{([a-z][a-z0-9\+\.-]+://\S+)(?" + end + end + + private + + def emoji_url(name) + emoji_path = "emoji/#{emoji_filename(name)}" + if context[:asset_host] + # Asset host is specified. + url_to_image(emoji_path) + elsif context[:asset_root] + # Gitlab url is specified + File.join(context[:asset_root], url_to_image(emoji_path)) + else + # All other cases + url_to_image(emoji_path) + end + end + + def url_to_image(image) + ActionController::Base.helpers.url_to_image(image) + end + + # Build a regexp that matches all valid :emoji: names. + def self.emoji_pattern + @emoji_pattern ||= /:(#{Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):/ + end + + def emoji_pattern + self.class.emoji_pattern + end + + def emoji_filename(name) + "#{Emoji.emoji_filename(name)}.png" + end + end + end +end diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb new file mode 100644 index 00000000000..f5737a7ac19 --- /dev/null +++ b/lib/banzai/filter/external_issue_reference_filter.rb @@ -0,0 +1,69 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces external issue tracker references with links. + # References are ignored if the project doesn't use an external issue + # tracker. + class ExternalIssueReferenceFilter < ReferenceFilter + # Public: Find `JIRA-123` issue references in text + # + # ExternalIssueReferenceFilter.references_in(text) do |match, issue| + # "##{issue}" + # end + # + # text - String text to search. + # + # Yields the String match and the String issue reference. + # + # Returns a String replaced with the return of the block. + def self.references_in(text) + text.gsub(ExternalIssue.reference_pattern) do |match| + yield match, $~[:issue] + end + end + + def call + # Early return if the project isn't using an external tracker + return doc if project.nil? || project.default_issues_tracker? + + replace_text_nodes_matching(ExternalIssue.reference_pattern) do |content| + issue_link_filter(content) + end + + replace_link_nodes_with_href(ExternalIssue.reference_pattern) do |link, text| + issue_link_filter(link, link_text: text) + end + end + + # Replace `JIRA-123` issue references in text with links to the referenced + # issue's details page. + # + # text - String text to replace references in. + # + # Returns a String with `JIRA-123` references replaced with links. All + # links have `gfm` and `gfm-issue` class names attached for styling. + def issue_link_filter(text, link_text: nil) + project = context[:project] + + self.class.references_in(text) do |match, issue| + url = url_for_issue(issue, project, only_path: context[:only_path]) + + title = escape_once("Issue in #{project.external_issue_tracker.title}") + klass = reference_class(:issue) + data = data_attribute(project: project.id) + + text = link_text || match + + %(#{text}) + end + end + + def url_for_issue(*args) + IssuesHelper.url_for_issue(*args) + end + end + end +end diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb new file mode 100644 index 00000000000..ac87b9820af --- /dev/null +++ b/lib/banzai/filter/external_link_filter.rb @@ -0,0 +1,34 @@ +require 'banzai' +require 'html/pipeline/filter' + +module Banzai + module Filter + # HTML Filter to add a `rel="nofollow"` attribute to external links + # + class ExternalLinkFilter < HTML::Pipeline::Filter + def call + doc.search('a').each do |node| + link = node.attr('href') + + next unless link + + # Skip non-HTTP(S) links + next unless link.start_with?('http') + + # Skip internal links + next if link.start_with?(internal_url) + + node.set_attribute('rel', 'nofollow') + end + + doc + end + + private + + def internal_url + @internal_url ||= Gitlab.config.gitlab.url + end + end + end +end diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb new file mode 100644 index 00000000000..51180cb901a --- /dev/null +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -0,0 +1,23 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces issue references with links. References to + # issues that do not exist are ignored. + # + # This filter supports cross-project references. + class IssueReferenceFilter < AbstractReferenceFilter + def self.object_class + Issue + end + + def find_object(project, id) + project.get_issue(id) + end + + def url_for_object(issue, project) + IssuesHelper.url_for_issue(issue.iid, project, only_path: context[:only_path]) + end + end + end +end diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb new file mode 100644 index 00000000000..07bac2dd7fd --- /dev/null +++ b/lib/banzai/filter/label_reference_filter.rb @@ -0,0 +1,96 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces label references with links. + class LabelReferenceFilter < ReferenceFilter + # Public: Find label references in text + # + # LabelReferenceFilter.references_in(text) do |match, id, name| + # "#{Label.find(id)}" + # end + # + # text - String text to search. + # + # Yields the String match, an optional Integer label ID, and an optional + # String label name. + # + # Returns a String replaced with the return of the block. + def self.references_in(text) + text.gsub(Label.reference_pattern) do |match| + yield match, $~[:label_id].to_i, $~[:label_name] + end + end + + def self.referenced_by(node) + { label: LazyReference.new(Label, node.attr("data-label")) } + end + + def call + replace_text_nodes_matching(Label.reference_pattern) do |content| + label_link_filter(content) + end + + replace_link_nodes_with_href(Label.reference_pattern) do |link, text| + label_link_filter(link, link_text: text) + end + end + + # Replace label references in text with links to the label specified. + # + # text - String text to replace references in. + # + # Returns a String with label references replaced with links. All links + # have `gfm` and `gfm-label` class names attached for styling. + def label_link_filter(text, link_text: nil) + project = context[:project] + + self.class.references_in(text) do |match, id, name| + params = label_params(id, name) + + if label = project.labels.find_by(params) + url = url_for_label(project, label) + klass = reference_class(:label) + data = data_attribute( + original: link_text || match, + project: project.id, + label: label.id + ) + + text = link_text || render_colored_label(label) + + %(#{text}) + else + match + end + end + end + + def url_for_label(project, label) + h = Gitlab::Application.routes.url_helpers + h.namespace_project_issues_url( project.namespace, project, label_name: label.name, + only_path: context[:only_path]) + end + + def render_colored_label(label) + LabelsHelper.render_colored_label(label) + end + + # Parameters to pass to `Label.find_by` based on the given arguments + # + # id - Integer ID to pass. If present, returns {id: id} + # name - String name to pass. If `id` is absent, finds by name without + # surrounding quotes. + # + # Returns a Hash. + def label_params(id, name) + if name + { name: name.tr('"', '') } + else + { id: id } + end + end + end + end +end diff --git a/lib/banzai/filter/markdown_filter.rb b/lib/banzai/filter/markdown_filter.rb new file mode 100644 index 00000000000..0072bab1f99 --- /dev/null +++ b/lib/banzai/filter/markdown_filter.rb @@ -0,0 +1,42 @@ +require 'banzai' +require 'html/pipeline/filter' + +module Banzai + module Filter + class MarkdownFilter < HTML::Pipeline::TextFilter + def initialize(text, context = nil, result = nil) + super text, context, result + @text = @text.gsub "\r", '' + end + + def call + html = self.class.renderer.render(@text) + html.rstrip! + html + end + + private + + def self.redcarpet_options + # https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use + @redcarpet_options ||= { + fenced_code_blocks: true, + footnotes: true, + lax_spacing: true, + no_intra_emphasis: true, + space_after_headers: true, + strikethrough: true, + superscript: true, + tables: true + }.freeze + end + + def self.renderer + @renderer ||= begin + renderer = Redcarpet::Render::HTML.new + Redcarpet::Markdown.new(renderer, redcarpet_options) + end + end + end + end +end diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb new file mode 100644 index 00000000000..755b946a34b --- /dev/null +++ b/lib/banzai/filter/merge_request_reference_filter.rb @@ -0,0 +1,41 @@ +require 'banzai' + +module Banzai + module Filter + # HTML filter that replaces merge request references with links. References + # to merge requests that do not exist are ignored. + # + # This filter supports cross-project references. + class MergeRequestReferenceFilter < AbstractReferenceFilter + def self.object_class + MergeRequest + end + + def find_object(project, id) + project.merge_requests.find_by(iid: id) + end + + def url_for_object(mr, project) + h = Gitlab::Application.routes.url_helpers + h.namespace_project_merge_request_url(project.namespace, project, mr, + only_path: context[:only_path]) + end + + def object_link_text_extras(object, matches) + extras = super + + path = matches[:path] if matches.names.include?("path") + case path + when '/diffs' + extras.unshift "diffs" + when '/commits' + extras.unshift "commits" + when '/builds' + extras.unshift "builds" + end + + extras + end + end + end +end diff --git a/lib/banzai/filter/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb new file mode 100644 index 00000000000..89e7a79789a --- /dev/null +++ b/lib/banzai/filter/redactor_filter.rb @@ -0,0 +1,43 @@ +require 'banzai' +require 'html/pipeline/filter' + +module Banzai + module Filter + # 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) + # The reference should be replaced by the original text, + # which is not always the same as the rendered text. + text = node.attr('data-original') || node.text + node.replace(text) + end + end + + doc + end + + private + + def user_can_reference?(node) + if node.has_attribute?('data-reference-filter') + reference_type = node.attr('data-reference-filter') + reference_filter = Banzai::Filter.const_get(reference_type) + + reference_filter.user_can_reference?(current_user, node, context) + else + true + end + end + + def current_user + context[:current_user] + end + end + end +end diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb new file mode 100644 index 00000000000..33457a3f361 --- /dev/null +++ b/lib/banzai/filter/reference_filter.rb @@ -0,0 +1,190 @@ +require 'active_support/core_ext/string/output_safety' +require 'banzai' +require 'html/pipeline/filter' + +module Banzai + module Filter + # Base class for GitLab Flavored Markdown reference filters. + # + # References within
, , , and