diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/concerns/page_limiter.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/grafana_api_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/uploads_controller.rb | 2 | ||||
-rw-r--r-- | app/helpers/submodule_helper.rb | 78 | ||||
-rw-r--r-- | app/models/active_session.rb | 2 | ||||
-rw-r--r-- | app/models/hooks/web_hook.rb | 5 | ||||
-rw-r--r-- | app/policies/group_policy.rb | 9 | ||||
-rw-r--r-- | app/policies/project_policy.rb | 13 | ||||
-rw-r--r-- | app/services/error_tracking/list_projects_service.rb | 16 | ||||
-rw-r--r-- | app/services/users/update_service.rb | 8 | ||||
-rw-r--r-- | app/views/devise/mailer/_confirmation_instructions_account.html.haml | 2 | ||||
-rw-r--r-- | app/views/devise/mailer/_confirmation_instructions_account.text.erb | 2 |
12 files changed, 97 insertions, 44 deletions
diff --git a/app/controllers/concerns/page_limiter.rb b/app/controllers/concerns/page_limiter.rb index 1d044a41899..97df540d31b 100644 --- a/app/controllers/concerns/page_limiter.rb +++ b/app/controllers/concerns/page_limiter.rb @@ -58,7 +58,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], diff --git a/app/controllers/projects/grafana_api_controller.rb b/app/controllers/projects/grafana_api_controller.rb index d5099367873..9cd511f6a11 100644 --- a/app/controllers/projects/grafana_api_controller.rb +++ b/app/controllers/projects/grafana_api_controller.rb @@ -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 diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 09419a4589d..66f715f32af 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -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 diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb index e3e2f423da3..c38d69df8e4 100644 --- a/app/helpers/submodule_helper.rb +++ b/app/helpers/submodule_helper.rb @@ -17,40 +17,26 @@ 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] - - gitlab_hosts.each do |host| - if url.start_with?(host) - namespace, _, project = url.sub(host, '').rpartition('/') - break - end - end - - namespace.delete_prefix!('/') - project.rstrip! - project.delete_suffix!('.git') - - if self_url?(url, namespace, project) - [ - url_helpers.namespace_project_path(namespace, project), - url_helpers.namespace_project_tree_path(namespace, project, submodule_item_id), - (url_helpers.namespace_project_compare_path(namespace, project, to: submodule_item_id, from: old_submodule_item_id) if old_submodule_item_id) - ] - elsif relative_self_url?(url) - relative_self_links(url, submodule_item_id, old_submodule_item_id, repository.project) - elsif gist_github_dot_com_url?(url) - gist_github_com_tree_links(namespace, project, submodule_item_id) - elsif github_dot_com_url?(url) - github_com_tree_links(namespace, project, submodule_item_id, old_submodule_item_id) - elsif gitlab_dot_com_url?(url) - gitlab_com_tree_links(namespace, project, submodule_item_id, old_submodule_item_id) - else - [sanitize_submodule_url(url), nil, nil] - end + namespace, project = extract_namespace_project(url) + + if namespace.blank? || project.blank? + return [sanitize_submodule_url(url), nil, nil] + end + + if self_url?(url, namespace, project) + [ + url_helpers.namespace_project_path(namespace, project), + url_helpers.namespace_project_tree_path(namespace, project, submodule_item_id), + (url_helpers.namespace_project_compare_path(namespace, project, to: submodule_item_id, from: old_submodule_item_id) if old_submodule_item_id) + ] + elsif relative_self_url?(url) + relative_self_links(url, submodule_item_id, old_submodule_item_id, repository.project) + elsif gist_github_dot_com_url?(url) + gist_github_com_tree_links(namespace, project, submodule_item_id) + elsif github_dot_com_url?(url) + github_com_tree_links(namespace, project, submodule_item_id, old_submodule_item_id) + elsif gitlab_dot_com_url?(url) + gitlab_com_tree_links(namespace, project, submodule_item_id, old_submodule_item_id) else [sanitize_submodule_url(url), nil, nil] end @@ -58,6 +44,30 @@ module SubmoduleHelper 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 diff --git a/app/models/active_session.rb b/app/models/active_session.rb index b16c4a2b353..2d1dec1977d 100644 --- a/app/models/active_session.rb +++ b/app/models/active_session.rb @@ -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 diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 189291a38ec..49418cda3ac 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -41,6 +41,7 @@ class WebHook < ApplicationRecord after_initialize :initialize_url_variables before_validation :reset_token + before_validation :reset_url_variables, unless: ->(hook) { hook.is_a?(ServiceHook) } before_validation :set_branch_filter_nil, if: :branch_filter_strategy_all_branches? validates :push_events_branch_filter, untrusted_regexp: true, if: :branch_filter_strategy_regex? validates :push_events_branch_filter, "web_hooks/wildcard_branch_filter": true, if: :branch_filter_strategy_wildcard? @@ -213,6 +214,10 @@ class WebHook < ApplicationRecord 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 next_failure_count recent_failures.succ.clamp(1, MAX_FAILURES) end diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 858c145de3f..8eea995529c 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -273,6 +273,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 @@ -338,12 +341,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 diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 7f67e80e432..fd3dbb54d57 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -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 @@ -308,6 +310,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 @@ -340,6 +344,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 @@ -919,12 +924,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 diff --git a/app/services/error_tracking/list_projects_service.rb b/app/services/error_tracking/list_projects_service.rb index 2f23d47029c..d52306ef805 100644 --- a/app/services/error_tracking/list_projects_service.rb +++ b/app/services/error_tracking/list_projects_service.rb @@ -2,6 +2,8 @@ module ErrorTracking class ListProjectsService < ErrorTracking::BaseService + MASKED_TOKEN_REGEX = /\A\*+\z/.freeze + private def perform @@ -20,23 +22,31 @@ module ErrorTracking def project_error_tracking_setting (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 strong_memoize_attr :project_error_tracking_setting - 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 diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb index cb2711b6fee..96018db5974 100644 --- a/app/services/users/update_service.rb +++ b/app/services/users/update_service.rb @@ -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 diff --git a/app/views/devise/mailer/_confirmation_instructions_account.html.haml b/app/views/devise/mailer/_confirmation_instructions_account.html.haml index 9d469ff6e7b..c1655818770 100644 --- a/app/views/devise/mailer/_confirmation_instructions_account.html.haml +++ b/app/views/devise/mailer/_confirmation_instructions_account.html.haml @@ -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 diff --git a/app/views/devise/mailer/_confirmation_instructions_account.text.erb b/app/views/devise/mailer/_confirmation_instructions_account.text.erb index e6da78e3a3d..7e4f38885f6 100644 --- a/app/views/devise/mailer/_confirmation_instructions_account.text.erb +++ b/app/views/devise/mailer/_confirmation_instructions_account.text.erb @@ -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? %> |