Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-05-10 00:08:52 +00:00
parent ab5672c13d
commit 38c1da5195
110 changed files with 506 additions and 1644 deletions

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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)

View File

@ -102,6 +102,7 @@ export default {
category="tertiary"
no-caret
placement="right"
data-qa-selector="delete_merged_branches_dropdown_button"
:items="dropdownItems"
/>
<gl-modal

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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])

View File

@ -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") }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -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'] ||= []

View File

@ -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).

View File

@ -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. |

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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).

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1,59 @@
---
stage: Create
group: Code Review
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
# Merge request commits **(FREE)**
Each merge request has a history of the commits made to the source branch
after the merge request was created.
These commits are displayed on the merge request's **Commits** tab.
From this tab, you can review commit messages and copy a commit's SHA when you need to
[cherry-pick changes](cherry_pick_changes.md).
## Navigate merge request commits
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0.
To navigate commits in a merge request:
1. Select the **Commits** tab.
1. Select the commit link. The most recent commit is displayed.
1. Navigate through the commits by either:
- Selecting **Prev** and **Next** buttons below the tab buttons.
- Using the <kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts.
![Merge requests commit navigation](img/commit_nav_v16_0.png)
## View merge request commits in context
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29274) in GitLab 13.12 [with a flag](../../../administration/feature_flags.md) named `context_commits`. Enabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.8.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) in GitLab 14.9. [Feature flag `context_commits`](https://gitlab.com/gitlab-org/gitlab/-/issues/320757) removed.
When reviewing a merge request, it helps to have more context about the changes
made. That includes unchanged lines in unchanged files, and previous commits
that have already merged that the change is built on.
To add previously merged commits to a merge request for more context:
1. Go to your merge request.
1. Select the **Commits** tab.
1. Scroll to the end of the list of commits, and select **Add previously merged commits**:
1. Select the commits that you want to add.
1. Select **Save changes**.
## View diffs between commits
To view the changes between previously merged commits:
1. On your merge request, select the **Changes** tab.
1. By **Compare**, select the commit you want to view:
![Previously merged commits](img/previously_merged_commits_v16_0.png)
If you selected to add previously merged commits, they are displayed in the list.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -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(

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 ""

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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|

View File

@ -16,6 +16,8 @@ module QA
end
before do
QA::Support::Helpers::ImportSource.enable(%w[gitlab_project])
Flow::Login.sign_in
end

View File

@ -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

View File

@ -64,6 +64,8 @@ module QA
end
before do
QA::Support::Helpers::ImportSource.enable('git')
Flow::Login.sign_in
imported_project

View File

@ -25,6 +25,8 @@ module QA
end
before do
QA::Support::Helpers::ImportSource.enable('git')
Flow::Login.sign_in
imported_project

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) }

View File

@ -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)

View File

@ -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 }

View File

@ -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 | {}

View File

@ -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

View File

@ -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)

View File

@ -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) }

View File

@ -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"

View File

@ -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);
});

View File

@ -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',
);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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) }

View File

@ -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',

View File

@ -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

View File

@ -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

View File

@ -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 } })

View File

@ -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!) {

View File

@ -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

View File

@ -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' }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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|

View File

@ -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

View File

@ -1,4 +0,0 @@
source 'https://rubygems.org'
# Specify your gem's dependencies in omniauth-cas3.gemspec
gemspec

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
require 'omniauth/cas3'

View File

@ -1,2 +0,0 @@
require 'omniauth/cas3/version'
require 'omniauth/strategies/cas3'

View File

@ -1,5 +0,0 @@
module Omniauth
module Cas3
VERSION = '1.1.4'
end
end

View File

@ -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