From 77d15aff0eaa7dd8a8ce988436a502c5ab6bb55b Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 19 Mar 2020 00:09:27 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- Gemfile | 2 +- .../concerns/authenticates_2fa_for_admin_mode.rb | 84 +++++++++++++++++++++ .../concerns/authenticates_2fa_for_admin_mode.rb | 84 --------------------- app/models/user_highest_role.rb | 2 + app/models/users_statistics.rb | 18 +++++ app/workers/error_tracking_issue_link_worker.rb | 4 + changelogs/unreleased/user-creation-count.yml | 5 ++ config/application.rb | 2 - config/environments/development.rb | 2 +- config/environments/test.rb | 2 +- config/initializers/2_gitlab.rb | 1 + .../initializers_before_autoloader/002_zeitwerk.rb | 59 --------------- config/settings.rb | 6 ++ doc/administration/auth/smartcard.md | 20 ++++- doc/user/admin_area/settings/usage_statistics.md | 1 + doc/user/group/epics/index.md | 8 ++ doc/user/project/issues/index.md | 22 +++++- doc/user/project/merge_requests/index.md | 14 +++- lib/gitlab/graphql/docs/helper.rb | 2 + lib/gitlab/graphql/docs/renderer.rb | 2 +- lib/gitlab/metrics/exporter/base_exporter.rb | 3 - lib/tasks/gitlab/graphql.rake | 1 - scripts/static-analysis | 1 + spec/factories/user_highest_roles.rb | 8 ++ spec/fast_spec_helper.rb | 7 +- spec/lib/gitlab/fogbugz_import/importer_spec.rb | 1 - spec/lib/gitlab/graphql/docs/renderer_spec.rb | 1 - spec/models/user_highest_role_spec.rb | 16 ++++ spec/services/service_response_spec.rb | 3 +- .../error_tracking_issue_link_worker_spec.rb | 14 ++++ vendor/project_templates/gatsby.tar.gz | Bin 78324 -> 79051 bytes 31 files changed, 224 insertions(+), 171 deletions(-) create mode 100644 app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb delete mode 100644 app/controllers/concerns/authenticates_2fa_for_admin_mode.rb create mode 100644 changelogs/unreleased/user-creation-count.yml create mode 100644 config/initializers/2_gitlab.rb delete mode 100644 config/initializers_before_autoloader/002_zeitwerk.rb diff --git a/Gemfile b/Gemfile index b2734269a8c..e70e64c0875 100644 --- a/Gemfile +++ b/Gemfile @@ -475,7 +475,7 @@ gem 'lograge', '~> 0.5' gem 'grape_logging', '~> 1.7' # DNS Lookup -gem 'gitlab-net-dns', '~> 0.9.1', require: 'net/dns' +gem 'gitlab-net-dns', '~> 0.9.1' # Countries list gem 'countries', '~> 3.0' diff --git a/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb b/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb new file mode 100644 index 00000000000..c6fd1d55e51 --- /dev/null +++ b/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +module Authenticates2FAForAdminMode + extend ActiveSupport::Concern + + included do + include AuthenticatesWithTwoFactor + end + + def admin_mode_prompt_for_two_factor(user) + return handle_locked_user(user) unless user.can?(:log_in) + + session[:otp_user_id] = user.id + setup_u2f_authentication(user) + + render 'admin/sessions/two_factor', layout: 'application' + end + + def admin_mode_authenticate_with_two_factor + user = current_user + + return handle_locked_user(user) unless user.can?(:log_in) + + if user_params[:otp_attempt].present? && session[:otp_user_id] + admin_mode_authenticate_with_two_factor_via_otp(user) + elsif user_params[:device_response].present? && session[:otp_user_id] + admin_mode_authenticate_with_two_factor_via_u2f(user) + elsif user && user.valid_password?(user_params[:password]) + admin_mode_prompt_for_two_factor(user) + else + invalid_login_redirect + end + end + + def admin_mode_authenticate_with_two_factor_via_otp(user) + if valid_otp_attempt?(user) + # Remove any lingering user data from login + session.delete(:otp_user_id) + + user.save! + + # The admin user has successfully passed 2fa, enable admin mode ignoring password + enable_admin_mode + else + user.increment_failed_attempts! + Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=OTP") + flash.now[:alert] = _('Invalid two-factor code.') + + admin_mode_prompt_for_two_factor(user) + end + end + + def admin_mode_authenticate_with_two_factor_via_u2f(user) + if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge]) + # Remove any lingering user data from login + session.delete(:otp_user_id) + session.delete(:challenge) + + # The admin user has successfully passed 2fa, enable admin mode ignoring password + enable_admin_mode + else + user.increment_failed_attempts! + Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=U2F") + flash.now[:alert] = _('Authentication via U2F device failed.') + + admin_mode_prompt_for_two_factor(user) + end + end + + private + + def enable_admin_mode + if current_user_mode.enable_admin_mode!(skip_password_validation: true) + redirect_to redirect_path, notice: _('Admin mode enabled') + else + invalid_login_redirect + end + end + + def invalid_login_redirect + flash.now[:alert] = _('Invalid login or password') + render :new + end +end diff --git a/app/controllers/concerns/authenticates_2fa_for_admin_mode.rb b/app/controllers/concerns/authenticates_2fa_for_admin_mode.rb deleted file mode 100644 index c6fd1d55e51..00000000000 --- a/app/controllers/concerns/authenticates_2fa_for_admin_mode.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true - -module Authenticates2FAForAdminMode - extend ActiveSupport::Concern - - included do - include AuthenticatesWithTwoFactor - end - - def admin_mode_prompt_for_two_factor(user) - return handle_locked_user(user) unless user.can?(:log_in) - - session[:otp_user_id] = user.id - setup_u2f_authentication(user) - - render 'admin/sessions/two_factor', layout: 'application' - end - - def admin_mode_authenticate_with_two_factor - user = current_user - - return handle_locked_user(user) unless user.can?(:log_in) - - if user_params[:otp_attempt].present? && session[:otp_user_id] - admin_mode_authenticate_with_two_factor_via_otp(user) - elsif user_params[:device_response].present? && session[:otp_user_id] - admin_mode_authenticate_with_two_factor_via_u2f(user) - elsif user && user.valid_password?(user_params[:password]) - admin_mode_prompt_for_two_factor(user) - else - invalid_login_redirect - end - end - - def admin_mode_authenticate_with_two_factor_via_otp(user) - if valid_otp_attempt?(user) - # Remove any lingering user data from login - session.delete(:otp_user_id) - - user.save! - - # The admin user has successfully passed 2fa, enable admin mode ignoring password - enable_admin_mode - else - user.increment_failed_attempts! - Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=OTP") - flash.now[:alert] = _('Invalid two-factor code.') - - admin_mode_prompt_for_two_factor(user) - end - end - - def admin_mode_authenticate_with_two_factor_via_u2f(user) - if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge]) - # Remove any lingering user data from login - session.delete(:otp_user_id) - session.delete(:challenge) - - # The admin user has successfully passed 2fa, enable admin mode ignoring password - enable_admin_mode - else - user.increment_failed_attempts! - Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=U2F") - flash.now[:alert] = _('Authentication via U2F device failed.') - - admin_mode_prompt_for_two_factor(user) - end - end - - private - - def enable_admin_mode - if current_user_mode.enable_admin_mode!(skip_password_validation: true) - redirect_to redirect_path, notice: _('Admin mode enabled') - else - invalid_login_redirect - end - end - - def invalid_login_redirect - flash.now[:alert] = _('Invalid login or password') - render :new - end -end diff --git a/app/models/user_highest_role.rb b/app/models/user_highest_role.rb index dc166273787..4853fc3d248 100644 --- a/app/models/user_highest_role.rb +++ b/app/models/user_highest_role.rb @@ -4,4 +4,6 @@ class UserHighestRole < ApplicationRecord belongs_to :user, optional: false validates :highest_access_level, allow_nil: true, inclusion: { in: Gitlab::Access.all_values } + + scope :with_highest_access_level, -> (highest_access_level) { where(highest_access_level: highest_access_level) } end diff --git a/app/models/users_statistics.rb b/app/models/users_statistics.rb index 5c5f62d5d87..5b4c0ef37d0 100644 --- a/app/models/users_statistics.rb +++ b/app/models/users_statistics.rb @@ -11,4 +11,22 @@ class UsersStatistics < ApplicationRecord :bots, :blocked ].freeze + + private + + def highest_role_stats + return unless Feature.enabled?(:users_statistics) + + { + owner: batch_count_for_access_level(Gitlab::Access::OWNER), + maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER), + developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER), + reporter: batch_count_for_access_level(Gitlab::Access::REPORTER), + guest: batch_count_for_access_level(Gitlab::Access::GUEST) + } + end + + def batch_count_for_access_level(access_level) + Gitlab::Database::BatchCount.batch_count(UserHighestRole.with_highest_access_level(access_level)) + end end diff --git a/app/workers/error_tracking_issue_link_worker.rb b/app/workers/error_tracking_issue_link_worker.rb index 9febd5cfecc..fa8af4f1822 100644 --- a/app/workers/error_tracking_issue_link_worker.rb +++ b/app/workers/error_tracking_issue_link_worker.rb @@ -63,6 +63,10 @@ class ErrorTrackingIssueLinkWorker # rubocop:disable Scalability/IdempotentWorke sentry_client .repos(organization_slug) .find { |repo| repo.project_id == issue.project_id && repo.status == 'active' } + rescue Sentry::Client::Error => e + logger.info("Unable to retrieve Sentry repo for organization #{organization_slug}, id #{sentry_issue_id}, with error: #{e.message}") + + nil end def organization_slug diff --git a/changelogs/unreleased/user-creation-count.yml b/changelogs/unreleased/user-creation-count.yml new file mode 100644 index 00000000000..8365b786adc --- /dev/null +++ b/changelogs/unreleased/user-creation-count.yml @@ -0,0 +1,5 @@ +--- +title: Add metric to derive new users count +merge_request: 27351 +author: +type: added diff --git a/config/application.rb b/config/application.rb index e1be913b5c3..14e92bf5905 100644 --- a/config/application.rb +++ b/config/application.rb @@ -32,8 +32,6 @@ module Gitlab config.active_record.sqlite3.represent_boolean_as_integer = true - config.autoloader = :zeitwerk - # Sidekiq uses eager loading, but directories not in the standard Rails # directories must be added to the eager load paths: # https://github.com/mperham/sidekiq/wiki/FAQ#why-doesnt-sidekiq-autoload-my-rails-application-code diff --git a/config/environments/development.rb b/config/environments/development.rb index c42d7127a22..25d57467060 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -42,7 +42,7 @@ Rails.application.configure do config.action_mailer.raise_delivery_errors = true # Don't make a mess when bootstrapping a development environment config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1') - config.action_mailer.preview_path = Rails.root.join('app', 'mailers', 'previews') + config.action_mailer.preview_path = 'app/mailers/previews' config.eager_load = false diff --git a/config/environments/test.rb b/config/environments/test.rb index f8fb7f60f0d..71cd5200415 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -43,7 +43,7 @@ Rails.application.configure do # Print deprecation notices to the stderr config.active_support.deprecation = :stderr - config.eager_load = false + config.eager_load = true config.cache_store = :null_store diff --git a/config/initializers/2_gitlab.rb b/config/initializers/2_gitlab.rb new file mode 100644 index 00000000000..8b7f245b7b0 --- /dev/null +++ b/config/initializers/2_gitlab.rb @@ -0,0 +1 @@ +require_dependency 'gitlab' diff --git a/config/initializers_before_autoloader/002_zeitwerk.rb b/config/initializers_before_autoloader/002_zeitwerk.rb deleted file mode 100644 index df0c16b0bc0..00000000000 --- a/config/initializers_before_autoloader/002_zeitwerk.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -Rails.autoloaders.each do |autoloader| - # We need to ignore these since these are non-Ruby files - # that do not define Ruby classes / modules - autoloader.ignore(Rails.root.join('lib/support')) - # Ignore generators since these are loaded manually by Rails - autoloader.ignore(Rails.root.join('lib/generators')) - autoloader.ignore(Rails.root.join('ee/lib/generators')) if Gitlab.ee? - # Mailer previews are also loaded manually by Rails - autoloader.ignore(Rails.root.join('app/mailers/previews')) - autoloader.ignore(Rails.root.join('ee/app/mailers/previews')) if Gitlab.ee? - # Ignore these files because these are only used in Rake tasks - # and are not available in production - autoloader.ignore(Rails.root.join('lib/gitlab/graphql/docs')) - - autoloader.inflector.inflect( - 'authenticates_2fa_for_admin_mode' => 'Authenticates2FAForAdminMode', - 'api' => 'API', - 'api_guard' => 'APIGuard', - 'group_api_compatibility' => 'GroupAPICompatibility', - 'project_api_compatibility' => 'ProjectAPICompatibility', - 'cte' => 'CTE', - 'recursive_cte' => 'RecursiveCTE', - 'cidr' => 'CIDR', - 'cli' => 'CLI', - 'dn' => 'DN', - 'hmac_token' => 'HMACToken', - 'html' => 'HTML', - 'html_parser' => 'HTMLParser', - 'html_gitlab' => 'HTMLGitlab', - 'http' => 'HTTP', - 'http_connection_adapter' => 'HTTPConnectionAdapter', - 'http_clone_enabled_check' => 'HTTPCloneEnabledCheck', - 'chunked_io' => 'ChunkedIO', - 'http_io' => 'HttpIO', - 'json' => 'JSON', - 'json_formatter' => 'JSONFormatter', - 'json_web_token' => 'JSONWebToken', - 'as_json' => 'AsJSON', - 'ldap_key' => 'LDAPKey', - 'mr_note' => 'MRNote', - 'pdf' => 'PDF', - 'rsa_token' => 'RSAToken', - 'san_extension' => 'SANExtension', - 'sca' => 'SCA', - 'spdx' => 'SPDX', - 'sql' => 'SQL', - 'ssh_key' => 'SSHKey', - 'ssh_key_with_user' => 'SSHKeyWithUser', - 'ssh_public_key' => 'SSHPublicKey', - 'git_push_ssh_proxy' => 'GitPushSSHProxy', - 'git_user_default_ssh_config_check' => 'GitUserDefaultSSHConfigCheck', - 'binary_stl' => 'BinarySTL', - 'text_stl' => 'TextSTL', - 'svg' => 'SVG', - 'function_uri' => 'FunctionURI' - ) -end diff --git a/config/settings.rb b/config/settings.rb index a9e91ce22d7..144a068ef2a 100644 --- a/config/settings.rb +++ b/config/settings.rb @@ -3,6 +3,12 @@ require 'settingslogic' require 'digest/md5' +# We can not use `Rails.root` here, as this file might be loaded without the +# full Rails environment being loaded. We can not use `require_relative` either, +# as Rails uses `load` for `require_dependency` (used when loading the Rails +# environment). This could then lead to this file being loaded twice. +require_dependency File.expand_path('../lib/gitlab', __dir__) + class Settings < Settingslogic source ENV.fetch('GITLAB_CONFIG') { Pathname.new(File.expand_path('..', __dir__)).join('config/gitlab.yml') } namespace ENV.fetch('GITLAB_ENV') { Rails.env } diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md index 9f3e9e3de59..6aa79200f4a 100644 --- a/doc/administration/auth/smartcard.md +++ b/doc/administration/auth/smartcard.md @@ -49,7 +49,7 @@ Certificate: Subject: CN=Gitlab User, emailAddress=gitlab-user@example.com ``` -### Authentication against a local database with X.509 certificates and SAN extensions **(PREMIUM ONLY)** +### Authentication against a local database with X.509 certificates and SAN extension > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/8605) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3. @@ -135,6 +135,12 @@ attribute. As a prerequisite, you must use an LDAP server that: listen *:3444 ssl; ``` + - It can also be configured to run on a different hostname: + + ```plaintext + listen smartcard.example.com:443 ssl; + ``` + - The additional NGINX server context must be configured to require the client side certificate: @@ -156,7 +162,7 @@ attribute. As a prerequisite, you must use an LDAP server that: ```plaintext server { - listen *:3444 ssl; + listen smartcard.example.com:3443 ssl; # certificate for configuring SSL ssl_certificate /path/to/example.com.crt; @@ -195,10 +201,16 @@ attribute. As a prerequisite, you must use an LDAP server that: # Path to a file containing a CA certificate ca_file: '/etc/ssl/certs/CA.pem' - # Port where the client side certificate is requested by NGINX - client_certificate_required_port: 3444 + # Host and port where the client side certificate is requested by the + # webserver (NGINX/Apache) + client_certificate_required_host: smartcard.example.com + client_certificate_required_port: 3443 ``` + NOTE: **Note** + Assign a value to at least one of the following variables: + `client_certificate_required_host` or `client_certificate_required_port`. + 1. Save the file and [restart](../restart_gitlab.md#installations-from-source) GitLab for the changes to take effect. diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md index fff7544139e..535e0ff34d0 100644 --- a/doc/user/admin_area/settings/usage_statistics.md +++ b/doc/user/admin_area/settings/usage_statistics.md @@ -402,6 +402,7 @@ but commented out to help encourage others to add to it in the future. --> |groups|usage_activity_by_stage|manage| |ldap_keys|usage_activity_by_stage|manage| |ldap_users: 0|usage_activity_by_stage|manage| +|users_created|usage_activity_by_stage|manage| |clusters|usage_activity_by_stage|monitor| |clusters_applications_prometheus|usage_activity_by_stage|monitor| |operations_dashboard_default_dashboard|usage_activity_by_stage|monitor| diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md index 7712b86bbe2..5f070ef0f80 100644 --- a/doc/user/group/epics/index.md +++ b/doc/user/group/epics/index.md @@ -350,6 +350,14 @@ You can [award an emoji](../../award_emojis.md) to that epic or its comments. You can [turn on notifications](../../profile/notifications.md) to be alerted about epic events. +## Limits + +This section gives an overview of limits of Epics and an overview of their background. + +### Description and comment length + +See [Issues: Description and comment length](../../project/issues/index.md#description-and-comment-length) +