Merge tag 'debian/15.5.7+ds1-1' into bullseye-fasttrack
gitlab Debian release 15.5.7+ds1-1
This commit is contained in:
commit
a900ba5e48
106 changed files with 1667 additions and 829 deletions
35
CHANGELOG.md
35
CHANGELOG.md
|
@ -2,6 +2,41 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 15.5.7 (2023-01-09)
|
||||
|
||||
### Security (10 changes)
|
||||
|
||||
- [Avoid regex with potential for poorly performing backtracking](gitlab-org/security/gitlab@c3f8d8c93e99ac3f226668086bfbf21739b02a0e) ([merge request](gitlab-org/security/gitlab!2989))
|
||||
- [Protect web-hook url variables after changing URL](gitlab-org/security/gitlab@8a18fea752a2759938b4c3d28516b6ed9386404f) ([merge request](gitlab-org/security/gitlab!2978))
|
||||
- [Limit the size of user agent to reduce ReDos attack](gitlab-org/security/gitlab@293db707009b7dd133a9a55b25892506013062fd) ([merge request](gitlab-org/security/gitlab!2991))
|
||||
- [Only allow safe params for diff helper](gitlab-org/security/gitlab@0c5de464c1d062103d6bc81cca45f7298929ca68) ([merge request](gitlab-org/security/gitlab!2951))
|
||||
- [Protect Sentry auth-token after changing URL](gitlab-org/security/gitlab@a2c3380748eb3aa36f23c74f1666c741fafec635) ([merge request](gitlab-org/security/gitlab!2986))
|
||||
- [Delete project specific licenses when license policy is deleted](gitlab-org/security/gitlab@312a28196df206b501861b6528b4b6fcaf7cc686) ([merge request](gitlab-org/security/gitlab!2896))
|
||||
- [Restrict user avatar availability based on visibility restrictions](gitlab-org/security/gitlab@f7b5c0a57b64c15edb0f555dd53c26b9d6147f0e) ([merge request](gitlab-org/security/gitlab!2973))
|
||||
- [Policy change to read and destroy token without license for .com](gitlab-org/security/gitlab@b51bc20ba07d8ef3d339aeacd1b0f904521f4158) ([merge request](gitlab-org/security/gitlab!2914))
|
||||
- [Restrict Grafana API access on public projects](gitlab-org/security/gitlab@d9798aa2d31ddef9ed6fedfc7b32bc8a8bac76bc) ([merge request](gitlab-org/security/gitlab!2959))
|
||||
- [Fix "Race condition enables verified email forgery"](gitlab-org/security/gitlab@95e65f637ed193b9c8b3c39af58a9bc0d552bad2) ([merge request](gitlab-org/security/gitlab!2962))
|
||||
|
||||
## 15.5.6 (2022-12-07)
|
||||
|
||||
No changes.
|
||||
|
||||
## 15.5.5 (2022-11-30)
|
||||
|
||||
### Security (11 changes)
|
||||
|
||||
- [Send resolved_address param to gitaly during repository import](gitlab-org/security/gitlab@768edcdca74fa09f7ba50c324aacd86fb71ed7e7) ([merge request](gitlab-org/security/gitlab!2939))
|
||||
- [Add size validation during nuspec file extraction](gitlab-org/security/gitlab@27f79d015684896b66e0418db253613e3efa1df7) ([merge request](gitlab-org/security/gitlab!2936))
|
||||
- [Cross-site scripting in Jira Integration](gitlab-org/security/gitlab@efcb2fc3110b7cf997b3e1a1e173e6462a54f208) ([merge request](gitlab-org/security/gitlab!2931))
|
||||
- [Protect web-hook secret tokens after changing URL](gitlab-org/security/gitlab@00b75ba0c52c10a578091ad89440e8ae78cbe066) ([merge request](gitlab-org/security/gitlab!2921))
|
||||
- [Redact secret tokens from web-hook logs](gitlab-org/security/gitlab@27699db7e44e7808f5ec415860ed03c55ae554b0) ([merge request](gitlab-org/security/gitlab!2917))
|
||||
- [Prevent unauthorized users from seeing Release information on tag pages](gitlab-org/security/gitlab@112d45bdba5e0d34f77eec1ffaf86443e28b2c8c) ([merge request](gitlab-org/security/gitlab!2926))
|
||||
- [Update after_import to expire cache before removing prohibited branches](gitlab-org/security/gitlab@5e84ca50689dceb7614e181ee7addbc3671dc935) ([merge request](gitlab-org/security/gitlab!2904))
|
||||
- [Deny all package permissions when group access is restricted by IP](gitlab-org/security/gitlab@23a8ba46641053317c45f58037499235438b5ad8) ([merge request](gitlab-org/security/gitlab!2901))
|
||||
- [Redact user emails from project webhook data](gitlab-org/security/gitlab@9f49c4d34fffd598af19d2db548281847855f987) ([merge request](gitlab-org/security/gitlab!2907))
|
||||
- [Disallow local URls for build_runner_session if dictated by app setting](gitlab-org/security/gitlab@087415cf7a780c97b1d4055590858a98c673c64b) ([merge request](gitlab-org/security/gitlab!2867))
|
||||
- [Prevent token bypass for extenal authorisation](gitlab-org/security/gitlab@96a6193a6e03bd1f76c2792cca404d2e672dfcf4) ([merge request](gitlab-org/security/gitlab!2884))
|
||||
|
||||
## 15.5.4 (2022-11-11)
|
||||
|
||||
### Fixed (3 changes)
|
||||
|
|
|
@ -1 +1 @@
|
|||
15.5.4
|
||||
15.5.7
|
|
@ -1 +1 @@
|
|||
1.62.0
|
||||
15.5.7
|
2
Gemfile
2
Gemfile
|
@ -503,7 +503,7 @@ gem 'ssh_data', '~> 1.3'
|
|||
gem 'spamcheck', '~> 1.0.0'
|
||||
|
||||
# Gitaly GRPC protocol definitions
|
||||
gem 'gitaly', '~> 15.4.0-rc2'
|
||||
gem 'gitaly', '~> 15.5.2'
|
||||
|
||||
# KAS GRPC protocol definitions
|
||||
gem 'kas-grpc', '~> 0.0.2'
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
{"name":"gettext_i18n_rails","version":"1.8.0","platform":"ruby","checksum":"95e5cf8440b1e08705b27f2bccb56143272c5a7a0dabcf54ea1bd701140a496f"},
|
||||
{"name":"gettext_i18n_rails_js","version":"1.3.0","platform":"ruby","checksum":"5d10afe4be3639bff78c50a56768c20f39aecdabc580c08aa45573911c2bd687"},
|
||||
{"name":"git","version":"1.11.0","platform":"ruby","checksum":"7e95ba4da8298a0373ef1a6862aa22007d761f3c8274b675aa787966fecea0f1"},
|
||||
{"name":"gitaly","version":"15.4.0.pre.rc2","platform":"ruby","checksum":"48764528a730605a46f00cf86c7cfcb92d25f4f3d8cb9e09557baac3e9f3f8e3"},
|
||||
{"name":"gitaly","version":"15.5.2","platform":"ruby","checksum":"62babe0596a4505bf95051ea50f17160055e6cf6cacf209273691542120d7881"},
|
||||
{"name":"github-markup","version":"1.7.0","platform":"ruby","checksum":"97eb27c70662d9cc1d5997cd6c99832026fae5d4913b5dce1ce6c9f65078e69d"},
|
||||
{"name":"gitlab","version":"4.16.1","platform":"ruby","checksum":"13fd7059cbdad5a1a21b15fa2cf9070b97d92e27f8c688581fe3d84dc038074f"},
|
||||
{"name":"gitlab-chronic","version":"0.10.5","platform":"ruby","checksum":"f80f18dc699b708870a80685243331290bc10cfeedb6b99c92219722f729c875"},
|
||||
|
|
|
@ -547,7 +547,7 @@ GEM
|
|||
rails (>= 3.2.0)
|
||||
git (1.11.0)
|
||||
rchardet (~> 1.8)
|
||||
gitaly (15.4.0.pre.rc2)
|
||||
gitaly (15.5.2)
|
||||
grpc (~> 1.0)
|
||||
github-markup (1.7.0)
|
||||
gitlab (4.16.1)
|
||||
|
@ -1622,7 +1622,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.3)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.3)
|
||||
gitaly (~> 15.4.0.pre.rc2)
|
||||
gitaly (~> 15.5.2)
|
||||
github-markup (~> 1.7.0)
|
||||
gitlab-chronic (~> 0.10.5)
|
||||
gitlab-dangerfiles (~> 3.5.2)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
15.5.4
|
||||
15.5.7
|
|
@ -57,7 +57,7 @@ module PageLimiter
|
|||
|
||||
# Record the page limit being hit in Prometheus
|
||||
def record_page_limit_interception
|
||||
dd = DeviceDetector.new(request.user_agent)
|
||||
dd = Gitlab::SafeDeviceDetector.new(request.user_agent)
|
||||
|
||||
Gitlab::Metrics.counter(:gitlab_page_out_of_bounds,
|
||||
controller: params[:controller],
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
|
||||
feature_category :authentication_and_authorization
|
||||
|
||||
before_action :check_personal_access_tokens_enabled
|
||||
|
||||
def index
|
||||
set_index_vars
|
||||
scopes = params[:scopes].split(',').map(&:squish).select(&:present?).map(&:to_sym) unless params[:scopes].nil?
|
||||
|
@ -85,8 +83,4 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
|
|||
def page
|
||||
(params[:page] || 1).to_i
|
||||
end
|
||||
|
||||
def check_personal_access_tokens_enabled
|
||||
render_404 if Gitlab::CurrentSettings.personal_access_tokens_disabled?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,8 @@ class Projects::GrafanaApiController < Projects::ApplicationController
|
|||
include RenderServiceResults
|
||||
include MetricsDashboard
|
||||
|
||||
before_action :authorize_read_grafana!, only: :proxy
|
||||
|
||||
feature_category :metrics
|
||||
urgency :low
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ class UploadsController < ApplicationController
|
|||
# access to itself when a secret is given.
|
||||
# For instance, user avatars are readable by anyone,
|
||||
# while temporary, user snippet uploads are not.
|
||||
return false if !current_user && public_visibility_restricted?
|
||||
|
||||
!secret? || can?(current_user, :update_user, model)
|
||||
when Appearance
|
||||
true
|
||||
|
|
|
@ -244,6 +244,10 @@ module DiffHelper
|
|||
{}
|
||||
end
|
||||
|
||||
def params_with_whitespace
|
||||
hide_whitespace? ? safe_params.except(:w) : safe_params.merge(w: 1)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def diff_btn(title, name, selected)
|
||||
|
@ -277,10 +281,6 @@ module DiffHelper
|
|||
params[:w] == '1'
|
||||
end
|
||||
|
||||
def params_with_whitespace
|
||||
hide_whitespace? ? request.query_parameters.except(:w) : request.query_parameters.merge(w: 1)
|
||||
end
|
||||
|
||||
def toggle_whitespace_link(url, options)
|
||||
options[:class] = [*options[:class], 'btn gl-button btn-default'].join(' ')
|
||||
link_to "#{hide_whitespace? ? 'Show' : 'Hide'} whitespace changes", url, class: options[:class]
|
||||
|
|
|
@ -17,22 +17,11 @@ module SubmoduleHelper
|
|||
url = File.join(Gitlab.config.gitlab.url, repository.project.full_path)
|
||||
end
|
||||
|
||||
if url =~ %r{([^/:]+)/([^/]+(?:\.git)?)\Z}
|
||||
namespace = Regexp.last_match(1)
|
||||
project = Regexp.last_match(2)
|
||||
gitlab_hosts = [Gitlab.config.gitlab.url,
|
||||
Gitlab.config.gitlab_shell.ssh_path_prefix]
|
||||
namespace, project = extract_namespace_project(url)
|
||||
|
||||
gitlab_hosts.each do |host|
|
||||
if url.start_with?(host)
|
||||
namespace, _, project = url.sub(host, '').rpartition('/')
|
||||
break
|
||||
if namespace.blank? || project.blank?
|
||||
return [sanitize_submodule_url(url), nil, nil]
|
||||
end
|
||||
end
|
||||
|
||||
namespace.delete_prefix!('/')
|
||||
project.rstrip!
|
||||
project.delete_suffix!('.git')
|
||||
|
||||
if self_url?(url, namespace, project)
|
||||
[
|
||||
|
@ -51,13 +40,34 @@ module SubmoduleHelper
|
|||
else
|
||||
[sanitize_submodule_url(url), nil, nil]
|
||||
end
|
||||
else
|
||||
[sanitize_submodule_url(url), nil, nil]
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def extract_namespace_project(url)
|
||||
namespace_fragment, _, project = url.rpartition('/')
|
||||
namespace = namespace_fragment.rpartition(%r{[:/]}).last
|
||||
|
||||
return [nil, nil] unless project.present? && namespace.present?
|
||||
|
||||
gitlab_hosts = [Gitlab.config.gitlab.url,
|
||||
Gitlab.config.gitlab_shell.ssh_path_prefix]
|
||||
|
||||
matching_host = gitlab_hosts.find do |host|
|
||||
url.start_with?(host)
|
||||
end
|
||||
|
||||
if matching_host
|
||||
namespace, _, project = url.delete_prefix(matching_host).rpartition('/')
|
||||
end
|
||||
|
||||
namespace.delete_prefix!('/')
|
||||
project.rstrip!
|
||||
project.delete_suffix!('.git')
|
||||
|
||||
[namespace, project]
|
||||
end
|
||||
|
||||
def gist_github_dot_com_url?(url)
|
||||
url =~ %r{gist\.github\.com[/:][^/]+/[^/]+\Z}
|
||||
end
|
||||
|
|
|
@ -67,7 +67,7 @@ class ActiveSession
|
|||
def self.set(user, request)
|
||||
Gitlab::Redis::Sessions.with do |redis|
|
||||
session_private_id = request.session.id.private_id
|
||||
client = DeviceDetector.new(request.user_agent)
|
||||
client = Gitlab::SafeDeviceDetector.new(request.user_agent)
|
||||
timestamp = Time.current
|
||||
expiry = Settings.gitlab['session_expire_delay'] * 60
|
||||
|
||||
|
|
|
@ -799,10 +799,6 @@ class ApplicationSetting < ApplicationRecord
|
|||
::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.include?(diagram_type)
|
||||
end
|
||||
|
||||
def personal_access_tokens_disabled?
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parsed_grafana_url
|
||||
|
|
|
@ -13,14 +13,15 @@ module Ci
|
|||
belongs_to :build, class_name: 'Ci::Build', inverse_of: :runner_session
|
||||
|
||||
validates :build, presence: true
|
||||
validates :url, addressable_url: { schemes: %w(https) }
|
||||
validates :url, public_url: { schemes: %w(https) }
|
||||
|
||||
def terminal_specification
|
||||
wss_url = Gitlab::UrlHelpers.as_wss(self.url)
|
||||
wss_url = Gitlab::UrlHelpers.as_wss(Addressable::URI.escape(self.url))
|
||||
return {} unless wss_url.present?
|
||||
|
||||
wss_url = "#{wss_url}/exec"
|
||||
channel_specification(wss_url, TERMINAL_SUBPROTOCOL)
|
||||
parsed_wss_url = URI.parse(wss_url)
|
||||
parsed_wss_url.path += '/exec'
|
||||
channel_specification(parsed_wss_url, TERMINAL_SUBPROTOCOL)
|
||||
end
|
||||
|
||||
def service_specification(service: nil, path: nil, port: nil, subprotocols: nil)
|
||||
|
@ -28,20 +29,21 @@ module Ci
|
|||
|
||||
port = port.presence || DEFAULT_PORT_NAME
|
||||
service = service.presence || DEFAULT_SERVICE_NAME
|
||||
url = "#{self.url}/proxy/#{service}/#{port}/#{path}"
|
||||
parsed_url = URI.parse(Addressable::URI.escape(self.url))
|
||||
parsed_url.path += "/proxy/#{service}/#{port}/#{path}"
|
||||
subprotocols = subprotocols.presence || ::Ci::BuildRunnerSession::TERMINAL_SUBPROTOCOL
|
||||
|
||||
channel_specification(url, subprotocols)
|
||||
channel_specification(parsed_url, subprotocols)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def channel_specification(url, subprotocol)
|
||||
return {} if subprotocol.blank? || url.blank?
|
||||
def channel_specification(parsed_url, subprotocol)
|
||||
return {} if subprotocol.blank? || parsed_url.blank?
|
||||
|
||||
{
|
||||
subprotocols: Array(subprotocol),
|
||||
url: url,
|
||||
url: Addressable::URI.unescape(parsed_url.to_s),
|
||||
headers: { Authorization: [authorization.presence] }.compact,
|
||||
ca_pem: certificate.presence
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ class WebHook < ApplicationRecord
|
|||
validate :no_missing_url_variables
|
||||
|
||||
after_initialize :initialize_url_variables
|
||||
before_validation :reset_token
|
||||
before_validation :reset_url_variables, unless: ->(hook) { hook.is_a?(ServiceHook) }
|
||||
|
||||
scope :executable, -> do
|
||||
next all unless Feature.enabled?(:web_hooks_disable_failed)
|
||||
|
@ -200,6 +202,14 @@ class WebHook < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def reset_token
|
||||
self.token = nil if url_changed? && !encrypted_token_changed?
|
||||
end
|
||||
|
||||
def reset_url_variables
|
||||
self.url_variables = {} if url_changed? && !encrypted_url_variables_changed?
|
||||
end
|
||||
|
||||
def web_hooks_disable_failed?
|
||||
self.class.web_hooks_disable_failed?(self)
|
||||
end
|
||||
|
|
|
@ -48,6 +48,13 @@ class WebHookLog < ApplicationRecord
|
|||
request_data == OVERSIZE_REQUEST_DATA
|
||||
end
|
||||
|
||||
def request_headers
|
||||
super unless web_hook.token?
|
||||
super if self[:request_headers]['X-Gitlab-Token'] == _('[REDACTED]')
|
||||
|
||||
self[:request_headers].merge('X-Gitlab-Token' => _('[REDACTED]'))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def obfuscate_basic_auth
|
||||
|
|
|
@ -98,7 +98,10 @@ module Integrations
|
|||
def self.valid_jira_cloud_url?(url)
|
||||
return false unless url.present?
|
||||
|
||||
!!URI(url).hostname&.end_with?(JIRA_CLOUD_HOST)
|
||||
uri = URI.parse(url)
|
||||
uri.is_a?(URI::HTTPS) && !!uri.hostname&.end_with?(JIRA_CLOUD_HOST)
|
||||
rescue URI::InvalidURIError
|
||||
false
|
||||
end
|
||||
|
||||
def data_fields
|
||||
|
|
|
@ -2145,8 +2145,8 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def after_import
|
||||
repository.remove_prohibited_branches
|
||||
repository.expire_content_cache
|
||||
repository.remove_prohibited_branches
|
||||
wiki.repository.expire_content_cache
|
||||
|
||||
DetectRepositoryLanguagesWorker.perform_async(id)
|
||||
|
|
|
@ -980,12 +980,12 @@ class Repository
|
|||
end
|
||||
end
|
||||
|
||||
def clone_as_mirror(url, http_authorization_header: "")
|
||||
import_repository(url, http_authorization_header: http_authorization_header, mirror: true)
|
||||
def clone_as_mirror(url, http_authorization_header: "", resolved_address: "")
|
||||
import_repository(url, http_authorization_header: http_authorization_header, mirror: true, resolved_address: resolved_address)
|
||||
end
|
||||
|
||||
def fetch_as_mirror(url, forced: false, refmap: :all_refs, prune: true, http_authorization_header: "")
|
||||
fetch_remote(url, refmap: refmap, forced: forced, prune: prune, http_authorization_header: http_authorization_header)
|
||||
def fetch_as_mirror(url, forced: false, refmap: :all_refs, prune: true, http_authorization_header: "", resolved_address: "")
|
||||
fetch_remote(url, refmap: refmap, forced: forced, prune: prune, http_authorization_header: http_authorization_header, resolved_address: resolved_address)
|
||||
end
|
||||
|
||||
def fetch_source_branch!(source_repository, source_branch, local_ref)
|
||||
|
|
|
@ -1574,7 +1574,7 @@ class User < ApplicationRecord
|
|||
name: name,
|
||||
username: username,
|
||||
avatar_url: avatar_url(only_path: false),
|
||||
email: public_email.presence || _('[REDACTED]')
|
||||
email: webhook_email
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -272,6 +272,9 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
rule { can?(:admin_group) & resource_access_token_feature_available }.policy do
|
||||
enable :read_resource_access_tokens
|
||||
enable :destroy_resource_access_tokens
|
||||
end
|
||||
|
||||
rule { can?(:admin_group) & resource_access_token_creation_allowed }.policy do
|
||||
enable :admin_setting_to_allow_project_access_token_creation
|
||||
end
|
||||
|
||||
|
@ -332,12 +335,16 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
true
|
||||
end
|
||||
|
||||
def resource_access_token_create_feature_available?
|
||||
true
|
||||
end
|
||||
|
||||
def can_read_group_member?
|
||||
!(@subject.private? && access_level == GroupMember::NO_ACCESS)
|
||||
end
|
||||
|
||||
def resource_access_token_creation_allowed?
|
||||
resource_access_token_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
|
||||
resource_access_token_create_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
|
||||
end
|
||||
|
||||
def valid_dependency_proxy_deploy_token
|
||||
|
|
|
@ -25,3 +25,5 @@ module Packages
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Packages::Policies::GroupPolicy.prepend_mod_with('Packages::Policies::GroupPolicy')
|
||||
|
|
|
@ -52,3 +52,5 @@ module Packages
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Packages::Policies::ProjectPolicy.prepend_mod_with('Packages::Policies::ProjectPolicy')
|
||||
|
|
|
@ -157,7 +157,9 @@ class ProjectPolicy < BasePolicy
|
|||
condition(:service_desk_enabled) { @subject.service_desk_enabled? }
|
||||
|
||||
with_scope :subject
|
||||
condition(:resource_access_token_feature_available) { resource_access_token_feature_available? }
|
||||
condition(:resource_access_token_feature_available) do
|
||||
resource_access_token_feature_available?
|
||||
end
|
||||
condition(:resource_access_token_creation_allowed) { resource_access_token_creation_allowed? }
|
||||
|
||||
# We aren't checking `:read_issue` or `:read_merge_request` in this case
|
||||
|
@ -310,6 +312,8 @@ class ProjectPolicy < BasePolicy
|
|||
rule { guest & can?(:download_code) }.enable :build_download_code
|
||||
rule { guest & can?(:read_container_image) }.enable :build_read_container_image
|
||||
|
||||
rule { guest & ~public_project }.enable :read_grafana
|
||||
|
||||
rule { can?(:reporter_access) }.policy do
|
||||
enable :admin_issue_board
|
||||
enable :download_code
|
||||
|
@ -342,6 +346,7 @@ class ProjectPolicy < BasePolicy
|
|||
enable :read_package
|
||||
enable :read_product_analytics
|
||||
enable :read_ci_cd_analytics
|
||||
enable :read_grafana
|
||||
end
|
||||
|
||||
# We define `:public_user_access` separately because there are cases in gitlab-ee
|
||||
|
@ -794,7 +799,7 @@ class ProjectPolicy < BasePolicy
|
|||
|
||||
rule { project_bot }.enable :project_bot_access
|
||||
|
||||
rule { can?(:read_all_resources) & resource_access_token_feature_available }.enable :read_resource_access_tokens
|
||||
rule { can?(:read_all_resources) }.enable :read_resource_access_tokens
|
||||
|
||||
rule { can?(:admin_project) & resource_access_token_feature_available }.policy do
|
||||
enable :read_resource_access_tokens
|
||||
|
@ -915,12 +920,16 @@ class ProjectPolicy < BasePolicy
|
|||
true
|
||||
end
|
||||
|
||||
def resource_access_token_create_feature_available?
|
||||
true
|
||||
end
|
||||
|
||||
def resource_access_token_creation_allowed?
|
||||
group = project.group
|
||||
|
||||
return true unless group # always enable for projects in personal namespaces
|
||||
|
||||
resource_access_token_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
|
||||
resource_access_token_create_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
|
||||
end
|
||||
|
||||
def project
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
module ErrorTracking
|
||||
class ListProjectsService < ErrorTracking::BaseService
|
||||
MASKED_TOKEN_REGEX = /\A\*+\z/.freeze
|
||||
|
||||
private
|
||||
|
||||
def perform
|
||||
|
@ -21,23 +23,31 @@ module ErrorTracking
|
|||
def project_error_tracking_setting
|
||||
@project_error_tracking_setting ||= begin
|
||||
(super || project.build_error_tracking_setting).tap do |setting|
|
||||
url_changed = !setting.api_url&.start_with?(params[:api_host])
|
||||
|
||||
setting.api_url = ErrorTracking::ProjectErrorTrackingSetting.build_api_url_from(
|
||||
api_host: params[:api_host],
|
||||
organization_slug: 'org',
|
||||
project_slug: 'proj'
|
||||
)
|
||||
|
||||
setting.token = token(setting)
|
||||
setting.token = token(setting, url_changed)
|
||||
setting.enabled = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def token(setting)
|
||||
def token(setting, url_changed)
|
||||
return if url_changed && masked_token?
|
||||
|
||||
# Use param token if not masked, otherwise use database token
|
||||
return params[:token] unless /\A\*+\z/.match?(params[:token])
|
||||
return params[:token] unless masked_token?
|
||||
|
||||
setting.token
|
||||
end
|
||||
|
||||
def masked_token?
|
||||
MASKED_TOKEN_REGEX.match?(params[:token])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,9 +104,15 @@ module Packages
|
|||
entry = zip_file.glob('*.nuspec').first
|
||||
|
||||
raise ExtractionError, 'nuspec file not found' unless entry
|
||||
raise ExtractionError, 'nuspec file too big' if entry.size > MAX_FILE_SIZE
|
||||
raise ExtractionError, 'nuspec file too big' if MAX_FILE_SIZE < entry.size
|
||||
|
||||
entry.get_input_stream.read
|
||||
Tempfile.open("nuget_extraction_package_file_#{@package_file_id}") do |file|
|
||||
entry.extract(file.path) { true } # allow #extract to overwrite the file
|
||||
file.unlink
|
||||
file.read
|
||||
end
|
||||
rescue Zip::EntrySizeError => e
|
||||
raise ExtractionError, "nuspec file has the wrong entry size: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ module Projects
|
|||
|
||||
private
|
||||
|
||||
attr_reader :resolved_address
|
||||
|
||||
def after_execute_hook
|
||||
# Defined in EE::Projects::ImportService
|
||||
end
|
||||
|
@ -64,11 +66,7 @@ module Projects
|
|||
def add_repository_to_project
|
||||
if project.external_import? && !unknown_url?
|
||||
begin
|
||||
Gitlab::UrlBlocker.validate!(
|
||||
project.import_url,
|
||||
schemes: Project::VALID_IMPORT_PROTOCOLS,
|
||||
ports: Project::VALID_IMPORT_PORTS
|
||||
)
|
||||
@resolved_address = get_resolved_address
|
||||
rescue Gitlab::UrlBlocker::BlockedUrlError => e
|
||||
raise e, s_("ImportProjects|Blocked import URL: %{message}") % { message: e.message }
|
||||
end
|
||||
|
@ -97,9 +95,9 @@ module Projects
|
|||
|
||||
if refmap
|
||||
project.ensure_repository
|
||||
project.repository.fetch_as_mirror(project.import_url, refmap: refmap)
|
||||
project.repository.fetch_as_mirror(project.import_url, refmap: refmap, resolved_address: resolved_address)
|
||||
else
|
||||
project.repository.import_repository(project.import_url)
|
||||
project.repository.import_repository(project.import_url, resolved_address: resolved_address)
|
||||
end
|
||||
rescue ::Gitlab::Git::CommandError => e
|
||||
# Expire cache to prevent scenarios such as:
|
||||
|
@ -157,6 +155,26 @@ module Projects
|
|||
def importer_imports_repository?
|
||||
has_importer? && importer_class.try(:imports_repository?)
|
||||
end
|
||||
|
||||
def get_resolved_address
|
||||
Gitlab::UrlBlocker
|
||||
.validate!(
|
||||
project.import_url,
|
||||
schemes: Project::VALID_IMPORT_PROTOCOLS,
|
||||
ports: Project::VALID_IMPORT_PORTS,
|
||||
dns_rebind_protection: dns_rebind_protection?)
|
||||
.then do |(import_url, resolved_host)|
|
||||
next '' if resolved_host.nil? || !import_url.scheme.in?(%w[http https])
|
||||
|
||||
import_url.host.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def dns_rebind_protection?
|
||||
return false if Gitlab.http_proxy_env?
|
||||
|
||||
Gitlab::CurrentSettings.dns_rebinding_protection_enabled?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ module ResourceAccessTokens
|
|||
return error("User does not have permission to create #{resource_type} access token") unless has_permission_to_create?
|
||||
|
||||
access_level = params[:access_level] || Gitlab::Access::MAINTAINER
|
||||
return error("Could not provision owner access to project access token") if do_not_allow_owner_access_level_for_project_bot?(access_level)
|
||||
|
||||
user = create_user
|
||||
|
||||
|
@ -107,7 +108,7 @@ module ResourceAccessTokens
|
|||
end
|
||||
|
||||
def create_membership(resource, user, access_level)
|
||||
resource.add_member(user, access_level, current_user: current_user, expires_at: params[:expires_at])
|
||||
resource.add_member(user, access_level, expires_at: params[:expires_at])
|
||||
end
|
||||
|
||||
def log_event(token)
|
||||
|
@ -121,6 +122,12 @@ module ResourceAccessTokens
|
|||
def success(access_token)
|
||||
ServiceResponse.success(payload: { access_token: access_token })
|
||||
end
|
||||
|
||||
def do_not_allow_owner_access_level_for_project_bot?(access_level)
|
||||
resource.is_a?(Project) &&
|
||||
access_level == Gitlab::Access::OWNER &&
|
||||
!current_user.can?(:manage_owners, resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ module Users
|
|||
|
||||
assign_identity
|
||||
build_canonical_email
|
||||
reset_unconfirmed_email
|
||||
|
||||
if @user.save(validate: validate) && update_status
|
||||
notify_success(user_exists)
|
||||
|
@ -64,6 +65,13 @@ module Users
|
|||
Users::UpdateCanonicalEmailService.new(user: @user).execute
|
||||
end
|
||||
|
||||
def reset_unconfirmed_email
|
||||
return unless @user.persisted?
|
||||
return unless @user.email_changed?
|
||||
|
||||
@user.update_column(:unconfirmed_email, nil)
|
||||
end
|
||||
|
||||
def update_status
|
||||
return true unless @status_params
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ module WebHooks
|
|||
private
|
||||
|
||||
def log_execution
|
||||
log_data[:request_headers]['X-Gitlab-Token'] = _('[REDACTED]') if hook.token?
|
||||
|
||||
WebHookLog.create!(web_hook: hook, **log_data)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- confirmation_link = confirmation_url(@resource, confirmation_token: @token)
|
||||
- if @resource.unconfirmed_email.present? || !@resource.created_recently?
|
||||
#content
|
||||
= email_default_heading(@resource.unconfirmed_email || @resource.email)
|
||||
= email_default_heading(@email)
|
||||
%p= _('Click the link below to confirm your email address.')
|
||||
#cta
|
||||
= link_to _('Confirm your email address'), confirmation_link
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<% if @resource.unconfirmed_email.present? || !@resource.created_recently? %>
|
||||
<%= @resource.unconfirmed_email || @resource.email %>,
|
||||
<%= @email %>,
|
||||
<%= _('Use the link below to confirm your email address.') %>
|
||||
<% else %>
|
||||
<% if Gitlab.com? %>
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
= link_to profile_chat_names_path do
|
||||
%strong.fly-out-top-item-name
|
||||
= _('Chat')
|
||||
- unless Gitlab::CurrentSettings.personal_access_tokens_disabled?
|
||||
= nav_link(controller: :personal_access_tokens) do
|
||||
= link_to profile_personal_access_tokens_path do
|
||||
.nav-icon-container
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- if can?(current_user, :read_release, release)
|
||||
.gl-text-secondary
|
||||
= sprite_icon("rocket", size: 12)
|
||||
= _("Release")
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
%pre.wrap{ data: { qa_selector: 'tag_message_content' } }
|
||||
= strip_signature(@tag.message)
|
||||
|
||||
- if can?(current_user, :read_release, @release)
|
||||
.gl-mb-3.gl-mt-3
|
||||
- if @release&.description.present?
|
||||
.description.md{ data: { qa_selector: 'tag_release_notes_content' } }
|
||||
|
|
23
debian/changelog
vendored
23
debian/changelog
vendored
|
@ -1,3 +1,26 @@
|
|||
gitlab (15.5.7+ds1-1) experimental; urgency=medium
|
||||
|
||||
* Remove abandoned omniauth gems from depends
|
||||
* New upstream version 15.5.7+ds1
|
||||
* Refresh patch
|
||||
|
||||
-- Mohammed Bilal <mdbilal@disroot.org> Tue, 10 Jan 2023 11:35:55 +0530
|
||||
|
||||
gitlab (15.5.4+ds3-4) experimental; urgency=medium
|
||||
|
||||
* Team Upload.
|
||||
* Set "Rules-Requires-Root: no" to circumvent debhelper bug, see
|
||||
https://lists.debian.org/debian-devel/2022/12/msg00108.html
|
||||
* Remove dead symlink, choking build
|
||||
|
||||
-- Nilesh Patra <nilesh@debian.org> Thu, 15 Dec 2022 21:39:00 +0000
|
||||
|
||||
gitlab (15.5.4+ds3-3) experimental; urgency=medium
|
||||
|
||||
* Relax dependency on gitlab-labkit (to match gitaly)
|
||||
|
||||
-- Pirate Praveen <praveen@debian.org> Mon, 12 Dec 2022 21:45:29 +0530
|
||||
|
||||
gitlab (15.5.4+ds3-2~fto11+2) bullseye-fasttrack; urgency=medium
|
||||
|
||||
* Relax dependency on gitlab-labkit (to match gitaly)
|
||||
|
|
5
debian/control
vendored
5
debian/control
vendored
|
@ -77,6 +77,7 @@ Vcs-Browser: https://salsa.debian.org/ruby-team/gitlab
|
|||
Homepage: https://about.gitlab.com/
|
||||
XS-Ruby-Versions: all
|
||||
XS-Go-Import-Path: gitlab.com/gitlab-org/gitlab
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: gitlab
|
||||
Section: contrib/net
|
||||
|
@ -127,8 +128,6 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
|
|||
ruby-omniauth (>= 2.1~),
|
||||
ruby-omniauth-auth0 (>= 2.0~),
|
||||
ruby-omniauth-azure-activedirectory-v2 (>= 2.0~),
|
||||
ruby-omniauth-azure-oauth2 (>= 0.0.10~),
|
||||
ruby-omniauth-cas3 (>= 1.1.4~),
|
||||
ruby-omniauth-dingtalk-oauth2 (>= 1.0.1~),
|
||||
ruby-omniauth-alicloud (>= 2.0~),
|
||||
ruby-omniauth-facebook (>= 4.0~),
|
||||
|
@ -141,10 +140,8 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
|
|||
ruby-omniauth-shibboleth (>= 1.3~),
|
||||
ruby-omniauth-twitter (>= 1.4~),
|
||||
ruby-omniauth-oauth (>= 1.2~),
|
||||
ruby-omniauth-crowd (>= 2.2~),
|
||||
ruby-omniauth-authentiq (>= 0.3.3~),
|
||||
ruby-omniauth-openid-connect (>= 0.10~),
|
||||
ruby-omniauth-salesforce (>= 1.0.5~),
|
||||
ruby-omniauth-atlassian-oauth2 (>= 0.2.0~),
|
||||
ruby-rack-oauth2 (>= 1.21.3~),
|
||||
ruby-jwt (>= 2.1~),
|
||||
|
|
|
@ -455,8 +455,8 @@ gitlab Gemfile
|
|||
+gem 'spamcheck', '~> 1.0'
|
||||
|
||||
# Gitaly GRPC protocol definitions
|
||||
-gem 'gitaly', '~> 15.4.0-rc2'
|
||||
+gem 'gitaly', '~> 15.4'
|
||||
-gem 'gitaly', '~> 15.5.2'
|
||||
+gem 'gitaly', '~> 15.5'
|
||||
|
||||
# KAS GRPC protocol definitions
|
||||
gem 'kas-grpc', '~> 0.0.2'
|
||||
|
|
2
debian/rules
vendored
2
debian/rules
vendored
|
@ -19,6 +19,8 @@ override_dh_auto_configure-arch:
|
|||
if [ -d ${BUILDDIR}/vendor ]; then ${RM} -rf ${BUILDDIR}/vendor; fi
|
||||
if [ -d ${BUILDDIR}/workhorse-vendor ]; then mv ${BUILDDIR}/workhorse-vendor \
|
||||
${BUILDDIR}/vendor; fi
|
||||
# Remove non-existent symlink
|
||||
find ${BUILDDIR} -name test.git -delete
|
||||
# temporary step till protobuf 1.5 vs 1.3 is resolved
|
||||
ln -s /usr/share/gocode/src/gitlab.com/gitlab-org/gitaly/v15/vendor/github.com/prometheus ${BUILDDIR}/vendor/github.com
|
||||
ln -s /usr/share/gocode/src/gitlab.com/gitlab-org/gitaly/v15/vendor/github.com/matttproud ${BUILDDIR}/vendor/github.com
|
||||
|
|
|
@ -55,9 +55,10 @@ To set up the Grafana API in Grafana:
|
|||
1. Select **Save Changes**.
|
||||
|
||||
NOTE:
|
||||
If the Grafana integration is enabled, any user with read access to the GitLab
|
||||
project can query metrics from the Prometheus instance. All requests proxied
|
||||
through GitLab are authenticated with the same Grafana Administrator API token.
|
||||
If the Grafana integration is enabled, users with the Reporter role on public
|
||||
projects and the Guest role on non-public projects can query metrics from the
|
||||
Prometheus instance. All requests proxied through GitLab are authenticated with
|
||||
the same Grafana Administrator API token.
|
||||
|
||||
### Generate a link to a panel
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ using Omnibus, learn to install a custom CA in the
|
|||
Alternatively, learn where to install custom certificates by using
|
||||
`openssl version -d`.
|
||||
|
||||
When external authorization is enabled, [deploy tokens](../../project/deploy_tokens/index.md)
|
||||
and [deploy keys](../../project/deploy_keys/index.md) can't be used for Git operations.
|
||||
|
||||
## Configuration
|
||||
|
||||
The external authorization service can be enabled by an administrator:
|
||||
|
|
|
@ -48,9 +48,6 @@ You cannot use group access tokens to create other group, project, or personal a
|
|||
Group access tokens inherit the [default prefix setting](../../admin_area/settings/account_and_limit_settings.md#personal-access-token-prefix)
|
||||
configured for personal access tokens.
|
||||
|
||||
NOTE:
|
||||
Group access tokens are not FIPS compliant and creation and use are disabled when [FIPS mode](../../../development/fips_compliance.md) is enabled.
|
||||
|
||||
## Create a group access token using UI
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214045) in GitLab 14.7.
|
||||
|
|
|
@ -62,6 +62,7 @@ For most package types, the following credential types are valid:
|
|||
|
||||
NOTE:
|
||||
If you have not activated the "Packages" feature for your project at **Settings > General > Project features**, you will receive a 403 Forbidden response.
|
||||
Accessing package registry via deploy token is not available when external authorization is enabled.
|
||||
|
||||
## Use GitLab CI/CD to build packages
|
||||
|
||||
|
|
|
@ -45,9 +45,6 @@ For examples of how you can use a personal access token to authenticate with the
|
|||
Alternately, GitLab administrators can use the API to create [impersonation tokens](../../api/index.md#impersonation-tokens).
|
||||
Use impersonation tokens to automate authentication as a specific user.
|
||||
|
||||
NOTE:
|
||||
Personal access tokens are not FIPS compliant and creation and use are disabled when [FIPS mode](../../development/fips_compliance.md) is enabled.
|
||||
|
||||
## Create a personal access token
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348660) in GitLab 15.3, default expiration of 30 days is populated in the UI.
|
||||
|
|
|
@ -18,6 +18,8 @@ Depending on your needs, you might want to use a [deploy token](../deploy_tokens
|
|||
| Validity | Valid as long as it's registered and enabled. | Can be given an expiration date. |
|
||||
| Registry access | Cannot access a package registry. | Can read from and write to a package registry. |
|
||||
|
||||
Deploy keys can't be used for Git operations if [external authorization](../../admin_area/settings/external_authorization.md) is enabled.
|
||||
|
||||
## Scope
|
||||
|
||||
A deploy key has a defined scope when it is created:
|
||||
|
|
|
@ -41,6 +41,8 @@ You can create deploy tokens at either the project or group level:
|
|||
By default, a deploy token does not expire. You can optionally set an expiry date when you create
|
||||
it. Expiry occurs at midnight UTC on that date.
|
||||
|
||||
Deploy tokens can't be used for Git operations and Package Registry operations if [external authorization](../../admin_area/settings/external_authorization.md) is enabled.
|
||||
|
||||
## Scope
|
||||
|
||||
A deploy token's scope determines the actions it can perform.
|
||||
|
|
|
@ -48,9 +48,6 @@ You cannot use project access tokens to create other group, project, or personal
|
|||
Project access tokens inherit the [default prefix setting](../../admin_area/settings/account_and_limit_settings.md#personal-access-token-prefix)
|
||||
configured for personal access tokens.
|
||||
|
||||
NOTE:
|
||||
Project access tokens are not FIPS compliant and creation and use are disabled when [FIPS mode](../../../development/fips_compliance.md) is enabled.
|
||||
|
||||
## Create a project access token
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89114) in GitLab 15.1, Owners can select Owner role for project access tokens.
|
||||
|
|
|
@ -94,7 +94,8 @@ module API
|
|||
success Entities::Ci::JobRequest::Response
|
||||
http_codes [[201, 'Job was scheduled'],
|
||||
[204, 'No job for Runner'],
|
||||
[403, 'Forbidden']]
|
||||
[403, 'Forbidden'],
|
||||
[409, 'Conflict']]
|
||||
end
|
||||
params do
|
||||
requires :token, type: String, desc: %q(Runner's authentication token)
|
||||
|
|
|
@ -165,6 +165,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def with_deploy_token(raw, &block)
|
||||
raise ::Gitlab::Auth::UnauthorizedError if Gitlab::ExternalAuthorization.enabled?
|
||||
|
||||
token = ::DeployToken.active.find_by_token(raw.password)
|
||||
return unless token
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ module Gitlab
|
|||
# deploy tokens are accepted with deploy token headers and basic auth headers
|
||||
def deploy_token_from_request
|
||||
return unless route_authentication_setting[:deploy_token_allowed]
|
||||
return if Gitlab::ExternalAuthorization.enabled?
|
||||
|
||||
token = current_request.env[DEPLOY_TOKEN_HEADER].presence || parsed_oauth_token
|
||||
|
||||
|
|
|
@ -855,7 +855,11 @@ module Gitlab
|
|||
# no_tags - should we use --no-tags flag?
|
||||
# prune - should we use --prune flag?
|
||||
# check_tags_changed - should we ask gitaly to calculate whether any tags changed?
|
||||
def fetch_remote(url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false, http_authorization_header: "")
|
||||
# resolved_address - resolved IP address for provided URL
|
||||
def fetch_remote( # rubocop:disable Metrics/ParameterLists
|
||||
url,
|
||||
refmap: nil, ssh_auth: nil, forced: false, no_tags: false, prune: true,
|
||||
check_tags_changed: false, http_authorization_header: "", resolved_address: "")
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_repository_client.fetch_remote(
|
||||
url,
|
||||
|
@ -866,16 +870,17 @@ module Gitlab
|
|||
prune: prune,
|
||||
check_tags_changed: check_tags_changed,
|
||||
timeout: GITLAB_PROJECTS_TIMEOUT,
|
||||
http_authorization_header: http_authorization_header
|
||||
http_authorization_header: http_authorization_header,
|
||||
resolved_address: resolved_address
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def import_repository(url, http_authorization_header: '', mirror: false)
|
||||
def import_repository(url, http_authorization_header: '', mirror: false, resolved_address: '')
|
||||
raise ArgumentError, "don't use disk paths with import_repository: #{url.inspect}" if url.start_with?('.', '/')
|
||||
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_repository_client.import_repository(url, http_authorization_header: http_authorization_header, mirror: mirror)
|
||||
gitaly_repository_client.import_repository(url, http_authorization_header: http_authorization_header, mirror: mirror, resolved_address: resolved_address)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def deploy_key?
|
||||
actor.is_a?(DeployKey)
|
||||
actor.is_a?(DeployKey) && !Gitlab::ExternalAuthorization.enabled?
|
||||
end
|
||||
|
||||
def deploy_token
|
||||
|
@ -375,7 +375,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def deploy_token?
|
||||
actor.is_a?(DeployToken)
|
||||
actor.is_a?(DeployToken) && !Gitlab::ExternalAuthorization.enabled?
|
||||
end
|
||||
|
||||
def ci?
|
||||
|
|
|
@ -78,7 +78,7 @@ module Gitlab
|
|||
# rubocop: disable Metrics/ParameterLists
|
||||
# The `remote` parameter is going away soonish anyway, at which point the
|
||||
# Rubocop warning can be enabled again.
|
||||
def fetch_remote(url, refmap:, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false, http_authorization_header: "")
|
||||
def fetch_remote(url, refmap:, ssh_auth:, forced:, no_tags:, timeout:, prune: true, check_tags_changed: false, http_authorization_header: "", resolved_address: "")
|
||||
request = Gitaly::FetchRemoteRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
force: forced,
|
||||
|
@ -89,7 +89,8 @@ module Gitlab
|
|||
remote_params: Gitaly::Remote.new(
|
||||
url: url,
|
||||
mirror_refmaps: Array.wrap(refmap).map(&:to_s),
|
||||
http_authorization_header: http_authorization_header
|
||||
http_authorization_header: http_authorization_header,
|
||||
resolved_address: resolved_address
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -145,12 +146,13 @@ module Gitlab
|
|||
)
|
||||
end
|
||||
|
||||
def import_repository(source, http_authorization_header: '', mirror: false)
|
||||
def import_repository(source, http_authorization_header: '', mirror: false, resolved_address: '')
|
||||
request = Gitaly::CreateRepositoryFromURLRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
url: source,
|
||||
http_authorization_header: http_authorization_header,
|
||||
mirror: mirror
|
||||
mirror: mirror,
|
||||
resolved_address: resolved_address
|
||||
)
|
||||
|
||||
GitalyClient.call(
|
||||
|
|
|
@ -57,7 +57,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def user_email(user)
|
||||
user.respond_to?(:email) ? user.email : ""
|
||||
user.respond_to?(:webhook_email) ? user.webhook_email : ""
|
||||
end
|
||||
|
||||
def event_specific_project_data(event)
|
||||
|
|
|
@ -43,7 +43,7 @@ module Gitlab
|
|||
project_id: project.id,
|
||||
user_username: project_member.user.username,
|
||||
user_name: project_member.user.name,
|
||||
user_email: project_member.user.email,
|
||||
user_email: project_member.user.webhook_email,
|
||||
user_id: project_member.user.id,
|
||||
access_level: project_member.human_access,
|
||||
project_visibility: project.visibility
|
||||
|
|
16
lib/gitlab/safe_device_detector.rb
Normal file
16
lib/gitlab/safe_device_detector.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
# rubocop:disable Gitlab/NamespacedClass
|
||||
require 'device_detector'
|
||||
|
||||
module Gitlab
|
||||
class SafeDeviceDetector < ::DeviceDetector
|
||||
USER_AGENT_MAX_SIZE = 1024
|
||||
|
||||
def initialize(user_agent)
|
||||
super(user_agent)
|
||||
@user_agent = user_agent && user_agent[0..USER_AGENT_MAX_SIZE]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:enable Gitlab/NamespacedClass
|
|
@ -36,14 +36,6 @@ RSpec.describe Profiles::PersonalAccessTokensController do
|
|||
expect(created_token.expires_at).to eq(expires_at)
|
||||
end
|
||||
|
||||
it 'does not allow creation when personal access tokens are disabled' do
|
||||
allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true)
|
||||
|
||||
post :create, params: { personal_access_token: token_attributes }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
|
||||
it_behaves_like "#create access token" do
|
||||
let(:url) { :create }
|
||||
end
|
||||
|
@ -78,14 +70,6 @@ RSpec.describe Profiles::PersonalAccessTokensController do
|
|||
)
|
||||
end
|
||||
|
||||
it 'returns 404 when personal access tokens are disabled' do
|
||||
allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true)
|
||||
|
||||
get :index
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
|
||||
context "access_token_pagination feature flag is enabled" do
|
||||
before do
|
||||
stub_feature_flags(access_token_pagination: true)
|
||||
|
|
|
@ -2,13 +2,20 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::GrafanaApiController do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
RSpec.describe Projects::GrafanaApiController, feature_category: :metrics do
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
let_it_be(:reporter) { create(:user) }
|
||||
let_it_be(:guest) { create(:user) }
|
||||
let(:anonymous) { nil }
|
||||
let(:user) { reporter }
|
||||
|
||||
before_all do
|
||||
project.add_reporter(reporter)
|
||||
project.add_guest(guest)
|
||||
end
|
||||
|
||||
before do
|
||||
project.add_reporter(user)
|
||||
sign_in(user)
|
||||
sign_in(user) if user
|
||||
end
|
||||
|
||||
describe 'GET #proxy' do
|
||||
|
@ -41,6 +48,39 @@ RSpec.describe Projects::GrafanaApiController do
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'accessible' do
|
||||
let(:service_result) { nil }
|
||||
|
||||
it 'returns non erroneous response' do
|
||||
get :proxy, params: params
|
||||
|
||||
# We don't care about the specific code as long it's not an error.
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'not accessible' do
|
||||
let(:service_result) { nil }
|
||||
|
||||
it 'returns 404 Not found' do
|
||||
get :proxy, params: params
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
expect(Grafana::ProxyService).not_to have_received(:new)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'login required' do
|
||||
let(:service_result) { nil }
|
||||
|
||||
it 'redirects to login page' do
|
||||
get :proxy, params: params
|
||||
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
expect(Grafana::ProxyService).not_to have_received(:new)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a successful result' do
|
||||
let(:service_result) { { status: :success, body: '{}' } }
|
||||
|
||||
|
@ -96,6 +136,38 @@ RSpec.describe Projects::GrafanaApiController do
|
|||
it_behaves_like 'error response', :bad_request
|
||||
end
|
||||
end
|
||||
|
||||
context 'as guest' do
|
||||
let(:user) { guest }
|
||||
|
||||
it_behaves_like 'not accessible'
|
||||
end
|
||||
|
||||
context 'as anonymous' do
|
||||
let(:user) { anonymous }
|
||||
|
||||
it_behaves_like 'not accessible'
|
||||
end
|
||||
|
||||
context 'on a private project' do
|
||||
let_it_be(:project) { create(:project, :private) }
|
||||
|
||||
before_all do
|
||||
project.add_guest(guest)
|
||||
end
|
||||
|
||||
context 'as anonymous' do
|
||||
let(:user) { anonymous }
|
||||
|
||||
it_behaves_like 'login required'
|
||||
end
|
||||
|
||||
context 'as guest' do
|
||||
let(:user) { guest }
|
||||
|
||||
it_behaves_like 'accessible'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #metrics_dashboard' do
|
||||
|
|
|
@ -1380,7 +1380,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
|||
{
|
||||
'Channel' => {
|
||||
'Subprotocols' => ["terminal.gitlab.com"],
|
||||
'Url' => 'wss://localhost/proxy/build/default_port/',
|
||||
'Url' => 'wss://gitlab.example.com/proxy/build/default_port/',
|
||||
'Header' => {
|
||||
'Authorization' => [nil]
|
||||
},
|
||||
|
@ -1536,7 +1536,8 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
|||
allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil)
|
||||
|
||||
expect(job.runner_session_url).to start_with('https://')
|
||||
expect(Gitlab::Workhorse).to receive(:channel_websocket).with(a_hash_including(url: "wss://localhost/proxy/build/default_port/"))
|
||||
expect(Gitlab::Workhorse).to receive(:channel_websocket)
|
||||
.with(a_hash_including(url: "wss://gitlab.example.com/proxy/build/default_port/"))
|
||||
|
||||
make_request
|
||||
end
|
||||
|
|
|
@ -268,6 +268,11 @@ RSpec.describe UploadsController do
|
|||
end
|
||||
|
||||
context "when not signed in" do
|
||||
context "when restricted visibility level is not set to public" do
|
||||
before do
|
||||
stub_application_setting(restricted_visibility_levels: [])
|
||||
end
|
||||
|
||||
it "responds with status 200" do
|
||||
get :show, params: { model: "user", mounted_as: "avatar", id: user.id, filename: "dk.png" }
|
||||
|
||||
|
@ -282,6 +287,19 @@ RSpec.describe UploadsController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when restricted visibility level is set to public" do
|
||||
before do
|
||||
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
|
||||
end
|
||||
|
||||
it "responds with status 401" do
|
||||
get :show, params: { model: "user", mounted_as: "avatar", id: user.id, filename: "dk.png" }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when viewing a project avatar" do
|
||||
|
|
|
@ -716,7 +716,7 @@ FactoryBot.define do
|
|||
|
||||
trait :with_runner_session do
|
||||
after(:build) do |build|
|
||||
build.build_runner_session(url: 'https://localhost')
|
||||
build.build_runner_session(url: 'https://gitlab.example.com')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@ FactoryBot.define do
|
|||
enable_ssl_verification { false }
|
||||
project
|
||||
|
||||
trait :url_variables do
|
||||
url_variables { { 'abc' => 'supers3cret' } }
|
||||
end
|
||||
|
||||
trait :token do
|
||||
token { generate(:token) }
|
||||
end
|
||||
|
|
|
@ -329,7 +329,7 @@ RSpec.describe 'Project' do
|
|||
it 'has working links to submodules' do
|
||||
click_link('645f6c4c')
|
||||
|
||||
expect(page).to have_selector('[data-testid="branches-select"]', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6')
|
||||
expect(page).to have_selector('.ref-selector', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6')
|
||||
end
|
||||
|
||||
context 'for signed commit on default branch', :js do
|
||||
|
|
|
@ -53,6 +53,8 @@ RSpec.describe 'Developer views tags' do
|
|||
end
|
||||
|
||||
it 'views a specific tag page' do
|
||||
create(:release, project: project, tag: 'v1.0.0', name: 'v1.0.0', description: nil)
|
||||
|
||||
click_on 'v1.0.0'
|
||||
|
||||
expect(page).to have_current_path(
|
||||
|
|
99
spec/fixtures/clusters/chain_certificates.pem
vendored
99
spec/fixtures/clusters/chain_certificates.pem
vendored
|
@ -1,67 +1,66 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIGYzCCBUugAwIBAgIQAaQHyOeT/PBR4ioLKYneZDANBgkqhkiG9w0BAQsFADBY
|
||||
MIIGYjCCBUqgAwIBAgIQATfkha/xTr3pbLHVWlPq4jANBgkqhkiG9w0BAQsFADBY
|
||||
MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEuMCwGA1UE
|
||||
AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgSDIgMjAyMTAeFw0yMTEw
|
||||
MTgxODUwMDRaFw0yMjExMTkxODUwMDNaMBsxGTAXBgNVBAMMEGFib3V0LmdpdGxh
|
||||
Yi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWSo0eziN/0lq5
|
||||
dIcS7ZceJw2odzZeT0tRkcKEW8iagNul6JetrFlk6h5lxoLEu35+MK6/fWHNmt7u
|
||||
eQk7HS0uRipskAzeGrL1Hvk8EjIcHXXTxpRu7JqWOu7ZSXwNxW5cqn7L9/N2gYwt
|
||||
Jg/sfkv9AFQiNOdKrarKfbcBstxmra6rQbh5ggLG5UBT23N4ZrA3XnzvEx3+GjtO
|
||||
u/a5izbk7FQP3gyXKyfm/SQRpNsytYa9jJqu5Hmyzfap5KaueOJbtJEOk8dR/HWR
|
||||
i/gmAUevq62MNxorYbz8YU/P1468tS7iORkD31Tc2QWCMQSPya5qGaCGnz7dVgWy
|
||||
E1xTPbBXAgMBAAGjggNkMIIDYDAbBgNVHREEFDASghBhYm91dC5naXRsYWIuY29t
|
||||
AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgMjAyMiBRMzAeFw0yMjA3
|
||||
MjIxOTQyMTFaFw0yMzA4MjMxOTQyMTBaMBsxGTAXBgNVBAMMEGFib3V0LmdpdGxh
|
||||
Yi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFFFQs8EITaWo5
|
||||
0U18/mPTDLencU/7siJT/4P8oeDkemyx98wzK6vuNj/2JEZ3v1psKun5n8Pb/fHa
|
||||
somKd/4icHgC4rnxrO6zayfb+cKzVghQe12Nj75lx6RtppqTgAmSOa3Tai5niICT
|
||||
I8s3d2wsHtfEgqAavcD0/zdPIk25Ji7yfquldSthnlhQqI4Pm3OxTiyFj/V5ZhFl
|
||||
IWZLvQaENjBSDVZQDcaPdWwodfXNA8fJmqk7cTLQ9P9NgjWvva7acl+Yd6hOFzV0
|
||||
EllBl/WF1KB+YzGuHI0CQHT7sv3GW1lXeE2EqrWoSdLTOSAqm6y02DyE79d1xvG6
|
||||
XXfX5ILlAgMBAAGjggNjMIIDXzAbBgNVHREEFDASghBhYm91dC5naXRsYWIuY29t
|
||||
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
HQYDVR0OBBYEFJFVruwpjWeUfGJXl3m5grAjhAwPMFcGA1UdIARQME4wCAYGZ4EM
|
||||
HQYDVR0OBBYEFHK7MnjGDptQWjfmJ2fr3IrjxEopMFcGA1UdIARQME4wCAYGZ4EM
|
||||
AQIBMEIGCisGAQQBoDIKAQMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
|
||||
YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDAYDVR0TAQH/BAIwADCBngYIKwYBBQUH
|
||||
AQEEgZEwgY4wQAYIKwYBBQUHMAGGNGh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29t
|
||||
L2NhL2dzYXRsYXNyM2R2dGxzY2FoMjIwMjEwSgYIKwYBBQUHMAKGPmh0dHA6Ly9z
|
||||
ZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzYXRsYXNyM2R2dGxzY2FoMjIw
|
||||
MjEuY3J0MB8GA1UdIwQYMBaAFCo0uar6vzyI8Ufy0hJ4vsXlqrBpMEgGA1UdHwRB
|
||||
L2NhL2dzYXRsYXNyM2R2dGxzY2EyMDIycTMwSgYIKwYBBQUHMAKGPmh0dHA6Ly9z
|
||||
ZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzYXRsYXNyM2R2dGxzY2EyMDIy
|
||||
cTMuY3J0MB8GA1UdIwQYMBaAFPqROWOa+60QJOW+tbnaq9nERmmrMEgGA1UdHwRB
|
||||
MD8wPaA7oDmGN2h0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vY2EvZ3NhdGxhc3Iz
|
||||
ZHZ0bHNjYWgyMjAyMS5jcmwwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB3AG9T
|
||||
dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABfJS9R5YAAAQDAEgwRgIh
|
||||
AOOZmc41vB2ICwkwEB5Bmpm/X8UHfjbxwrCXEdeRmO+qAiEAg/JugZIrG2PeV4bA
|
||||
Gm6rry7HUfB954bQJ4p0PeQVmwsAdABGpVXrdfqRIDC1oolp9PN9ESxBdL79SbiF
|
||||
q/L8cP5tRwAAAXyUvUeOAAAEAwBFMEMCHyRAiTz2fZ8DuQF6hrVP+IMTCPBtjB3D
|
||||
m4naI8tC/foCIDXFCRIYjRb00CFI6piLYGihRy+GYF5nMQhQ9uE6hltzAHcAUaOw
|
||||
9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF8lL1ICgAABAMASDBGAiEA
|
||||
5d/bXb9TPZWhwSH8GGji/LDFL6OJnZtOV94sBaDiFgMCIQCtl00oCRMFFnqsvBo6
|
||||
SRtnDqJkEHYBS12I4LyC+D1onjANBgkqhkiG9w0BAQsFAAOCAQEAE5xcno79J+Ec
|
||||
DIPJKnJCugKiM7yKjCjCp/63osCbRC+jUwRyXBIe/oTdY3geKwDOQAvyEeJPSWP1
|
||||
LbNp0l3yHbYXfsYl/NMTrJpjrJrrRO5BxG/d3IPwXIlcZrrdDSoGfGYIF9N23iqB
|
||||
in15L7B+PodTl8/mSQZTjbLoecPvl+AOcLyStcWCKYQUlQb3x4UV3R4Z1ukwGbBC
|
||||
cDbTR2XOSJzA9ECJcxKnWjQRQUc54pdG3pt13Wu2dVapX5sWZpV05rga3bBDjCqw
|
||||
DcfKuYbOChm2i6CQ578lAntPTIS02EkGFHrmYxrIAvlhGksHpJNJtRoff1KkQKni
|
||||
r8emWp7D2Q==
|
||||
ZHZ0bHNjYTIwMjJxMy5jcmwwggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB1AG9T
|
||||
dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABgiduiHEAAAQDAEYwRAIg
|
||||
SYQrru/KAKfe+hUqpJmk7Fc8drkgtY3IcAurTOwbM68CIBYO9sbDspd5p7v17RQi
|
||||
QQkjdRwSjHiIgvlX0Y1JqmXjAHYArfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWG
|
||||
NOvcgooAAAGCJ26IcQAABAMARzBFAiBc5a10annqMEH69bdEFy/Vo1gb3S3GQ993
|
||||
BCRV7ZXG4gIhAMqnsoKkU6ITwRXwE9KGjHnijJ8QrBrnK0i+JFaGe1ffAHYAs3N3
|
||||
B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZoAAAGCJ26I6QAABAMARzBFAiAf
|
||||
lW8Agd0DB68YA8XAbnlq7QNHw3uRMzNdS8gtRUe75gIhANTe+mt2p1ryW83P31OW
|
||||
jH3cEGJxdUNT/oDM3Fzesx94MA0GCSqGSIb3DQEBCwUAA4IBAQAfivKEmjqqOFFh
|
||||
VsX2XYkoDtreghpqMwHMCLwNk852Alr/Seyv9Ilng8cunU4NmhvEtsYVXkfE4XvB
|
||||
0QIVxkg1w7A+p7ejMjh6doLJ0aWNWIVW/DwOeP0qstF9lqvLdLDABoVn0BtYCDTH
|
||||
gjG80e2xpvPiKHGvBL+hlOIJwUuIAT3jN23sS1GoiYQGKsz0lovB09/6MGG0Qj8C
|
||||
3i9a59T9XBpwSKdpKd4u/CB6koBXD3atbBNBACuAMcFckTEtmkCFtSpqBuocJGKf
|
||||
LB4MFVaEwrd7Lc1ACC1et5FDtEI4I3/CerkRZTV+mRz5n6tB91AK3dRvjElfhiuh
|
||||
XXYRULvB
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIExTCCA62gAwIBAgIQeimFGrf0XWZ5UGZBtv/XHTANBgkqhkiG9w0BAQsFADBM
|
||||
MIIEjzCCA3egAwIBAgIQfCoMIT/GVVNFyR8ZH7hO+jANBgkqhkiG9w0BAQsFADBM
|
||||
MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv
|
||||
YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMTA2MTYxMjAwMDBaFw0y
|
||||
NDA2MTYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu
|
||||
IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIERWIFRMUyBDQSBI
|
||||
MiAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1JTAQMj+QUYF
|
||||
3d9X5eOWFOphbB6GpHE3J0uvUXcQwxnd8Jz26aQCE1ZYxJFEc2WmsxuVeVXU+rZj
|
||||
7+MYD7Mg72bhuiwUdwRGRN4a2N122LfIQlTFlHu/fwcNqYX/fe3phvZt9upnH4oJ
|
||||
aLBbay+t+HPPC4em74x2WKaIl31ZXzgzllLomnlLISLOKiQe1rEHp4yy3/yE2a4G
|
||||
1l/lprA49dcyM/oylm9Bbkum2F4C+EOjHgTAoDVJrJpdWvPj0CU+HkmftujfFp4S
|
||||
55LECSr2TfJt7xjgR3eLUx12nlpoauWEzZ0/i6OIDPfbmqcksw4ani/YO07LbRM6
|
||||
cY9VZzkAvwIDAQABo4IBlTCCAZEwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
|
||||
YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjA0MjAxMjAwMDBaFw0y
|
||||
NTA0MjAwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu
|
||||
IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIERWIFRMUyBDQSAy
|
||||
MDIyIFEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKh6ZjxOZpzO
|
||||
N6VUNU02x5nTqCc28i/G1Rg+6QndBdbXLDQyfAhjSdEQN+V4XRFizm37Lz83lNuP
|
||||
ezDpXizZVT+y27mgtWA3i6QGMjVQpAmvCkX/qB+bZY7dSuBAoeNjN1iQ3XU7/A4c
|
||||
gkCYvXCxwUgUFDwES2nd1JwBpukh44IK/uSqvzSgjMvJeW4+XGpSnsTtK8Vp/lA8
|
||||
k521/y0oqGwGbJ3Fr7JZ+1l3DXR6iISk1B3UuiAGzLUeSE50IRWGdcDMWtEFz1cW
|
||||
ehMX7MJKrtUecqoiWoycgjLEEOZCbiGGaHyAIzA1072wXgopK/AUsRg32Vklw+c4
|
||||
2enULTY1ZQIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
|
||||
CCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW
|
||||
BBQqNLmq+r88iPFH8tISeL7F5aqwaTAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj
|
||||
BBT6kTljmvutECTlvrW52qvZxEZpqzAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj
|
||||
move4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw
|
||||
Mi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1
|
||||
cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w
|
||||
K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwVwYD
|
||||
VR0gBFAwTjAIBgZngQwBAgEwQgYKKwYBBAGgMgoBAzA0MDIGCCsGAQUFBwIBFiZo
|
||||
dHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEAEsIwXEhdAfoUGaKAnYfVI7zsOY7Sx8bpC/obGxXa4Kyu8CVx+TtT
|
||||
g8WmKNF7+I7C51NZEmhvb8UDI1G9ny7iYIRDajQD5AeZowbfC69aHQSI9LiOeAZb
|
||||
YaRDJfWps9redPwoaC0iT5R4xLOnWwCtmIho1bv/YG3pMAvaQ+qn04kuUvWO7LEp
|
||||
u7FdHmx1DdgkefcqYgN/rAZ8E39S9VxWV+64PNUDey8vkAIH8FCTxbWiITty6dsH
|
||||
SulKQ9pSa93k9PHTf+di08mMQBq5WBWTiFeMYZEWyE/z7NHdU3eLMZjq6y/nKlF9
|
||||
nywrToh4AgdZK6JnbU+lqbNiexJbaBoA3w==
|
||||
K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD
|
||||
VR0gBBowGDAIBgZngQwBAgEwDAYKKwYBBAGgMgoBAzANBgkqhkiG9w0BAQsFAAOC
|
||||
AQEAFDMseeU/gsZwP9pZOKe7onasYRgFaFfZDfuKRrzxqOgMcAIdxi+X7TY+nlKG
|
||||
L1xi2NVHQ5pz0Sslh59EtBTrJrwhR3QgvZ+kv7OAHU01fc25tdpV8pBQyLIXTg60
|
||||
YYgpX0RdA39XkYHQ6zCu1SrsgiDOTtKwi5UCYXPYaTT0rWMOXOQgH6l97Y7lHAS7
|
||||
Ip/HqSLKmT0Cp2foBi36BGu7SdJsmVdjbC3CYXjhILH79r/hgjk5PHvvfRqVSrJy
|
||||
2lWQru3d4nCQfBrutTJaXc/W+kXyngEMMS+JhP4xYA/97qZbhNXHGOak+UAwKRge
|
||||
/vxBtbkpBXWLYhpbIi6/5FlssA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIExTCCA62gAwIBAgIQeimFGrf0XWZ5UGZBtv/XHTANBgkqhkiG9w0BAQsFADBM
|
||||
MIIEjzCCA3egAwIBAgIQfCoMIT/GVVNFyR8ZH7hO+jANBgkqhkiG9w0BAQsFADBM
|
||||
MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv
|
||||
YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMTA2MTYxMjAwMDBaFw0y
|
||||
NDA2MTYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu
|
||||
IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIERWIFRMUyBDQSBI
|
||||
MiAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1JTAQMj+QUYF
|
||||
3d9X5eOWFOphbB6GpHE3J0uvUXcQwxnd8Jz26aQCE1ZYxJFEc2WmsxuVeVXU+rZj
|
||||
7+MYD7Mg72bhuiwUdwRGRN4a2N122LfIQlTFlHu/fwcNqYX/fe3phvZt9upnH4oJ
|
||||
aLBbay+t+HPPC4em74x2WKaIl31ZXzgzllLomnlLISLOKiQe1rEHp4yy3/yE2a4G
|
||||
1l/lprA49dcyM/oylm9Bbkum2F4C+EOjHgTAoDVJrJpdWvPj0CU+HkmftujfFp4S
|
||||
55LECSr2TfJt7xjgR3eLUx12nlpoauWEzZ0/i6OIDPfbmqcksw4ani/YO07LbRM6
|
||||
cY9VZzkAvwIDAQABo4IBlTCCAZEwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
|
||||
YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjA0MjAxMjAwMDBaFw0y
|
||||
NTA0MjAwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu
|
||||
IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIERWIFRMUyBDQSAy
|
||||
MDIyIFEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKh6ZjxOZpzO
|
||||
N6VUNU02x5nTqCc28i/G1Rg+6QndBdbXLDQyfAhjSdEQN+V4XRFizm37Lz83lNuP
|
||||
ezDpXizZVT+y27mgtWA3i6QGMjVQpAmvCkX/qB+bZY7dSuBAoeNjN1iQ3XU7/A4c
|
||||
gkCYvXCxwUgUFDwES2nd1JwBpukh44IK/uSqvzSgjMvJeW4+XGpSnsTtK8Vp/lA8
|
||||
k521/y0oqGwGbJ3Fr7JZ+1l3DXR6iISk1B3UuiAGzLUeSE50IRWGdcDMWtEFz1cW
|
||||
ehMX7MJKrtUecqoiWoycgjLEEOZCbiGGaHyAIzA1072wXgopK/AUsRg32Vklw+c4
|
||||
2enULTY1ZQIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
|
||||
CCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW
|
||||
BBQqNLmq+r88iPFH8tISeL7F5aqwaTAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj
|
||||
BBT6kTljmvutECTlvrW52qvZxEZpqzAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj
|
||||
move4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw
|
||||
Mi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1
|
||||
cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w
|
||||
K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwVwYD
|
||||
VR0gBFAwTjAIBgZngQwBAgEwQgYKKwYBBAGgMgoBAzA0MDIGCCsGAQUFBwIBFiZo
|
||||
dHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEAEsIwXEhdAfoUGaKAnYfVI7zsOY7Sx8bpC/obGxXa4Kyu8CVx+TtT
|
||||
g8WmKNF7+I7C51NZEmhvb8UDI1G9ny7iYIRDajQD5AeZowbfC69aHQSI9LiOeAZb
|
||||
YaRDJfWps9redPwoaC0iT5R4xLOnWwCtmIho1bv/YG3pMAvaQ+qn04kuUvWO7LEp
|
||||
u7FdHmx1DdgkefcqYgN/rAZ8E39S9VxWV+64PNUDey8vkAIH8FCTxbWiITty6dsH
|
||||
SulKQ9pSa93k9PHTf+di08mMQBq5WBWTiFeMYZEWyE/z7NHdU3eLMZjq6y/nKlF9
|
||||
nywrToh4AgdZK6JnbU+lqbNiexJbaBoA3w==
|
||||
K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD
|
||||
VR0gBBowGDAIBgZngQwBAgEwDAYKKwYBBAGgMgoBAzANBgkqhkiG9w0BAQsFAAOC
|
||||
AQEAFDMseeU/gsZwP9pZOKe7onasYRgFaFfZDfuKRrzxqOgMcAIdxi+X7TY+nlKG
|
||||
L1xi2NVHQ5pz0Sslh59EtBTrJrwhR3QgvZ+kv7OAHU01fc25tdpV8pBQyLIXTg60
|
||||
YYgpX0RdA39XkYHQ6zCu1SrsgiDOTtKwi5UCYXPYaTT0rWMOXOQgH6l97Y7lHAS7
|
||||
Ip/HqSLKmT0Cp2foBi36BGu7SdJsmVdjbC3CYXjhILH79r/hgjk5PHvvfRqVSrJy
|
||||
2lWQru3d4nCQfBrutTJaXc/W+kXyngEMMS+JhP4xYA/97qZbhNXHGOak+UAwKRge
|
||||
/vxBtbkpBXWLYhpbIi6/5FlssA==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
58
spec/fixtures/clusters/leaf_certificate.pem
vendored
58
spec/fixtures/clusters/leaf_certificate.pem
vendored
|
@ -1,37 +1,37 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIGYzCCBUugAwIBAgIQAaQHyOeT/PBR4ioLKYneZDANBgkqhkiG9w0BAQsFADBY
|
||||
MIIGYjCCBUqgAwIBAgIQATfkha/xTr3pbLHVWlPq4jANBgkqhkiG9w0BAQsFADBY
|
||||
MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEuMCwGA1UE
|
||||
AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgSDIgMjAyMTAeFw0yMTEw
|
||||
MTgxODUwMDRaFw0yMjExMTkxODUwMDNaMBsxGTAXBgNVBAMMEGFib3V0LmdpdGxh
|
||||
Yi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWSo0eziN/0lq5
|
||||
dIcS7ZceJw2odzZeT0tRkcKEW8iagNul6JetrFlk6h5lxoLEu35+MK6/fWHNmt7u
|
||||
eQk7HS0uRipskAzeGrL1Hvk8EjIcHXXTxpRu7JqWOu7ZSXwNxW5cqn7L9/N2gYwt
|
||||
Jg/sfkv9AFQiNOdKrarKfbcBstxmra6rQbh5ggLG5UBT23N4ZrA3XnzvEx3+GjtO
|
||||
u/a5izbk7FQP3gyXKyfm/SQRpNsytYa9jJqu5Hmyzfap5KaueOJbtJEOk8dR/HWR
|
||||
i/gmAUevq62MNxorYbz8YU/P1468tS7iORkD31Tc2QWCMQSPya5qGaCGnz7dVgWy
|
||||
E1xTPbBXAgMBAAGjggNkMIIDYDAbBgNVHREEFDASghBhYm91dC5naXRsYWIuY29t
|
||||
AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgMjAyMiBRMzAeFw0yMjA3
|
||||
MjIxOTQyMTFaFw0yMzA4MjMxOTQyMTBaMBsxGTAXBgNVBAMMEGFib3V0LmdpdGxh
|
||||
Yi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFFFQs8EITaWo5
|
||||
0U18/mPTDLencU/7siJT/4P8oeDkemyx98wzK6vuNj/2JEZ3v1psKun5n8Pb/fHa
|
||||
somKd/4icHgC4rnxrO6zayfb+cKzVghQe12Nj75lx6RtppqTgAmSOa3Tai5niICT
|
||||
I8s3d2wsHtfEgqAavcD0/zdPIk25Ji7yfquldSthnlhQqI4Pm3OxTiyFj/V5ZhFl
|
||||
IWZLvQaENjBSDVZQDcaPdWwodfXNA8fJmqk7cTLQ9P9NgjWvva7acl+Yd6hOFzV0
|
||||
EllBl/WF1KB+YzGuHI0CQHT7sv3GW1lXeE2EqrWoSdLTOSAqm6y02DyE79d1xvG6
|
||||
XXfX5ILlAgMBAAGjggNjMIIDXzAbBgNVHREEFDASghBhYm91dC5naXRsYWIuY29t
|
||||
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
HQYDVR0OBBYEFJFVruwpjWeUfGJXl3m5grAjhAwPMFcGA1UdIARQME4wCAYGZ4EM
|
||||
HQYDVR0OBBYEFHK7MnjGDptQWjfmJ2fr3IrjxEopMFcGA1UdIARQME4wCAYGZ4EM
|
||||
AQIBMEIGCisGAQQBoDIKAQMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
|
||||
YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDAYDVR0TAQH/BAIwADCBngYIKwYBBQUH
|
||||
AQEEgZEwgY4wQAYIKwYBBQUHMAGGNGh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29t
|
||||
L2NhL2dzYXRsYXNyM2R2dGxzY2FoMjIwMjEwSgYIKwYBBQUHMAKGPmh0dHA6Ly9z
|
||||
ZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzYXRsYXNyM2R2dGxzY2FoMjIw
|
||||
MjEuY3J0MB8GA1UdIwQYMBaAFCo0uar6vzyI8Ufy0hJ4vsXlqrBpMEgGA1UdHwRB
|
||||
L2NhL2dzYXRsYXNyM2R2dGxzY2EyMDIycTMwSgYIKwYBBQUHMAKGPmh0dHA6Ly9z
|
||||
ZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzYXRsYXNyM2R2dGxzY2EyMDIy
|
||||
cTMuY3J0MB8GA1UdIwQYMBaAFPqROWOa+60QJOW+tbnaq9nERmmrMEgGA1UdHwRB
|
||||
MD8wPaA7oDmGN2h0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vY2EvZ3NhdGxhc3Iz
|
||||
ZHZ0bHNjYWgyMjAyMS5jcmwwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB3AG9T
|
||||
dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABfJS9R5YAAAQDAEgwRgIh
|
||||
AOOZmc41vB2ICwkwEB5Bmpm/X8UHfjbxwrCXEdeRmO+qAiEAg/JugZIrG2PeV4bA
|
||||
Gm6rry7HUfB954bQJ4p0PeQVmwsAdABGpVXrdfqRIDC1oolp9PN9ESxBdL79SbiF
|
||||
q/L8cP5tRwAAAXyUvUeOAAAEAwBFMEMCHyRAiTz2fZ8DuQF6hrVP+IMTCPBtjB3D
|
||||
m4naI8tC/foCIDXFCRIYjRb00CFI6piLYGihRy+GYF5nMQhQ9uE6hltzAHcAUaOw
|
||||
9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF8lL1ICgAABAMASDBGAiEA
|
||||
5d/bXb9TPZWhwSH8GGji/LDFL6OJnZtOV94sBaDiFgMCIQCtl00oCRMFFnqsvBo6
|
||||
SRtnDqJkEHYBS12I4LyC+D1onjANBgkqhkiG9w0BAQsFAAOCAQEAE5xcno79J+Ec
|
||||
DIPJKnJCugKiM7yKjCjCp/63osCbRC+jUwRyXBIe/oTdY3geKwDOQAvyEeJPSWP1
|
||||
LbNp0l3yHbYXfsYl/NMTrJpjrJrrRO5BxG/d3IPwXIlcZrrdDSoGfGYIF9N23iqB
|
||||
in15L7B+PodTl8/mSQZTjbLoecPvl+AOcLyStcWCKYQUlQb3x4UV3R4Z1ukwGbBC
|
||||
cDbTR2XOSJzA9ECJcxKnWjQRQUc54pdG3pt13Wu2dVapX5sWZpV05rga3bBDjCqw
|
||||
DcfKuYbOChm2i6CQ578lAntPTIS02EkGFHrmYxrIAvlhGksHpJNJtRoff1KkQKni
|
||||
r8emWp7D2Q==
|
||||
ZHZ0bHNjYTIwMjJxMy5jcmwwggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB1AG9T
|
||||
dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABgiduiHEAAAQDAEYwRAIg
|
||||
SYQrru/KAKfe+hUqpJmk7Fc8drkgtY3IcAurTOwbM68CIBYO9sbDspd5p7v17RQi
|
||||
QQkjdRwSjHiIgvlX0Y1JqmXjAHYArfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWG
|
||||
NOvcgooAAAGCJ26IcQAABAMARzBFAiBc5a10annqMEH69bdEFy/Vo1gb3S3GQ993
|
||||
BCRV7ZXG4gIhAMqnsoKkU6ITwRXwE9KGjHnijJ8QrBrnK0i+JFaGe1ffAHYAs3N3
|
||||
B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZoAAAGCJ26I6QAABAMARzBFAiAf
|
||||
lW8Agd0DB68YA8XAbnlq7QNHw3uRMzNdS8gtRUe75gIhANTe+mt2p1ryW83P31OW
|
||||
jH3cEGJxdUNT/oDM3Fzesx94MA0GCSqGSIb3DQEBCwUAA4IBAQAfivKEmjqqOFFh
|
||||
VsX2XYkoDtreghpqMwHMCLwNk852Alr/Seyv9Ilng8cunU4NmhvEtsYVXkfE4XvB
|
||||
0QIVxkg1w7A+p7ejMjh6doLJ0aWNWIVW/DwOeP0qstF9lqvLdLDABoVn0BtYCDTH
|
||||
gjG80e2xpvPiKHGvBL+hlOIJwUuIAT3jN23sS1GoiYQGKsz0lovB09/6MGG0Qj8C
|
||||
3i9a59T9XBpwSKdpKd4u/CB6koBXD3atbBNBACuAMcFckTEtmkCFtSpqBuocJGKf
|
||||
LB4MFVaEwrd7Lc1ACC1et5FDtEI4I3/CerkRZTV+mRz5n6tB91AK3dRvjElfhiuh
|
||||
XXYRULvB
|
||||
-----END CERTIFICATE-----
|
||||
|
|
BIN
spec/fixtures/packages/nuget/corrupted_package.nupkg
vendored
Normal file
BIN
spec/fixtures/packages/nuget/corrupted_package.nupkg
vendored
Normal file
Binary file not shown.
|
@ -445,6 +445,19 @@ RSpec.describe DiffHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#params_with_whitespace' do
|
||||
before do
|
||||
controller.params[:protocol] = 'HACKED!'
|
||||
controller.params[:host] = 'HACKED!'
|
||||
end
|
||||
|
||||
subject { helper.params_with_whitespace }
|
||||
|
||||
it "filters with safe_params" do
|
||||
expect(subject).to eq({ 'w' => 1 })
|
||||
end
|
||||
end
|
||||
|
||||
describe "#render_fork_suggestion" do
|
||||
subject { helper.render_fork_suggestion }
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe SubmoduleHelper do
|
||||
RSpec.describe SubmoduleHelper, feature_category: :source_code_management do
|
||||
include RepoHelpers
|
||||
|
||||
let(:submodule_item) { double(id: 'hash', path: 'rack') }
|
||||
|
|
|
@ -114,6 +114,18 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
|
|||
|
||||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
|
||||
context 'when the external_authorization_service is enabled' do
|
||||
before do
|
||||
stub_application_setting(external_authorization_service_enabled: true)
|
||||
end
|
||||
|
||||
context 'with a valid deploy token' do
|
||||
let(:raw) { username_and_password(token.username, token.token) }
|
||||
|
||||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :personal_access_token' do
|
||||
|
|
|
@ -188,7 +188,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
end
|
||||
|
||||
it 'returns nil if valid feed_token and disabled' do
|
||||
allow(Gitlab::CurrentSettings).to receive_messages(disable_feed_token: true)
|
||||
stub_application_setting(disable_feed_token: true)
|
||||
set_param(:feed_token, user.feed_token)
|
||||
|
||||
expect(find_user_from_feed_token(:rss)).to be_nil
|
||||
|
@ -388,6 +388,15 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the external_authorization_service is enabled' do
|
||||
before do
|
||||
stub_application_setting(external_authorization_service_enabled: true)
|
||||
set_header(described_class::DEPLOY_TOKEN_HEADER, deploy_token.token)
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_user_from_access_token' do
|
||||
|
|
|
@ -528,12 +528,13 @@ RSpec.describe Gitlab::Git::Repository do
|
|||
prune: false,
|
||||
check_tags_changed: false,
|
||||
refmap: nil,
|
||||
http_authorization_header: ""
|
||||
http_authorization_header: "",
|
||||
resolved_address: '172.16.123.1'
|
||||
}
|
||||
|
||||
expect(repository.gitaly_repository_client).to receive(:fetch_remote).with(url, expected_opts)
|
||||
|
||||
repository.fetch_remote(url, ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false, check_tags_changed: false)
|
||||
repository.fetch_remote(url, ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false, check_tags_changed: false, resolved_address: '172.16.123.1')
|
||||
end
|
||||
|
||||
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RepositoryService, :fetch_remote do
|
||||
|
@ -2454,7 +2455,7 @@ RSpec.describe Gitlab::Git::Repository do
|
|||
|
||||
it 'delegates to Gitaly' do
|
||||
expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |svc|
|
||||
expect(svc).to receive(:import_repository).with(url, http_authorization_header: '', mirror: false).and_return(nil)
|
||||
expect(svc).to receive(:import_repository).with(url, http_authorization_header: '', mirror: false, resolved_address: '').and_return(nil)
|
||||
end
|
||||
|
||||
repository.import_repository(url)
|
||||
|
|
|
@ -5,6 +5,7 @@ require 'spec_helper'
|
|||
RSpec.describe Gitlab::GitAccess, :aggregate_failures do
|
||||
include TermsHelper
|
||||
include AdminModeHelper
|
||||
include ExternalAuthorizationServiceHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:actor) { user }
|
||||
|
@ -111,6 +112,19 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the external_authorization_service is enabled' do
|
||||
before do
|
||||
stub_application_setting(external_authorization_service_enabled: true)
|
||||
end
|
||||
|
||||
it 'blocks push and pull with "not found"' do
|
||||
aggregate_failures do
|
||||
expect { push_access_check }.to raise_not_found
|
||||
expect { pull_access_check }.to raise_not_found
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when actor is a User' do
|
||||
|
@ -176,6 +190,20 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures do
|
|||
expect { push_access_check }.to raise_not_found
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the external_authorization_service is enabled' do
|
||||
before do
|
||||
stub_application_setting(external_authorization_service_enabled: true)
|
||||
end
|
||||
|
||||
it 'blocks pull access' do
|
||||
expect { pull_access_check }.to raise_not_found
|
||||
end
|
||||
|
||||
it 'blocks the push' do
|
||||
expect { push_access_check }.to raise_not_found
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -133,6 +133,40 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#import_repository' do
|
||||
let(:source) { 'https://example.com/git/repo.git' }
|
||||
|
||||
it 'sends a create_repository_from_url message' do
|
||||
expected_request = gitaly_request_with_params(
|
||||
url: source,
|
||||
resolved_address: ''
|
||||
)
|
||||
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
.to receive(:create_repository_from_url)
|
||||
.with(expected_request, kind_of(Hash))
|
||||
.and_return(double(value: true))
|
||||
|
||||
client.import_repository(source)
|
||||
end
|
||||
|
||||
context 'when http_host is provided' do
|
||||
it 'sends a create_repository_from_url message with http_host provided in the request' do
|
||||
expected_request = gitaly_request_with_params(
|
||||
url: source,
|
||||
resolved_address: '172.16.123.1'
|
||||
)
|
||||
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
.to receive(:create_repository_from_url)
|
||||
.with(expected_request, kind_of(Hash))
|
||||
.and_return(double(value: true))
|
||||
|
||||
client.import_repository(source, resolved_address: '172.16.123.1')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#fetch_remote' do
|
||||
let(:url) { 'https://example.com/git/repo.git' }
|
||||
|
||||
|
@ -141,7 +175,8 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
|
|||
remote_params: Gitaly::Remote.new(
|
||||
url: url,
|
||||
http_authorization_header: "",
|
||||
mirror_refmaps: []
|
||||
mirror_refmaps: [],
|
||||
resolved_address: ''
|
||||
),
|
||||
ssh_key: '',
|
||||
known_hosts: '',
|
||||
|
@ -159,6 +194,32 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
|
|||
client.fetch_remote(url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false)
|
||||
end
|
||||
|
||||
context 'with resolved address' do
|
||||
it 'sends a fetch_remote_request message' do
|
||||
expected_request = gitaly_request_with_params(
|
||||
remote_params: Gitaly::Remote.new(
|
||||
url: url,
|
||||
http_authorization_header: "",
|
||||
mirror_refmaps: [],
|
||||
resolved_address: '172.16.123.1'
|
||||
),
|
||||
ssh_key: '',
|
||||
known_hosts: '',
|
||||
force: false,
|
||||
no_tags: false,
|
||||
no_prune: false,
|
||||
check_tags_changed: false
|
||||
)
|
||||
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
.to receive(:fetch_remote)
|
||||
.with(expected_request, kind_of(Hash))
|
||||
.and_return(double(value: true))
|
||||
|
||||
client.fetch_remote(url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false, resolved_address: '172.16.123.1')
|
||||
end
|
||||
end
|
||||
|
||||
context 'SSH auth' do
|
||||
where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do
|
||||
false | false | 'key' | 'known_hosts' | {}
|
||||
|
|
|
@ -29,8 +29,8 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
|
|||
expect(data[:path_with_namespace]).to eq(project.full_path)
|
||||
expect(data[:project_id]).to eq(project.id)
|
||||
expect(data[:owner_name]).to eq('John')
|
||||
expect(data[:owner_email]).to eq('john@example.com')
|
||||
expect(data[:owners]).to contain_exactly({ name: 'John', email: 'john@example.com' })
|
||||
expect(data[:owner_email]).to eq(_('[REDACTED]'))
|
||||
expect(data[:owners]).to contain_exactly({ name: 'John', email: _('[REDACTED]') })
|
||||
expect(data[:project_visibility]).to eq('internal')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ RSpec.describe Gitlab::HookData::ProjectMemberBuilder do
|
|||
expect(data[:user_username]).to eq('johndoe')
|
||||
expect(data[:user_name]).to eq('John Doe')
|
||||
expect(data[:user_id]).to eq(user.id)
|
||||
expect(data[:user_email]).to eq('john@example.com')
|
||||
expect(data[:user_email]).to eq(_('[REDACTED]'))
|
||||
expect(data[:access_level]).to eq('Developer')
|
||||
expect(data[:project_visibility]).to eq('internal')
|
||||
end
|
||||
|
|
20
spec/lib/gitlab/safe_device_detector_spec.rb
Normal file
20
spec/lib/gitlab/safe_device_detector_spec.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'device_detector'
|
||||
require_relative '../../../lib/gitlab/safe_device_detector'
|
||||
|
||||
RSpec.describe Gitlab::SafeDeviceDetector, feature_category: :authentication_and_authorization do
|
||||
it 'retains the behavior for normal user agents' do
|
||||
chrome_user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \
|
||||
(KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
|
||||
|
||||
expect(described_class.new(chrome_user_agent).user_agent).to be_eql(chrome_user_agent)
|
||||
expect(described_class.new(chrome_user_agent).name).to be_eql('Chrome')
|
||||
end
|
||||
|
||||
it 'truncates big user agents' do
|
||||
big_user_agent = "chrome #{'abc' * 1024}"
|
||||
expect(described_class.new(big_user_agent).user_agent).not_to be_eql(big_user_agent)
|
||||
end
|
||||
end
|
|
@ -89,31 +89,32 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
describe '.categories' do
|
||||
it 'gets CE unique category names' do
|
||||
expect(described_class.categories).to include(
|
||||
'deploy_token_packages',
|
||||
'user_packages',
|
||||
'ecosystem',
|
||||
'analytics',
|
||||
'ide_edit',
|
||||
'search',
|
||||
'source_code',
|
||||
'incident_management',
|
||||
'incident_management_alerts',
|
||||
'testing',
|
||||
'issues_edit',
|
||||
'snippets',
|
||||
'code_review',
|
||||
'terraform',
|
||||
'ci_templates',
|
||||
'quickactions',
|
||||
'pipeline_authoring',
|
||||
'secure',
|
||||
'importer',
|
||||
'geo',
|
||||
'work_items',
|
||||
'ci_users',
|
||||
'code_review',
|
||||
'deploy_token_packages',
|
||||
'ecosystem',
|
||||
'environments',
|
||||
'error_tracking',
|
||||
'geo',
|
||||
'ide_edit',
|
||||
'importer',
|
||||
'incident_management_alerts',
|
||||
'incident_management',
|
||||
'issues_edit',
|
||||
'kubernetes_agent',
|
||||
'manage',
|
||||
'kubernetes_agent'
|
||||
'pipeline_authoring',
|
||||
'quickactions',
|
||||
'search',
|
||||
'secure',
|
||||
'snippets',
|
||||
'source_code',
|
||||
'terraform',
|
||||
'testing',
|
||||
'user_packages',
|
||||
'work_items'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ RSpec.describe DeviseMailer do
|
|||
subject { described_class.confirmation_instructions(user, 'faketoken', {}) }
|
||||
|
||||
context "when confirming a new account" do
|
||||
let(:user) { build(:user, created_at: 1.minute.ago, unconfirmed_email: nil) }
|
||||
let(:user) { create(:user, created_at: 1.minute.ago) }
|
||||
|
||||
it "shows the expected text" do
|
||||
expect(subject.body.encoded).to have_text "Welcome"
|
||||
|
@ -20,7 +20,13 @@ RSpec.describe DeviseMailer do
|
|||
end
|
||||
|
||||
context "when confirming the unconfirmed_email" do
|
||||
let(:user) { build(:user, unconfirmed_email: 'jdoe@example.com') }
|
||||
subject { described_class.confirmation_instructions(user, user.confirmation_token, { to: user.unconfirmed_email }) }
|
||||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
user.update!(email: 'unconfirmed-email@example.com')
|
||||
end
|
||||
|
||||
it "shows the expected text" do
|
||||
expect(subject.body.encoded).not_to have_text "Welcome"
|
||||
|
@ -30,7 +36,7 @@ RSpec.describe DeviseMailer do
|
|||
end
|
||||
|
||||
context "when re-confirming the primary email after a security issue" do
|
||||
let(:user) { build(:user, created_at: 10.days.ago, unconfirmed_email: nil) }
|
||||
let(:user) { create(:user, created_at: Devise.confirm_within.ago) }
|
||||
|
||||
it "shows the expected text" do
|
||||
expect(subject.body.encoded).not_to have_text "Welcome"
|
||||
|
|
|
@ -1466,10 +1466,4 @@ RSpec.describe ApplicationSetting do
|
|||
expect(setting.personal_access_token_prefix).to eql('glpat-')
|
||||
end
|
||||
end
|
||||
|
||||
describe '.personal_access_tokens_disabled?' do
|
||||
it 'is false' do
|
||||
expect(setting.personal_access_tokens_disabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,45 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
it { is_expected.to validate_presence_of(:build) }
|
||||
it { is_expected.to validate_presence_of(:url).with_message('must be a valid URL') }
|
||||
|
||||
context 'url validation of local web hook address' do
|
||||
let(:url) { 'https://127.0.0.1:7777' }
|
||||
|
||||
subject(:build_with_local_runner_session_url) do
|
||||
create(:ci_build).tap { |b| b.update!(runner_session_attributes: { url: url }) }
|
||||
end
|
||||
|
||||
context 'with allow_local_requests_from_web_hooks_and_services? stubbed' do
|
||||
before do
|
||||
allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
|
||||
stub_application_setting(allow_local_requests_from_web_hooks_and_services: allow_local_requests)
|
||||
end
|
||||
|
||||
context 'as returning true' do
|
||||
let(:allow_local_requests) { true }
|
||||
|
||||
it 'creates a new session', :aggregate_failures do
|
||||
session = build_with_local_runner_session_url.reload.runner_session
|
||||
|
||||
expect(session.errors).to be_empty
|
||||
expect(session).to be_a(Ci::BuildRunnerSession)
|
||||
expect(session.url).to eq(url)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as returning false' do
|
||||
let(:allow_local_requests) { false }
|
||||
|
||||
it 'does not create a new session' do
|
||||
expect { build_with_local_runner_session_url }.to raise_error(ActiveRecord::RecordInvalid) do |err|
|
||||
expect(err.record.errors.full_messages).to include(
|
||||
'Runner session url is blocked: Requests to localhost are not allowed'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'nested attribute assignment' do
|
||||
it 'creates a new session' do
|
||||
simple_build = create(:ci_build)
|
||||
|
@ -49,6 +88,12 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
expect(specification).to be_empty
|
||||
end
|
||||
|
||||
it 'returns url with appended query if url has query' do
|
||||
subject.url = 'https://new.example.com:7777/some_path?dummy='
|
||||
|
||||
expect(specification[:url]).to eq('wss://new.example.com:7777/some_path/exec?dummy=')
|
||||
end
|
||||
|
||||
context 'when url is present' do
|
||||
it 'returns ca_pem nil if empty certificate' do
|
||||
subject.certificate = ''
|
||||
|
@ -72,7 +117,7 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
let(:specification) { subject.service_specification(service: service, port: port, path: path, subprotocols: subprotocols) }
|
||||
|
||||
it 'returns service proxy url' do
|
||||
expect(specification[:url]).to eq "https://localhost/proxy/#{service}/#{port}/#{path}"
|
||||
expect(specification[:url]).to eq "https://gitlab.example.com/proxy/#{service}/#{port}/#{path}"
|
||||
end
|
||||
|
||||
it 'returns default service proxy websocket subprotocol' do
|
||||
|
@ -85,11 +130,17 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
expect(specification).to be_empty
|
||||
end
|
||||
|
||||
it 'returns url with appended query if url has query' do
|
||||
subject.url = 'https://new.example.com:7777/some_path?dummy='
|
||||
|
||||
expect(specification[:url]).to eq("https://new.example.com:7777/some_path/proxy/#{service}/#{port}/#{path}?dummy=")
|
||||
end
|
||||
|
||||
context 'when port is not present' do
|
||||
let(:port) { nil }
|
||||
|
||||
it 'uses the default port name' do
|
||||
expect(specification[:url]).to eq "https://localhost/proxy/#{service}/default_port/#{path}"
|
||||
expect(specification[:url]).to eq "https://gitlab.example.com/proxy/#{service}/default_port/#{path}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -97,7 +148,7 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
|
|||
let(:service) { '' }
|
||||
|
||||
it 'uses the service name "build" as default' do
|
||||
expect(specification[:url]).to eq "https://localhost/proxy/build/#{port}/#{path}"
|
||||
expect(specification[:url]).to eq "https://gitlab.example.com/proxy/build/#{port}/#{path}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -185,4 +185,22 @@ RSpec.describe WebHookLog do
|
|||
it { expect(web_hook_log.internal_error?).to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#request_headers' do
|
||||
let(:hook) { build(:project_hook, :token) }
|
||||
let(:web_hook_log) { build(:web_hook_log, request_headers: request_headers) }
|
||||
let(:expected_headers) { { 'X-Gitlab-Token' => _('[REDACTED]') } }
|
||||
|
||||
context 'with redacted headers token' do
|
||||
let(:request_headers) { { 'X-Gitlab-Token' => _('[REDACTED]') } }
|
||||
|
||||
it { expect(web_hook_log.request_headers).to eq(expected_headers) }
|
||||
end
|
||||
|
||||
context 'with exposed headers token' do
|
||||
let(:request_headers) { { 'X-Gitlab-Token' => hook.token } }
|
||||
|
||||
it { expect(web_hook_log.request_headers).to eq(expected_headers) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe WebHook do
|
||||
RSpec.describe WebHook, feature_category: :integrations do
|
||||
include AfterNextHelpers
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
@ -131,6 +131,62 @@ RSpec.describe WebHook do
|
|||
expect(hook.push_events_branch_filter).to eq('')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'before_validation :reset_token' do
|
||||
subject(:hook) { build_stubbed(:project_hook, :token, project: project) }
|
||||
|
||||
it 'resets token if url changed' do
|
||||
hook.url = 'https://webhook.example.com/new-hook'
|
||||
|
||||
expect(hook).to be_valid
|
||||
expect(hook.token).to be_nil
|
||||
end
|
||||
|
||||
it 'does not reset token if new url is set together with the same token' do
|
||||
hook.url = 'https://webhook.example.com/new-hook'
|
||||
current_token = hook.token
|
||||
hook.token = current_token
|
||||
|
||||
expect(hook).to be_valid
|
||||
expect(hook.token).to eq(current_token)
|
||||
expect(hook.url).to eq('https://webhook.example.com/new-hook')
|
||||
end
|
||||
|
||||
it 'does not reset token if new url is set together with a new token' do
|
||||
hook.url = 'https://webhook.example.com/new-hook'
|
||||
hook.token = 'token'
|
||||
|
||||
expect(hook).to be_valid
|
||||
expect(hook.token).to eq('token')
|
||||
expect(hook.url).to eq('https://webhook.example.com/new-hook')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'before_validation :reset_url_variables' do
|
||||
subject(:hook) { build_stubbed(:project_hook, :url_variables, project: project, url: 'http://example.com/{abc}') }
|
||||
|
||||
it 'resets url variables if url changed' do
|
||||
hook.url = 'http://example.com/new-hook'
|
||||
|
||||
expect(hook).to be_valid
|
||||
expect(hook.url_variables).to eq({})
|
||||
end
|
||||
|
||||
it 'resets url variables if url is changed but url variables stayed the same' do
|
||||
hook.url = 'http://test.example.com/{abc}'
|
||||
|
||||
expect(hook).not_to be_valid
|
||||
expect(hook.url_variables).to eq({})
|
||||
end
|
||||
|
||||
it 'does not reset url variables if both url and url variables are changed' do
|
||||
hook.url = 'http://example.com/{one}/{two}'
|
||||
hook.url_variables = { 'one' => 'foo', 'two' => 'bar' }
|
||||
|
||||
expect(hook).to be_valid
|
||||
expect(hook.url_variables).to eq({ 'one' => 'foo', 'two' => 'bar' })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'encrypted attributes' do
|
||||
|
@ -242,7 +298,7 @@ RSpec.describe WebHook do
|
|||
end
|
||||
|
||||
describe '#executable?' do
|
||||
let(:web_hook) { create(:project_hook, project: project) }
|
||||
let_it_be(:web_hook) { create(:project_hook, project: project) }
|
||||
|
||||
where(:recent_failures, :not_until, :executable) do
|
||||
[
|
||||
|
|
|
@ -230,8 +230,11 @@ RSpec.describe Integrations::Jira do
|
|||
|
||||
where(:url, :result) do
|
||||
'https://abc.atlassian.net' | true
|
||||
'http://abc.atlassian.net' | false
|
||||
'abc.atlassian.net' | false # This is how it behaves currently, but we may need to consider adding scheme if missing
|
||||
'https://somethingelse.com' | false
|
||||
'javascript://test.atlassian.net/%250dalert(document.domain)' | false
|
||||
'https://example.com".atlassian.net' | false
|
||||
nil | false
|
||||
end
|
||||
|
||||
|
@ -289,7 +292,7 @@ RSpec.describe Integrations::Jira do
|
|||
let(:server_info_results) { { 'deploymentType' => 'FutureCloud' } }
|
||||
|
||||
context 'and URL ends in .atlassian.net' do
|
||||
let(:api_url) { 'http://example-api.atlassian.net' }
|
||||
let(:api_url) { 'https://example-api.atlassian.net' }
|
||||
|
||||
it 'deployment_type is set to cloud' do
|
||||
expect(integration.jira_tracker_data).to be_deployment_cloud
|
||||
|
@ -297,7 +300,7 @@ RSpec.describe Integrations::Jira do
|
|||
end
|
||||
|
||||
context 'and URL is something else' do
|
||||
let(:api_url) { 'http://my-jira-api.someserver.com' }
|
||||
let(:api_url) { 'https://my-jira-api.someserver.com' }
|
||||
|
||||
it 'deployment_type is set to server' do
|
||||
expect(integration.jira_tracker_data).to be_deployment_server
|
||||
|
@ -309,7 +312,7 @@ RSpec.describe Integrations::Jira do
|
|||
let(:server_info_results) { {} }
|
||||
|
||||
context 'and URL ends in .atlassian.net' do
|
||||
let(:api_url) { 'http://example-api.atlassian.net' }
|
||||
let(:api_url) { 'https://example-api.atlassian.net' }
|
||||
|
||||
it 'deployment_type is set to cloud' do
|
||||
expect(Gitlab::AppLogger).to receive(:warn).with(message: "Jira API returned no ServerInfo, setting deployment_type from URL", server_info: server_info_results, url: api_url)
|
||||
|
@ -318,7 +321,7 @@ RSpec.describe Integrations::Jira do
|
|||
end
|
||||
|
||||
context 'and URL is something else' do
|
||||
let(:api_url) { 'http://my-jira-api.someserver.com' }
|
||||
let(:api_url) { 'https://my-jira-api.someserver.com' }
|
||||
|
||||
it 'deployment_type is set to server' do
|
||||
expect(Gitlab::AppLogger).to receive(:warn).with(message: "Jira API returned no ServerInfo, setting deployment_type from URL", server_info: server_info_results, url: api_url)
|
||||
|
|
|
@ -22,7 +22,7 @@ RSpec.describe ProjectImportState, type: :model do
|
|||
|
||||
before do
|
||||
allow_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:import_repository)
|
||||
.with(project.import_url, http_authorization_header: '', mirror: false).and_return(true)
|
||||
.with(project.import_url, http_authorization_header: '', mirror: false, resolved_address: '').and_return(true)
|
||||
|
||||
# Works around https://github.com/rspec/rspec-mocks/issues/910
|
||||
allow(Project).to receive(:find).with(project.id).and_return(project)
|
||||
|
|
|
@ -5521,8 +5521,8 @@ RSpec.describe Project, factory_default: :keep do
|
|||
let(:import_state) { create(:import_state, project: project) }
|
||||
|
||||
it 'runs the correct hooks' do
|
||||
expect(project.repository).to receive(:remove_prohibited_branches)
|
||||
expect(project.repository).to receive(:expire_content_cache)
|
||||
expect(project.repository).to receive(:expire_content_cache).ordered
|
||||
expect(project.repository).to receive(:remove_prohibited_branches).ordered
|
||||
expect(project.wiki.repository).to receive(:expire_content_cache)
|
||||
expect(import_state).to receive(:finish)
|
||||
expect(project).to receive(:update_project_counter_caches)
|
||||
|
|
|
@ -1224,11 +1224,22 @@ RSpec.describe Repository do
|
|||
it 'fetches the URL without creating a remote' do
|
||||
expect(repository)
|
||||
.to receive(:fetch_remote)
|
||||
.with(url, forced: false, prune: true, refmap: :all_refs, http_authorization_header: "")
|
||||
.with(url, forced: false, prune: true, refmap: :all_refs, http_authorization_header: "", resolved_address: '')
|
||||
.and_return(nil)
|
||||
|
||||
repository.fetch_as_mirror(url)
|
||||
end
|
||||
|
||||
context 'with http_host provided' do
|
||||
it 'fetches the URL with resolved_address value' do
|
||||
expect(repository)
|
||||
.to receive(:fetch_remote)
|
||||
.with(url, forced: false, prune: true, refmap: :all_refs, http_authorization_header: "", resolved_address: '172.16.123.1')
|
||||
.and_return(nil)
|
||||
|
||||
repository.fetch_as_mirror(url, resolved_address: '172.16.123.1')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#fetch_ref' do
|
||||
|
|
|
@ -292,6 +292,34 @@ RSpec.describe User do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'confirmation instructions for unconfirmed email' do
|
||||
let(:unconfirmed_email) { 'first-unconfirmed-email@example.com' }
|
||||
let(:another_unconfirmed_email) { 'another-unconfirmed-email@example.com' }
|
||||
|
||||
context 'when email is changed to another before performing the job that sends confirmation instructions for previous email change request' do
|
||||
it "mentions the recipient's email in the message body", :aggregate_failures do
|
||||
same_user = User.find(user.id)
|
||||
same_user.update!(email: unconfirmed_email)
|
||||
|
||||
user.update!(email: another_unconfirmed_email)
|
||||
|
||||
perform_enqueued_jobs
|
||||
|
||||
confirmation_instructions_for_unconfirmed_email = ActionMailer::Base.deliveries.find do |message|
|
||||
message.subject == 'Confirmation instructions' && message.to.include?(unconfirmed_email)
|
||||
end
|
||||
expect(confirmation_instructions_for_unconfirmed_email.html_part.body.encoded).to match same_user.unconfirmed_email
|
||||
expect(confirmation_instructions_for_unconfirmed_email.text_part.body.encoded).to match same_user.unconfirmed_email
|
||||
|
||||
confirmation_instructions_for_another_unconfirmed_email = ActionMailer::Base.deliveries.find do |message|
|
||||
message.subject == 'Confirmation instructions' && message.to.include?(another_unconfirmed_email)
|
||||
end
|
||||
expect(confirmation_instructions_for_another_unconfirmed_email.html_part.body.encoded).to match user.unconfirmed_email
|
||||
expect(confirmation_instructions_for_another_unconfirmed_email.text_part.body.encoded).to match user.unconfirmed_email
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
|
|
|
@ -643,6 +643,35 @@ RSpec.describe ProjectPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'read_grafana', feature_category: :metrics do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:policy) { :read_grafana }
|
||||
|
||||
where(:project_visibility, :role, :allowed) do
|
||||
:public | :anonymous | false
|
||||
:public | :guest | false
|
||||
:public | :reporter | true
|
||||
:internal | :anonymous | false
|
||||
:internal | :guest | true
|
||||
:internal | :reporter | true
|
||||
:private | :anonymous | false
|
||||
:private | :guest | true
|
||||
:private | :reporter | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:current_user) { public_send(role) }
|
||||
let(:project) { public_send("#{project_visibility}_project") }
|
||||
|
||||
if params[:allowed]
|
||||
it { is_expected.to be_allowed(policy) }
|
||||
else
|
||||
it { is_expected.not_to be_allowed(policy) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'update_max_artifacts_size' do
|
||||
context 'when no user' do
|
||||
let(:current_user) { anonymous }
|
||||
|
|
|
@ -10,18 +10,6 @@ RSpec.describe Admin::ImpersonationTokensController, :enable_admin_mode do
|
|||
sign_in(admin)
|
||||
end
|
||||
|
||||
context 'when impersonation is enabled' do
|
||||
before do
|
||||
stub_config_setting(impersonation_enabled: true)
|
||||
end
|
||||
|
||||
it 'responds ok' do
|
||||
get admin_user_impersonation_tokens_path(user_id: user.username)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context "when impersonation is disabled" do
|
||||
before do
|
||||
stub_config_setting(impersonation_enabled: false)
|
||||
|
|
|
@ -949,6 +949,41 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with session url set to local URL' do
|
||||
let(:job_params) { { session: { url: 'https://127.0.0.1:7777' } } }
|
||||
|
||||
context 'with allow_local_requests_from_web_hooks_and_services? stubbed' do
|
||||
before do
|
||||
allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
|
||||
stub_application_setting(allow_local_requests_from_web_hooks_and_services: allow_local_requests)
|
||||
ci_build
|
||||
end
|
||||
|
||||
let(:ci_build) { create(:ci_build, :pending, :queued, pipeline: pipeline) }
|
||||
|
||||
context 'as returning true' do
|
||||
let(:allow_local_requests) { true }
|
||||
|
||||
it 'creates a new session' do
|
||||
request_job(**job_params)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as returning false' do
|
||||
let(:allow_local_requests) { false }
|
||||
|
||||
it 'returns :unprocessable_entity status code', :aggregate_failures do
|
||||
request_job(**job_params)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:conflict)
|
||||
expect(response.body).to include('409 Conflict')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def request_job(token = runner.token, **params)
|
||||
new_params = params.merge(token: token, last_update: last_update)
|
||||
post api('/jobs/request'), params: new_params.to_json, headers: { 'User-Agent' => user_agent, 'Content-Type': 'application/json' }
|
||||
|
|
|
@ -31,5 +31,16 @@ RSpec.describe JiraConnect::UsersController do
|
|||
expect(response.body).not_to include('Return to GitLab')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a script injected' do
|
||||
let(:return_to) { 'javascript://test.atlassian.net/%250dalert(document.domain)' }
|
||||
|
||||
it 'does not include a return url' do
|
||||
get '/-/jira_connect/users', params: { return_to: return_to }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response.body).not_to include('Return to GitLab')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ErrorTracking::ListProjectsService do
|
||||
RSpec.describe ErrorTracking::ListProjectsService, feature_category: :integrations do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project, reload: true) { create(:project) }
|
||||
|
||||
|
@ -51,7 +51,10 @@ RSpec.describe ErrorTracking::ListProjectsService do
|
|||
end
|
||||
|
||||
context 'masked param token' do
|
||||
let(:params) { ActionController::Parameters.new(token: "*********", api_host: new_api_host) }
|
||||
let(:params) { ActionController::Parameters.new(token: "*********", api_host: api_host) }
|
||||
|
||||
context 'with the current api host' do
|
||||
let(:api_host) { 'https://sentrytest.gitlab.com' }
|
||||
|
||||
before do
|
||||
expect(error_tracking_setting).to receive(:list_sentry_projects)
|
||||
|
@ -63,6 +66,21 @@ RSpec.describe ErrorTracking::ListProjectsService do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with a new api host' do
|
||||
let(:api_host) { new_api_host }
|
||||
|
||||
it 'returns an error' do
|
||||
expect(result[:message]).to start_with('Token is a required field')
|
||||
expect(error_tracking_setting).not_to be_valid
|
||||
expect(error_tracking_setting).not_to receive(:list_sentry_projects)
|
||||
end
|
||||
|
||||
it 'resets the token' do
|
||||
expect { subject.execute }.to change { error_tracking_setting.token }.from(token).to(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid url' do
|
||||
let(:params) do
|
||||
ActionController::Parameters.new(
|
||||
|
|
|
@ -114,5 +114,16 @@ RSpec.describe Packages::Nuget::MetadataExtractionService do
|
|||
|
||||
it { expect { subject }.to raise_error(::Packages::Nuget::MetadataExtractionService::ExtractionError, 'nuspec file too big') }
|
||||
end
|
||||
|
||||
context 'with a corrupted nupkg file with a wrong entry size' do
|
||||
let(:nupkg_fixture_path) { expand_fixture_path('packages/nuget/corrupted_package.nupkg') }
|
||||
let(:expected_error) { "nuspec file has the wrong entry size: entry 'DummyProject.DummyPackage.nuspec' should be 255B, but is larger when inflated." }
|
||||
|
||||
before do
|
||||
allow(Zip::File).to receive(:new).and_return(Zip::File.new(nupkg_fixture_path, false, false))
|
||||
end
|
||||
|
||||
it { expect { subject }.to raise_error(::Packages::Nuget::MetadataExtractionService::ExtractionError, expected_error) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -127,6 +127,41 @@ RSpec.describe Projects::ImportService do
|
|||
project.import_type = 'bitbucket'
|
||||
end
|
||||
|
||||
context 'when importer supports refmap' do
|
||||
before do
|
||||
project.import_type = 'gitea'
|
||||
end
|
||||
|
||||
it 'succeeds if repository fetch as mirror is successful' do
|
||||
expect(project).to receive(:ensure_repository)
|
||||
expect(project.repository).to receive(:fetch_as_mirror).with('https://bitbucket.org/vim/vim.git', refmap: Gitlab::LegacyGithubImport::Importer.refmap, resolved_address: '').and_return(true)
|
||||
expect_next_instance_of(Gitlab::LegacyGithubImport::Importer) do |importer|
|
||||
expect(importer).to receive(:execute).and_return(true)
|
||||
end
|
||||
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsImportService) do |service|
|
||||
expect(service).to receive(:execute).and_return(status: :success)
|
||||
end
|
||||
|
||||
result = subject.execute
|
||||
|
||||
expect(result[:status]).to eq :success
|
||||
end
|
||||
|
||||
it 'fails if repository fetch as mirror fails' do
|
||||
expect(project).to receive(:ensure_repository)
|
||||
expect(project.repository)
|
||||
.to receive(:fetch_as_mirror)
|
||||
.and_raise(Gitlab::Git::CommandError, 'Failed to import the repository /a/b/c')
|
||||
|
||||
result = subject.execute
|
||||
|
||||
expect(result[:status]).to eq :error
|
||||
expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - Failed to import the repository [FILTERED]"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when importer does not support refmap' do
|
||||
it 'succeeds if repository import is successful' do
|
||||
expect(project.repository).to receive(:import_repository).and_return(true)
|
||||
expect_next_instance_of(Gitlab::BitbucketImport::Importer) do |importer|
|
||||
|
@ -145,6 +180,7 @@ RSpec.describe Projects::ImportService do
|
|||
it 'fails if repository import fails' do
|
||||
expect(project.repository)
|
||||
.to receive(:import_repository)
|
||||
.with('https://bitbucket.org/vim/vim.git', resolved_address: '')
|
||||
.and_raise(Gitlab::Git::CommandError, 'Failed to import the repository /a/b/c')
|
||||
|
||||
result = subject.execute
|
||||
|
@ -152,6 +188,7 @@ RSpec.describe Projects::ImportService do
|
|||
expect(result[:status]).to eq :error
|
||||
expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - Failed to import the repository [FILTERED]"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when lfs import fails' do
|
||||
it 'logs the error' do
|
||||
|
@ -287,6 +324,102 @@ RSpec.describe Projects::ImportService do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when DNS rebind protection is disabled' do
|
||||
before do
|
||||
allow(Gitlab::CurrentSettings).to receive(:dns_rebinding_protection_enabled?).and_return(false)
|
||||
project.import_url = "https://example.com/group/project"
|
||||
|
||||
allow(Gitlab::UrlBlocker).to receive(:validate!)
|
||||
.with(project.import_url, ports: Project::VALID_IMPORT_PORTS, schemes: Project::VALID_IMPORT_PROTOCOLS, dns_rebind_protection: false)
|
||||
.and_return([Addressable::URI.parse("https://example.com/group/project"), nil])
|
||||
end
|
||||
|
||||
it 'imports repository with url without additional resolved address' do
|
||||
expect(project.repository).to receive(:import_repository).with('https://example.com/group/project', resolved_address: '').and_return(true)
|
||||
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsImportService) do |service|
|
||||
expect(service).to receive(:execute).and_return(status: :success)
|
||||
end
|
||||
|
||||
result = subject.execute
|
||||
|
||||
expect(result[:status]).to eq(:success)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when DNS rebind protection is enabled' do
|
||||
before do
|
||||
allow(Gitlab::CurrentSettings).to receive(:http_proxy_env?).and_return(false)
|
||||
allow(Gitlab::CurrentSettings).to receive(:dns_rebinding_protection_enabled?).and_return(true)
|
||||
end
|
||||
|
||||
context 'when https url is provided' do
|
||||
before do
|
||||
project.import_url = "https://example.com/group/project"
|
||||
|
||||
allow(Gitlab::UrlBlocker).to receive(:validate!)
|
||||
.with(project.import_url, ports: Project::VALID_IMPORT_PORTS, schemes: Project::VALID_IMPORT_PROTOCOLS, dns_rebind_protection: true)
|
||||
.and_return([Addressable::URI.parse("https://172.16.123.1/group/project"), 'example.com'])
|
||||
end
|
||||
|
||||
it 'imports repository with url and additional resolved address' do
|
||||
expect(project.repository).to receive(:import_repository).with('https://example.com/group/project', resolved_address: '172.16.123.1').and_return(true)
|
||||
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsImportService) do |service|
|
||||
expect(service).to receive(:execute).and_return(status: :success)
|
||||
end
|
||||
|
||||
result = subject.execute
|
||||
|
||||
expect(result[:status]).to eq(:success)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when http url is provided' do
|
||||
before do
|
||||
project.import_url = "http://example.com/group/project"
|
||||
|
||||
allow(Gitlab::UrlBlocker).to receive(:validate!)
|
||||
.with(project.import_url, ports: Project::VALID_IMPORT_PORTS, schemes: Project::VALID_IMPORT_PROTOCOLS, dns_rebind_protection: true)
|
||||
.and_return([Addressable::URI.parse("http://172.16.123.1/group/project"), 'example.com'])
|
||||
end
|
||||
|
||||
it 'imports repository with url and additional resolved address' do
|
||||
expect(project.repository).to receive(:import_repository).with('http://example.com/group/project', resolved_address: '172.16.123.1').and_return(true)
|
||||
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsImportService) do |service|
|
||||
expect(service).to receive(:execute).and_return(status: :success)
|
||||
end
|
||||
|
||||
result = subject.execute
|
||||
|
||||
expect(result[:status]).to eq(:success)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when git address is provided' do
|
||||
before do
|
||||
project.import_url = "git://example.com/group/project.git"
|
||||
|
||||
allow(Gitlab::UrlBlocker).to receive(:validate!)
|
||||
.with(project.import_url, ports: Project::VALID_IMPORT_PORTS, schemes: Project::VALID_IMPORT_PROTOCOLS, dns_rebind_protection: true)
|
||||
.and_return([Addressable::URI.parse("git://172.16.123.1/group/project"), 'example.com'])
|
||||
end
|
||||
|
||||
it 'imports repository with url and without resolved address' do
|
||||
expect(project.repository).to receive(:import_repository).with('git://example.com/group/project.git', resolved_address: '').and_return(true)
|
||||
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsImportService) do |service|
|
||||
expect(service).to receive(:execute).and_return(status: :success)
|
||||
end
|
||||
|
||||
result = subject.execute
|
||||
|
||||
expect(result[:status]).to eq(:success)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'measurable service' do
|
||||
let(:base_log_data) do
|
||||
{
|
||||
|
|
|
@ -77,6 +77,34 @@ RSpec.describe Users::UpdateService do
|
|||
subject
|
||||
end
|
||||
|
||||
context 'when race condition' do
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/382957
|
||||
it 'updates email for stale user', :aggregate_failures do
|
||||
unconfirmed_email = 'unconfirmed-email-user-has-access-to@example.com'
|
||||
forgery_email = 'forgery@example.com'
|
||||
|
||||
user.update!(email: unconfirmed_email)
|
||||
|
||||
stale_user = User.find(user.id)
|
||||
|
||||
service1 = described_class.new(stale_user, { email: unconfirmed_email }.merge(user: stale_user))
|
||||
|
||||
service2 = described_class.new(user, { email: forgery_email }.merge(user: user))
|
||||
|
||||
service2.execute
|
||||
reloaded_user = User.find(user.id)
|
||||
expect(reloaded_user.unconfirmed_email).to eq(forgery_email)
|
||||
expect(stale_user.confirmation_token).not_to eq(user.confirmation_token)
|
||||
expect(reloaded_user.confirmation_token).to eq(user.confirmation_token)
|
||||
|
||||
service1.execute
|
||||
reloaded_user = User.find(user.id)
|
||||
expect(reloaded_user.unconfirmed_email).to eq(unconfirmed_email)
|
||||
expect(stale_user.confirmation_token).not_to eq(user.confirmation_token)
|
||||
expect(reloaded_user.confirmation_token).to eq(stale_user.confirmation_token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when check_password is true' do
|
||||
def update_user(user, opts)
|
||||
described_class.new(user, opts.merge(user: user)).execute(check_password: true)
|
||||
|
@ -139,8 +167,23 @@ RSpec.describe Users::UpdateService do
|
|||
update_user(user, job_title: 'supreme leader of the universe')
|
||||
end.not_to change { user.user_canonical_email }
|
||||
end
|
||||
|
||||
it 'does not reset unconfirmed email' do
|
||||
unconfirmed_email = 'unconfirmed-email@example.com'
|
||||
user.update!(email: unconfirmed_email)
|
||||
|
||||
expect do
|
||||
update_user(user, job_title: 'supreme leader of the universe')
|
||||
end.not_to change { user.unconfirmed_email }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not try to reset unconfirmed email for a new user' do
|
||||
expect do
|
||||
update_user(build(:user), job_title: 'supreme leader of the universe')
|
||||
end.not_to raise_error
|
||||
end
|
||||
|
||||
def update_user(user, opts)
|
||||
described_class.new(user, opts.merge(user: user)).execute
|
||||
|
|
|
@ -129,7 +129,10 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
|
|||
|
||||
context 'there is userinfo' do
|
||||
before do
|
||||
project_hook.update!(url: 'http://{one}:{two}@example.com')
|
||||
project_hook.update!(
|
||||
url: 'http://{one}:{two}@example.com',
|
||||
url_variables: { 'one' => 'a', 'two' => 'b' }
|
||||
)
|
||||
stub_full_request('http://example.com', method: :post)
|
||||
end
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue