diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-01 00:10:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-01 00:10:43 +0300 |
commit | d9115c777949c14b7e12332f85fe99b100af2aeb (patch) | |
tree | 34f094a0bdb519787adafa54d58075188a30b7b5 /app | |
parent | 34d6e7c91beed4420759ce5a8e1e9607db8f9c45 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue | 13 | ||||
-rw-r--r-- | app/controllers/jira_connect/app_descriptor_controller.rb | 8 | ||||
-rw-r--r-- | app/controllers/jira_connect/application_controller.rb | 24 | ||||
-rw-r--r-- | app/controllers/jira_connect/subscriptions_controller.rb | 6 | ||||
-rw-r--r-- | app/controllers/projects/pipelines_controller.rb | 9 | ||||
-rw-r--r-- | app/controllers/users_controller.rb | 7 | ||||
-rw-r--r-- | app/finders/ci/pipelines_finder.rb | 3 | ||||
-rw-r--r-- | app/helpers/integrations_helper.rb | 2 | ||||
-rw-r--r-- | app/models/design_management/design.rb | 2 | ||||
-rw-r--r-- | app/models/integrations/datadog.rb | 9 | ||||
-rw-r--r-- | app/models/jira_connect_installation.rb | 4 | ||||
-rw-r--r-- | app/services/groups/destroy_service.rb | 35 | ||||
-rw-r--r-- | app/services/jira_connect_subscriptions/create_service.rb | 7 | ||||
-rw-r--r-- | app/services/resource_access_tokens/create_service.rb | 2 |
14 files changed, 81 insertions, 50 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue index 0b70e74b8ff..2dfdaa0ea28 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue @@ -39,7 +39,7 @@ export default { return this.value.map((i) => i.type); }, tokens() { - const tokens = [ + return [ { type: this.$options.userType, icon: 'user', @@ -77,20 +77,15 @@ export default { token: PipelineStatusToken, operators: OPERATOR_IS_ONLY, }, - ]; - - if (gon.features.pipelineSourceFilter) { - tokens.push({ + { type: this.$options.sourceType, icon: 'trigger-source', title: s__('Pipeline|Source'), unique: true, token: PipelineSourceToken, operators: OPERATOR_IS_ONLY, - }); - } - - return tokens; + }, + ]; }, parsedParams() { return map(this.params, (val, key) => ({ diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb index a0f387631dd..74fac6ff9bb 100644 --- a/app/controllers/jira_connect/app_descriptor_controller.rb +++ b/app/controllers/jira_connect/app_descriptor_controller.rb @@ -47,7 +47,13 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController postInstallPage: { key: 'gitlab-configuration', name: { value: 'GitLab Configuration' }, - url: relative_to_base_path(jira_connect_subscriptions_path) + url: relative_to_base_path(jira_connect_subscriptions_path), + conditions: [ + { + condition: 'user_is_admin', + invert: false + } + ] } } diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb index a6529ecb4ce..352e78d6255 100644 --- a/app/controllers/jira_connect/application_controller.rb +++ b/app/controllers/jira_connect/application_controller.rb @@ -38,12 +38,30 @@ class JiraConnect::ApplicationController < ApplicationController end def installation_from_jwt - return unless auth_token - strong_memoize(:installation_from_jwt) do + next unless claims['iss'] + + JiraConnectInstallation.find_by_client_key(claims['iss']) + end + end + + def claims + strong_memoize(:claims) do + next {} unless auth_token + # Decode without verification to get `client_key` in `iss` payload, _ = Atlassian::Jwt.decode(auth_token, nil, false) - JiraConnectInstallation.find_by_client_key(payload['iss']) + payload + end + end + + def jira_user + strong_memoize(:jira_user) do + next unless installation_from_jwt + next unless claims['sub'] + + # This only works for Jira Cloud installations. + installation_from_jwt.client.user_info(claims['sub']) end end diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb index a9c4dbf2b17..903ad395e44 100644 --- a/app/controllers/jira_connect/subscriptions_controller.rb +++ b/app/controllers/jira_connect/subscriptions_controller.rb @@ -44,7 +44,9 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController def destroy subscription = current_jira_installation.subscriptions.find(params[:id]) - if subscription.destroy + if !jira_user&.site_admin? + render json: { error: 'forbidden' }, status: :forbidden + elsif subscription.destroy render json: { success: true } else render json: { error: subscription.errors.full_messages.join(', ') }, status: :unprocessable_entity @@ -54,7 +56,7 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController private def create_service - JiraConnectSubscriptions::CreateService.new(current_jira_installation, current_user, namespace_path: params['namespace_path']) + JiraConnectSubscriptions::CreateService.new(current_jira_installation, current_user, namespace_path: params['namespace_path'], jira_user: jira_user) end def allow_rendering_in_iframe diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 33d7eb4a09e..9ad342f3936 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -14,10 +14,6 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :ensure_pipeline, only: [:show, :downloadable_artifacts] - before_action do - push_frontend_feature_flag(:pipeline_source_filter, project, type: :development, default_enabled: :yaml) - end - # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596 before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? } @@ -297,10 +293,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def index_params - permitted_params = [:scope, :username, :ref, :status] - permitted_params << :source if Feature.enabled?(:pipeline_source_filter, project, default_enabled: :yaml) - - params.permit(*permitted_params) + params.permit(:scope, :username, :ref, :status, :source) end def enable_code_quality_walkthrough_experiment diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a089f600bd8..26f56307862 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -20,7 +20,7 @@ class UsersController < ApplicationController skip_before_action :authenticate_user! prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } - before_action :user, except: [:exists, :ssh_keys] + before_action :user, except: [:exists] before_action :authorize_read_user_profile!, only: [:calendar, :calendar_activities, :groups, :projects, :contributed, :starred, :snippets, :followers, :following] @@ -44,12 +44,7 @@ class UsersController < ApplicationController # Get all keys of a user(params[:username]) in a text format # Helpful for sysadmins to put in respective servers - # - # Uses `UserFinder` rather than `find_routable!` because this endpoint should - # be publicly available regardless of instance visibility settings. def ssh_keys - user = UserFinder.new(params[:username]).find_by_username - render plain: user.all_ssh_keys.join("\n") end diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb index a79840216da..37168ae9e5b 100644 --- a/app/finders/ci/pipelines_finder.rb +++ b/app/finders/ci/pipelines_finder.rb @@ -29,8 +29,7 @@ module Ci items = by_username(items) items = by_yaml_errors(items) items = by_updated_at(items) - - items = by_source(items) if Feature.enabled?(:pipeline_source_filter, project, default_enabled: :yaml) + items = by_source(items) sort_items(items) end diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb index f15566a551a..904508867d3 100644 --- a/app/helpers/integrations_helper.rb +++ b/app/helpers/integrations_helper.rb @@ -137,7 +137,7 @@ module IntegrationsHelper def jira_issue_breadcrumb_link(issue_reference) link_to '', { class: 'gl-display-flex gl-align-items-center gl-white-space-nowrap' } do icon = image_tag image_path('illustrations/logos/jira.svg'), width: 15, height: 15, class: 'gl-mr-2' - [icon, issue_reference].join.html_safe + [icon, html_escape(issue_reference)].join.html_safe end end diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb index 79f5a63bcb6..feb1bf5438c 100644 --- a/app/models/design_management/design.rb +++ b/app/models/design_management/design.rb @@ -169,7 +169,7 @@ module DesignManagement @link_reference_pattern ||= begin path_segment = %r{issues/#{Gitlab::Regex.issue}/designs} ext = Regexp.new(Regexp.union(SAFE_IMAGE_EXT + DANGEROUS_IMAGE_EXT).source, Regexp::IGNORECASE) - valid_char = %r{[^/\s]} # any char that is not a forward slash or whitespace + valid_char = %r{[[:word:]\.\-\+]} filename_pattern = %r{ (?<url_filename> #{valid_char}+ \. #{ext}) }x diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb index 5516e6bc2c0..6422f6bddab 100644 --- a/app/models/integrations/datadog.rb +++ b/app/models/integrations/datadog.rb @@ -8,7 +8,6 @@ module Integrations DEFAULT_DOMAIN = 'datadoghq.com' URL_TEMPLATE = 'https://webhooks-http-intake.logs.%{datadog_domain}/api/v2/webhook' - URL_TEMPLATE_API_KEYS = 'https://app.%{datadog_domain}/account/settings#api' URL_API_KEYS_DOCS = "https://docs.#{DEFAULT_DOMAIN}/account_management/api-app-keys/" SUPPORTED_EVENTS = %w[ @@ -90,7 +89,7 @@ module Integrations help: ERB::Util.html_escape( s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.') ) % { - linkOpen: '<a href="%s" target="_blank" rel="noopener noreferrer">'.html_safe % api_keys_url, + linkOpen: %Q{<a href="#{URL_API_KEYS_DOCS}" target="_blank" rel="noopener noreferrer">}.html_safe, linkClose: '</a>'.html_safe }, required: true @@ -132,12 +131,6 @@ module Integrations url.to_s end - def api_keys_url - return URL_API_KEYS_DOCS unless datadog_site.presence - - sprintf(URL_TEMPLATE_API_KEYS, datadog_domain: datadog_domain) - end - def execute(data) object_kind = data[:object_kind] object_kind = 'job' if object_kind == 'build' diff --git a/app/models/jira_connect_installation.rb b/app/models/jira_connect_installation.rb index 759d44fb29e..e34543534f3 100644 --- a/app/models/jira_connect_installation.rb +++ b/app/models/jira_connect_installation.rb @@ -20,4 +20,8 @@ class JiraConnectInstallation < ApplicationRecord id: JiraConnectSubscription.for_project(project) }) } + + def client + Atlassian::JiraConnect::Client.new(base_url, shared_secret) + end end diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb index 08c4e0231e7..5ffa746e109 100644 --- a/app/services/groups/destroy_service.rb +++ b/app/services/groups/destroy_service.rb @@ -29,14 +29,7 @@ module Groups group.chat_team&.remove_mattermost_team(current_user) - # If any other groups are shared with the group that is being destroyed, - # we should specifically trigger update of all project authorizations - # for users that are the direct members of this group. - # If not, the project authorization records of these users to projects within the shared groups - # will never be removed, causing inconsistencies with access permissions. - if any_other_groups_are_shared_with_this_group? - user_ids_for_project_authorizations_refresh = group.users_ids_of_direct_members - end + user_ids_for_project_authorizations_refresh = obtain_user_ids_for_project_authorizations_refresh group.destroy @@ -52,9 +45,33 @@ module Groups private - def any_other_groups_are_shared_with_this_group? + def any_groups_shared_with_this_group? group.shared_group_links.any? end + + def any_projects_shared_with_this_group? + group.project_group_links.any? + end + + # Destroying a group automatically destroys all project authorizations directly + # associated with the group and descendents. However, project authorizations + # for projects and groups this group is shared with are not. Without a manual + # refresh, the project authorization records of these users to shared projects + # and projects within the shared groups will never be removed, causing + # inconsistencies with access permissions. + # + # This method retrieves the user IDs that need to be refreshed. If only + # groups are shared with this group, only direct members need to be refreshed. + # If projects are also shared with the group, direct members *and* shared + # members of other groups need to be refreshed. + # `Group#user_ids_for_project_authorizations` returns both direct and shared + # members' user IDs. + def obtain_user_ids_for_project_authorizations_refresh + return unless any_projects_shared_with_this_group? || any_groups_shared_with_this_group? + return group.user_ids_for_project_authorizations if any_projects_shared_with_this_group? + + group.users_ids_of_direct_members + end end end diff --git a/app/services/jira_connect_subscriptions/create_service.rb b/app/services/jira_connect_subscriptions/create_service.rb index 38e5fe7e690..2f31a3c8d4e 100644 --- a/app/services/jira_connect_subscriptions/create_service.rb +++ b/app/services/jira_connect_subscriptions/create_service.rb @@ -5,8 +5,11 @@ module JiraConnectSubscriptions include Gitlab::Utils::StrongMemoize MERGE_REQUEST_SYNC_BATCH_SIZE = 20 MERGE_REQUEST_SYNC_BATCH_DELAY = 1.minute.freeze + NOT_SITE_ADMIN = 'The Jira user is not a site administrator.' def execute + return error(NOT_SITE_ADMIN, 403) unless can_administer_jira? + unless namespace && can?(current_user, :create_jira_connect_subscription, namespace) return error('Invalid namespace. Please make sure you have sufficient permissions', 401) end @@ -16,6 +19,10 @@ module JiraConnectSubscriptions private + def can_administer_jira? + @params[:jira_user]&.site_admin? + end + def create_subscription subscription = JiraConnectSubscription.new(installation: jira_connect_installation, namespace: namespace) diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb index 34aa414de8f..e0371e5d80f 100644 --- a/app/services/resource_access_tokens/create_service.rb +++ b/app/services/resource_access_tokens/create_service.rb @@ -16,6 +16,8 @@ module ResourceAccessTokens return error(user.errors.full_messages.to_sentence) unless user.persisted? + user.update!(external: true) if current_user.external? + access_level = params[:access_level] || Gitlab::Access::MAINTAINER member = create_membership(resource, user, access_level) |