diff options
Diffstat (limited to 'lib/gitlab')
-rw-r--r-- | lib/gitlab/auth.rb | 12 | ||||
-rw-r--r-- | lib/gitlab/auth/user_access_denied_reason.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/diff/suggestions_parser.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/utils.rb | 18 | ||||
-rw-r--r-- | lib/gitlab/utils/nokogiri.rb | 24 |
5 files changed, 59 insertions, 5 deletions
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index c6997288b65..4489fc9f3b2 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -84,7 +84,7 @@ module Gitlab Gitlab::Auth::UniqueIpsLimiter.limit_user! do user = User.by_login(login) - break if user && !user.can?(:log_in) + break if user && !can_user_login_with_non_expired_password?(user) authenticators = [] @@ -182,7 +182,7 @@ module Gitlab if valid_oauth_token?(token) user = User.id_in(token.resource_owner_id).first - return unless user&.can?(:log_in) + return unless user && can_user_login_with_non_expired_password?(user) Gitlab::Auth::Result.new(user, nil, :oauth, full_authentication_abilities) end @@ -200,7 +200,7 @@ module Gitlab return if project && token.user.project_bot? && !project.bots.include?(token.user) - if token.user.can?(:log_in) || token.user.project_bot? + if can_user_login_with_non_expired_password?(token.user) || token.user.project_bot? Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes)) end end @@ -285,7 +285,7 @@ module Gitlab return unless build.project.builds_enabled? if build.user - return unless build.user.can?(:log_in) || (build.user.project_bot? && build.project.bots&.include?(build.user)) + return unless can_user_login_with_non_expired_password?(build.user) || (build.user.project_bot? && build.project.bots&.include?(build.user)) # If user is assigned to build, use restricted credentials of user Gitlab::Auth::Result.new(build.user, build.project, :build, build_authentication_abilities) @@ -380,6 +380,10 @@ module Gitlab user.increment_failed_attempts! end + + def can_user_login_with_non_expired_password?(user) + user.can?(:log_in) && !user.password_expired? + end end end end diff --git a/lib/gitlab/auth/user_access_denied_reason.rb b/lib/gitlab/auth/user_access_denied_reason.rb index 36b54ba2e46..6639000dba8 100644 --- a/lib/gitlab/auth/user_access_denied_reason.rb +++ b/lib/gitlab/auth/user_access_denied_reason.rb @@ -23,6 +23,9 @@ module Gitlab "Your primary email address is not confirmed. "\ "Please check your inbox for the confirmation instructions. "\ "In case the link is expired, you can request a new confirmation email at #{Rails.application.routes.url_helpers.new_user_confirmation_url}" + when :password_expired + "Your password expired. "\ + "Please access GitLab from a web browser to update your password." else "Your account has been blocked." end @@ -41,6 +44,8 @@ module Gitlab :deactivated elsif !@user.confirmed? :unconfirmed + elsif @user.password_expired? + :password_expired else :blocked end diff --git a/lib/gitlab/diff/suggestions_parser.rb b/lib/gitlab/diff/suggestions_parser.rb index f3e6fc455ac..6f126147113 100644 --- a/lib/gitlab/diff/suggestions_parser.rb +++ b/lib/gitlab/diff/suggestions_parser.rb @@ -6,6 +6,9 @@ module Gitlab # Matches for instance "-1", "+1" or "-1+2". SUGGESTION_CONTEXT = /^(\-(?<above>\d+))?(\+(?<below>\d+))?$/.freeze + CSS = 'pre.language-suggestion' + XPATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS).freeze + class << self # Returns an array of Gitlab::Diff::Suggestion which represents each # suggestion in the given text. @@ -17,7 +20,7 @@ module Gitlab no_original_data: true, suggestions_filter_enabled: supports_suggestion) doc = Nokogiri::HTML(html) - suggestion_nodes = doc.search('pre.language-suggestion') + suggestion_nodes = doc.xpath(XPATH) return [] if suggestion_nodes.empty? diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb index d70e5c3594c..77e0e2ca96c 100644 --- a/lib/gitlab/utils.rb +++ b/lib/gitlab/utils.rb @@ -197,6 +197,24 @@ module Gitlab rescue Addressable::URI::InvalidURIError, TypeError end + def removes_sensitive_data_from_url(uri_string) + uri = parse_url(uri_string) + + return unless uri + return uri_string unless uri.fragment + + stripped_params = CGI.parse(uri.fragment) + if stripped_params['access_token'] + stripped_params['access_token'] = 'filtered' + filtered_query = Addressable::URI.new + filtered_query.query_values = stripped_params + + uri.fragment = filtered_query.query + end + + uri.to_s + end + # Invert a hash, collecting all keys that map to a given value in an array. # # Unlike `Hash#invert`, where the last encountered pair wins, and which has the diff --git a/lib/gitlab/utils/nokogiri.rb b/lib/gitlab/utils/nokogiri.rb new file mode 100644 index 00000000000..4b37bb7e5ea --- /dev/null +++ b/lib/gitlab/utils/nokogiri.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Gitlab + module Utils + class Nokogiri + class << self + # Use Nokogiri to convert a css selector into an xpath selector. + # Nokogiri can use css selectors with `doc.search()`. However + # for large node trees, it is _much_ slower than using xpath, + # by several orders of magnitude. + # https://gitlab.com/gitlab-org/gitlab/-/issues/329186 + def css_to_xpath(css) + xpath = ::Nokogiri::CSS.xpath_for(css) + + # Due to https://github.com/sparklemotion/nokogiri/issues/572, + # we remove the leading `//` and add `descendant-or-self::` + # in order to ensure we're searching from this node and all + # descendants. + xpath.map { |t| "descendant-or-self::#{t[2..-1]}" }.join('|') + end + end + end + end +end |