diff options
110 files changed, 507 insertions, 1645 deletions
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 @@ -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 @@ -62,14 +62,6 @@ PATH 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: omniauth-gitlab (4.0.0) @@ -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" /> <gl-modal diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0767fadbe71..9749af08dca 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -29,7 +29,6 @@ class ApplicationController < ActionController::Base before_action :limit_session_time, if: -> { !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): | <a id="boardepicancestorsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. | | <a id="boardepicancestorscreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. | | <a id="boardepicancestorscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. | -| <a id="boardepicancestorsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="boardepicancestorsiid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". | | <a id="boardepicancestorsiidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. | | <a id="boardepicancestorsiids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. | @@ -11829,7 +11828,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="boardepicancestorsor"></a>`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. | | <a id="boardepicancestorssearch"></a>`search` | [`String`](#string) | Search query for title or description. | | <a id="boardepicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. | -| <a id="boardepicancestorsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="boardepicancestorsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. | | <a id="boardepicancestorstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="boardepicancestorstoplevelhierarchyonly"></a>`topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. | @@ -11854,7 +11852,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="boardepicchildrenconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. | | <a id="boardepicchildrencreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. | | <a id="boardepicchildrencreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. | -| <a id="boardepicchildrenenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="boardepicchildreniid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". | | <a id="boardepicchildreniidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. | | <a id="boardepicchildreniids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. | @@ -11868,7 +11865,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="boardepicchildrenor"></a>`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. | | <a id="boardepicchildrensearch"></a>`search` | [`String`](#string) | Search query for title or description. | | <a id="boardepicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. | -| <a id="boardepicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="boardepicchildrenstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. | | <a id="boardepicchildrentimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="boardepicchildrentoplevelhierarchyonly"></a>`topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. | @@ -14011,7 +14007,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="epicancestorsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. | | <a id="epicancestorscreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. | | <a id="epicancestorscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. | -| <a id="epicancestorsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="epicancestorsiid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". | | <a id="epicancestorsiidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. | | <a id="epicancestorsiids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. | @@ -14025,7 +14020,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="epicancestorsor"></a>`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. | | <a id="epicancestorssearch"></a>`search` | [`String`](#string) | Search query for title or description. | | <a id="epicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. | -| <a id="epicancestorsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="epicancestorsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. | | <a id="epicancestorstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="epicancestorstoplevelhierarchyonly"></a>`topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. | @@ -14050,7 +14044,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="epicchildrenconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. | | <a id="epicchildrencreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. | | <a id="epicchildrencreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. | -| <a id="epicchildrenenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="epicchildreniid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". | | <a id="epicchildreniidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. | | <a id="epicchildreniids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. | @@ -14064,7 +14057,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="epicchildrenor"></a>`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. | | <a id="epicchildrensearch"></a>`search` | [`String`](#string) | Search query for title or description. | | <a id="epicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. | -| <a id="epicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="epicchildrenstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. | | <a id="epicchildrentimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="epicchildrentoplevelhierarchyonly"></a>`topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. | @@ -15126,7 +15118,6 @@ Returns [`Epic`](#epic). | <a id="groupepicconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. | | <a id="groupepiccreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. | | <a id="groupepiccreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. | -| <a id="groupepicenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="groupepiciid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". | | <a id="groupepiciidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. | | <a id="groupepiciids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. | @@ -15140,7 +15131,6 @@ Returns [`Epic`](#epic). | <a id="groupepicor"></a>`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. | | <a id="groupepicsearch"></a>`search` | [`String`](#string) | Search query for title or description. | | <a id="groupepicsort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. | -| <a id="groupepicstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="groupepicstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. | | <a id="groupepictimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="groupepictoplevelhierarchyonly"></a>`topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. | @@ -15177,7 +15167,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="groupepicsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter epics by given confidentiality. | | <a id="groupepicscreatedafter"></a>`createdAfter` | [`Time`](#time) | Epics created after this date. | | <a id="groupepicscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Epics created before this date. | -| <a id="groupepicsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="groupepicsiid"></a>`iid` | [`ID`](#id) | IID of the epic, e.g., "1". | | <a id="groupepicsiidstartswith"></a>`iidStartsWith` | [`String`](#string) | Filter epics by IID for autocomplete. | | <a id="groupepicsiids"></a>`iids` | [`[ID!]`](#id) | List of IIDs of epics, e.g., `[1, 2]`. | @@ -15191,7 +15180,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="groupepicsor"></a>`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. | | <a id="groupepicssearch"></a>`search` | [`String`](#string) | Search query for title or description. | | <a id="groupepicssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. | -| <a id="groupepicsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="groupepicsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. | | <a id="groupepicstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="groupepicstoplevelhierarchyonly"></a>`topLevelHierarchyOnly` | [`Boolean`](#boolean) | Filter epics with a top-level hierarchy. | @@ -15317,7 +15305,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | -| <a id="groupiterationsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="groupiterationsid"></a>`id` | [`ID`](#id) | Global ID of the Iteration to look up. | | <a id="groupiterationsiid"></a>`iid` | [`ID`](#id) | Internal ID of the Iteration to look up. | | <a id="groupiterationsin"></a>`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): | <a id="groupiterationsiterationcadenceids"></a>`iterationCadenceIds` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Global iteration cadence IDs by which to look up the iterations. | | <a id="groupiterationssearch"></a>`search` | [`String`](#string) | Query used for fuzzy-searching in the fields selected in the argument `in`. Returns all iterations if empty. | | <a id="groupiterationssort"></a>`sort` | [`IterationSort`](#iterationsort) | List iterations by sort order. If unspecified, an arbitrary order (subject to change) is used. | -| <a id="groupiterationsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="groupiterationsstate"></a>`state` | [`IterationState`](#iterationstate) | Filter iterations by state. | | <a id="groupiterationstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="groupiterationstitle"></a>`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 | | ---- | ---- | ----------- | | <a id="groupmilestonescontainingdate"></a>`containingDate` | [`Time`](#time) | Date the milestone contains. | -| <a id="groupmilestonesenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="groupmilestonesids"></a>`ids` | [`[ID!]`](#id) | Array of global milestone IDs, e.g., `"gid://gitlab/Milestone/1"`. | | <a id="groupmilestonesincludeancestors"></a>`includeAncestors` | [`Boolean`](#boolean) | Include milestones from all parent groups. | | <a id="groupmilestonesincludedescendants"></a>`includeDescendants` | [`Boolean`](#boolean) | Include milestones from all subgroups and subprojects. | | <a id="groupmilestonessearchtitle"></a>`searchTitle` | [`String`](#string) | Search string for the title. | | <a id="groupmilestonessort"></a>`sort` | [`MilestoneSort`](#milestonesort) | Sort milestones by this criteria. | -| <a id="groupmilestonesstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="groupmilestonesstate"></a>`state` | [`MilestoneStateEnum`](#milestonestateenum) | Filter milestones by state. | | <a id="groupmilestonestimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="groupmilestonestitle"></a>`title` | [`String`](#string) | Title of the milestone. | @@ -18897,7 +18881,6 @@ Represents a product analytics dashboard visualization. | <a id="projectissuesenabled"></a>`issuesEnabled` | [`Boolean`](#boolean) | Indicates if Issues are enabled for the current user. | | <a id="projectjiraimportstatus"></a>`jiraImportStatus` | [`String`](#string) | Status of Jira import background job of the project. | | <a id="projectjiraimports"></a>`jiraImports` | [`JiraImportConnection`](#jiraimportconnection) | Jira imports into the project. (see [Connections](#connections)) | -| <a id="projectjitsukey"></a>`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. | | <a id="projectjobsenabled"></a>`jobsEnabled` | [`Boolean`](#boolean) | Indicates if CI/CD pipeline jobs are enabled for the current user. | | <a id="projectlanguages"></a>`languages` | [`[RepositoryLanguage!]`](#repositorylanguage) | Programming languages used in the project. | | <a id="projectlastactivityat"></a>`lastActivityAt` | [`Time`](#time) | Timestamp of the project last activity. | @@ -18945,6 +18928,7 @@ Represents a product analytics dashboard visualization. | <a id="projectterraformstates"></a>`terraformStates` | [`TerraformStateConnection`](#terraformstateconnection) | Terraform states associated with the project. (see [Connections](#connections)) | | <a id="projecttimelogcategories"></a>`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. | | <a id="projecttopics"></a>`topics` | [`[String!]`](#string) | List of project topics. | +| <a id="projecttrackingkey"></a>`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. | | <a id="projectuseraccessauthorizedagents"></a>`userAccessAuthorizedAgents` | [`ClusterAgentAuthorizationUserAccessConnection`](#clusteragentauthorizationuseraccessconnection) | Authorized cluster agents for the project through user_access keyword. (see [Connections](#connections)) | | <a id="projectuserpermissions"></a>`userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource. | | <a id="projectvisibility"></a>`visibility` | [`String`](#string) | Visibility of the project. | @@ -19614,7 +19598,6 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | -| <a id="projectiterationsenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="projectiterationsid"></a>`id` | [`ID`](#id) | Global ID of the Iteration to look up. | | <a id="projectiterationsiid"></a>`iid` | [`ID`](#id) | Internal ID of the Iteration to look up. | | <a id="projectiterationsin"></a>`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): | <a id="projectiterationsiterationcadenceids"></a>`iterationCadenceIds` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Global iteration cadence IDs by which to look up the iterations. | | <a id="projectiterationssearch"></a>`search` | [`String`](#string) | Query used for fuzzy-searching in the fields selected in the argument `in`. Returns all iterations if empty. | | <a id="projectiterationssort"></a>`sort` | [`IterationSort`](#iterationsort) | List iterations by sort order. If unspecified, an arbitrary order (subject to change) is used. | -| <a id="projectiterationsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="projectiterationsstate"></a>`state` | [`IterationState`](#iterationstate) | Filter iterations by state. | | <a id="projectiterationstimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="projectiterationstitle"></a>`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 | | ---- | ---- | ----------- | | <a id="projectmilestonescontainingdate"></a>`containingDate` | [`Time`](#time) | Date the milestone contains. | -| <a id="projectmilestonesenddate"></a>`endDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.end. | | <a id="projectmilestonesids"></a>`ids` | [`[ID!]`](#id) | Array of global milestone IDs, e.g., `"gid://gitlab/Milestone/1"`. | | <a id="projectmilestonesincludeancestors"></a>`includeAncestors` | [`Boolean`](#boolean) | Also return milestones in the project's parent group and its ancestors. | | <a id="projectmilestonessearchtitle"></a>`searchTitle` | [`String`](#string) | Search string for the title. | | <a id="projectmilestonessort"></a>`sort` | [`MilestoneSort`](#milestonesort) | Sort milestones by this criteria. | -| <a id="projectmilestonesstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. | | <a id="projectmilestonesstate"></a>`state` | [`MilestoneStateEnum`](#milestonestateenum) | Filter milestones by state. | | <a id="projectmilestonestimeframe"></a>`timeframe` | [`Timeframe`](#timeframe) | List items overlapping the given timeframe. | | <a id="projectmilestonestitle"></a>`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 { <div class="highlight"> <pre class="highlight"><code><span class="na">gemnasium-dependency_scanning</span><span class="pi">:</span> <span class="na">image</span><span class="pi">:</span> - <span class="na">name</span><span class="pi">:</span> <span class="s">$CI_TEMPLATE_REGISTRY_HOST/security-products/gemnasium-python:3-python-3.10</span></code></pre></div></div> + <span class="na">name</span><span class="pi">:</span> <span class="s">$CI_TEMPLATE_REGISTRY_HOST/security-products/gemnasium-python:4-python-3.10</span></code></pre></div></div> </p> </li> <li> @@ -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 <kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts. + +![Merge requests commit navigation](img/commit_nav_v16_0.png) + +## 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: + + ![Previously merged commits](img/previously_merged_commits_v16_0.png) + +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 Binary files differnew file mode 100644 index 00000000000..6005e516fff --- /dev/null +++ b/doc/user/project/merge_requests/img/commit_nav_v16_0.png diff --git a/doc/user/project/merge_requests/img/previously_merged_commits_v16_0.png b/doc/user/project/merge_requests/img/previously_merged_commits_v16_0.png Binary files differnew file mode 100644 index 00000000000..31204b6e801 --- /dev/null +++ b/doc/user/project/merge_requests/img/previously_merged_commits_v16_0.png diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb index a00ef7144d4..6639b3ec346 100644 --- a/lib/api/project_import.rb +++ b/lib/api/project_import.rb @@ -33,16 +33,14 @@ module API end end - before do - forbidden! unless Gitlab::CurrentSettings.import_sources.include?('gitlab_project') - end - resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do desc 'Workhorse authorize the project import upload' do detail 'This feature was introduced in GitLab 12.9' tags ['project_import'] end post 'import/authorize' do + forbidden! unless Gitlab::CurrentSettings.import_sources.include?('gitlab_project') + require_gitlab_workhorse! status 200 @@ -90,6 +88,8 @@ module API consumes ['multipart/form-data'] end post 'import' do + forbidden! unless Gitlab::CurrentSettings.import_sources.include?('gitlab_project') + require_gitlab_workhorse! check_rate_limit! :project_import, scope: [current_user, :project_import] @@ -164,6 +164,8 @@ module API ] end post 'remote-import' do + forbidden! unless Gitlab::CurrentSettings.import_sources.include?('gitlab_project') + check_rate_limit! :project_import, scope: [current_user, :project_import] response = ::Import::GitlabProjects::CreateProjectService.new( @@ -217,6 +219,8 @@ module API ] end post 'remote-import-s3' do + forbidden! unless Gitlab::CurrentSettings.import_sources.include?('gitlab_project') + check_rate_limit! :project_import, scope: [current_user, :project_import] response = ::Import::GitlabProjects::CreateProjectService.new( diff --git a/lib/gitlab/auth/o_auth/session.rb b/lib/gitlab/auth/o_auth/session.rb deleted file mode 100644 index 4925b107042..00000000000 --- a/lib/gitlab/auth/o_auth/session.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -# :nocov: -module Gitlab - module Auth - module OAuth - module Session - def self.create(provider, ticket) - Rails.cache.write("gitlab:#{provider}:#{ticket}", ticket, expires_in: Gitlab.config.omniauth.cas3.session_duration) - end - - def self.destroy(provider, ticket) - Rails.cache.delete("gitlab:#{provider}:#{ticket}") - end - - def self.valid?(provider, ticket) - Rails.cache.read("gitlab:#{provider}:#{ticket}").present? - end - end - end - end -end -# :nocov: diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml index c4ba49de931..dd9575371dc 100644 --- a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml @@ -14,7 +14,7 @@ variables: SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products" DS_EXCLUDED_ANALYZERS: "" DS_EXCLUDED_PATHS: "spec, test, tests, tmp" - DS_MAJOR_VERSION: 3 + DS_MAJOR_VERSION: 4 DS_SCHEMA_MODEL: 15 dependency_scanning: diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml index 1bc465c69f9..4d7c3930741 100644 --- a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml @@ -14,7 +14,7 @@ variables: SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products" DS_EXCLUDED_ANALYZERS: "" DS_EXCLUDED_PATHS: "spec, test, tests, tmp" - DS_MAJOR_VERSION: 3 + DS_MAJOR_VERSION: 4 DS_SCHEMA_MODEL: 15 dependency_scanning: diff --git a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml index 7b2e9e1222a..123dea09524 100644 --- a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml @@ -198,20 +198,12 @@ pmd-apex-sast: security-code-scan-sast: extends: .sast-analyzer - image: - name: "$SAST_ANALYZER_IMAGE" - variables: - SAST_ANALYZER_IMAGE_TAG: '3' - SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG" + script: + - echo "This job was deprecated in GitLab 15.9 and removed in GitLab 16.0" + - echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/390416" + - exit 1 rules: - - if: $SAST_DISABLED - when: never - - if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/ - when: never - - if: $CI_COMMIT_BRANCH - exists: - - '**/*.csproj' - - '**/*.vbproj' + - when: never semgrep-sast: extends: .sast-analyzer diff --git a/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml index c9404eebab2..88d10f8b235 100644 --- a/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml @@ -253,26 +253,12 @@ pmd-apex-sast: security-code-scan-sast: extends: .sast-analyzer - image: - name: "$SAST_ANALYZER_IMAGE" - variables: - SAST_ANALYZER_IMAGE_TAG: 3 - SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG" + script: + - echo "This job was deprecated in GitLab 15.9 and removed in GitLab 16.0" + - echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/390416" + - exit 1 rules: - - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1' - when: never - - if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/ - when: never - - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request. - exists: - - '**/*.csproj' - - '**/*.vbproj' - - if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline. - when: never - - if: $CI_COMMIT_BRANCH # If there's no open merge request, add it to a *branch* pipeline instead. - exists: - - '**/*.csproj' - - '**/*.vbproj' + - when: never semgrep-sast: extends: .sast-analyzer diff --git a/lib/gitlab/database/migrations/pg_backend_pid.rb b/lib/gitlab/database/migrations/pg_backend_pid.rb index 0c15aae9395..b59eb55cc6e 100644 --- a/lib/gitlab/database/migrations/pg_backend_pid.rb +++ b/lib/gitlab/database/migrations/pg_backend_pid.rb @@ -24,6 +24,8 @@ module Gitlab end def self.say(conn) + return unless ActiveRecord::Migration.verbose + pg_backend_pid = conn.select_value('SELECT pg_backend_pid()') db_name = Gitlab::Database.db_config_name(conn) diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb index f933be673ab..81ad7a7f9e1 100644 --- a/lib/gitlab/omniauth_initializer.rb +++ b/lib/gitlab/omniauth_initializer.rb @@ -21,8 +21,6 @@ module Gitlab class << self def default_arguments_for(provider_name) case provider_name - when 'cas3' - { on_single_sign_out: cas3_signout_handler } when 'shibboleth' { fail_with_empty_uid: true } when 'google_oauth2' @@ -39,18 +37,6 @@ module Gitlab def full_host proc { |_env| Settings.gitlab['base_url'] } end - - private - - def cas3_signout_handler - lambda do |request| - ticket = request.params[:session_index] - raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket) - - Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket) - true - end - end end private diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2b65ff3e8fb..3e540f31a87 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -21500,9 +21500,6 @@ msgstr "" msgid "GroupsNew|Connect instance" msgstr "" -msgid "GroupsNew|Contact an administrator to enable options for importing your group." -msgstr "" - msgid "GroupsNew|Create a token with %{code_start}api%{code_end} and %{code_start}read_repository%{code_end} scopes in the %{pat_link_start}user settings%{pat_link_end} of the source GitLab instance. For %{short_living_link_start}security reasons%{short_living_link_end}, set a short expiration date for the token. Keep in mind that large migrations take more time." msgstr "" @@ -21545,9 +21542,6 @@ msgstr "" msgid "GroupsNew|New subgroup" msgstr "" -msgid "GroupsNew|No import options available" -msgstr "" - msgid "GroupsNew|Not all group items are migrated. %{docs_link_start}What items are migrated%{docs_link_end}?" msgstr "" @@ -45445,6 +45439,9 @@ msgstr "" msgid "There was a problem updating the keep latest artifacts setting." msgstr "" +msgid "There was a problem with the credit card details you entered. Use a different credit card and try again." +msgstr "" + msgid "There was an error creating the dashboard, branch name is invalid." msgstr "" diff --git a/qa/qa/page/component/import/selection.rb b/qa/qa/page/component/import/selection.rb index 6cacdd84f13..db2ff74e0f8 100644 --- a/qa/qa/page/component/import/selection.rb +++ b/qa/qa/page/component/import/selection.rb @@ -14,6 +14,10 @@ module QA end def click_gitlab + retry_until(reload: true, max_attempts: 10, message: 'Waiting for import source to be enabled') do + has_element?(:gitlab_import_button) + end + click_element(:gitlab_import_button) end end diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb index 7163bc7464d..a97d0afd160 100644 --- a/qa/qa/page/project/branches/show.rb +++ b/qa/qa/page/project/branches/show.rb @@ -24,6 +24,7 @@ module QA end view 'app/assets/javascripts/branches/components/delete_merged_branches.vue' do + element :delete_merged_branches_dropdown_button element :delete_merged_branches_button element :delete_merged_branches_input element :delete_merged_branches_confirmation_button @@ -54,6 +55,7 @@ module QA end def delete_merged_branches(branches_length) + click_element(:delete_merged_branches_dropdown_button) click_element(:delete_merged_branches_button) fill_element(:delete_merged_branches_input, branches_length) click_element(:delete_merged_branches_confirmation_button) diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb index 8624e4c3d83..8ea0b57ef3e 100644 --- a/qa/qa/page/project/new.rb +++ b/qa/qa/page/project/new.rb @@ -87,11 +87,15 @@ module QA end def click_github_link - click_link 'GitHub' + retry_until(reload: true, max_attempts: 10, message: 'Waiting for import source to be enabled') do + click_link 'GitHub' + end end def click_repo_by_url_link - click_button 'Repository by URL' + retry_until(reload: true, max_attempts: 10, message: 'Waiting for import source to be enabled') do + click_button 'Repository by URL' + end end def disable_initialize_with_readme diff --git a/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb index 85b62ec2ad1..fa64489fb83 100644 --- a/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb +++ b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb @@ -9,6 +9,10 @@ module QA describe 'GitHub import' do include_context 'with github import' + before do + QA::Support::Helpers::ImportSource.enable('github') + end + context 'when imported via api' do it 'imports project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347670' do expect_project_import_finished_successfully diff --git a/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb index 94a3835b6c9..62da946d750 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb @@ -29,6 +29,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable('github') + Flow::Login.sign_in(as: user) Page::Main::Menu.perform(&:go_to_create_project) Page::Project::New.perform do |project_page| diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb index 82e2136cd22..8cdcf1dd721 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb @@ -16,6 +16,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable(%w[gitlab_project]) + Flow::Login.sign_in end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb index 748b989deb8..112149a7a5f 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb @@ -11,6 +11,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable(%w[gitlab_project]) + Flow::Login.sign_in merge_request.visit! end diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb index bf328a2bced..077267ae38a 100644 --- a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb @@ -64,6 +64,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable('git') + Flow::Login.sign_in imported_project diff --git a/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb index fe320f10416..13ad0d1d22a 100644 --- a/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb @@ -25,6 +25,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable('git') + Flow::Login.sign_in imported_project diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb index f8ab9ef15ab..e30703728b2 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb @@ -262,6 +262,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable('git') + Runtime::Feature.enable(:maven_central_request_forwarding) Flow::Login.sign_in_unless_signed_in diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb index b70ec0bafbc..653f42ac3f8 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb @@ -190,6 +190,8 @@ module QA end before do + QA::Support::Helpers::ImportSource.enable('git') + Runtime::Feature.enable(:maven_central_request_forwarding) Flow::Login.sign_in_unless_signed_in diff --git a/qa/qa/support/helpers/import_source.rb b/qa/qa/support/helpers/import_source.rb new file mode 100644 index 00000000000..f25466dc1a0 --- /dev/null +++ b/qa/qa/support/helpers/import_source.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module QA + module Support + module Helpers + module ImportSource + def self.enable(new_import_sources) + current_import_sources = Runtime::ApplicationSettings.get_application_settings[:import_sources] + + import_sources = current_import_sources | Array(new_import_sources) + + return if (import_sources - current_import_sources).blank? + + Runtime::ApplicationSettings.set_application_settings(import_sources: import_sources) + end + end + end + end +end diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb index 40a5c59fa2d..3b099ba2613 100644 --- a/spec/controllers/import/fogbugz_controller_spec.rb +++ b/spec/controllers/import/fogbugz_controller_spec.rb @@ -11,6 +11,8 @@ RSpec.describe Import::FogbugzController, feature_category: :importers do let(:namespace_id) { 5 } before do + stub_application_setting(import_sources: ['fogbugz']) + sign_in(user) end diff --git a/spec/controllers/import/gitea_controller_spec.rb b/spec/controllers/import/gitea_controller_spec.rb index 94b02f7c1b9..3dfda909a93 100644 --- a/spec/controllers/import/gitea_controller_spec.rb +++ b/spec/controllers/import/gitea_controller_spec.rb @@ -10,6 +10,10 @@ RSpec.describe Import::GiteaController, feature_category: :importers do include_context 'a GitHub-ish import controller' + before do + stub_application_setting(import_sources: ['gitea']) + end + def assign_host_url session[:gitea_host_url] = host_url end diff --git a/spec/controllers/import/manifest_controller_spec.rb b/spec/controllers/import/manifest_controller_spec.rb index 23d5d37ed88..69eb736375c 100644 --- a/spec/controllers/import/manifest_controller_spec.rb +++ b/spec/controllers/import/manifest_controller_spec.rb @@ -13,6 +13,8 @@ RSpec.describe Import::ManifestController, :clean_gitlab_redis_shared_state, fea end before do + stub_application_setting(import_sources: ['manifest']) + sign_in(user) end diff --git a/spec/controllers/profiles/accounts_controller_spec.rb b/spec/controllers/profiles/accounts_controller_spec.rb index ba349768b0f..f0ee2e178cf 100644 --- a/spec/controllers/profiles/accounts_controller_spec.rb +++ b/spec/controllers/profiles/accounts_controller_spec.rb @@ -16,18 +16,16 @@ RSpec.describe Profiles::AccountsController do expect(response).to have_gitlab_http_status(:not_found) end - [:saml, :cas3].each do |provider| - describe "#{provider} provider" do - let(:user) { create(:omniauth_user, provider: provider.to_s) } + describe "saml provider" do + let(:user) { create(:omniauth_user, provider: 'saml') } - it "does not allow to unlink connected account" do - identity = user.identities.last + it "does not allow to unlink connected account" do + identity = user.identities.last - delete :unlink, params: { provider: provider.to_s } + delete :unlink, params: { provider: 'saml' } - expect(response).to have_gitlab_http_status(:found) - expect(user.reload.identities).to include(identity) - end + expect(response).to have_gitlab_http_status(:found) + expect(user.reload.identities).to include(identity) end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 8f687332901..2808b6181f3 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -53,17 +53,6 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do end it 'modify import sources' do - expect(current_settings.import_sources).not_to be_empty - - page.within('[data-testid="admin-visibility-access-settings"]') do - Gitlab::ImportSources.options.map do |name, _| - uncheck name - end - - click_button 'Save changes' - end - - expect(page).to have_content "Application settings saved successfully" expect(current_settings.import_sources).to be_empty page.within('[data-testid="admin-visibility-access-settings"]') do diff --git a/spec/features/file_uploads/project_import_spec.rb b/spec/features/file_uploads/project_import_spec.rb index c261834206d..3934e0319ad 100644 --- a/spec/features/file_uploads/project_import_spec.rb +++ b/spec/features/file_uploads/project_import_spec.rb @@ -22,6 +22,10 @@ RSpec.describe 'Upload a project export archive', :api, :js, feature_category: : ) end + before do + stub_application_setting(import_sources: ['gitlab_project']) + end + RSpec.shared_examples 'for a project export archive' do it { expect { subject }.to change { Project.count }.by(1) } diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb index bb3eb34637b..aba38eb0196 100644 --- a/spec/features/import/manifest_import_spec.rb +++ b/spec/features/import/manifest_import_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js, let(:group) { create(:group) } before do + stub_application_setting(import_sources: ['manifest']) + sign_in(user) group.add_owner(user) diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb index bd96d65f984..ca20a1cd81b 100644 --- a/spec/features/oauth_login_spec.rb +++ b/spec/features/oauth_login_spec.rb @@ -16,7 +16,7 @@ RSpec.describe 'OAuth Login', :allow_forgery_protection, feature_category: :syst end providers = [:github, :twitter, :bitbucket, :gitlab, :google_oauth2, - :facebook, :cas3, :auth0, :salesforce, :dingtalk, :alicloud] + :facebook, :auth0, :salesforce, :dingtalk, :alicloud] around do |example| with_omniauth_full_host { example.run } diff --git a/spec/features/oauth_registration_spec.rb b/spec/features/oauth_registration_spec.rb index 3c1004e452f..c88a018a592 100644 --- a/spec/features/oauth_registration_spec.rb +++ b/spec/features/oauth_registration_spec.rb @@ -21,7 +21,6 @@ RSpec.describe 'OAuth Registration', :js, :allow_forgery_protection, feature_cat :gitlab | {} :google_oauth2 | {} :facebook | {} - :cas3 | {} :auth0 | {} :salesforce | { extra: { email_verified: true } } :dingtalk | {} diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 038d58a20ab..91651617966 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -354,7 +354,7 @@ RSpec.describe 'Environments page', :js, feature_category: :projects do wait_for_requests end - it 'enqueues the delayed job', :js do + it 'enqueues the delayed job', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/409990' do expect(delayed_job.reload).to be_pending end end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 8fb11f06cdd..f4ed0728402 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Import/Export - project import integration test', :js, feature_c let(:export_path) { "#{Dir.tmpdir}/import_file_spec" } before do + stub_application_setting(import_sources: ['gitlab_project']) stub_uploads_object_storage(FileUploader) allow_next_instance_of(Gitlab::ImportExport) do |instance| allow(instance).to receive(:storage_path).and_return(export_path) diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index 12a97dee710..351662af217 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -5,6 +5,10 @@ require 'spec_helper' RSpec.describe 'New project', :js, feature_category: :projects do include Features::TopNavSpecHelpers + before do + stub_application_setting(import_sources: Gitlab::ImportSources.values) + end + context 'as a user' do let_it_be(:user) { create(:user) } diff --git a/spec/frontend/branches/components/__snapshots__/delete_merged_branches_spec.js.snap b/spec/frontend/branches/components/__snapshots__/delete_merged_branches_spec.js.snap index 68b1d4bcbd2..300b6f4a39a 100644 --- a/spec/frontend/branches/components/__snapshots__/delete_merged_branches_spec.js.snap +++ b/spec/frontend/branches/components/__snapshots__/delete_merged_branches_spec.js.snap @@ -5,6 +5,7 @@ exports[`Delete merged branches component Delete merged branches confirmation mo <gl-base-dropdown-stub category="tertiary" class="gl-disclosure-dropdown" + data-qa-selector="delete_merged_branches_dropdown_button" icon="ellipsis_v" nocaret="true" placement="right" diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js index 566cf93f688..cdfe8b02b48 100644 --- a/spec/frontend/notes/components/notes_app_spec.js +++ b/spec/frontend/notes/components/notes_app_spec.js @@ -122,7 +122,9 @@ describe('note_app', () => { ); }); - 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,18 +45,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do end context 'with parameters' do - it 'calls MilestonesFinder with correct parameters' 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(start_date: start_date, end_date: end_date, state: 'closed') - end - - it 'understands the timeframe argument' do + it 'timeframe argument' do start_date = now end_date = start_date + 1.hour @@ -64,7 +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(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) - - 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') + 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(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 `<cas:authenticationSuccess>` 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 `<cas:authenticationSuccess>` node in - # a `<cas:serviceResponse>` 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 `<cas:serviceResponse>` 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 @@ -<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> - <cas:authenticationFailure> - </cas:authenticationFailure> -</cas:serviceResponse> 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 @@ -<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> - <cas:authenticationSuccess> - <cas:user>psegel</cas:user> - <cas:employeeid>54</cas:employeeid> - <cas:first_name>P. Segel</cas:first_name> - <cas:first_name>Peter</cas:first_name> - <cas:last_name>Segel</cas:last_name> - <cas:email>psegel@intridea.com</cas:email> - <cas:location>Washington, D.C.</cas:location> - <cas:image>/images/user.jpg</cas:image> - <cas:phone>555-555-5555</cas:phone> - <cas:hire_date>2004-07-13</cas:hire_date> - </cas:authenticationSuccess> -</cas:serviceResponse> 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 @@ -<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> - <cas:authenticationSuccess> - <cas:user>psegel</cas:user> - <cas:attributes> - <cas:employeeid>54</cas:employeeid> - <cas:first_name>P. Segel</cas:first_name> - <cas:first_name>Peter</cas:first_name> - <cas:last_name>Segel</cas:last_name> - <cas:email>psegel@intridea.com</cas:email> - <cas:location>Washington, D.C.</cas:location> - <cas:image>/images/user.jpg</cas:image> - <cas:phone>555-555-5555</cas:phone> - <cas:hire_date>2004-07-13</cas:hire_date> - </cas:attributes> - </cas:authenticationSuccess> -</cas:serviceResponse> 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[ - <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}"> - <saml:NameID>@NOT_USED@</saml:NameID> - <samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex> - </samlp:LogoutRequest> - ] - 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[ - <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="foobarbaz" Version="2.0" IssueInstant="2014-10-19T17:13:50Z"> - <saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">@NOT_USED@</saml:NameID> - <samlp:SessionIndex>ST-foo-bar</samlp:SessionIndex> - </samlp:LogoutRequest> - ] - 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[ - <samlp:LogoutRequest ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}"> - <saml:NameID>@NOT_USED@</saml:NameID> - <samlp:SessionIndex>ST-789000-456def789ghi</samlp:SessionIndex> - </samlp:LogoutRequest> - ] - 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[ - <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}"> - <saml:NameID>@NOT_USED@</saml:NameID> - <samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex> - </samlp:LogoutRequest> - ] - 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' ) |