Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ab5672c13d
commit
38c1da5195
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
4
Gemfile
4
Gemfile
|
|
@ -53,7 +53,6 @@ gem 'omniauth', '~> 2.1.0'
|
|||
gem 'omniauth-auth0', '~> 3.1'
|
||||
gem 'omniauth-azure-activedirectory-v2', '~> 2.0'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.9', path: 'vendor/gems/omniauth-azure-oauth2' # See gem README.md
|
||||
gem 'omniauth-cas3', '~> 1.1.4', path: 'vendor/gems/omniauth-cas3' # See vendor/gems/omniauth-cas3/README.md
|
||||
gem 'omniauth-dingtalk-oauth2', '~> 1.0'
|
||||
gem 'omniauth-alicloud', '~> 2.0.1'
|
||||
gem 'omniauth-facebook', '~> 4.0.0'
|
||||
|
|
@ -457,7 +456,8 @@ group :test do
|
|||
|
||||
gem 'capybara', '~> 3.39'
|
||||
gem 'capybara-screenshot', '~> 1.0.26'
|
||||
gem 'selenium-webdriver', '~> 4.9.0'
|
||||
# 4.9.1 drops Ruby 2.7 support. We can upgrade further after we drop Ruby 2.7 support.
|
||||
gem 'selenium-webdriver', '= 4.9.0'
|
||||
|
||||
gem 'graphlyte', '~> 1.0.0'
|
||||
|
||||
|
|
|
|||
11
Gemfile.lock
11
Gemfile.lock
|
|
@ -61,14 +61,6 @@ PATH
|
|||
omniauth (~> 2.0)
|
||||
omniauth-oauth2 (~> 1.4)
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/omniauth-cas3
|
||||
specs:
|
||||
omniauth-cas3 (1.1.4)
|
||||
addressable (~> 2.3)
|
||||
nokogiri (~> 1.7, >= 1.7.1)
|
||||
omniauth (~> 2.0)
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/omniauth-gitlab
|
||||
specs:
|
||||
|
|
@ -1849,7 +1841,6 @@ DEPENDENCIES
|
|||
omniauth-auth0 (~> 3.1)
|
||||
omniauth-azure-activedirectory-v2 (~> 2.0)
|
||||
omniauth-azure-oauth2 (~> 0.0.9)!
|
||||
omniauth-cas3 (~> 1.1.4)!
|
||||
omniauth-dingtalk-oauth2 (~> 1.0)
|
||||
omniauth-facebook (~> 4.0.0)
|
||||
omniauth-github (= 2.0.1)
|
||||
|
|
@ -1920,7 +1911,7 @@ DEPENDENCIES
|
|||
sassc-rails (~> 2.1.0)
|
||||
sd_notify (~> 0.1.0)
|
||||
seed-fu (~> 2.3.7)
|
||||
selenium-webdriver (~> 4.9.0)
|
||||
selenium-webdriver (= 4.9.0)
|
||||
semver_dialects (~> 1.2.1)
|
||||
sentry-rails (~> 5.8.0)
|
||||
sentry-raven (~> 3.1)
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ export default {
|
|||
category="tertiary"
|
||||
no-caret
|
||||
placement="right"
|
||||
data-qa-selector="delete_merged_branches_dropdown_button"
|
||||
:items="dropdownItems"
|
||||
/>
|
||||
<gl-modal
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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") }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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'] ||= []
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
@ -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. |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||

|
||||
|
||||
## View merge request commits in context
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29274) in GitLab 13.12 [with a flag](../../../administration/feature_flags.md) named `context_commits`. Enabled by default.
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.8.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.9. [Feature flag `context_commits`](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) removed.
|
||||
|
||||
When reviewing a merge request, it helps to have more context about the changes
|
||||
made. That includes unchanged lines in unchanged files, and previous commits
|
||||
that have already merged that the change is built on.
|
||||
|
||||
To add previously merged commits to a merge request for more context:
|
||||
|
||||
1. Go to your merge request.
|
||||
1. Select the **Commits** tab.
|
||||
1. Scroll to the end of the list of commits, and select **Add previously merged commits**:
|
||||
1. Select the commits that you want to add.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## View diffs between commits
|
||||
|
||||
To view the changes between previously merged commits:
|
||||
|
||||
1. On your merge request, select the **Changes** tab.
|
||||
1. By **Compare**, select the commit you want to view:
|
||||
|
||||

|
||||
|
||||
If you selected to add previously merged commits, they are displayed in the list.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
QA::Support::Helpers::ImportSource.enable(%w[gitlab_project])
|
||||
|
||||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
QA::Support::Helpers::ImportSource.enable('git')
|
||||
|
||||
Flow::Login.sign_in
|
||||
|
||||
imported_project
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
QA::Support::Helpers::ImportSource.enable('git')
|
||||
|
||||
Flow::Login.sign_in
|
||||
|
||||
imported_project
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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 | {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Resolvers::GroupMilestonesResolver do
|
||||
RSpec.describe Resolvers::GroupMilestonesResolver, feature_category: :team_planning do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
include GraphqlHelpers
|
||||
|
||||
describe '#resolve' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
def resolve_group_milestones(args = {}, context = { current_user: current_user })
|
||||
resolve(described_class, obj: group, args: args, ctx: context, arg_style: :internal)
|
||||
def resolve_group_milestones(args: {}, context: { current_user: current_user }, arg_style: :internal)
|
||||
resolve(described_class, obj: group, args: args, ctx: context, arg_style: arg_style)
|
||||
end
|
||||
|
||||
let_it_be(:now) { Time.now }
|
||||
|
|
@ -45,7 +45,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
end
|
||||
|
||||
context 'with parameters' do
|
||||
it 'calls MilestonesFinder with correct parameters' do
|
||||
it 'timeframe argument' do
|
||||
start_date = now
|
||||
end_date = start_date + 1.hour
|
||||
|
||||
|
|
@ -53,18 +53,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
.with(args(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date))
|
||||
.and_call_original
|
||||
|
||||
resolve_group_milestones(start_date: start_date, end_date: end_date, state: 'closed')
|
||||
end
|
||||
|
||||
it 'understands the timeframe argument' do
|
||||
start_date = now
|
||||
end_date = start_date + 1.hour
|
||||
|
||||
expect(MilestonesFinder).to receive(:new)
|
||||
.with(args(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date))
|
||||
.and_call_original
|
||||
|
||||
resolve_group_milestones(timeframe: { start: start_date, end: end_date }, state: 'closed')
|
||||
resolve_group_milestones(args: { timeframe: { start: start_date, end: end_date }, state: 'closed' })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -76,7 +65,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
.with(args(ids: [milestone.id.to_s], group_ids: group.id, state: 'all'))
|
||||
.and_call_original
|
||||
|
||||
resolve_group_milestones(ids: [milestone.to_global_id])
|
||||
resolve_group_milestones(args: { ids: [milestone.to_global_id] })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -86,12 +75,12 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
.with(args(group_ids: group.id, state: 'all', sort: :due_date_desc))
|
||||
.and_call_original
|
||||
|
||||
resolve_group_milestones(sort: :due_date_desc)
|
||||
resolve_group_milestones(args: { sort: :due_date_desc })
|
||||
end
|
||||
|
||||
%i[expired_last_due_date_asc expired_last_due_date_desc].each do |sort_by|
|
||||
it "uses offset-pagination when sorting by #{sort_by}" do
|
||||
resolved = resolve_group_milestones(sort: sort_by)
|
||||
resolved = resolve_group_milestones(args: { sort: sort_by })
|
||||
|
||||
expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
|
||||
end
|
||||
|
|
@ -99,31 +88,18 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
end
|
||||
|
||||
context 'by timeframe' do
|
||||
context 'when start_date and end_date are present' do
|
||||
context 'when start date is after end_date' do
|
||||
it 'generates an error' do
|
||||
expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate") do
|
||||
resolve_group_milestones(start_date: now, end_date: now - 2.days)
|
||||
context 'when timeframe start and end are present' do
|
||||
context 'when start is after end' do
|
||||
it 'raises error' do
|
||||
expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, 'start must be before end') do
|
||||
resolve_group_milestones(
|
||||
args: { timeframe: { start: now.to_date, end: now.to_date - 2.days } },
|
||||
arg_style: :internal_prepared
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only start_date is present' do
|
||||
it 'generates an error' do
|
||||
expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
|
||||
resolve_group_milestones(start_date: now)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only end_date is present' do
|
||||
it 'generates an error' do
|
||||
expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
|
||||
resolve_group_milestones(end_date: now)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when including descendant milestones in a public group' do
|
||||
|
|
@ -143,7 +119,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
create(:milestone, group: inaccessible_group)
|
||||
create(:milestone, project: inaccessible_project)
|
||||
|
||||
expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
|
||||
expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -169,7 +145,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
let(:args) { {} }
|
||||
|
||||
it 'finds milestones only in accessible projects and groups' do
|
||||
expect(resolve_group_milestones(args)).to match_array([milestone1])
|
||||
expect(resolve_group_milestones(args: args)).to match_array([milestone1])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -177,7 +153,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
let(:args) { { include_descendants: true } }
|
||||
|
||||
it 'finds milestones only in accessible projects and groups' do
|
||||
expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
|
||||
expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -185,7 +161,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
let(:args) { { include_ancestors: true } }
|
||||
|
||||
it 'finds milestones only in accessible projects and groups' do
|
||||
expect(resolve_group_milestones(args)).to match_array([milestone1, milestone6])
|
||||
expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone6])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -193,7 +169,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
|
|||
let(:args) { { include_descendants: true, include_ancestors: true } }
|
||||
|
||||
it 'finds milestones only in accessible projects and groups' do
|
||||
expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3, milestone6])
|
||||
expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3, milestone6])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -33,28 +33,28 @@ RSpec.describe ProfilesHelper do
|
|||
end
|
||||
|
||||
it "returns omniauth provider label for users with external attributes" do
|
||||
stub_omniauth_setting(sync_profile_from_provider: ['cas3'])
|
||||
stub_omniauth_setting(sync_profile_from_provider: [example_omniauth_provider])
|
||||
stub_omniauth_setting(sync_profile_attributes: true)
|
||||
stub_cas_omniauth_provider
|
||||
cas_user = create(:omniauth_user, provider: 'cas3')
|
||||
cas_user.create_user_synced_attributes_metadata(provider: 'cas3', name_synced: true, email_synced: true, location_synced: true)
|
||||
allow(helper).to receive(:current_user).and_return(cas_user)
|
||||
stub_auth0_omniauth_provider
|
||||
auth0_user = create(:omniauth_user, provider: example_omniauth_provider)
|
||||
auth0_user.create_user_synced_attributes_metadata(provider: example_omniauth_provider, name_synced: true, email_synced: true, location_synced: true)
|
||||
allow(helper).to receive(:current_user).and_return(auth0_user)
|
||||
|
||||
expect(helper.attribute_provider_label(:email)).to eq('CAS')
|
||||
expect(helper.attribute_provider_label(:name)).to eq('CAS')
|
||||
expect(helper.attribute_provider_label(:location)).to eq('CAS')
|
||||
expect(helper.attribute_provider_label(:email)).to eq(example_omniauth_provider_label)
|
||||
expect(helper.attribute_provider_label(:name)).to eq(example_omniauth_provider_label)
|
||||
expect(helper.attribute_provider_label(:location)).to eq(example_omniauth_provider_label)
|
||||
end
|
||||
|
||||
it "returns the correct omniauth provider label for users with some external attributes" do
|
||||
stub_omniauth_setting(sync_profile_from_provider: ['cas3'])
|
||||
stub_omniauth_setting(sync_profile_from_provider: [example_omniauth_provider])
|
||||
stub_omniauth_setting(sync_profile_attributes: true)
|
||||
stub_cas_omniauth_provider
|
||||
cas_user = create(:omniauth_user, provider: 'cas3')
|
||||
cas_user.create_user_synced_attributes_metadata(provider: 'cas3', name_synced: false, email_synced: true, location_synced: false)
|
||||
allow(helper).to receive(:current_user).and_return(cas_user)
|
||||
stub_auth0_omniauth_provider
|
||||
auth0_user = create(:omniauth_user, provider: example_omniauth_provider)
|
||||
auth0_user.create_user_synced_attributes_metadata(provider: example_omniauth_provider, name_synced: false, email_synced: true, location_synced: false)
|
||||
allow(helper).to receive(:current_user).and_return(auth0_user)
|
||||
|
||||
expect(helper.attribute_provider_label(:name)).to be_nil
|
||||
expect(helper.attribute_provider_label(:email)).to eq('CAS')
|
||||
expect(helper.attribute_provider_label(:email)).to eq(example_omniauth_provider_label)
|
||||
expect(helper.attribute_provider_label(:location)).to be_nil
|
||||
end
|
||||
|
||||
|
|
@ -118,12 +118,20 @@ RSpec.describe ProfilesHelper do
|
|||
end
|
||||
end
|
||||
|
||||
def stub_cas_omniauth_provider
|
||||
def stub_auth0_omniauth_provider
|
||||
provider = OpenStruct.new(
|
||||
'name' => 'cas3',
|
||||
'label' => 'CAS'
|
||||
'name' => example_omniauth_provider,
|
||||
'label' => example_omniauth_provider_label
|
||||
)
|
||||
|
||||
stub_omniauth_setting(providers: [provider])
|
||||
end
|
||||
|
||||
def example_omniauth_provider
|
||||
"auth0"
|
||||
end
|
||||
|
||||
def example_omniauth_provider_label
|
||||
"Auth0"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 } })
|
||||
|
|
|
|||
|
|
@ -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!) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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' }
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# Specify your gem's dependencies in omniauth-cas3.gemspec
|
||||
gemspec
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1 +0,0 @@
|
|||
require 'omniauth/cas3'
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
require 'omniauth/cas3/version'
|
||||
require 'omniauth/strategies/cas3'
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
module Omniauth
|
||||
module Cas3
|
||||
VERSION = '1.1.4'
|
||||
end
|
||||
end
|
||||
|
|
@ -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'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue