summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-06-10 10:49:07 +0200
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-06-10 10:49:07 +0200
commit51046dd22628cc54e92ca6da016c05762158e8ea (patch)
treea9352e9e0be4b74ee2622d85ee93a10e748fb225 /lib
parentd7e125116124b9c08c27b4a02f4738619db1d2f5 (diff)
parentcea3cf177c68bb1fa9326d4e88631b7737ae8a98 (diff)
downloadgitlab-ce-51046dd22628cc54e92ca6da016c05762158e8ea.tar.gz
Merge branch 'master' into refactor/ci-config-add-global-entry
* master: (147 commits) Minor MR comment fixes. Update CHANGELOG for 8.8.4 and 8.8.5 Properly quote table name in Rake task for MySQL and PostgreSQL compatibility Checks based on whether data is loaded not undefined Checks for undefined when inserting autocomplete into textarea Ignore frequent emojis in search. Fixed tests CHANGELOG Improved the UX of issue & milestone date picker Change date format to be non zero padded in order to fix failing test Update method name for better understanding Add tests for dates on tooltips Fix local timeago on user dashboard Update CHANGELOG Toggling a task in a description with mentions doesn't creates a Todo Update CHANGELOG Fixed failing label subscribe test Tests update Updated subscribe icon Fixed failing tests ...
Diffstat (limited to 'lib')
-rw-r--r--lib/api/entities.rb1
-rw-r--r--lib/api/issues.rb4
-rw-r--r--lib/api/merge_requests.rb2
-rw-r--r--lib/api/session.rb3
-rw-r--r--lib/banzai/filter/external_link_filter.rb1
-rw-r--r--lib/banzai/filter/wiki_link_filter.rb32
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb40
-rw-r--r--lib/gitlab/auth.rb95
-rw-r--r--lib/gitlab/auth/ip_rate_limiter.rb42
-rw-r--r--lib/gitlab/backend/grack_auth.rb55
-rw-r--r--lib/gitlab/current_settings.rb5
-rw-r--r--lib/gitlab/github_import/importer.rb1
-rw-r--r--lib/gitlab/gon_helper.rb1
-rw-r--r--lib/gitlab/o_auth/user.rb17
-rw-r--r--lib/gitlab/saml/user.rb4
-rw-r--r--lib/gitlab/workhorse.rb7
-rw-r--r--lib/tasks/gitlab/db.rake2
17 files changed, 206 insertions, 106 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 66c138eb902..50d69274b2e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -351,6 +351,7 @@ module API
expose :signin_enabled
expose :gravatar_enabled
expose :sign_in_text
+ expose :after_sign_up_text
expose :created_at
expose :updated_at
expose :home_page_url
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index f59a4d6c012..4c43257c48a 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -51,7 +51,7 @@ module API
# GET /issues?labels=foo,bar
# GET /issues?labels=foo,bar&state=opened
get do
- issues = current_user.issues
+ issues = current_user.issues.inc_notes_with_associations
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
issues.reorder(issuable_order_by => issuable_sort)
@@ -82,7 +82,7 @@ module API
# GET /projects/:id/issues?milestone=1.0.0&state=closed
# GET /issues?iid=42
get ":id/issues" do
- issues = user_project.issues.visible_to_user(current_user)
+ issues = user_project.issues.inc_notes_with_associations.visible_to_user(current_user)
issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
issues = filter_by_iid(issues, params[:iid]) unless params[:iid].nil?
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 2e7836dc8fb..43221d5622a 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -41,7 +41,7 @@ module API
#
get ":id/merge_requests" do
authorize! :read_merge_request, user_project
- merge_requests = user_project.merge_requests
+ merge_requests = user_project.merge_requests.inc_notes_with_associations
unless params[:iid].nil?
merge_requests = filter_by_iid(merge_requests, params[:iid])
diff --git a/lib/api/session.rb b/lib/api/session.rb
index cc646895914..56e69b2366f 100644
--- a/lib/api/session.rb
+++ b/lib/api/session.rb
@@ -11,8 +11,7 @@ module API
# Example Request:
# POST /session
post "/session" do
- auth = Gitlab::Auth.new
- user = auth.find(params[:email] || params[:login], params[:password])
+ user = Gitlab::Auth.find_in_gitlab_or_ldap(params[:email] || params[:login], params[:password])
return unauthorized! unless user
present user, with: Entities::UserLogin
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index 38c4219518e..f73ecfc9418 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -15,6 +15,7 @@ module Banzai
next if link.start_with?(internal_url)
node.set_attribute('rel', 'nofollow noreferrer')
+ node.set_attribute('target', '_blank')
end
doc
diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
index 7dc771afd71..37a2779d453 100644
--- a/lib/banzai/filter/wiki_link_filter.rb
+++ b/lib/banzai/filter/wiki_link_filter.rb
@@ -2,7 +2,8 @@ require 'uri'
module Banzai
module Filter
- # HTML filter that "fixes" relative links to files in a repository.
+ # HTML filter that "fixes" links to pages/files in a wiki.
+ # Rewrite rules are documented in the `WikiPipeline` spec.
#
# Context options:
# :project_wiki
@@ -25,36 +26,15 @@ module Banzai
end
def process_link_attr(html_attr)
- return if html_attr.blank? || file_reference?(html_attr) || hierarchical_link?(html_attr)
+ return if html_attr.blank?
- uri = URI(html_attr.value)
- if uri.relative? && uri.path.present?
- html_attr.value = rebuild_wiki_uri(uri).to_s
- end
+ html_attr.value = apply_rewrite_rules(html_attr.value)
rescue URI::Error
# noop
end
- def rebuild_wiki_uri(uri)
- uri.path = ::File.join(project_wiki_base_path, uri.path)
- uri
- end
-
- def project_wiki
- context[:project_wiki]
- end
-
- def file_reference?(html_attr)
- !File.extname(html_attr.value).blank?
- end
-
- # Of the form `./link`, `../link`, or similar
- def hierarchical_link?(html_attr)
- html_attr.value[0] == '.'
- end
-
- def project_wiki_base_path
- project_wiki && project_wiki.wiki_base_path
+ def apply_rewrite_rules(link_string)
+ Rewriter.new(link_string, wiki: context[:project_wiki], slug: context[:page_slug]).apply_rules
end
end
end
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
new file mode 100644
index 00000000000..2e2c8da311e
--- /dev/null
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -0,0 +1,40 @@
+module Banzai
+ module Filter
+ class WikiLinkFilter < HTML::Pipeline::Filter
+ class Rewriter
+ def initialize(link_string, wiki:, slug:)
+ @uri = Addressable::URI.parse(link_string)
+ @wiki_base_path = wiki && wiki.wiki_base_path
+ @slug = slug
+ end
+
+ def apply_rules
+ apply_file_link_rules!
+ apply_hierarchical_link_rules!
+ apply_relative_link_rules!
+ @uri.to_s
+ end
+
+ private
+
+ # Of the form 'file.md'
+ def apply_file_link_rules!
+ @uri = Addressable::URI.join(@slug, @uri) if @uri.extname.present?
+ end
+
+ # Of the form `./link`, `../link`, or similar
+ def apply_hierarchical_link_rules!
+ @uri = Addressable::URI.join(@slug, @uri) if @uri.to_s[0] == '.'
+ end
+
+ # Any link _not_ of the form `http://example.com/`
+ def apply_relative_link_rules!
+ if @uri.relative? && @uri.path.present?
+ link = ::File.join(@wiki_base_path, @uri.path)
+ @uri = Addressable::URI.parse(link)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 30509528b8b..076e2af7d38 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -1,17 +1,86 @@
module Gitlab
- class Auth
- def find(login, password)
- user = User.by_login(login)
-
- # If no user is found, or it's an LDAP server, try LDAP.
- # LDAP users are only authenticated via LDAP
- if user.nil? || user.ldap_user?
- # Second chance - try LDAP authentication
- return nil unless Gitlab::LDAP::Config.enabled?
-
- Gitlab::LDAP::Authentication.login(login, password)
- else
- user if user.valid_password?(password)
+ module Auth
+ Result = Struct.new(:user, :type)
+
+ class << self
+ def find(login, password, project:, ip:)
+ raise "Must provide an IP for rate limiting" if ip.nil?
+
+ result = Result.new
+
+ if valid_ci_request?(login, password, project)
+ result.type = :ci
+ elsif result.user = find_in_gitlab_or_ldap(login, password)
+ result.type = :gitlab_or_ldap
+ elsif result.user = oauth_access_token_check(login, password)
+ result.type = :oauth
+ end
+
+ rate_limit!(ip, success: !!result.user || (result.type == :ci), login: login)
+ result
+ end
+
+ def find_in_gitlab_or_ldap(login, password)
+ user = User.by_login(login)
+
+ # If no user is found, or it's an LDAP server, try LDAP.
+ # LDAP users are only authenticated via LDAP
+ if user.nil? || user.ldap_user?
+ # Second chance - try LDAP authentication
+ return nil unless Gitlab::LDAP::Config.enabled?
+
+ Gitlab::LDAP::Authentication.login(login, password)
+ else
+ user if user.valid_password?(password)
+ end
+ end
+
+ def rate_limit!(ip, success:, login:)
+ rate_limiter = Gitlab::Auth::IpRateLimiter.new(ip)
+ return unless rate_limiter.enabled?
+
+ if success
+ # Repeated login 'failures' are normal behavior for some Git clients so
+ # it is important to reset the ban counter once the client has proven
+ # they are not a 'bad guy'.
+ rate_limiter.reset!
+ else
+ # Register a login failure so that Rack::Attack can block the next
+ # request from this IP if needed.
+ rate_limiter.register_fail!
+
+ if rate_limiter.banned?
+ Rails.logger.info "IP #{ip} failed to login " \
+ "as #{login} but has been temporarily banned from Git auth"
+ end
+ end
+ end
+
+ private
+
+ def valid_ci_request?(login, password, project)
+ matched_login = /(?<service>^[a-zA-Z]*-ci)-token$/.match(login)
+
+ return false unless project && matched_login.present?
+
+ underscored_service = matched_login['service'].underscore
+
+ if underscored_service == 'gitlab_ci'
+ project && project.valid_build_token?(password)
+ elsif Service.available_services_names.include?(underscored_service)
+ # We treat underscored_service as a trusted input because it is included
+ # in the Service.available_services_names whitelist.
+ service = project.public_send("#{underscored_service}_service")
+
+ service && service.activated? && service.valid_token?(password)
+ end
+ end
+
+ def oauth_access_token_check(login, password)
+ if login == "oauth2" && password.present?
+ token = Doorkeeper::AccessToken.by_token(password)
+ token && token.accessible? && User.find_by(id: token.resource_owner_id)
+ end
end
end
end
diff --git a/lib/gitlab/auth/ip_rate_limiter.rb b/lib/gitlab/auth/ip_rate_limiter.rb
new file mode 100644
index 00000000000..1089bc9f89e
--- /dev/null
+++ b/lib/gitlab/auth/ip_rate_limiter.rb
@@ -0,0 +1,42 @@
+module Gitlab
+ module Auth
+ class IpRateLimiter
+ attr_reader :ip
+
+ def initialize(ip)
+ @ip = ip
+ @banned = false
+ end
+
+ def enabled?
+ config.enabled
+ end
+
+ def reset!
+ Rack::Attack::Allow2Ban.reset(ip, config)
+ end
+
+ def register_fail!
+ # Allow2Ban.filter will return false if this IP has not failed too often yet
+ @banned = Rack::Attack::Allow2Ban.filter(ip, config) do
+ # If we return false here, the failure for this IP is ignored by Allow2Ban
+ ip_can_be_banned?
+ end
+ end
+
+ def banned?
+ @banned
+ end
+
+ private
+
+ def config
+ Gitlab.config.rack_attack.git_basic_auth
+ end
+
+ def ip_can_be_banned?
+ config.ip_whitelist.exclude?(ip)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index cdcaae8094c..9e09d2e118d 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -36,10 +36,7 @@ module Grack
lfs_response = Gitlab::Lfs::Router.new(project, @user, @request).try_call
return lfs_response unless lfs_response.nil?
- if project && authorized_request?
- # Tell gitlab-workhorse the request is OK, and what the GL_ID is
- render_grack_auth_ok
- elsif @user.nil? && !@ci
+ if @user.nil? && !@ci
unauthorized
else
render_not_found
@@ -98,7 +95,7 @@ module Grack
end
def authenticate_user(login, password)
- user = Gitlab::Auth.new.find(login, password)
+ user = Gitlab::Auth.find_in_gitlab_or_ldap(login, password)
unless user
user = oauth_access_token_check(login, password)
@@ -141,36 +138,6 @@ module Grack
user
end
- def authorized_request?
- return true if @ci
-
- case git_cmd
- when *Gitlab::GitAccess::DOWNLOAD_COMMANDS
- if !Gitlab.config.gitlab_shell.upload_pack
- false
- elsif user
- Gitlab::GitAccess.new(user, project).download_access_check.allowed?
- elsif project.public?
- # Allow clone/fetch for public projects
- true
- else
- false
- end
- when *Gitlab::GitAccess::PUSH_COMMANDS
- if !Gitlab.config.gitlab_shell.receive_pack
- false
- elsif user
- # Skip user authorization on upload request.
- # It will be done by the pre-receive hook in the repository.
- true
- else
- false
- end
- else
- false
- end
- end
-
def git_cmd
if @request.get?
@request.params['service']
@@ -197,24 +164,6 @@ module Grack
end
end
- def render_grack_auth_ok
- repo_path =
- if @request.path_info =~ /^([\w\.\/-]+)\.wiki\.git/
- ProjectWiki.new(project).repository.path_to_repo
- else
- project.repository.path_to_repo
- end
-
- [
- 200,
- { "Content-Type" => "application/json" },
- [JSON.dump({
- 'GL_ID' => Gitlab::ShellEnv.gl_id(@user),
- 'RepoPath' => repo_path,
- })]
- ]
- end
-
def render_not_found
[404, { "Content-Type" => "text/plain" }, ["Not Found"]]
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 92c7e8b9d88..5e7532f57ae 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -26,7 +26,10 @@ module Gitlab
signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'],
gravatar_enabled: Settings.gravatar['enabled'],
- sign_in_text: Settings.extra['sign_in_text'],
+ sign_in_text: nil,
+ after_sign_up_text: nil,
+ help_page_text: nil,
+ shared_runners_text: nil,
restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
session_expire_delay: Settings.gitlab['session_expire_delay'],
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index 442b4c389fe..5ef9d66ba68 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -146,6 +146,7 @@ module Gitlab
def update_webhooks(hooks, options)
hooks.each do |hook|
+ sleep rate_limit_sleep_time if rate_limit_exceed?
client.edit_hook(repo, hook.id, hook.name, hook.config, options)
end
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index ab900b641c4..f751a3a12fd 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -8,6 +8,7 @@ module Gitlab
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
gon.shortcuts_path = help_shortcuts_path
gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
+ gon.award_menu_url = emojis_path
if current_user
gon.current_user_id = current_user.id
diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb
index 356e96fcbab..78f3ecb4cb4 100644
--- a/lib/gitlab/o_auth/user.rb
+++ b/lib/gitlab/o_auth/user.rb
@@ -69,13 +69,20 @@ module Gitlab
return unless ldap_person
# If a corresponding person exists with same uid in a LDAP server,
- # set up a Gitlab user with dual LDAP and Omniauth identities.
- if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn, ldap_person.provider)
- # Case when a LDAP user already exists in Gitlab. Add the Omniauth identity to existing account.
+ # check if the user already has a GitLab account.
+ user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn, ldap_person.provider)
+ if user
+ # Case when a LDAP user already exists in Gitlab. Add the OAuth identity to existing account.
+ log.info "LDAP account found for user #{user.username}. Building new #{auth_hash.provider} identity."
user.identities.build(extern_uid: auth_hash.uid, provider: auth_hash.provider)
else
- # No account in Gitlab yet: create it and add the LDAP identity
- user = build_new_user
+ log.info "No existing LDAP account was found in GitLab. Checking for #{auth_hash.provider} account."
+ user = find_by_uid_and_provider
+ if user.nil?
+ log.info "No user found using #{auth_hash.provider} provider. Creating a new one."
+ user = build_new_user
+ end
+ log.info "Correct account has been found. Adding LDAP identity to user: #{user.username}."
user.identities.new(provider: ldap_person.provider, extern_uid: ldap_person.dn)
end
diff --git a/lib/gitlab/saml/user.rb b/lib/gitlab/saml/user.rb
index dba4bbfc899..8943022612c 100644
--- a/lib/gitlab/saml/user.rb
+++ b/lib/gitlab/saml/user.rb
@@ -12,12 +12,12 @@ module Gitlab
end
def gl_user
- @user ||= find_by_uid_and_provider
-
if auto_link_ldap_user?
@user ||= find_or_create_ldap_user
end
+ @user ||= find_by_uid_and_provider
+
if auto_link_saml_user?
@user ||= find_by_email
end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 7f6ef71b303..56af739b1ef 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -6,6 +6,13 @@ module Gitlab
SEND_DATA_HEADER = 'Gitlab-Workhorse-Send-Data'
class << self
+ def git_http_ok(repository, user)
+ {
+ 'GL_ID' => Gitlab::ShellEnv.gl_id(user),
+ 'RepoPath' => repository.path_to_repo,
+ }
+ end
+
def send_git_blob(repository, blob)
params = {
'RepoPath' => repository.path_to_repo,
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 86584e91093..7230b9485be 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -34,7 +34,7 @@ namespace :gitlab do
# PG: http://www.postgresql.org/docs/current/static/ddl-depend.html
# MySQL: http://dev.mysql.com/doc/refman/5.7/en/drop-table.html
# Add `IF EXISTS` because cascade could have already deleted a table.
- tables.each { |t| connection.execute("DROP TABLE IF EXISTS #{t} CASCADE") }
+ tables.each { |t| connection.execute("DROP TABLE IF EXISTS #{connection.quote_table_name(t)} CASCADE") }
end
desc 'Configures the database by running migrate, or by loading the schema and seeding if needed'