Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-06 06:07:26 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-06 06:07:26 +0300
commit5e448ff06309854c838fb5eaa46fd05ebc5218ab (patch)
tree0fd59db933c6f11053028559a8f6fc2e2b050f6e /app
parentbdad4dd5dabec7a0a611d5241fa2d56359884420 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/controllers/graphql_controller.rb36
-rw-r--r--app/graphql/cached_introspection_query.rb107
-rw-r--r--app/models/integration.rb7
-rw-r--r--app/models/project.rb23
4 files changed, 168 insertions, 5 deletions
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index ff4fce9ad1e..11ac641419f 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -12,6 +12,9 @@ class GraphqlController < ApplicationController
# Max size of the query text in characters
MAX_QUERY_SIZE = 10_000
+ # The query string of a standard IntrospectionQuery, used to compare incoming requests for caching
+ CACHED_INTROSPECTION_QUERY_STRING = CachedIntrospectionQuery.query_string
+
# If a user is using their session to access GraphQL, we need to have session
# storage, since the admin-mode check is session wide.
# We can't enable this for anonymous users because that would cause users using
@@ -54,7 +57,12 @@ class GraphqlController < ApplicationController
urgency :low, [:execute]
def execute
- result = multiplex? ? execute_multiplex : execute_query
+ result = if Feature.enabled?(:cache_introspection_query) && params[:operationName] == 'IntrospectionQuery'
+ execute_introspection_query
+ else
+ multiplex? ? execute_multiplex : execute_query
+ end
+
render json: result
end
@@ -259,4 +267,30 @@ class GraphqlController < ApplicationController
def logs
RequestStore.store[:graphql_logs].to_a
end
+
+ def execute_introspection_query
+ if introspection_query_can_use_cache?
+ # Context for caching: https://gitlab.com/gitlab-org/gitlab/-/issues/409448
+ Rails.cache.fetch(
+ introspection_query_cache_key,
+ expires_in: 1.day) do
+ execute_query.to_json
+ end
+ else
+ execute_query
+ end
+ end
+
+ def introspection_query_can_use_cache?
+ graphql_query = GraphQL::Query.new(GitlabSchema, query: query, variables: build_variables(params[:variables]))
+
+ CACHED_INTROSPECTION_QUERY_STRING == graphql_query.query_string.squish
+ end
+
+ def introspection_query_cache_key
+ # We use context[:remove_deprecated] here as an introspection query result can differ based on the
+ # visibility of schema items. Visibility can be affected by the remove_deprecated param. For more context, see:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/409448#note_1377558096
+ ['introspection-query-cache', Gitlab.revision, context[:remove_deprecated]]
+ end
end
diff --git a/app/graphql/cached_introspection_query.rb b/app/graphql/cached_introspection_query.rb
new file mode 100644
index 00000000000..f2b98426714
--- /dev/null
+++ b/app/graphql/cached_introspection_query.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+module CachedIntrospectionQuery
+ def self.query_string
+ <<~QUERY.squish
+ query IntrospectionQuery {
+ __schema {
+ queryType {
+ name
+ }
+ mutationType {
+ name
+ }
+ subscriptionType {
+ name
+ }
+ types {
+ ...FullType
+ }
+ directives {
+ name
+ description
+ locations
+ args {
+ ...InputValue
+ }
+ }
+ }
+ }
+
+ fragment FullType on __Type {
+ kind
+ name
+ description
+ fields(includeDeprecated: true) {
+ name
+ description
+ args {
+ ...InputValue
+ }
+ type {
+ ...TypeRef
+ }
+ isDeprecated
+ deprecationReason
+ }
+ inputFields {
+ ...InputValue
+ }
+ interfaces {
+ ...TypeRef
+ }
+ enumValues(includeDeprecated: true) {
+ name
+ description
+ isDeprecated
+ deprecationReason
+ }
+ possibleTypes {
+ ...TypeRef
+ }
+ }
+
+ fragment InputValue on __InputValue {
+ name
+ description
+ type {
+ ...TypeRef
+ }
+ defaultValue
+ }
+
+ fragment TypeRef on __Type {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ ofType {
+ kind
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ QUERY
+ end
+end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 43e923511bb..fa3a47f8936 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -28,7 +28,7 @@ class Integration < ApplicationRecord
# TODO Shimo is temporary disabled on group and instance-levels.
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/345677
PROJECT_SPECIFIC_INTEGRATION_NAMES = %w[
- apple_app_store google_play jenkins shimo
+ apple_app_store gitlab_slack_application google_play jenkins shimo
].freeze
# Fake integrations to help with local development.
@@ -282,7 +282,6 @@ class Integration < ApplicationRecord
# Returns a list of available integration names.
# Example: ["asana", ...]
- # @deprecated
def self.available_integration_names(include_project_specific: true, include_dev: true)
names = integration_names
names += project_specific_integration_names if include_project_specific
@@ -302,7 +301,9 @@ class Integration < ApplicationRecord
end
def self.project_specific_integration_names
- PROJECT_SPECIFIC_INTEGRATION_NAMES
+ names = PROJECT_SPECIFIC_INTEGRATION_NAMES.dup
+ names.delete('gitlab_slack_application') unless Gitlab::CurrentSettings.slack_app_enabled || Rails.env.test?
+ names
end
# Returns a list of available integration types.
diff --git a/app/models/project.rb b/app/models/project.rb
index 05e61e70853..e5278f7f1ea 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -195,6 +195,7 @@ class Project < ApplicationRecord
has_one :emails_on_push_integration, class_name: 'Integrations::EmailsOnPush'
has_one :ewm_integration, class_name: 'Integrations::Ewm'
has_one :external_wiki_integration, class_name: 'Integrations::ExternalWiki'
+ has_one :gitlab_slack_application_integration, class_name: 'Integrations::GitlabSlackApplication'
has_one :google_play_integration, class_name: 'Integrations::GooglePlay'
has_one :hangouts_chat_integration, class_name: 'Integrations::HangoutsChat'
has_one :harbor_integration, class_name: 'Integrations::Harbor'
@@ -796,6 +797,20 @@ class Project < ApplicationRecord
preload(:project_feature, :route, :creator, group: :parent, namespace: [:route, :owner])
end
+ def self.with_slack_application_disabled
+ # Using Arel to avoid exposing what the column backing the type: attribute is
+ # rubocop: disable GitlabSecurity/PublicSend
+ with_active_slack = Integration.active.by_name(:gitlab_slack_application)
+ join_contraint = arel_table[:id].eq(Integration.arel_table[:project_id])
+ constraint = with_active_slack.where_clause.send(:predicates).reduce(join_contraint) { |a, b| a.and(b) }
+ join = arel_table.join(Integration.arel_table, Arel::Nodes::OuterJoin).on(constraint).join_sources
+ # rubocop: enable GitlabSecurity/PublicSend
+
+ joins(join).where(integrations: { id: nil })
+ rescue Integration::UnknownType
+ all
+ end
+
def self.eager_load_namespace_and_owner
includes(namespace: :owner)
end
@@ -1707,7 +1722,13 @@ class Project < ApplicationRecord
end
def disabled_integrations
- %w[shimo zentao]
+ return [] if Rails.env.development?
+
+ names = %w[shimo zentao]
+
+ # The Slack Slash Commands integration is only available for customers who cannot use the GitLab for Slack app.
+ # The GitLab for Slack app integration is only available when enabled through settings.
+ names << (Gitlab::CurrentSettings.slack_app_enabled ? 'slack_slash_commands' : 'gitlab_slack_application')
end
def find_or_initialize_integration(name)