From 38c1da5195bdcaab0b20bf6303a675b9283ac476 Mon Sep 17 00:00:00 2001
From: GitLab Bot
Date: Wed, 10 May 2023 00:08:52 +0000
Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master
---
.gitlab/ci/rules.gitlab-ci.yml | 6 -
.gitlab/ci/vendored-gems.gitlab-ci.yml | 8 -
Gemfile | 4 +-
Gemfile.lock | 11 +-
.../components/delete_merged_branches.vue | 1 +
app/controllers/application_controller.rb | 15 -
.../omniauth_callbacks_controller.rb | 17 +-
.../concerns/time_frame_arguments.rb | 42 +--
app/graphql/resolvers/milestones_resolver.rb | 2 -
app/models/users/banned_user.rb | 2 +
app/models/users/credit_card_validation.rb | 30 +-
app/policies/identity_provider_policy.rb | 4 +-
app/services/projects/create_service.rb | 3 +
app/views/groups/new.html.haml | 11 +-
.../ci_remove_legacy_predefined_variables.yml | 2 +-
.../development/environment_details_vue.yml | 2 +-
config/gitlab.yml.example | 27 +-
config/initializers/1_settings.rb | 6 +-
.../16_0/16-0-cas3-authentication.yml | 23 ++
doc/api/graphql/reference/index.md | 22 +-
doc/integration/cas.md | 9 +-
doc/update/removals.md | 8 +
.../settings/account_and_limit_settings.md | 11 +
.../dependency_scanning/index.md | 8 +-
doc/user/gitlab_com/index.md | 16 ++
doc/user/project/import/bitbucket_server.md | 4 +-
doc/user/project/import/fogbugz.md | 3 +
doc/user/project/import/gitea.md | 3 +
doc/user/project/import/github.md | 5 +
doc/user/project/import/manifest.md | 3 +
doc/user/project/import/repo_by_url.md | 3 +
doc/user/project/merge_requests/commits.md | 59 ++++
.../merge_requests/img/commit_nav_v16_0.png | Bin 0 -> 10423 bytes
.../img/previously_merged_commits_v16_0.png | Bin 0 -> 15992 bytes
lib/api/project_import.rb | 12 +-
lib/gitlab/auth/o_auth/session.rb | 23 --
.../Jobs/Dependency-Scanning.gitlab-ci.yml | 2 +-
.../Dependency-Scanning.latest.gitlab-ci.yml | 2 +-
.../ci/templates/Jobs/SAST.gitlab-ci.yml | 18 +-
.../templates/Jobs/SAST.latest.gitlab-ci.yml | 24 +-
.../database/migrations/pg_backend_pid.rb | 2 +
lib/gitlab/omniauth_initializer.rb | 14 -
locale/gitlab.pot | 9 +-
qa/qa/page/component/import/selection.rb | 4 +
qa/qa/page/project/branches/show.rb | 2 +
qa/qa/page/project/new.rb | 8 +-
.../import/import_github_repo_spec.rb | 4 +
.../import/import_github_repo_spec.rb | 2 +
.../revert/reverting_merge_request_spec.rb | 2 +
.../view_merge_request_diff_patch_spec.rb | 2 +
.../online_garbage_collection_spec.rb | 2 +
.../terraform_module_registry_spec.rb | 2 +
.../maven/maven_group_level_spec.rb | 2 +
.../maven/maven_project_level_spec.rb | 2 +
qa/qa/support/helpers/import_source.rb | 19 ++
.../import/fogbugz_controller_spec.rb | 2 +
.../import/gitea_controller_spec.rb | 4 +
.../import/manifest_controller_spec.rb | 2 +
.../profiles/accounts_controller_spec.rb | 16 +-
spec/features/admin/admin_settings_spec.rb | 11 -
.../file_uploads/project_import_spec.rb | 4 +
spec/features/import/manifest_import_spec.rb | 2 +
spec/features/oauth_login_spec.rb | 2 +-
spec/features/oauth_registration_spec.rb | 1 -
.../environments/environments_spec.rb | 2 +-
.../import_export/import_file_spec.rb | 1 +
spec/features/projects/new_project_spec.rb | 4 +
.../delete_merged_branches_spec.js.snap | 1 +
.../notes/components/notes_app_spec.js | 4 +-
.../new/preserve_url_fragment_spec.js | 10 -
.../group_milestones_resolver_spec.rb | 66 ++---
.../project_milestones_resolver_spec.rb | 38 ---
spec/helpers/profiles_helper_spec.rb | 42 +--
.../migrations/pg_backend_pid_spec.rb | 8 +
.../fogbugz_import/project_creator_spec.rb | 6 +-
.../project_creator_spec.rb | 2 +
.../manifest_import/project_creator_spec.rb | 4 +-
spec/lib/gitlab/omniauth_initializer_spec.rb | 8 -
.../users/credit_card_validation_spec.rb | 103 +++++++
.../policies/identity_provider_policy_spec.rb | 10 +-
.../api/graphql/group/milestones_spec.rb | 6 -
.../api/graphql/project/milestones_spec.rb | 29 --
spec/requests/api/project_import_spec.rb | 20 ++
spec/requests/api/projects_spec.rb | 1 +
.../requests/import/github_controller_spec.rb | 2 +
.../import/github_groups_controller_spec.rb | 2 +
.../import/gitlab_projects_controller_spec.rb | 2 +
spec/services/import/fogbugz_service_spec.rb | 1 +
.../create_project_service_spec.rb | 1 +
spec/services/projects/create_service_spec.rb | 4 +
vendor/gems/omniauth-cas3/.gitlab-ci.yml | 28 --
vendor/gems/omniauth-cas3/Gemfile | 4 -
vendor/gems/omniauth-cas3/Gemfile.lock | 65 -----
vendor/gems/omniauth-cas3/LICENSE | 23 --
vendor/gems/omniauth-cas3/README.md | 134 ---------
vendor/gems/omniauth-cas3/Rakefile | 15 -
.../gems/omniauth-cas3/lib/omniauth-cas3.rb | 1 -
.../gems/omniauth-cas3/lib/omniauth/cas3.rb | 2 -
.../lib/omniauth/cas3/version.rb | 5 -
.../lib/omniauth/strategies/cas3.rb | 227 ---------------
.../strategies/cas3/logout_request.rb | 73 -----
.../cas3/service_ticket_validator.rb | 103 -------
.../gems/omniauth-cas3/omniauth-cas3.gemspec | 27 --
.../spec/fixtures/cas_failure.xml | 4 -
.../spec/fixtures/cas_success.xml | 14 -
.../spec/fixtures/cas_success_jasig.xml | 16 --
.../strategies/cas3/logout_request_spec.rb | 127 ---------
.../cas3/service_ticket_validator_spec.rb | 55 ----
.../spec/omniauth/strategies/cas3_spec.rb | 266 ------------------
vendor/gems/omniauth-cas3/spec/spec_helper.rb | 13 -
110 files changed, 506 insertions(+), 1644 deletions(-)
create mode 100644 data/removals/16_0/16-0-cas3-authentication.yml
create mode 100644 doc/user/project/merge_requests/commits.md
create mode 100644 doc/user/project/merge_requests/img/commit_nav_v16_0.png
create mode 100644 doc/user/project/merge_requests/img/previously_merged_commits_v16_0.png
delete mode 100644 lib/gitlab/auth/o_auth/session.rb
create mode 100644 qa/qa/support/helpers/import_source.rb
delete mode 100644 vendor/gems/omniauth-cas3/.gitlab-ci.yml
delete mode 100644 vendor/gems/omniauth-cas3/Gemfile
delete mode 100644 vendor/gems/omniauth-cas3/Gemfile.lock
delete mode 100644 vendor/gems/omniauth-cas3/LICENSE
delete mode 100644 vendor/gems/omniauth-cas3/README.md
delete mode 100644 vendor/gems/omniauth-cas3/Rakefile
delete mode 100644 vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb
delete mode 100644 vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb
delete mode 100644 vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb
delete mode 100644 vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb
delete mode 100644 vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb
delete mode 100644 vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb
delete mode 100644 vendor/gems/omniauth-cas3/omniauth-cas3.gemspec
delete mode 100644 vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml
delete mode 100644 vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml
delete mode 100644 vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml
delete mode 100644 vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb
delete mode 100644 vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb
delete mode 100644 vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb
delete mode 100644 vendor/gems/omniauth-cas3/spec/spec_helper.rb
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 87641327d97..82f46df80a7 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -2042,12 +2042,6 @@
changes: ["vendor/gems/omniauth-azure-oauth2/**/*"]
- <<: *if-merge-request-labels-run-all-rspec
-.vendor:rules:omniauth-cas3:
- rules:
- - <<: *if-merge-request
- changes: ["vendor/gems/omniauth-cas3/**/*"]
- - <<: *if-merge-request-labels-run-all-rspec
-
.vendor:rules:omniauth_crowd:
rules:
- <<: *if-merge-request
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index a2af802c659..3773a343d6d 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -38,14 +38,6 @@ vendor omniauth-azure-oauth2:
include: vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
strategy: depend
-vendor omniauth-cas3:
- extends:
- - .vendor:rules:omniauth-cas3
- needs: []
- trigger:
- include: vendor/gems/omniauth-cas3/.gitlab-ci.yml
- strategy: depend
-
vendor omniauth_crowd:
extends:
- .vendor:rules:omniauth_crowd
diff --git a/Gemfile b/Gemfile
index b60a3e3181d..e1d07891f06 100644
--- a/Gemfile
+++ b/Gemfile
@@ -53,7 +53,6 @@ gem 'omniauth', '~> 2.1.0'
gem 'omniauth-auth0', '~> 3.1'
gem 'omniauth-azure-activedirectory-v2', '~> 2.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9', path: 'vendor/gems/omniauth-azure-oauth2' # See gem README.md
-gem 'omniauth-cas3', '~> 1.1.4', path: 'vendor/gems/omniauth-cas3' # See vendor/gems/omniauth-cas3/README.md
gem 'omniauth-dingtalk-oauth2', '~> 1.0'
gem 'omniauth-alicloud', '~> 2.0.1'
gem 'omniauth-facebook', '~> 4.0.0'
@@ -457,7 +456,8 @@ group :test do
gem 'capybara', '~> 3.39'
gem 'capybara-screenshot', '~> 1.0.26'
- gem 'selenium-webdriver', '~> 4.9.0'
+ # 4.9.1 drops Ruby 2.7 support. We can upgrade further after we drop Ruby 2.7 support.
+ gem 'selenium-webdriver', '= 4.9.0'
gem 'graphlyte', '~> 1.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index ddd70e5f856..c1fd5ac738f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -61,14 +61,6 @@ PATH
omniauth (~> 2.0)
omniauth-oauth2 (~> 1.4)
-PATH
- remote: vendor/gems/omniauth-cas3
- specs:
- omniauth-cas3 (1.1.4)
- addressable (~> 2.3)
- nokogiri (~> 1.7, >= 1.7.1)
- omniauth (~> 2.0)
-
PATH
remote: vendor/gems/omniauth-gitlab
specs:
@@ -1849,7 +1841,6 @@ DEPENDENCIES
omniauth-auth0 (~> 3.1)
omniauth-azure-activedirectory-v2 (~> 2.0)
omniauth-azure-oauth2 (~> 0.0.9)!
- omniauth-cas3 (~> 1.1.4)!
omniauth-dingtalk-oauth2 (~> 1.0)
omniauth-facebook (~> 4.0.0)
omniauth-github (= 2.0.1)
@@ -1920,7 +1911,7 @@ DEPENDENCIES
sassc-rails (~> 2.1.0)
sd_notify (~> 0.1.0)
seed-fu (~> 2.3.7)
- selenium-webdriver (~> 4.9.0)
+ selenium-webdriver (= 4.9.0)
semver_dialects (~> 1.2.1)
sentry-rails (~> 5.8.0)
sentry-raven (~> 3.1)
diff --git a/app/assets/javascripts/branches/components/delete_merged_branches.vue b/app/assets/javascripts/branches/components/delete_merged_branches.vue
index 73d7a59e67e..d9d8f1d742d 100644
--- a/app/assets/javascripts/branches/components/delete_merged_branches.vue
+++ b/app/assets/javascripts/branches/components/delete_merged_branches.vue
@@ -102,6 +102,7 @@ export default {
category="tertiary"
no-caret
placement="right"
+ data-qa-selector="delete_merged_branches_dropdown_button"
:items="dropdownItems"
/>
{ !current_user }
before_action :authenticate_user!, except: [:route_not_found]
before_action :enforce_terms!, if: :should_enforce_terms?
- before_action :validate_user_service_ticket!
before_action :check_password_expiration, if: :html_request?
before_action :ldap_security_check
before_action :default_headers
@@ -326,20 +325,6 @@ class ApplicationController < ActionController::Base
headers['Content-Disposition'] = "attachment; filename=\"#{csv_filename}\""
end
- def validate_user_service_ticket!
- return unless signed_in? && session[:service_tickets]
-
- valid = session[:service_tickets].all? do |provider, ticket|
- Gitlab::Auth::OAuth::Session.valid?(provider, ticket)
- end
-
- unless valid
- session[:service_tickets] = nil
- sign_out current_user
- redirect_to new_user_session_path
- end
- end
-
def check_password_expiration
return if session[:impersonator_id] || !current_user&.allow_password_authentication?
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index b9964e8ca01..a2e0670d7e1 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -10,7 +10,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
after_action :verify_known_sign_in
- protect_from_forgery except: [:cas3, :failure] + AuthHelper.saml_providers, with: :exception, prepend: true
+ protect_from_forgery except: [:failure] + AuthHelper.saml_providers, with: :exception, prepend: true
feature_category :system_access
@@ -57,15 +57,6 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_unverified_saml_initiation
end
- def cas3
- ticket = params['ticket']
- if ticket
- handle_service_ticket oauth['provider'], ticket
- end
-
- handle_omniauth
- end
-
def auth0
if oauth['uid'].blank?
fail_auth0_login
@@ -146,12 +137,6 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to profile_account_path, notice: _('Authentication method updated')
end
- def handle_service_ticket(provider, ticket)
- Gitlab::Auth::OAuth::Session.create provider, ticket
- session[:service_tickets] ||= {}
- session[:service_tickets][provider] = ticket
- end
-
def build_auth_user(auth_user_class)
auth_user_class.new(oauth)
end
diff --git a/app/graphql/resolvers/concerns/time_frame_arguments.rb b/app/graphql/resolvers/concerns/time_frame_arguments.rb
index 87b7a96045c..c26898bb2f1 100644
--- a/app/graphql/resolvers/concerns/time_frame_arguments.rb
+++ b/app/graphql/resolvers/concerns/time_frame_arguments.rb
@@ -3,51 +3,15 @@
module TimeFrameArguments
extend ActiveSupport::Concern
- OVERLAPPING_TIMEFRAME_DESC = 'List items overlapping a time frame defined by startDate..endDate (if one date is provided, both must be present)'
-
included do
- argument :start_date, Types::TimeType,
- required: false,
- description: OVERLAPPING_TIMEFRAME_DESC,
- deprecated: { reason: 'Use timeframe.start', milestone: '13.5' }
-
- argument :end_date, Types::TimeType,
- required: false,
- description: OVERLAPPING_TIMEFRAME_DESC,
- deprecated: { reason: 'Use timeframe.end', milestone: '13.5' }
-
argument :timeframe, Types::TimeframeInputType,
required: false,
description: 'List items overlapping the given timeframe.'
end
- # TODO: remove when the start_date and end_date arguments are removed
- def validate_timeframe_params!(args)
- return unless %i[start_date end_date timeframe].any? { |k| args[k].present? }
-
- # the timeframe is passed in as a TimeframeInputType
- timeframe = args[:timeframe].to_h if args[:timeframe]
- return if timeframe && %i[start_date end_date].all? { |k| args[k].nil? }
-
- error_message =
- if timeframe.present?
- "startDate and endDate are deprecated in favor of timeframe. Please use only timeframe."
- elsif args[:start_date].nil? || args[:end_date].nil?
- "Both startDate and endDate must be present."
- elsif args[:start_date] > args[:end_date]
- "startDate is after endDate"
- end
-
- if error_message
- raise Gitlab::Graphql::Errors::ArgumentError, error_message
- end
- end
-
def transform_timeframe_parameters(args)
- if args[:timeframe]
- args[:timeframe].to_h.transform_keys { |k| :"#{k}_date" }
- else
- args.slice(:start_date, :end_date)
- end
+ return {} unless args[:timeframe]
+
+ args[:timeframe].to_h.transform_keys { |k| :"#{k}_date" }
end
end
diff --git a/app/graphql/resolvers/milestones_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb
index 25ff783b408..563c6594665 100644
--- a/app/graphql/resolvers/milestones_resolver.rb
+++ b/app/graphql/resolvers/milestones_resolver.rb
@@ -40,8 +40,6 @@ module Resolvers
NON_STABLE_CURSOR_SORTS = %i[expired_last_due_date_asc expired_last_due_date_desc].freeze
def resolve_with_lookahead(**args)
- validate_timeframe_params!(args)
-
milestones = apply_lookahead(MilestonesFinder.new(milestones_finder_params(args)).execute)
if non_stable_cursor_sort?(args[:sort])
diff --git a/app/models/users/banned_user.rb b/app/models/users/banned_user.rb
index 466fc71f83a..8a62744c7d6 100644
--- a/app/models/users/banned_user.rb
+++ b/app/models/users/banned_user.rb
@@ -5,6 +5,8 @@ module Users
self.primary_key = :user_id
belongs_to :user
+ has_one :credit_card_validation, class_name: '::Users::CreditCardValidation', primary_key: 'user_id',
+ foreign_key: 'user_id', inverse_of: :banned_user
validates :user, presence: true
validates :user_id, uniqueness: { message: N_("banned user already exists") }
diff --git a/app/models/users/credit_card_validation.rb b/app/models/users/credit_card_validation.rb
index 272f31aa9ce..1b0fd8682db 100644
--- a/app/models/users/credit_card_validation.rb
+++ b/app/models/users/credit_card_validation.rb
@@ -7,6 +7,8 @@ module Users
self.table_name = 'user_credit_card_validations'
belongs_to :user
+ belongs_to :banned_user, class_name: '::Users::BannedUser', foreign_key: :user_id,
+ inverse_of: :credit_card_validation
validates :holder_name, length: { maximum: 50 }
validates :network, length: { maximum: 32 }
@@ -14,18 +16,32 @@ module Users
greater_than_or_equal_to: 0, less_than_or_equal_to: 9999
}
+ scope :by_banned_user, -> { joins(:banned_user) }
+ scope :similar_by_holder_name, ->(holder_name) do
+ if holder_name.present?
+ where('lower(holder_name) = lower(:value)', value: holder_name)
+ else
+ none
+ end
+ end
+ scope :similar_to, ->(credit_card_validation) do
+ where(
+ expiration_date: credit_card_validation.expiration_date,
+ last_digits: credit_card_validation.last_digits,
+ network: credit_card_validation.network
+ )
+ end
+
def similar_records
- self.class.where(
- expiration_date: expiration_date,
- last_digits: last_digits,
- network: network
- ).order(credit_card_validated_at: :desc).includes(:user)
+ self.class.similar_to(self).order(credit_card_validated_at: :desc).includes(:user)
end
def similar_holder_names_count
- return 0 unless holder_name
+ self.class.similar_by_holder_name(holder_name).count
+ end
- self.class.where('lower(holder_name) = lower(:value)', value: holder_name).count
+ def used_by_banned_user?
+ self.class.by_banned_user.similar_to(self).similar_by_holder_name(holder_name).exists?
end
end
end
diff --git a/app/policies/identity_provider_policy.rb b/app/policies/identity_provider_policy.rb
index c539fc64d3f..1e748c78555 100644
--- a/app/policies/identity_provider_policy.rb
+++ b/app/policies/identity_provider_policy.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class IdentityProviderPolicy < BasePolicy
- desc "Provider is SAML or CAS3"
- condition(:protected_provider, scope: :subject, score: 0) { %w(saml cas3).include?(@subject.to_s) }
+ desc "Provider is SAML"
+ condition(:protected_provider, scope: :subject, score: 0) { @subject.to_s == 'saml' }
rule { anonymous }.prevent_all
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index ac19f21ffc7..8ad2b0ac761 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -294,6 +294,9 @@ module Projects
return if INTERNAL_IMPORT_SOURCES.include?(import_type)
+ # Skip validation when creating project from a built in template
+ return if @params[:import_export_upload].present? && import_type == 'gitlab_project'
+
unless ::Gitlab::CurrentSettings.import_sources&.include?(import_type)
raise ImportSourceDisabledError, "#{import_type} import source is disabled"
end
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 1d306d4d3b8..88cb8d989fa 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -16,11 +16,6 @@
= render 'new_group_fields', f: f, group_name_id: 'create-group-name'
#import-group-pane.tab-pane
- - if import_sources_enabled?
- = render 'import_group_from_another_instance_panel'
- .gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
- = render 'import_group_from_file_panel'
- - else
- .nothing-here-block
- %h4= s_('GroupsNew|No import options available')
- %p= s_('GroupsNew|Contact an administrator to enable options for importing your group.')
+ = render 'import_group_from_another_instance_panel'
+ .gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
+ = render 'import_group_from_file_panel'
diff --git a/config/feature_flags/development/ci_remove_legacy_predefined_variables.yml b/config/feature_flags/development/ci_remove_legacy_predefined_variables.yml
index dd54b9d6d2a..48f09f39dff 100644
--- a/config/feature_flags/development/ci_remove_legacy_predefined_variables.yml
+++ b/config/feature_flags/development/ci_remove_legacy_predefined_variables.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/404533
milestone: '15.11'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/environment_details_vue.yml b/config/feature_flags/development/environment_details_vue.yml
index c757329c271..c90038a600c 100644
--- a/config/feature_flags/development/environment_details_vue.yml
+++ b/config/feature_flags/development/environment_details_vue.yml
@@ -5,4 +5,4 @@ rollout_issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/384914"
milestone: '15.7'
type: development
group: group::configure
-default_enabled: false
+default_enabled: true
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 4c1ca26e004..e46bc5b646c 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -127,8 +127,8 @@ production: &base
# username_changing_enabled: false # default: true - User can change their username/namespace
## Default theme ID
## 1 - Indigo
- ## 2 - Dark
- ## 3 - Light
+ ## 2 - Gray
+ ## 3 - Light Gray
## 4 - Blue
## 5 - Green
## 6 - Light Indigo
@@ -136,6 +136,7 @@ production: &base
## 8 - Light Green
## 9 - Red
## 10 - Light Red
+ ## 11 - Dark Mode (alpha)
# default_theme: 1 # default: 1
## Automatic issue closing
@@ -1001,7 +1002,7 @@ production: &base
# auto_sign_in_with_provider: saml
# Sync user's profile from the specified Omniauth providers every time the user logs in (default: empty).
- # Define the allowed providers using an array, e.g. ["cas3", "saml", "twitter"],
+ # Define the allowed providers using an array, e.g. ["saml", "twitter"],
# or as true/false to allow all providers or none.
# When authenticating using LDAP, the user's email is always synced.
# sync_profile_from_provider: []
@@ -1067,15 +1068,6 @@ production: &base
# - { name: 'alicloud',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET' }
- # See omniauth-cas3 for more configuration details
- # - { name: 'cas3',
- # label: 'cas3',
- # args: {
- # url: 'https://sso.example.com',
- # disable_ssl_verification: false,
- # login_url: '/cas/login',
- # service_validate_url: '/cas/p3/serviceValidate',
- # logout_url: '/cas/logout' } }
# - { name: 'github',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET',
@@ -1139,10 +1131,6 @@ production: &base
# client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
# namespace: 'YOUR_AUTH0_DOMAIN' } }
- # SSO maximum session duration in seconds. Defaults to CAS default of 8 hours.
- # cas3:
- # session_duration: 28800
-
# FortiAuthenticator settings
forti_authenticator:
# Allow using FortiAuthenticator as OTP provider
@@ -1583,13 +1571,6 @@ test:
- { name: 'alicloud',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
- - { name: 'cas3',
- label: 'cas3',
- args: { url: 'https://sso.example.com',
- disable_ssl_verification: false,
- login_url: '/cas/login',
- service_validate_url: '/cas/p3/serviceValidate',
- logout_url: '/cas/logout' } }
- { name: 'github',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 6b41b32e15c..a3076f0014d 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -112,10 +112,6 @@ if Settings.omniauth['sync_email_from_provider']
end
Settings.omniauth['providers'] ||= []
-Settings.omniauth['cas3'] ||= {}
-Settings.omniauth.cas3['session_duration'] ||= 8.hours
-Settings.omniauth['session_tickets'] ||= {}
-Settings.omniauth.session_tickets['cas3'] = 'ticket'
# Handle backward compatibility with the renamed kerberos_spnego provider
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96335#note_1094265436
@@ -232,7 +228,7 @@ Settings.gitlab.default_projects_features['builds'] = true if Settin
Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil?
Settings.gitlab.default_projects_features['visibility_level'] = Settings.__send__(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
Settings.gitlab['domain_allowlist'] ||= []
-Settings.gitlab['import_sources'] ||= Gitlab::ImportSources.values
+Settings.gitlab['import_sources'] ||= []
Settings.gitlab['trusted_proxies'] ||= []
Settings.gitlab['content_security_policy'] ||= {}
Settings.gitlab['allowed_hosts'] ||= []
diff --git a/data/removals/16_0/16-0-cas3-authentication.yml b/data/removals/16_0/16-0-cas3-authentication.yml
new file mode 100644
index 00000000000..cd85f1bd38d
--- /dev/null
+++ b/data/removals/16_0/16-0-cas3-authentication.yml
@@ -0,0 +1,23 @@
+# This is a template for announcing a feature removal or other important change.
+#
+# Please refer to the deprecation guidelines to confirm your understanding of GitLab's definitions.
+# https://docs.gitlab.com/ee/development/deprecation_guidelines/#terminology
+#
+# If this is a breaking change, it must happen in a major release.
+#
+# For more information please refer to the handbook documentation here:
+# https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-and-other-planned-breaking-change-announcements
+#
+# Please delete this line and above before submitting your merge request.
+#
+# REQUIRED FIELDS
+#
+- title: "CAS OmniAuth provider is removed" # (required) Clearly explain the change. For example, "The `confidential` field for a `Note` is removed" or "CI/CD job names are limited to 250 characters."
+ announcement_milestone: "15.3" # (required) The milestone when this feature was deprecated.
+ removal_milestone: "16.0" # (required) The milestone when this feature is being removed.
+ breaking_change: true # (required) Change to false if this is not a breaking change.
+ reporter: jessieay # (required) GitLab username of the person reporting the removal
+ stage: Manage # (required) String value of the stage that the feature was created in. e.g., Growth
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369127 # (required) Link to the deprecation issue in GitLab
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ The `omniauth-cas3` gem that provides GitLab with the CAS OmniAuth provider is being removed. You can no longer authenticate into a GitLab instance through CAS. This gem sees very little use. [The gem](https://rubygems.org/gems/omniauth-cas3/) has not had a new release in almost 5 years, which means that its dependencies are out of date and required manual patching during GitLab's [upgrade to OmniAuth 2.0](https://gitlab.com/gitlab-org/gitlab/-/issues/30073).
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index ed67905e6b1..560f1a4c60a 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -11815,7 +11815,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
| `createdAfter` | [`Time`](#time) | Epics created after this date. |
| `createdBefore` | [`Time`](#time) | Epics created before this date. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| `iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| `iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. |
@@ -11829,7 +11828,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| `search` | [`String`](#string) | Search query for title or description. |
| `sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`EpicState`](#epicstate) | Filter epics by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. |
@@ -11854,7 +11852,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
| `createdAfter` | [`Time`](#time) | Epics created after this date. |
| `createdBefore` | [`Time`](#time) | Epics created before this date. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| `iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| `iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. |
@@ -11868,7 +11865,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| `search` | [`String`](#string) | Search query for title or description. |
| `sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`EpicState`](#epicstate) | Filter epics by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. |
@@ -14011,7 +14007,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
| `createdAfter` | [`Time`](#time) | Epics created after this date. |
| `createdBefore` | [`Time`](#time) | Epics created before this date. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| `iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| `iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. |
@@ -14025,7 +14020,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| `search` | [`String`](#string) | Search query for title or description. |
| `sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`EpicState`](#epicstate) | Filter epics by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. |
@@ -14050,7 +14044,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
| `createdAfter` | [`Time`](#time) | Epics created after this date. |
| `createdBefore` | [`Time`](#time) | Epics created before this date. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| `iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| `iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. |
@@ -14064,7 +14057,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| `search` | [`String`](#string) | Search query for title or description. |
| `sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`EpicState`](#epicstate) | Filter epics by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. |
@@ -15126,7 +15118,6 @@ Returns [`Epic`](#epic).
| `confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
| `createdAfter` | [`Time`](#time) | Epics created after this date. |
| `createdBefore` | [`Time`](#time) | Epics created before this date. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| `iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| `iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. |
@@ -15140,7 +15131,6 @@ Returns [`Epic`](#epic).
| `or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| `search` | [`String`](#string) | Search query for title or description. |
| `sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`EpicState`](#epicstate) | Filter epics by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. |
@@ -15177,7 +15167,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. |
| `createdAfter` | [`Time`](#time) | Epics created after this date. |
| `createdBefore` | [`Time`](#time) | Epics created before this date. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `iid` | [`ID`](#id) | IID of the epic, e.g., "1". |
| `iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. |
| `iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. |
@@ -15191,7 +15180,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| `search` | [`String`](#string) | Search query for title or description. |
| `sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`EpicState`](#epicstate) | Filter epics by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. |
@@ -15317,7 +15305,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `id` | [`ID`](#id) | Global ID of the Iteration to look up. |
| `iid` | [`ID`](#id) | Internal ID of the Iteration to look up. |
| `in` | [`[IterationSearchableField!]`](#iterationsearchablefield) | Fields in which the fuzzy-search should be performed with the query given in the argument `search`. Defaults to `[title]`. |
@@ -15325,7 +15312,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `iterationCadenceIds` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Global iteration cadence IDs by which to look up the iterations. |
| `search` | [`String`](#string) | Query used for fuzzy-searching in the fields selected in the argument `in`. Returns all iterations if empty. |
| `sort` | [`IterationSort`](#iterationsort) | List iterations by sort order. If unspecified, an arbitrary order (subject to change) is used. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`IterationState`](#iterationstate) | Filter iterations by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `title` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.4. The argument will be removed in 15.4. Please use `search` and `in` fields instead. |
@@ -15428,13 +15414,11 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| `containingDate` | [`Time`](#time) | Date the milestone contains. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `ids` | [`[ID!]`](#id) | Array of global milestone IDs, e.g., `"gid://gitlab/Milestone/1"`. |
| `includeAncestors` | [`Boolean`](#boolean) | Include milestones from all parent groups. |
| `includeDescendants` | [`Boolean`](#boolean) | Include milestones from all subgroups and subprojects. |
| `searchTitle` | [`String`](#string) | Search string for the title. |
| `sort` | [`MilestoneSort`](#milestonesort) | Sort milestones by this criteria. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`MilestoneStateEnum`](#milestonestateenum) | Filter milestones by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `title` | [`String`](#string) | Title of the milestone. |
@@ -18897,7 +18881,6 @@ Represents a product analytics dashboard visualization.
| `issuesEnabled` | [`Boolean`](#boolean) | Indicates if Issues are enabled for the current user. |
| `jiraImportStatus` | [`String`](#string) | Status of Jira import background job of the project. |
| `jiraImports` | [`JiraImportConnection`](#jiraimportconnection) | Jira imports into the project. (see [Connections](#connections)) |
-| `jitsuKey` **{warning-solid}** | [`String`](#string) | **Introduced** in 15.7. This feature is an Experiment. It can be changed or removed at any time. Jitsu key assigned to the project. |
| `jobsEnabled` | [`Boolean`](#boolean) | Indicates if CI/CD pipeline jobs are enabled for the current user. |
| `languages` | [`[RepositoryLanguage!]`](#repositorylanguage) | Programming languages used in the project. |
| `lastActivityAt` | [`Time`](#time) | Timestamp of the project last activity. |
@@ -18945,6 +18928,7 @@ Represents a product analytics dashboard visualization.
| `terraformStates` | [`TerraformStateConnection`](#terraformstateconnection) | Terraform states associated with the project. (see [Connections](#connections)) |
| `timelogCategories` **{warning-solid}** | [`TimeTrackingTimelogCategoryConnection`](#timetrackingtimelogcategoryconnection) | **Introduced** in 15.3. This feature is an Experiment. It can be changed or removed at any time. Timelog categories for the project. |
| `topics` | [`[String!]`](#string) | List of project topics. |
+| `trackingKey` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.0. This feature is an Experiment. It can be changed or removed at any time. Tracking key assigned to the project. |
| `userAccessAuthorizedAgents` | [`ClusterAgentAuthorizationUserAccessConnection`](#clusteragentauthorizationuseraccessconnection) | Authorized cluster agents for the project through user_access keyword. (see [Connections](#connections)) |
| `userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource. |
| `visibility` | [`String`](#string) | Visibility of the project. |
@@ -19614,7 +19598,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `id` | [`ID`](#id) | Global ID of the Iteration to look up. |
| `iid` | [`ID`](#id) | Internal ID of the Iteration to look up. |
| `in` | [`[IterationSearchableField!]`](#iterationsearchablefield) | Fields in which the fuzzy-search should be performed with the query given in the argument `search`. Defaults to `[title]`. |
@@ -19622,7 +19605,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
| `iterationCadenceIds` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Global iteration cadence IDs by which to look up the iterations. |
| `search` | [`String`](#string) | Query used for fuzzy-searching in the fields selected in the argument `in`. Returns all iterations if empty. |
| `sort` | [`IterationSort`](#iterationsort) | List iterations by sort order. If unspecified, an arbitrary order (subject to change) is used. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`IterationState`](#iterationstate) | Filter iterations by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `title` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.4. The argument will be removed in 15.4. Please use `search` and `in` fields instead. |
@@ -19746,12 +19728,10 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| `containingDate` | [`Time`](#time) | Date the milestone contains. |
-| `endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. |
| `ids` | [`[ID!]`](#id) | Array of global milestone IDs, e.g., `"gid://gitlab/Milestone/1"`. |
| `includeAncestors` | [`Boolean`](#boolean) | Also return milestones in the project's parent group and its ancestors. |
| `searchTitle` | [`String`](#string) | Search string for the title. |
| `sort` | [`MilestoneSort`](#milestonesort) | Sort milestones by this criteria. |
-| `startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
| `state` | [`MilestoneStateEnum`](#milestonestateenum) | Filter milestones by state. |
| `timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. |
| `title` | [`String`](#string) | Title of the milestone. |
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index 9cbd8cf03d5..bfeabde8a36 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -2,13 +2,16 @@
stage: Manage
group: Authentication and Authorization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+remove_date: '2023-08-15'
+redirect_to: '../administration/auth/index.md'
---
-# CAS OmniAuth provider (deprecated) **(FREE SELF)**
+# CAS OmniAuth provider (removed) **(FREE SELF)**
WARNING:
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/369127) in GitLab 15.3 and is planned for
-removal in 16.0.
+This feature was
+[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/369127) in GitLab
+15.3 and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/369128) in 16.0.
To enable the CAS OmniAuth provider you must register your application with your
CAS instance. This requires the service URL GitLab supplies to CAS. It should be
diff --git a/doc/update/removals.md b/doc/update/removals.md
index 17bcbd8d72d..3e72b2a7a5e 100644
--- a/doc/update/removals.md
+++ b/doc/update/removals.md
@@ -59,6 +59,14 @@ The Azure Storage Driver used to write to `//` as the default root directory. Th
In GitLab 16.0, the new default configuration for the storage driver uses `trimlegacyrootprefix: true`, and `/` is the default root directory. You can set your configuration to `trimlegacyrootprefix: false` if needed, to revert to the previous behavior.
+### CAS OmniAuth provider is removed
+
+WARNING:
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
+Review the details carefully before upgrading.
+
+The `omniauth-cas3` gem that provides GitLab with the CAS OmniAuth provider is being removed. You can no longer authenticate into a GitLab instance through CAS. This gem sees very little use. [The gem](https://rubygems.org/gems/omniauth-cas3/) has not had a new release in almost 5 years, which means that its dependencies are out of date and required manual patching during GitLab's [upgrade to OmniAuth 2.0](https://gitlab.com/gitlab-org/gitlab/-/issues/30073).
+
### CiCdSettingsUpdate mutation renamed to ProjectCiCdSettingsUpdate
WARNING:
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index e4176ae16e6..0abaf32bad0 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -332,6 +332,17 @@ By default, newly created users have a public profile. GitLab administrators can
1. On the left sidebar, select **Settings > General**, then expand **Account and limit**.
1. Select the **Make new users' profiles private by default** checkbox.
+## Prevent users from deleting their accounts **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26053) in GitLab 16.0 [with a flag](../../../administration/feature_flags.md) named `deleting_account_disabled_for_users`. Disabled by default.
+
+By default, users can delete their own accounts. GitLab administrators can prevent
+users from deleting their own accounts:
+
+1. On the top bar, select **Main menu > Admin**.
+1. On the left sidebar, select **Settings > General**, then expand **Account and limit**.
+1. Clear the **Allows users to delete their own accounts** checkbox.
+
## Troubleshooting
### 413 Request Entity Too Large
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index ba70a77d8c0..91f10b5ab60 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -331,7 +331,7 @@ table.supported-languages ul {
gemnasium-dependency_scanning:
image:
- name: $CI_TEMPLATE_REGISTRY_HOST/security-products/gemnasium-python:3-python-3.10
+ name: $CI_TEMPLATE_REGISTRY_HOST/security-products/gemnasium-python:4-python-3.10
@@ -1010,9 +1010,9 @@ import the following default dependency scanning analyzer images from `registry.
your [local Docker container registry](../../packages/container_registry/index.md):
```plaintext
-registry.gitlab.com/security-products/gemnasium:3
-registry.gitlab.com/security-products/gemnasium-maven:3
-registry.gitlab.com/security-products/gemnasium-python:3
+registry.gitlab.com/security-products/gemnasium:4
+registry.gitlab.com/security-products/gemnasium-maven:4
+registry.gitlab.com/security-products/gemnasium-python:4
```
The process for importing Docker images into a local offline Docker registry depends on
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 76cd94452a8..c90bfba6830 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -208,6 +208,22 @@ NOTE:
Cloudflare. Git LFS and imports other than a file upload are not affected by
this limit. Repository limits apply to both public and private projects.
+## Import sources
+
+GitLab.com has the following import sources enabled.
+
+| Import source | GitLab.com default | Default (self-managed) |
+|------------------------|--------------------| ---------------------------|
+| Bitbucket Cloud | **{check-circle}** Yes | **{dotted-circle}** No |
+| Bitbucket Server | **{check-circle}** Yes | **{dotted-circle}** No |
+| FogBugz | **{check-circle}** Yes | **{dotted-circle}** No |
+| GitLab Direct Transfer | **{check-circle}** Yes | **{dotted-circle}** No |
+| Gitea | **{check-circle}** Yes | **{dotted-circle}** No |
+| GitHub | **{check-circle}** Yes | **{dotted-circle}** No |
+| GitLab export | **{check-circle}** Yes | **{dotted-circle}** No |
+| Manifest file | **{check-circle}** Yes | **{dotted-circle}** No |
+| Repository by URL | **{check-circle}** Yes | **{dotted-circle}** No |
+
## IP range
GitLab.com uses the IP ranges `34.74.90.64/28` and `34.74.226.0/24` for traffic from its Web/API
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index c7dfc739b71..22f81365755 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -27,7 +27,9 @@ created as private in GitLab as well.
Prerequisites:
-- An administrator must enable **Bitbucket Server** in **Admin > Settings > General > Visibility and access controls > Import sources**.
+- [Bitbucket Server import source](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources)
+must be enabled. If not enabled, ask your GitLab administrator to enable it. The Bitbucket Server import source is enabled
+by default on GitLab.com.
- At least the Maintainer role on the destination group to import to. Using the Developer role for this purpose was
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in GitLab 16.0.
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index d66b1dbaa5d..6e378ccbb44 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -17,6 +17,9 @@ users.
Prerequisite:
+- [FogBugz import source](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources)
+must be enabled. If not enabled, ask your GitLab administrator to enable it. The FogBugz import source is enabled
+by default on GitLab.com.
- At least the Maintainer role on the destination group to import to. Using the Developer role for this purpose was
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in GitLab 16.0.
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
index f11dc3e18dc..2eb798fab0f 100644
--- a/doc/user/project/import/gitea.md
+++ b/doc/user/project/import/gitea.md
@@ -15,6 +15,9 @@ This requires Gitea `v1.0.0` or later.
Prerequisite:
+- [Gitea import source](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources)
+must be enabled. If not enabled, ask your GitLab administrator to enable it. The Gitea import source is enabled
+by default on GitLab.com.
- At least the Maintainer role on the destination group to import to. Using the Developer role for this purpose was
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in GitLab 16.0.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 1bd60a037fb..4bbb8cee534 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -38,6 +38,9 @@ For an overview of the import process, see [Migrating from GitHub to GitLab](htt
To import projects from GitHub:
+- [GitHub import source](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources)
+ must be enabled. If not enabled, ask your GitLab administrator to enable it. The GitHub import source is enabled
+ by default on GitLab.com.
- You must have at least the Maintainer role on the destination group to import to. Using the Developer role for this
purpose was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in
GitLab 16.0.
@@ -61,6 +64,8 @@ perimeter is specified in the [OmniAuth configuration](../../../integration/gith
If you are importing from GitHub Enterprise to a self-managed GitLab instance:
- You must first enable the [GitHub integration](../../../integration/github.md).
+- GitHub must be enabled as an import source in the
+ [Admin Area](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources).
- For GitLab 15.10 and earlier, you must add `github.com` and `api.github.com` entries in the
[allowlist for local requests](../../../security/webhooks.md#allow-outbound-requests-to-certain-ip-addresses-and-domains).
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index 8c7f749036c..545fd7810dc 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -17,6 +17,9 @@ repositories like the Android Open Source Project (AOSP).
## Requirements
+- [Manifest import source](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources)
+must be enabled. If not enabled, ask your GitLab administrator to enable it. The Manifest import source is enabled
+by default on GitLab.com.
- GitLab must use PostgreSQL for its database, because [subgroups](../../group/subgroups/index.md) are needed for the manifest import
to work. Read more about the [database requirements](../../../install/requirements.md#database).
- At least the Maintainer role on the destination group to import to. Using the Developer role for this purpose was
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index 0e7a32b785c..9f6d16cc04a 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -8,6 +8,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Prerequisite:
+- [Repository by URL import source](../../admin_area/settings/visibility_and_access_controls.md#configure-allowed-import-sources)
+must be enabled. If not enabled, ask your GitLab administrator to enable it. The Repository by URL import source is enabled
+by default on GitLab.com.
- At least the Maintainer role on the destination group to import to. Using the Developer role for this purpose was
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in GitLab 16.0.
diff --git a/doc/user/project/merge_requests/commits.md b/doc/user/project/merge_requests/commits.md
new file mode 100644
index 00000000000..cc6ecd8398f
--- /dev/null
+++ b/doc/user/project/merge_requests/commits.md
@@ -0,0 +1,59 @@
+---
+stage: Create
+group: Code Review
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+type: index, reference
+---
+
+# Merge request commits **(FREE)**
+
+Each merge request has a history of the commits made to the source branch
+after the merge request was created.
+
+These commits are displayed on the merge request's **Commits** tab.
+From this tab, you can review commit messages and copy a commit's SHA when you need to
+[cherry-pick changes](cherry_pick_changes.md).
+
+## Navigate merge request commits
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0.
+
+To navigate commits in a merge request:
+
+1. Select the **Commits** tab.
+1. Select the commit link. The most recent commit is displayed.
+1. Navigate through the commits by either:
+
+ - Selecting **Prev** and **Next** buttons below the tab buttons.
+ - Using the X and C keyboard shortcuts.
+
+
+
+## View merge request commits in context
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29274) in GitLab 13.12 [with a flag](../../../administration/feature_flags.md) named `context_commits`. Enabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.8.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.9. [Feature flag `context_commits`](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) removed.
+
+When reviewing a merge request, it helps to have more context about the changes
+made. That includes unchanged lines in unchanged files, and previous commits
+that have already merged that the change is built on.
+
+To add previously merged commits to a merge request for more context:
+
+1. Go to your merge request.
+1. Select the **Commits** tab.
+1. Scroll to the end of the list of commits, and select **Add previously merged commits**:
+1. Select the commits that you want to add.
+1. Select **Save changes**.
+
+## View diffs between commits
+
+To view the changes between previously merged commits:
+
+1. On your merge request, select the **Changes** tab.
+1. By **Compare**, select the commit you want to view:
+
+ 
+
+If you selected to add previously merged commits, they are displayed in the list.
diff --git a/doc/user/project/merge_requests/img/commit_nav_v16_0.png b/doc/user/project/merge_requests/img/commit_nav_v16_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..6005e516fff9b48687701a2f8eedb2d0019309d9
GIT binary patch
literal 10423
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 {
);
});
- it('should render form comment button as disabled', () => {
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/410409
+ // eslint-disable-next-line jest/no-disabled-tests
+ it.skip('should render form comment button as disabled', () => {
expect(findCommentButton().props('disabled')).toEqual(true);
});
diff --git a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
index e554521bfb5..6ff2bb42d8d 100644
--- a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
+++ b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
@@ -31,8 +31,6 @@ describe('preserve_url_fragment', () => {
it('does not add an empty query parameter to OmniAuth login buttons', () => {
preserveUrlFragment();
- expect(findFormAction('#oauth-login-cas3')).toBe('http://test.host/users/auth/cas3');
-
expect(findFormAction('#oauth-login-auth0')).toBe('http://test.host/users/auth/auth0');
});
@@ -40,10 +38,6 @@ describe('preserve_url_fragment', () => {
it('when "remember_me" is not present', () => {
preserveUrlFragment('#L65');
- expect(findFormAction('#oauth-login-cas3')).toBe(
- 'http://test.host/users/auth/cas3?redirect_fragment=L65',
- );
-
expect(findFormAction('#oauth-login-auth0')).toBe(
'http://test.host/users/auth/auth0?redirect_fragment=L65',
);
@@ -56,10 +50,6 @@ describe('preserve_url_fragment', () => {
preserveUrlFragment('#L65');
- expect(findFormAction('#oauth-login-cas3')).toBe(
- 'http://test.host/users/auth/cas3?remember_me=1&redirect_fragment=L65',
- );
-
expect(findFormAction('#oauth-login-auth0')).toBe(
'http://test.host/users/auth/auth0?remember_me=1&redirect_fragment=L65',
);
diff --git a/spec/graphql/resolvers/group_milestones_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
index a32a031a88f..b9b8ef1870b 100644
--- a/spec/graphql/resolvers/group_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
@@ -2,15 +2,15 @@
require 'spec_helper'
-RSpec.describe Resolvers::GroupMilestonesResolver do
+RSpec.describe Resolvers::GroupMilestonesResolver, feature_category: :team_planning do
using RSpec::Parameterized::TableSyntax
include GraphqlHelpers
describe '#resolve' do
let_it_be(:current_user) { create(:user) }
- def resolve_group_milestones(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: group, args: args, ctx: context, arg_style: :internal)
+ def resolve_group_milestones(args: {}, context: { current_user: current_user }, arg_style: :internal)
+ resolve(described_class, obj: group, args: args, ctx: context, arg_style: arg_style)
end
let_it_be(:now) { Time.now }
@@ -45,7 +45,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
end
context 'with parameters' do
- it 'calls MilestonesFinder with correct parameters' do
+ it 'timeframe argument' do
start_date = now
end_date = start_date + 1.hour
@@ -53,18 +53,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
.with(args(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date))
.and_call_original
- resolve_group_milestones(start_date: start_date, end_date: end_date, state: 'closed')
- end
-
- it 'understands the timeframe argument' do
- start_date = now
- end_date = start_date + 1.hour
-
- expect(MilestonesFinder).to receive(:new)
- .with(args(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date))
- .and_call_original
-
- resolve_group_milestones(timeframe: { start: start_date, end: end_date }, state: 'closed')
+ resolve_group_milestones(args: { timeframe: { start: start_date, end: end_date }, state: 'closed' })
end
end
@@ -76,7 +65,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
.with(args(ids: [milestone.id.to_s], group_ids: group.id, state: 'all'))
.and_call_original
- resolve_group_milestones(ids: [milestone.to_global_id])
+ resolve_group_milestones(args: { ids: [milestone.to_global_id] })
end
end
@@ -86,12 +75,12 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
.with(args(group_ids: group.id, state: 'all', sort: :due_date_desc))
.and_call_original
- resolve_group_milestones(sort: :due_date_desc)
+ resolve_group_milestones(args: { sort: :due_date_desc })
end
%i[expired_last_due_date_asc expired_last_due_date_desc].each do |sort_by|
it "uses offset-pagination when sorting by #{sort_by}" do
- resolved = resolve_group_milestones(sort: sort_by)
+ resolved = resolve_group_milestones(args: { sort: sort_by })
expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
end
@@ -99,31 +88,18 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
end
context 'by timeframe' do
- context 'when start_date and end_date are present' do
- context 'when start date is after end_date' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate") do
- resolve_group_milestones(start_date: now, end_date: now - 2.days)
+ context 'when timeframe start and end are present' do
+ context 'when start is after end' do
+ it 'raises error' do
+ expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, 'start must be before end') do
+ resolve_group_milestones(
+ args: { timeframe: { start: now.to_date, end: now.to_date - 2.days } },
+ arg_style: :internal_prepared
+ )
end
end
end
end
-
- context 'when only start_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_group_milestones(start_date: now)
- end
- end
- end
-
- context 'when only end_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_group_milestones(end_date: now)
- end
- end
- end
end
context 'when including descendant milestones in a public group' do
@@ -143,7 +119,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
create(:milestone, group: inaccessible_group)
create(:milestone, project: inaccessible_project)
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3])
end
end
@@ -169,7 +145,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { {} }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1])
end
end
@@ -177,7 +153,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { { include_descendants: true } }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3])
end
end
@@ -185,7 +161,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { { include_ancestors: true } }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone6])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone6])
end
end
@@ -193,7 +169,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { { include_descendants: true, include_ancestors: true } }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3, milestone6])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3, milestone6])
end
end
end
diff --git a/spec/graphql/resolvers/project_milestones_resolver_spec.rb b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
index ad1190e3df7..af6b16804b0 100644
--- a/spec/graphql/resolvers/project_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
@@ -94,44 +94,6 @@ RSpec.describe 'Resolvers::ProjectMilestonesResolver' do
end
context 'by timeframe' do
- context 'when start_date and end_date are present' do
- it 'calls MilestonesFinder with correct parameters' do
- start_date = now
- end_date = now + 5.days
-
- expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, state: 'all',
- start_date: start_date, end_date: end_date, sort: :due_date_asc))
- .and_call_original
-
- resolve_project_milestones(start_date: start_date, end_date: end_date)
- end
-
- context 'when start date is after end_date' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'startDate is after endDate') do
- resolve_project_milestones(start_date: now, end_date: now - 2.days)
- end
- end
- end
- end
-
- context 'when only start_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_project_milestones(start_date: now)
- end
- end
- end
-
- context 'when only end_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_project_milestones(end_date: now)
- end
- end
- end
-
context 'when passing a timeframe' do
it 'calls MilestonesFinder with correct parameters' do
start_date = now_date
diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb
index 7de8ca89d3d..ebe86ccb08d 100644
--- a/spec/helpers/profiles_helper_spec.rb
+++ b/spec/helpers/profiles_helper_spec.rb
@@ -33,28 +33,28 @@ RSpec.describe ProfilesHelper do
end
it "returns omniauth provider label for users with external attributes" do
- stub_omniauth_setting(sync_profile_from_provider: ['cas3'])
+ stub_omniauth_setting(sync_profile_from_provider: [example_omniauth_provider])
stub_omniauth_setting(sync_profile_attributes: true)
- stub_cas_omniauth_provider
- cas_user = create(:omniauth_user, provider: 'cas3')
- cas_user.create_user_synced_attributes_metadata(provider: 'cas3', name_synced: true, email_synced: true, location_synced: true)
- allow(helper).to receive(:current_user).and_return(cas_user)
+ stub_auth0_omniauth_provider
+ auth0_user = create(:omniauth_user, provider: example_omniauth_provider)
+ auth0_user.create_user_synced_attributes_metadata(provider: example_omniauth_provider, name_synced: true, email_synced: true, location_synced: true)
+ allow(helper).to receive(:current_user).and_return(auth0_user)
- expect(helper.attribute_provider_label(:email)).to eq('CAS')
- expect(helper.attribute_provider_label(:name)).to eq('CAS')
- expect(helper.attribute_provider_label(:location)).to eq('CAS')
+ expect(helper.attribute_provider_label(:email)).to eq(example_omniauth_provider_label)
+ expect(helper.attribute_provider_label(:name)).to eq(example_omniauth_provider_label)
+ expect(helper.attribute_provider_label(:location)).to eq(example_omniauth_provider_label)
end
it "returns the correct omniauth provider label for users with some external attributes" do
- stub_omniauth_setting(sync_profile_from_provider: ['cas3'])
+ stub_omniauth_setting(sync_profile_from_provider: [example_omniauth_provider])
stub_omniauth_setting(sync_profile_attributes: true)
- stub_cas_omniauth_provider
- cas_user = create(:omniauth_user, provider: 'cas3')
- cas_user.create_user_synced_attributes_metadata(provider: 'cas3', name_synced: false, email_synced: true, location_synced: false)
- allow(helper).to receive(:current_user).and_return(cas_user)
+ stub_auth0_omniauth_provider
+ auth0_user = create(:omniauth_user, provider: example_omniauth_provider)
+ auth0_user.create_user_synced_attributes_metadata(provider: example_omniauth_provider, name_synced: false, email_synced: true, location_synced: false)
+ allow(helper).to receive(:current_user).and_return(auth0_user)
expect(helper.attribute_provider_label(:name)).to be_nil
- expect(helper.attribute_provider_label(:email)).to eq('CAS')
+ expect(helper.attribute_provider_label(:email)).to eq(example_omniauth_provider_label)
expect(helper.attribute_provider_label(:location)).to be_nil
end
@@ -118,12 +118,20 @@ RSpec.describe ProfilesHelper do
end
end
- def stub_cas_omniauth_provider
+ def stub_auth0_omniauth_provider
provider = OpenStruct.new(
- 'name' => 'cas3',
- 'label' => 'CAS'
+ 'name' => example_omniauth_provider,
+ 'label' => example_omniauth_provider_label
)
stub_omniauth_setting(providers: [provider])
end
+
+ def example_omniauth_provider
+ "auth0"
+ end
+
+ def example_omniauth_provider_label
+ "Auth0"
+ end
end
diff --git a/spec/lib/gitlab/database/migrations/pg_backend_pid_spec.rb b/spec/lib/gitlab/database/migrations/pg_backend_pid_spec.rb
index 515f59345ee..33e83ea2575 100644
--- a/spec/lib/gitlab/database/migrations/pg_backend_pid_spec.rb
+++ b/spec/lib/gitlab/database/migrations/pg_backend_pid_spec.rb
@@ -40,5 +40,13 @@ RSpec.describe Gitlab::Database::Migrations::PgBackendPid, feature_category: :da
expect { described_class.say(conn) }.to output(expected_output).to_stdout
end
+
+ it 'outputs nothing if ActiveRecord::Migration.verbose is false' do
+ conn = ActiveRecord::Base.connection
+
+ allow(ActiveRecord::Migration).to receive(:verbose).and_return(false)
+
+ expect { described_class.say(conn) }.not_to output.to_stdout
+ end
end
end
diff --git a/spec/lib/gitlab/fogbugz_import/project_creator_spec.rb b/spec/lib/gitlab/fogbugz_import/project_creator_spec.rb
index 8be9f55dbb6..39dad1360a5 100644
--- a/spec/lib/gitlab/fogbugz_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/fogbugz_import/project_creator_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::FogbugzImport::ProjectCreator do
+RSpec.describe Gitlab::FogbugzImport::ProjectCreator, feature_category: :importers do
let(:user) { create(:user) }
let(:repo) do
instance_double(Gitlab::FogbugzImport::Repository,
@@ -22,6 +22,10 @@ RSpec.describe Gitlab::FogbugzImport::ProjectCreator do
project_creator.execute
end
+ before do
+ stub_application_setting(import_sources: ['fogbugz'])
+ end
+
it 'creates project with private visibility level' do
expect(subject.persisted?).to eq(true)
expect(subject.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
diff --git a/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb b/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
index f1dbe2bf8e2..15624a0558e 100644
--- a/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
@@ -23,6 +23,8 @@ RSpec.describe Gitlab::LegacyGithubImport::ProjectCreator do
allow_next_instance_of(Project) do |project|
allow(project).to receive(:add_import_job)
end
+
+ stub_application_setting(import_sources: ['github'])
end
describe '#execute' do
diff --git a/spec/lib/gitlab/manifest_import/project_creator_spec.rb b/spec/lib/gitlab/manifest_import/project_creator_spec.rb
index 0ab5b277552..2d878e5496e 100644
--- a/spec/lib/gitlab/manifest_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/manifest_import/project_creator_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::ManifestImport::ProjectCreator do
+RSpec.describe Gitlab::ManifestImport::ProjectCreator, feature_category: :importers do
let(:group) { create(:group) }
let(:user) { create(:user) }
let(:repository) do
@@ -14,6 +14,8 @@ RSpec.describe Gitlab::ManifestImport::ProjectCreator do
before do
group.add_owner(user)
+
+ stub_application_setting(import_sources: ['manifest'])
end
subject { described_class.new(repository, group, user) }
diff --git a/spec/lib/gitlab/omniauth_initializer_spec.rb b/spec/lib/gitlab/omniauth_initializer_spec.rb
index daef280dbaa..112fdb183ab 100644
--- a/spec/lib/gitlab/omniauth_initializer_spec.rb
+++ b/spec/lib/gitlab/omniauth_initializer_spec.rb
@@ -216,14 +216,6 @@ RSpec.describe Gitlab::OmniauthInitializer do
expect { subject.execute([hash_config]) }.to raise_error(NameError)
end
- it 'configures on_single_sign_out proc for cas3' do
- cas3_config = { 'name' => 'cas3', 'args' => {} }
-
- expect(devise_config).to receive(:omniauth).with(:cas3, { on_single_sign_out: an_instance_of(Proc) })
-
- subject.execute([cas3_config])
- end
-
it 'configures defaults for google_oauth2' do
google_config = {
'name' => 'google_oauth2',
diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb
index 58b529ff18a..4db3683c057 100644
--- a/spec/models/users/credit_card_validation_spec.rb
+++ b/spec/models/users/credit_card_validation_spec.rb
@@ -51,4 +51,107 @@ RSpec.describe Users::CreditCardValidation do
end
end
end
+
+ describe 'scopes' do
+ describe '.by_banned_user' do
+ let(:banned_user) { create(:banned_user) }
+ let!(:credit_card) { create(:credit_card_validation) }
+ let!(:banned_user_credit_card) { create(:credit_card_validation, user: banned_user.user) }
+
+ it 'returns only records associated to banned users' do
+ expect(described_class.by_banned_user).to match_array([banned_user_credit_card])
+ end
+ end
+
+ describe '.similar_by_holder_name' do
+ let!(:credit_card) { create(:credit_card_validation, holder_name: 'CARD MCHODLER') }
+ let!(:credit_card2) { create(:credit_card_validation, holder_name: 'RICHIE RICH') }
+
+ it 'returns only records that case-insensitive match the given holder name' do
+ expect(described_class.similar_by_holder_name('card mchodler')).to match_array([credit_card])
+ end
+
+ context 'when given holder name is falsey' do
+ it 'returns [] when given holder name is ""' do
+ expect(described_class.similar_by_holder_name('')).to match_array([])
+ end
+
+ it 'returns [] when given holder name is nil' do
+ expect(described_class.similar_by_holder_name(nil)).to match_array([])
+ end
+ end
+ end
+
+ describe '.similar_to' do
+ let(:credit_card) { create(:credit_card_validation) }
+
+ let!(:credit_card2) do
+ create(:credit_card_validation,
+ expiration_date: credit_card.expiration_date,
+ last_digits: credit_card.last_digits,
+ network: credit_card.network
+ )
+ end
+
+ let!(:credit_card3) do
+ create(:credit_card_validation,
+ expiration_date: credit_card.expiration_date,
+ last_digits: credit_card.last_digits,
+ network: 'UnknownCCNetwork'
+ )
+ end
+
+ it 'returns only records with similar expiration_date, last_digits, and network attribute values' do
+ expect(described_class.similar_to(credit_card)).to match_array([credit_card, credit_card2])
+ end
+ end
+ end
+
+ describe '#used_by_banned_user?' do
+ let(:credit_card_details) do
+ {
+ holder_name: 'Christ McLovin',
+ expiration_date: 2.years.from_now.end_of_month,
+ last_digits: 4242,
+ network: 'Visa'
+ }
+ end
+
+ let!(:credit_card) { create(:credit_card_validation, credit_card_details) }
+
+ subject { credit_card }
+
+ context 'when there is a similar credit card associated to a banned user' do
+ let_it_be(:banned_user) { create(:banned_user) }
+
+ let(:attrs) { credit_card_details.merge({ user: banned_user.user }) }
+ let!(:similar_credit_card) { create(:credit_card_validation, attrs) }
+
+ it { is_expected.to be_used_by_banned_user }
+
+ context 'when holder names do not match' do
+ let!(:similar_credit_card) do
+ create(:credit_card_validation, attrs.merge({ holder_name: 'Mary Goody' }))
+ end
+
+ it { is_expected.not_to be_used_by_banned_user }
+ end
+
+ context 'when .similar_to returns nothing' do
+ let!(:similar_credit_card) do
+ create(:credit_card_validation, attrs.merge({ network: 'DifferentNetwork' }))
+ end
+
+ it { is_expected.not_to be_used_by_banned_user }
+ end
+ end
+
+ context 'when there is a similar credit card not associated to a banned user' do
+ let!(:similar_credit_card) do
+ create(:credit_card_validation, credit_card_details)
+ end
+
+ it { is_expected.not_to be_used_by_banned_user }
+ end
+ end
end
diff --git a/spec/policies/identity_provider_policy_spec.rb b/spec/policies/identity_provider_policy_spec.rb
index f6b4e15cff9..cd617a28364 100644
--- a/spec/policies/identity_provider_policy_spec.rb
+++ b/spec/policies/identity_provider_policy_spec.rb
@@ -19,13 +19,11 @@ RSpec.describe IdentityProviderPolicy do
it { is_expected.not_to be_allowed(:unlink) }
end
- %w[saml cas3].each do |provider_name|
- context "when provider is #{provider_name}" do
- let(:provider) { provider_name }
+ context "when provider is saml" do
+ let(:provider) { 'saml' }
- it { is_expected.to be_allowed(:link) }
- it { is_expected.not_to be_allowed(:unlink) }
- end
+ it { is_expected.to be_allowed(:link) }
+ it { is_expected.not_to be_allowed(:unlink) }
end
end
end
diff --git a/spec/requests/api/graphql/group/milestones_spec.rb b/spec/requests/api/graphql/group/milestones_spec.rb
index 28cd68493c0..209588835f2 100644
--- a/spec/requests/api/graphql/group/milestones_spec.rb
+++ b/spec/requests/api/graphql/group/milestones_spec.rb
@@ -35,12 +35,6 @@ RSpec.describe 'Milestones through GroupQuery', feature_category: :team_planning
end
context 'when filtering by timeframe' do
- it 'fetches milestones between start_date and due_date' do
- fetch_milestones(user, { start_date: now.to_s, end_date: (now + 2.days).to_s })
-
- expect_array_response(milestone_2.to_global_id.to_s, milestone_3.to_global_id.to_s)
- end
-
it 'fetches milestones between timeframe start and end arguments' do
today = Date.today
fetch_milestones(user, { timeframe: { start: today.to_s, end: (today + 2.days).to_s } })
diff --git a/spec/requests/api/graphql/project/milestones_spec.rb b/spec/requests/api/graphql/project/milestones_spec.rb
index 3b31da77a75..7a79bf2184a 100644
--- a/spec/requests/api/graphql/project/milestones_spec.rb
+++ b/spec/requests/api/graphql/project/milestones_spec.rb
@@ -137,18 +137,6 @@ RSpec.describe 'getting milestone listings nested in a project', feature_categor
it_behaves_like 'searching with parameters'
end
- context 'searching by custom range' do
- let(:expected) { [no_end, fully_future] }
- let(:search_params) do
- {
- start_date: (today + 6.days).iso8601,
- end_date: (today + 7.days).iso8601
- }
- end
-
- it_behaves_like 'searching with parameters'
- end
-
context 'using timeframe argument' do
let(:expected) { [no_end, fully_future] }
let(:search_params) do
@@ -188,23 +176,6 @@ RSpec.describe 'getting milestone listings nested in a project', feature_categor
end
end
- it 'is invalid to provide timeframe and start_date/end_date' do
- query = <<~GQL
- query($path: ID!, $tstart: Date!, $tend: Date!, $start: Time!, $end: Time!) {
- project(fullPath: $path) {
- milestones(timeframe: { start: $tstart, end: $tend }, startDate: $start, endDate: $end) {
- nodes { id }
- }
- }
- }
- GQL
-
- post_graphql(query, current_user: current_user,
- variables: vars.merge(vars.transform_keys { |k| :"t#{k}" }))
-
- expect(graphql_errors).to contain_exactly(a_hash_including('message' => include('deprecated in favor of timeframe')))
- end
-
it 'is invalid to invert the timeframe arguments' do
query = <<~GQL
query($path: ID!, $start: Date!, $end: Date!) {
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 8ad5aaa8bc3..4496e3aa7c3 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -14,6 +14,8 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
before do
namespace.add_owner(user) if user
+
+ stub_application_setting(import_sources: ['gitlab_project'])
end
shared_examples 'requires authentication' do
@@ -26,6 +28,20 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
end
end
+ shared_examples 'requires import source to be enabled' do
+ context 'when gitlab_project import_sources is disabled' do
+ before do
+ stub_application_setting(import_sources: [])
+ end
+
+ it 'returns 403' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
describe 'POST /projects/import' do
subject { upload_archive(file_upload, workhorse_headers, params) }
@@ -43,6 +59,7 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
end
it_behaves_like 'requires authentication'
+ it_behaves_like 'requires import source to be enabled'
it 'executes a limited number of queries', :use_clean_rails_redis_caching do
control_count = ActiveRecord::QueryRecorder.new { subject }.count
@@ -337,6 +354,7 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
end
it_behaves_like 'requires authentication'
+ it_behaves_like 'requires import source to be enabled'
context 'when the response is successful' do
it 'schedules the import successfully' do
@@ -402,6 +420,7 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
end
it_behaves_like 'requires authentication'
+ it_behaves_like 'requires import source to be enabled'
context 'when the response is successful' do
it 'schedules the import successfully' do
@@ -496,6 +515,7 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
subject { post api('/projects/import/authorize', user), headers: workhorse_headers }
it_behaves_like 'requires authentication'
+ it_behaves_like 'requires import source to be enabled'
it 'authorizes importing project with workhorse header' do
subject
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index b4524ea0881..725268d9b6a 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1431,6 +1431,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :projects d
body: '001e# service=git-upload-pack',
headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' }
}
+ stub_application_setting(import_sources: ['git'])
stub_full_request(endpoint_url, method: :get).to_return(git_response)
project_params = { import_url: url, path: 'path-project-Foo', name: 'Foo Project' }
diff --git a/spec/requests/import/github_controller_spec.rb b/spec/requests/import/github_controller_spec.rb
index 5ac97e3d330..8d57c2895de 100644
--- a/spec/requests/import/github_controller_spec.rb
+++ b/spec/requests/import/github_controller_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe Import::GithubController, feature_category: :importers do
let_it_be(:user) { create(:user) }
before do
+ stub_application_setting(import_sources: ['github'])
+
login_as(user)
end
diff --git a/spec/requests/import/github_groups_controller_spec.rb b/spec/requests/import/github_groups_controller_spec.rb
index 6393dd35a98..dada84758f3 100644
--- a/spec/requests/import/github_groups_controller_spec.rb
+++ b/spec/requests/import/github_groups_controller_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe Import::GithubGroupsController, feature_category: :importers do
let(:params) { {} }
before do
+ stub_application_setting(import_sources: ['github'])
+
login_as(user)
end
diff --git a/spec/requests/import/gitlab_projects_controller_spec.rb b/spec/requests/import/gitlab_projects_controller_spec.rb
index fe3ea9e9c9e..732851c7828 100644
--- a/spec/requests/import/gitlab_projects_controller_spec.rb
+++ b/spec/requests/import/gitlab_projects_controller_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe Import::GitlabProjectsController, feature_category: :importers do
before do
login_as(user)
+
+ stub_application_setting(import_sources: ['gitlab_project'])
end
describe 'POST create' do
diff --git a/spec/services/import/fogbugz_service_spec.rb b/spec/services/import/fogbugz_service_spec.rb
index ad02dc31da1..e9c676dcd23 100644
--- a/spec/services/import/fogbugz_service_spec.rb
+++ b/spec/services/import/fogbugz_service_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Import::FogbugzService, feature_category: :importers do
before do
allow(subject).to receive(:authorized?).and_return(true)
+ stub_application_setting(import_sources: ['fogbugz'])
end
context 'when no repo is found' do
diff --git a/spec/services/import/gitlab_projects/create_project_service_spec.rb b/spec/services/import/gitlab_projects/create_project_service_spec.rb
index 35378bcee92..a77e9bdfce1 100644
--- a/spec/services/import/gitlab_projects/create_project_service_spec.rb
+++ b/spec/services/import/gitlab_projects/create_project_service_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe ::Import::GitlabProjects::CreateProjectService, :aggregate_failur
before do
stub_const('FakeStrategy', fake_file_acquisition_strategy)
+ stub_application_setting(import_sources: ['gitlab_project'])
end
describe 'validation' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 1c903954658..303a98cb35b 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -256,6 +256,10 @@ RSpec.describe Projects::CreateService, '#execute', feature_category: :projects
it_behaves_like 'has sync-ed traversal_ids'
context 'when project is an import' do
+ before do
+ stub_application_setting(import_sources: ['gitlab_project'])
+ end
+
context 'when user is not allowed to import projects' do
let(:group) do
create(:group).tap do |group|
diff --git a/vendor/gems/omniauth-cas3/.gitlab-ci.yml b/vendor/gems/omniauth-cas3/.gitlab-ci.yml
deleted file mode 100644
index e728d704d21..00000000000
--- a/vendor/gems/omniauth-cas3/.gitlab-ci.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-workflow:
- rules:
- - if: $CI_MERGE_REQUEST_ID
-
-.rspec:
- cache:
- key: omniauth-cas3-ruby
- paths:
- - vendor/gems/omniauth-cas3/vendor/ruby
- before_script:
- - cd vendor/gems/omniauth-cas3
- - ruby -v # Print out ruby version for debugging
- - gem install bundler --no-document # Bundler is not installed with the image
- - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby
- - bundle config set with 'development'
- - bundle config set --local frozen 'true' # Disallow Gemfile.lock changes on CI
- - bundle config # Show bundler configuration
- - bundle install -j $(nproc)
- script:
- - bundle exec rspec
-
-rspec-2.7:
- image: "ruby:2.7"
- extends: .rspec
-
-rspec-3.0:
- image: "ruby:3.0"
- extends: .rspec
diff --git a/vendor/gems/omniauth-cas3/Gemfile b/vendor/gems/omniauth-cas3/Gemfile
deleted file mode 100644
index adc6d8b37a3..00000000000
--- a/vendor/gems/omniauth-cas3/Gemfile
+++ /dev/null
@@ -1,4 +0,0 @@
-source 'https://rubygems.org'
-
-# Specify your gem's dependencies in omniauth-cas3.gemspec
-gemspec
diff --git a/vendor/gems/omniauth-cas3/Gemfile.lock b/vendor/gems/omniauth-cas3/Gemfile.lock
deleted file mode 100644
index a856e78f00f..00000000000
--- a/vendor/gems/omniauth-cas3/Gemfile.lock
+++ /dev/null
@@ -1,65 +0,0 @@
-PATH
- remote: .
- specs:
- omniauth-cas3 (1.1.4)
- addressable (~> 2.3)
- nokogiri (~> 1.7, >= 1.7.1)
- omniauth (~> 2.0)
-
-GEM
- remote: https://rubygems.org/
- specs:
- addressable (2.8.1)
- public_suffix (>= 2.0.2, < 6.0)
- awesome_print (1.9.2)
- crack (0.4.5)
- rexml
- diff-lcs (1.5.0)
- hashdiff (1.0.1)
- hashie (5.0.0)
- nokogiri (1.13.7)
- racc (~> 1.4)
- omniauth (2.1.0)
- hashie (>= 3.4.6)
- rack (>= 2.2.3)
- rack-protection
- public_suffix (5.0.0)
- racc (1.6.0)
- rack (2.2.4)
- rack-protection (2.2.2)
- rack
- rack-test (0.8.3)
- rack (>= 1.0, < 3)
- rake (10.5.0)
- rexml (3.2.5)
- rspec (3.11.0)
- rspec-core (~> 3.11.0)
- rspec-expectations (~> 3.11.0)
- rspec-mocks (~> 3.11.0)
- rspec-core (3.11.0)
- rspec-support (~> 3.11.0)
- rspec-expectations (3.11.0)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.11.0)
- rspec-mocks (3.11.1)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.11.0)
- rspec-support (3.11.0)
- webmock (3.18.1)
- addressable (>= 2.8.0)
- crack (>= 0.3.2)
- hashdiff (>= 0.4.0, < 2.0.0)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- awesome_print
- omniauth-cas3!
- rack-test (~> 0.6)
- rake (~> 10.0)
- rspec (>= 3.4)
- webmock
-
-BUNDLED WITH
- 2.3.21
diff --git a/vendor/gems/omniauth-cas3/LICENSE b/vendor/gems/omniauth-cas3/LICENSE
deleted file mode 100644
index 402cb6e4380..00000000000
--- a/vendor/gems/omniauth-cas3/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright (c) 2011 Derek Lindahl and CustomInk, LLC
-Copyright (c) 2015 tduehr
-
-MIT License
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/vendor/gems/omniauth-cas3/README.md b/vendor/gems/omniauth-cas3/README.md
deleted file mode 100644
index 3c66341defb..00000000000
--- a/vendor/gems/omniauth-cas3/README.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# OmniAuth CAS Strategy [![Gem Version][version_badge]][version] [![Build Status][travis_status]][travis]
-
-This is a fork of [omniauth-cas3](https://github.com/tduehr/omniauth-cas3) to
-support:
-
-1. OmniAuth v1 and v2. OmniAuth v2 disables GET requests by default
- and defaults to POST. GitLab already has patched v1 to use POST,
- but other dependencies need to be updated:
- https://gitlab.com/gitlab-org/gitlab/-/issues/30073.
-2. We may deprecate this library entirely in the future:
- https://gitlab.com/gitlab-org/gitlab/-/issues/366212
-
-[version_badge]: https://badge.fury.io/rb/omniauth-cas3.png
-[version]: http://badge.fury.io/rb/omniauth-cas3
-[travis]: http://travis-ci.org/tduehr/omniauth-cas3
-[travis_status]: https://secure.travis-ci.org/dlindahl/omniauth-cas3.png
-[releases]: https://github.com/tduehr/omniauth-cas3/releases
-
-This is a OmniAuth 1.0 compatible port of the previously available
-[OmniAuth CAS strategy][old_omniauth_cas] that was bundled with OmniAuth 0.3. This strategy has also been updated for CAS protocol version 3.0 and patched to deal with namespace issues.
-
-* [View the documentation][document_up]
-* [Changelog][releases]
-
-## Installation
-
-Add this line to your application's Gemfile:
-
- gem 'omniauth-cas3'
-
-And then execute:
-
- $ bundle
-
-Or install it yourself as:
-
- $ gem install omniauth-cas3
-
-## Usage
-
-Use like any other OmniAuth strategy:
-
-```ruby
-Rails.application.config.middleware.use OmniAuth::Builder do
- provider :cas3, host: 'cas.yourdomain.com'
-end
-```
-
-### Configuration Options
-
-#### Required
-
-OmniAuth CAS requires at least one of the following two configuration options:
-
- * `url` - Defines the URL of your CAS server (i.e. `http://example.org:8080`)
- * `host` - Defines the host of your CAS server (i.e. `example.org`).
-
-#### Optional
-
-Other configuration options:
-
- * `port` - The port to use for your configured CAS `host`. Optional if using `url`.
- * `ssl` - TRUE to connect to your CAS server over SSL. Optional if using `url`.
- * `service_validate_url` - The URL to use to validate a user. Defaults to `'/serviceValidate'`.
- * `callback_url` - The URL custom URL path which CAS uses to call back to the service. Defaults to `/users/auth/cas3/callback`.
- * `logout_url` - The URL to use to logout a user. Defaults to `'/logout'`.
- * `login_url` - Defines the URL used to prompt users for their login information. Defaults to `/login` If no `host` is configured, the host application's domain will be used.
- * `uid_field` - The user data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name).
- * `ca_path` - Optional when `ssl` is `true`. Sets path of a CA certification directory. See [Net::HTTP][net_http] for more details.
- * `disable_ssl_verification` - Optional when `ssl` is true. Disables verification.
- * `on_single_sign_out` - Optional. Callback used when a [CAS 3.1 Single Sign Out][sso]
- request is received.
- * `fetch_raw_info` - Optional. Callback used to return additional "raw" user
- info from other sources.
-
- ```ruby
- provider :cas3,
- fetch_raw_info: lambda { |strategy, options, ticket, user_info|
- ExternalService.get(user_info[:user]).attributes
- }
- ```
-
-Configurable options for values returned by CAS:
-
- * `uid_key` - The user ID data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name).
- * `name_key` - The data attribute containing user first and last name. Defaults to `'name'`.
- * `email_key` - The data attribute containing user email address. Defaults to `'email'`.
- * `nickname_key` - The data attribute containing user's nickname. Defaults to `'user'`.
- * `first_name_key` - The data attribute containing user first name. Defaults to `'first_name'`.
- * `last_name_key` - The data attribute containing user last name. Defaults to `'last_name'`.
- * `location_key` - The data attribute containing user location/address. Defaults to `'location'`.
- * `image_key` - The data attribute containing user image/picture. Defaults to `'image'`.
- * `phone_key` - The data attribute containing user contact phone number. Defaults to `'phone'`.
-
-## Migrating from OmniAuth 0.3
-
-Given the following OmniAuth 0.3 configuration:
-
-```ruby
-provider :CAS, cas_server: 'https://cas.example.com/cas/'
-```
-
-Your new settings should look similar to this:
-
-```ruby
-provider :cas3,
- host: 'cas.example.com',
- login_url: '/cas/login',
- service_validate_url: '/cas/p3/serviceValidate'
-```
-
-If you encounter problems wih SSL certificates you may want to set the `ca_path` parameter or activate `disable_ssl_verification` (not recommended).
-
-## Contributing
-
-1. Fork it
-2. Create your feature branch (`git checkout -b my-new-feature`)
-3. Commit your changes (`git commit -am 'Added some feature'`)
-4. Push to the branch (`git push origin my-new-feature`)
-5. Create new Pull Request
-
-## Thanks
-
-Special thanks go out to the following people
-
- * @dlindahl For the original work in porting this from OmniAuth 0.3
- * Phillip Aldridge (@iterateNZ) and JB Barth (@jbbarth) for helping out with Issue #3
- * Elber Ribeiro (@dynaum) for Ubuntu SSL configuration support
- * @rbq for README updates and OmniAuth 0.3 migration guide
-
-[old_omniauth_cas]: https://github.com/intridea/omniauth/blob/0-3-stable/oa-enterprise/lib/omniauth/strategies/cas.rb
-[document_up]: http://tduehr.github.com/omniauth-cas3/
-[net_http]: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
-[sso]: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
diff --git a/vendor/gems/omniauth-cas3/Rakefile b/vendor/gems/omniauth-cas3/Rakefile
deleted file mode 100644
index af92638ba13..00000000000
--- a/vendor/gems/omniauth-cas3/Rakefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env rake
-require 'bundler/gem_tasks'
-
-require 'rspec/core/rake_task'
-desc 'Default: run specs.'
-task default: :spec
-
-desc 'Run specs'
-RSpec::Core::RakeTask.new(:spec) do |t|
- t.rspec_opts = '--require spec_helper --color --order rand'
-end
-
-task :test do
- fail %q{This application uses RSpec. Try running "rake spec"}
-end
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb b/vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb
deleted file mode 100644
index 58509b933c8..00000000000
--- a/vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'omniauth/cas3'
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb b/vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb
deleted file mode 100644
index 80460aa1f31..00000000000
--- a/vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'omniauth/cas3/version'
-require 'omniauth/strategies/cas3'
\ No newline at end of file
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb b/vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb
deleted file mode 100644
index 9508dd69125..00000000000
--- a/vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module Omniauth
- module Cas3
- VERSION = '1.1.4'
- end
-end
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb
deleted file mode 100644
index 441529b67d8..00000000000
--- a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb
+++ /dev/null
@@ -1,227 +0,0 @@
-require 'omniauth'
-require 'addressable/uri'
-
-module OmniAuth
- module Strategies
- class CAS3
- include OmniAuth::Strategy
-
- # Custom Exceptions
- class MissingCASTicket < StandardError; end
- class InvalidCASTicket < StandardError; end
-
- autoload :ServiceTicketValidator, 'omniauth/strategies/cas3/service_ticket_validator'
- autoload :LogoutRequest, 'omniauth/strategies/cas3/logout_request'
-
- attr_accessor :raw_info
- alias_method :user_info, :raw_info
-
- option :name, :cas3 # Required property by OmniAuth::Strategy
-
- option :host, nil
- option :port, nil
- option :path, nil
- option :ssl, true
- option :service_validate_url, '/p3/serviceValidate'
- option :login_url, '/login'
- option :logout_url, '/logout'
- option :on_single_sign_out, Proc.new {}
- # A Proc or lambda that returns a Hash of additional user info to be
- # merged with the info returned by the CAS server.
- #
- # @param [Object] An instance of OmniAuth::Strategies::CAS for the current request
- # @param [String] The user's Service Ticket value
- # @param [Hash] The user info for the Service Ticket returned by the CAS server
- #
- # @return [Hash] Extra user info
- option :fetch_raw_info, Proc.new { Hash.new }
- # Make all the keys configurable with some defaults set here
- option :uid_field, 'user'
- option :name_key, 'name'
- option :email_key, 'email'
- option :nickname_key, 'user'
- option :first_name_key, 'first_name'
- option :last_name_key, 'last_name'
- option :location_key, 'location'
- option :image_key, 'image'
- option :phone_key, 'phone'
-
- # As required by https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
- AuthHashSchemaKeys = %w{name email nickname first_name last_name location image phone}
- info do
- prune!({
- name: raw_info[options[:name_key].to_s],
- email: raw_info[options[:email_key].to_s],
- nickname: raw_info[options[:nickname_key].to_s],
- first_name: raw_info[options[:first_name_key].to_s],
- last_name: raw_info[options[:last_name_key].to_s],
- location: raw_info[options[:location_key].to_s],
- image: raw_info[options[:image_key].to_s],
- phone: raw_info[options[:phone_key].to_s]
- })
- end
-
- extra do
- hash = {}
-
- unless skip_info?
- hash = raw_info.dup
- hash.delete_if { |k, _v| AuthHashSchemaKeys.include?(k) }
- end
-
- prune! hash
- end
-
- uid do
- raw_info[options[:uid_field].to_s]
- end
-
- credentials do
- prune!({ ticket: @ticket })
- end
-
- def callback_phase
- if on_sso_path?
- single_sign_out_phase
- else
- @ticket = request.params['ticket']
- return fail!(:no_ticket, MissingCASTicket.new('No CAS Ticket')) unless @ticket
- fetch_raw_info(@ticket)
- return fail!(:invalid_ticket, InvalidCASTicket.new('Invalid CAS Ticket')) if raw_info.empty?
- super
- end
- end
-
- def request_phase
- service_url = append_params(callback_url, return_url)
-
- [
- 302,
- {
- 'Location' => login_url(service_url),
- 'Content-Type' => 'text/plain'
- },
- ["You are being redirected to CAS for sign-in."]
- ]
- end
-
- def on_sso_path?
- request.post? && request.params.has_key?('logoutRequest')
- end
-
- def single_sign_out_phase
- logout_request_service.new(self, request).call(options)
- end
-
- # Build a CAS host with protocol and port
- #
- #
- def cas_url
- extract_url if options['url']
- validate_cas_setup
- @cas_url ||= begin
- uri = Addressable::URI.new
- uri.host = options.host
- uri.scheme = options.ssl ? 'https' : 'http'
- uri.port = options.port
- uri.path = options.path
- uri.to_s
- end
- end
-
- def extract_url
- url = Addressable::URI.parse(options.delete('url'))
- options.merge!(
- 'host' => url.host,
- 'port' => url.port,
- 'path' => url.path,
- 'ssl' => url.scheme == 'https'
- )
- end
-
- def validate_cas_setup
- if options.host.nil? || options.login_url.nil?
- raise ArgumentError.new(":host and :login_url MUST be provided")
- end
- end
-
- # Build a service-validation URL from +service+ and +ticket+.
- # If +service+ has a ticket param, first remove it. URL-encode
- # +service+ and add it and the +ticket+ as paraemters to the
- # CAS serviceValidate URL.
- #
- # @param [String] service the service (a.k.a. return-to) URL
- # @param [String] ticket the ticket to validate
- #
- # @return [String] a URL like `http://cas.mycompany.com/serviceValidate?service=...&ticket=...`
- def service_validate_url(service_url, ticket)
- service_url = Addressable::URI.parse(service_url)
- service_url.query_values = service_url.query_values.tap { |qs| qs.delete('ticket') }
- cas_url + append_params(options.service_validate_url, {
- service: service_url.to_s,
- ticket: ticket
- })
- end
-
- # Build a CAS login URL from +service+.
- #
- # @param [String] service the service (a.k.a. return-to) URL
- #
- # @return [String] a URL like `http://cas.mycompany.com/login?service=...`
- def login_url(service)
- cas_url + append_params(options.login_url, { service: service })
- end
-
- # Adds URL-escaped +parameters+ to +base+.
- #
- # @param [String] base the base URL
- # @param [String] params the parameters to append to the URL
- #
- # @return [String] the new joined URL.
- def append_params(base, params)
- params = params.each { |k,v| v = Rack::Utils.escape(v) }
- Addressable::URI.parse(base).tap do |base_uri|
- base_uri.query_values = (base_uri.query_values || {}).merge(params)
- end.to_s
- end
-
- # Validate the Service Ticket
- # @return [Object] the validated Service Ticket
- def validate_service_ticket(ticket)
- ServiceTicketValidator.new(self, options, callback_url, ticket).call
- end
-
- private
-
- def fetch_raw_info(ticket)
- ticket_user_info = validate_service_ticket(ticket).user_info
- custom_user_info = options.fetch_raw_info.call(self, options, ticket, ticket_user_info)
- self.raw_info = ticket_user_info.merge(custom_user_info)
- end
-
- # Deletes Hash pairs with `nil` values.
- # From https://github.com/mkdynamic/omniauth-facebook/blob/972ed5e3456bcaed7df1f55efd7c05c216c8f48e/lib/omniauth/strategies/facebook.rb#L122-127
- def prune!(hash)
- hash.delete_if do |_, value|
- prune!(value) if value.is_a?(Hash)
- value.nil? || (value.respond_to?(:empty?) && value.empty?)
- end
- end
-
- def return_url
- # If the request already has a `url` parameter, then it will already be appended to the callback URL.
- if request.params && request.params['url']
- {}
- else
- { url: request.referer }
- end
- end
-
- def logout_request_service
- LogoutRequest
- end
- end
- end
-end
-
-OmniAuth.config.add_camelization 'cas3', 'CAS3'
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb
deleted file mode 100644
index 72978227edb..00000000000
--- a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-module OmniAuth
- module Strategies
- class CAS3
- class LogoutRequest
- def initialize(strategy, request)
- @strategy, @request = strategy, request
- end
-
- def call(options = {})
- @options = options
-
- begin
- result = single_sign_out_callback.call(*logout_request)
- rescue StandardError => err
- return @strategy.fail! :logout_request, err
- else
- result = [200,{},'OK'] if result == true || result.nil?
- ensure
- return unless result
-
- # TODO: Why does ActionPack::Response return [status,headers,body]
- # when Rack::Response#new wants [body,status,headers]? Additionally,
- # why does Rack::Response differ in argument order from the usual
- # Rack-like [status,headers,body] array?
- return Rack::Response.new(result[2],result[0],result[1]).finish
- end
- end
-
- private
-
- def logout_request
- @logout_request ||= begin
- saml = parse_and_ensure_namespaces(@request.params['logoutRequest'])
- ns = saml.collect_namespaces
- name_id = saml.xpath('//saml:NameID', ns).text
- sess_idx = saml.xpath('//samlp:SessionIndex', ns).text
- inject_params(name_id:name_id, session_index:sess_idx)
- @request
- end
- end
-
- def parse_and_ensure_namespaces(logout_request_xml)
- doc = Nokogiri.parse(logout_request_xml)
- ns = doc.collect_namespaces
- if ns.include?('xmlns:samlp') && ns.include?('xmlns:saml')
- doc
- else
- add_namespaces(doc)
- end
- end
-
- def add_namespaces(logout_request_doc)
- root = logout_request_doc.root
- root.add_namespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol')
- root.add_namespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion\\')
-
- # In order to add namespaces properly we need to re-parse the document
- Nokogiri.parse(logout_request_doc.to_s)
- end
-
- def inject_params(new_params)
- new_params.each do |key, val|
- @request.update_param(key, val)
- end
- end
-
- def single_sign_out_callback
- @options[:on_single_sign_out]
- end
- end
- end
- end
-end
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb
deleted file mode 100644
index 4f9a61c5216..00000000000
--- a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-require 'net/http'
-require 'net/https'
-require 'nokogiri'
-
-module OmniAuth
- module Strategies
- class CAS3
- class ServiceTicketValidator
- VALIDATION_REQUEST_HEADERS = { 'Accept' => '*/*' }
-
- # Build a validator from a +configuration+, a
- # +return_to+ URL, and a +ticket+.
- #
- # @param [Hash] options the OmniAuth Strategy options
- # @param [String] return_to_url the URL of this CAS client service
- # @param [String] ticket the service ticket to validate
- def initialize(strategy, options, return_to_url, ticket)
- @options = options
- @uri = URI.parse(strategy.service_validate_url(return_to_url, ticket))
- end
-
- # Executes a network request to process the CAS Service Response
- def call
- @response_body = get_service_response_body
- @success_body = find_authentication_success(@response_body)
- self
- end
-
- # Request validation of the ticket from the CAS server's
- # serviceValidate (CAS 2.0) function.
- #
- # Swallows all XML parsing errors (and returns +nil+ in those cases).
- #
- # @return [Hash, nil] a user information hash if the response is valid; +nil+ otherwise.
- #
- # @raise any connection errors encountered.
- def user_info
- parse_user_info(@success_body)
- end
-
- private
-
- # turns an `` node into a Hash;
- # returns nil if given nil
- def parse_user_info(node)
- return nil if node.nil?
- {}.tap do |hash|
- node.children.each do |e|
- node_name = e.name.sub(/^cas:/, '')
- unless e.kind_of?(Nokogiri::XML::Text) || node_name == 'proxies'
- # There are no child elements
- if e.element_children.count == 0
- hash[node_name] = e.content
- elsif e.element_children.count
- # JASIG style extra attributes
- if node_name == 'attributes'
- hash.merge!(parse_user_info(e))
- else
- hash[node_name] = [] if hash[node_name].nil?
- hash[node_name].push(parse_user_info(e))
- end
- end
- end
- end
- end
- end
-
- # finds an `` node in
- # a `` body if present; returns nil
- # if the passed body is nil or if there is no such node.
- def find_authentication_success(body)
- return nil if body.nil? || body == ''
- begin
- doc = Nokogiri::XML(body)
- begin
- doc.xpath('/cas:serviceResponse/cas:authenticationSuccess')
- rescue Nokogiri::XML::XPath::SyntaxError
- doc.xpath('/serviceResponse/authenticationSuccess')
- end
- rescue Nokogiri::XML::XPath::SyntaxError
- nil
- end
- end
-
- # retrieves the `` XML from the CAS server
- def get_service_response_body
- result = ''
- http = Net::HTTP.new(@uri.host, @uri.port)
- http.use_ssl = @uri.port == 443 || @uri.instance_of?(URI::HTTPS)
- if http.use_ssl?
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @options.disable_ssl_verification?
- http.ca_path = @options.ca_path
- end
- http.start do |c|
- response = c.get "#{@uri.path}?#{@uri.query}", VALIDATION_REQUEST_HEADERS.dup
- result = response.body
- end
- result
- end
- end
- end
- end
-end
diff --git a/vendor/gems/omniauth-cas3/omniauth-cas3.gemspec b/vendor/gems/omniauth-cas3/omniauth-cas3.gemspec
deleted file mode 100644
index c976d85df99..00000000000
--- a/vendor/gems/omniauth-cas3/omniauth-cas3.gemspec
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- encoding: utf-8 -*-
-require File.expand_path('../lib/omniauth/cas3/version', __FILE__)
-
-Gem::Specification.new do |gem|
- gem.authors = ["Derek Lindahl, tduehr"]
- gem.email = ["td@matasano.com"]
- gem.summary = %q{CAS 3.0 Strategy for OmniAuth}
- gem.description = gem.summary
- gem.homepage = "https://github.com/tduehr/omniauth-cas3"
-
- gem.files = Dir.glob("lib/**/*.*")
- gem.test_files = Dir.glob("spec/**/**/*.*")
- gem.name = "omniauth-cas3"
- gem.require_paths = ["lib"]
- gem.version = Omniauth::Cas3::VERSION
-
- gem.add_dependency 'omniauth', '~> 2.0'
- gem.add_dependency 'nokogiri', '~> 1.7', '>= 1.7.1'
- gem.add_dependency 'addressable', '~> 2.3'
-
- gem.add_development_dependency 'rake', '~> 10.0'
- gem.add_development_dependency 'webmock'
- gem.add_development_dependency 'rspec', '>= 3.4'
- gem.add_development_dependency 'rack-test', '~> 0.6'
-
- gem.add_development_dependency 'awesome_print'
-end
diff --git a/vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml b/vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml
deleted file mode 100644
index f8238a18014..00000000000
--- a/vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml b/vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml
deleted file mode 100644
index 18904f64b35..00000000000
--- a/vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
- psegel
- 54
- P. Segel
- Peter
- Segel
- psegel@intridea.com
- Washington, D.C.
- /images/user.jpg
- 555-555-5555
- 2004-07-13
-
-
diff --git a/vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml b/vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml
deleted file mode 100644
index 72f58edfb46..00000000000
--- a/vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
- psegel
-
- 54
- P. Segel
- Peter
- Segel
- psegel@intridea.com
- Washington, D.C.
- /images/user.jpg
- 555-555-5555
- 2004-07-13
-
-
-
diff --git a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb
deleted file mode 100644
index 4834347fa03..00000000000
--- a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-require 'spec_helper'
-
-describe OmniAuth::Strategies::CAS3::LogoutRequest do
- let(:strategy) { double('strategy') }
- let(:env) do
- { 'rack.input' => StringIO.new('','r') }
- end
- let(:request) { double('request', params:params, env:env) }
- let(:params) { { 'url' => url, 'logoutRequest' => logoutRequest } }
- let(:url) { 'http://notes.dev/signed_in' }
- let(:logoutRequest) do
- %Q[
-
- @NOT_USED@
- ST-123456-123abc456def
-
- ]
- end
-
- subject { described_class.new(strategy, request).call(options) }
-
- describe 'SAML attributes' do
- let(:callback) { Proc.new{} }
- let(:options) do
- { on_single_sign_out: callback }
- end
-
- before do
- @rack_input = nil
- allow(callback).to receive(:call) do |req|
- @rack_input = req.env['rack.input'].read
- true
- end
- end
-
- it 'are parsed and injected into the Rack Request parameters', :skip => true do
- subject
- expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-123456-123abc456def'
- end
-
- it 'are parsed and injected even if saml defined inside NameID', :skip => true do
- request.params['logoutRequest'] =
- %Q[
-
- @NOT_USED@
- ST-foo-bar
-
- ]
- subject
- expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-foo-bar'
- end
-
- it 'are parsed and injected even if saml and samlp namespaces not defined', :skip => true do
- request.params['logoutRequest'] =
- %Q[
-
- @NOT_USED@
- ST-789000-456def789ghi
-
- ]
- subject
- expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-789000-456def789ghi'
- end
-
- context 'that raise when parsed' do
- let(:env) { { 'rack.input' => nil } }
-
- before do
- allow(strategy).to receive(:fail!)
- subject
- expect(strategy).to have_received(:fail!)
- end
-
- it 'responds with an error', skip: true do
- expect(strategy).to have_received(:fail!)
- end
- end
- end
-
- describe 'with a configured callback' do
- let(:options) do
- { on_single_sign_out: callback }
- end
-
- context 'that returns TRUE' do
- let(:callback) { Proc.new{true} }
-
- it 'responds with OK', skip: true do
- expect(subject[0]).to eq 200
- expect(subject[2].body).to eq ['OK']
- end
- end
-
- context 'that returns Nil' do
- let(:callback) { Proc.new{} }
-
- it 'responds with OK', skip: true do
- expect(subject[0]).to eq 200
- expect(subject[2].body).to eq ['OK']
- end
- end
-
- context 'that returns a tuple' do
- let(:callback) { Proc.new{ [400,{},'Bad Request'] } }
-
- it 'responds with OK', skip: true do
- expect(subject[0]).to eq 400
- expect(subject[2].body).to eq ['Bad Request']
- end
- end
-
- context 'that raises an error' do
- let(:exception) { RuntimeError.new('error' )}
- let(:callback) { Proc.new{raise exception} }
-
- before do
- allow(strategy).to receive(:fail!)
- subject
- end
-
- it 'responds with an error', skip: true do
- expect(strategy).to have_received(:fail!)
- .with(:logout_request, exception)
- end
- end
- end
-end
diff --git a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb
deleted file mode 100644
index b031d1d68fc..00000000000
--- a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'spec_helper'
-
-describe OmniAuth::Strategies::CAS3::ServiceTicketValidator do
- let(:strategy) do
- double('strategy',
- service_validate_url: 'https://example.org/serviceValidate'
- )
- end
- let(:provider_options) do
- double('provider_options',
- disable_ssl_verification?: false,
- ca_path: '/etc/ssl/certsZOMG'
- )
- end
- let(:validator) do
- OmniAuth::Strategies::CAS3::ServiceTicketValidator.new( strategy, provider_options, '/foo', nil )
- end
-
- describe '#call' do
- before do
- stub_request(:get, 'https://example.org/serviceValidate?')
- .to_return(status: 200, body: '')
- end
-
- subject { validator.call }
-
- it 'returns itself' do
- expect(subject).to eq validator
- end
-
- it 'uses the configured CA path' do
- subject
- expect(provider_options).to have_received :ca_path
- end
- end
-
- describe '#user_info' do
- let(:ok_fixture) do
- File.expand_path(File.join(File.dirname(__FILE__), '../../../fixtures/cas_success.xml'))
- end
- let(:service_response) { File.read(ok_fixture) }
-
- before do
- stub_request(:get, 'https://example.org/serviceValidate?')
- .to_return(status: 200, body:service_response)
- validator.call
- end
-
- subject { validator.user_info }
-
- it 'parses user info from the response' do
- expect(subject).to include 'user' => 'psegel'
- end
- end
-end
diff --git a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb
deleted file mode 100644
index f434d711f02..00000000000
--- a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb
+++ /dev/null
@@ -1,266 +0,0 @@
-require 'spec_helper'
-require 'securerandom'
-
-describe OmniAuth::Strategies::CAS3, type: :strategy do
- include Rack::Test::Methods
-
- let(:my_cas_provider) { Class.new(OmniAuth::Strategies::CAS3) }
- before do
- stub_const 'MyCasProvider', my_cas_provider
- end
- let(:app) do
- Rack::Builder.new {
- use OmniAuth::Test::PhonySession
- use MyCasProvider, name: :cas3, host: 'cas.example.org', ssl: false, port: 8080, uid_field: :employeeid
- run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
- }.to_app
- end
-
- let(:csrf_token) { SecureRandom.base64(32) }
- let(:base_env) { { 'rack.session' => { csrf: csrf_token }, 'rack.input' => StringIO.new("authenticity_token=#{escaped_token}") } }
- let(:post_env) { make_env('/auth/cas3', base_env.merge(request_env)) }
- let(:escaped_token) { URI.encode_www_form_component(csrf_token, Encoding::UTF_8) }
-
- def make_env(path = '/auth/cas3', props = {})
- {
- 'REQUEST_METHOD' => 'POST',
- 'PATH_INFO' => path,
- 'rack.session' => {},
- 'rack.input' => StringIO.new('test=true')
- }.merge(props)
- end
-
- # TODO: Verify that these are even useful tests
- shared_examples_for 'a CAS redirect response' do
- let(:redirect_params) { 'service=' + Rack::Utils.escape("http://example.org/auth/cas3/callback?url=#{Rack::Utils.escape(return_url)}") }
-
- before { post url, nil, post_env }
-
- subject { last_response }
-
- it { should be_redirect }
-
- it 'redirects to the CAS server' do
- expect(subject.status).to eq(302)
- expect(subject.headers).to include 'Location' => "http://cas.example.org:8080/login?#{redirect_params}"
- end
- end
-
- describe '#cas_url' do
- let(:params) { Hash.new }
- let(:provider) { MyCasProvider.new(nil, params) }
-
- subject { provider.cas_url }
-
- it 'raises an ArgumentError' do
- expect{subject}.to raise_error ArgumentError, %r{:host and :login_url MUST be provided}
- end
-
- context 'with an explicit :url option' do
- let(:url) { 'https://example.org:8080/my_cas' }
- let(:params) { super().merge url:url }
-
- before { subject }
-
- it { should eq url }
-
- it 'parses the URL into it the appropriate strategy options' do
- expect(provider.options).to include ssl:true
- expect(provider.options).to include host:'example.org'
- expect(provider.options).to include port:8080
- expect(provider.options).to include path:'/my_cas'
- end
- end
-
- context 'with explicit URL component' do
- let(:params) { super().merge host:'example.org', port:1234, ssl:true, path:'/a/path' }
-
- before { subject }
-
- it { should eq 'https://example.org:1234/a/path' }
-
- it 'parses the URL into it the appropriate strategy options' do
- expect(provider.options).to include ssl:true
- expect(provider.options).to include host:'example.org'
- expect(provider.options).to include port:1234
- expect(provider.options).to include path:'/a/path'
- end
- end
- end
-
- describe 'defaults' do
- subject { MyCasProvider.default_options.to_hash }
-
- it { should include('ssl' => true) }
- end
-
- describe 'POST /auth/cas3' do
- let(:return_url) { 'http://myapp.com/admin/foo' }
-
- context 'with a referer' do
- let(:url) { '/auth/cas3' }
-
- let(:request_env) { { 'HTTP_REFERER' => return_url } }
-
- it_behaves_like 'a CAS redirect response'
- end
-
- context 'with an explicit return URL' do
- let(:url) { "/auth/cas3?url=#{return_url}" }
-
- let(:request_env) { {} }
-
- it_behaves_like 'a CAS redirect response'
- end
- end
-
- describe 'GET /auth/cas3/callback' do
- context 'without a ticket' do
- before { get '/auth/cas3/callback' }
-
- subject { last_response }
-
- it { should be_redirect }
-
- it 'redirects with a failure message' do
- expect(subject.headers).to include 'Location' => '/auth/failure?message=no_ticket&strategy=cas3'
- end
- end
-
- context 'with an invalid ticket' do
- before do
- stub_request(:get, /^http:\/\/cas.example.org:8080?\/p3\/serviceValidate\?([^&]+&)?ticket=9391d/).
- to_return( body: File.read('spec/fixtures/cas_failure.xml') )
- get '/auth/cas3/callback?ticket=9391d'
- end
-
- subject { last_response }
-
- it { should be_redirect }
-
- it 'redirects with a failure message' do
- expect(subject.headers).to include 'Location' => '/auth/failure?message=invalid_ticket&strategy=cas3'
- end
- end
-
- describe 'with a valid ticket' do
- shared_examples :successful_validation do
- before do
- stub_request(:get, /^http:\/\/cas.example.org:8080?\/p3\/serviceValidate\?([^&]+&)?ticket=593af/)
- .with { |request| @request_uri = request.uri.to_s }
- .to_return( body: File.read("spec/fixtures/#{xml_file_name}") )
-
- get "/auth/cas3/callback?ticket=593af&url=#{return_url}"
- end
-
- it 'strips the ticket parameter from the callback URL' do
- expect(@request_uri.scan('ticket=').size).to eq 1
- end
-
- it 'properly encodes the service URL' do
- expect(WebMock).to have_requested(:get, 'http://cas.example.org:8080/p3/serviceValidate')
- .with(query: {
- ticket: '593af',
- service: 'http://example.org/auth/cas3/callback?url=' + Rack::Utils.escape('http://127.0.0.10/?some=parameter')
- })
- end
-
- context "request.env['omniauth.auth']" do
- subject { last_request.env['omniauth.auth'] }
-
- it { should be_kind_of Hash }
-
- it 'identifes the provider' do
- expect(subject.provider).to eq :cas3
- end
-
- it 'returns the UID of the user' do
- expect(subject.uid).to eq '54'
- end
-
- context 'the info hash' do
- subject { last_request.env['omniauth.auth']['info'] }
-
- it 'includes user info attributes' do
- expect(subject.name).to eq 'Peter Segel'
- expect(subject.first_name).to eq 'Peter'
- expect(subject.last_name).to eq 'Segel'
- expect(subject.nickname).to eq 'psegel'
- expect(subject.email).to eq 'psegel@intridea.com'
- expect(subject.location).to eq 'Washington, D.C.'
- expect(subject.image).to eq '/images/user.jpg'
- expect(subject.phone).to eq '555-555-5555'
- end
- end
-
- context 'the extra hash' do
- subject { last_request.env['omniauth.auth']['extra'] }
-
- it 'includes additional user attributes' do
- expect(subject.user).to eq 'psegel'
- expect(subject.employeeid).to eq '54'
- expect(subject.hire_date).to eq '2004-07-13'
- end
- end
-
- context 'the credentials hash' do
- subject { last_request.env['omniauth.auth']['credentials'] }
-
- it 'has a ticket value' do
- expect(subject.ticket).to eq '593af'
- end
- end
- end
-
- it 'calls through to the master app' do
- expect(last_response.body).to eq 'true'
- end
- end
-
- let(:return_url) { 'http://127.0.0.10/?some=parameter' }
-
- context 'with JASIG flavored XML' do
- let(:xml_file_name) { 'cas_success_jasig.xml' }
-
- it_behaves_like :successful_validation
- end
-
- context 'with classic XML' do
- let(:xml_file_name) { 'cas_success.xml' }
-
- it_behaves_like :successful_validation
- end
- end
- end
-
- describe 'POST /auth/cas3/callback' do
- describe 'with a Single Sign-Out logoutRequest' do
- let(:logoutRequest) do
- %Q[
-
- @NOT_USED@
- ST-123456-123abc456def
-
- ]
- end
-
- let(:logout_request) { double('logout_request', call:[200,{},'OK']) }
-
- subject do
- post 'auth/cas3/callback', logoutRequest:logoutRequest
- end
-
- before do
- allow_any_instance_of(MyCasProvider)
- .to receive(:logout_request_service)
- .and_return double('LogoutRequest', new:logout_request)
-
- subject
- end
-
- it 'initializes a LogoutRequest' do
- expect(logout_request).to have_received :call
- end
- end
- end
-end
diff --git a/vendor/gems/omniauth-cas3/spec/spec_helper.rb b/vendor/gems/omniauth-cas3/spec/spec_helper.rb
deleted file mode 100644
index 75231268ff3..00000000000
--- a/vendor/gems/omniauth-cas3/spec/spec_helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'bundler/setup'
-require 'awesome_print'
-
-RSpec.configure do |c|
- c.filter_run focus: true
- c.run_all_when_everything_filtered = true
-end
-
-require 'rack/test'
-require 'webmock/rspec'
-require 'omniauth-cas3'
-
-OmniAuth.config.logger = Logger.new( '/dev/null' )