diff options
Diffstat (limited to 'lib/api/helpers')
-rw-r--r-- | lib/api/helpers/caching.rb | 107 | ||||
-rw-r--r-- | lib/api/helpers/groups_helpers.rb | 4 | ||||
-rw-r--r-- | lib/api/helpers/integrations_helpers.rb (renamed from lib/api/helpers/services_helpers.rb) | 16 | ||||
-rw-r--r-- | lib/api/helpers/projects_helpers.rb | 2 | ||||
-rw-r--r-- | lib/api/helpers/runner.rb | 4 | ||||
-rw-r--r-- | lib/api/helpers/snippets_helpers.rb | 18 |
6 files changed, 45 insertions, 106 deletions
diff --git a/lib/api/helpers/caching.rb b/lib/api/helpers/caching.rb index f24ac7302c1..f567d85443f 100644 --- a/lib/api/helpers/caching.rb +++ b/lib/api/helpers/caching.rb @@ -8,18 +8,15 @@ module API module Helpers module Caching - # @return [ActiveSupport::Duration] - DEFAULT_EXPIRY = 1.day - + include Gitlab::Cache::Helpers # @return [Hash] DEFAULT_CACHE_OPTIONS = { - race_condition_ttl: 5.seconds + race_condition_ttl: 5.seconds, + version: 1 }.freeze - # @return [ActiveSupport::Cache::Store] - def cache - Rails.cache - end + # @return [Array] + PAGINATION_HEADERS = %w[X-Per-Page X-Page X-Next-Page X-Prev-Page Link X-Total X-Total-Pages].freeze # This is functionally equivalent to the standard `#present` used in # Grape endpoints, but the JSON for the object, or for each object of @@ -45,7 +42,7 @@ module API # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry # @param presenter_args [Hash] keyword arguments to be passed to the entity # @return [Gitlab::Json::PrecompiledJson] - def present_cached(obj_or_collection, with:, cache_context: -> (_) { current_user&.cache_key }, expires_in: DEFAULT_EXPIRY, **presenter_args) + def present_cached(obj_or_collection, with:, cache_context: -> (_) { current_user&.cache_key }, expires_in: Gitlab::Cache::Helpers::DEFAULT_EXPIRY, **presenter_args) json = if obj_or_collection.is_a?(Enumerable) cached_collection( @@ -79,15 +76,22 @@ module API # @param key [Object] any object that can be converted into a cache key # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry # @return [Gitlab::Json::PrecompiledJson] - def cache_action(key, **cache_opts) - json = cache.fetch(key, **apply_default_cache_options(cache_opts)) do + def cache_action(key, **custom_cache_opts) + cache_opts = apply_default_cache_options(custom_cache_opts) + + json, cached_headers = cache.fetch(key, **cache_opts) do response = yield - if response.is_a?(Gitlab::Json::PrecompiledJson) - response.to_s - else - Gitlab::Json.dump(response.as_json) - end + cached_body = response.is_a?(Gitlab::Json::PrecompiledJson) ? response.to_s : Gitlab::Json.dump(response.as_json) + cached_headers = header.slice(*PAGINATION_HEADERS) + + [cached_body, cached_headers] + end + + cached_headers.each do |key, value| + next if header.key?(key) + + header key, value end body Gitlab::Json::PrecompiledJson.new(json) @@ -120,77 +124,6 @@ module API def apply_default_cache_options(opts = {}) DEFAULT_CACHE_OPTIONS.merge(opts) end - - # Optionally uses a `Proc` to add context to a cache key - # - # @param object [Object] must respond to #cache_key - # @param context [Proc] a proc that will be called with the object as an argument, and which should return a - # string or array of strings to be combined into the cache key - # @return [String] - def contextual_cache_key(object, context) - return object.cache_key if context.nil? - - [object.cache_key, context.call(object)].flatten.join(":") - end - - # Used for fetching or rendering a single object - # - # @param object [Object] the object to render - # @param presenter [Grape::Entity] - # @param presenter_args [Hash] keyword arguments to be passed to the entity - # @param context [Proc] - # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry - # @return [String] - def cached_object(object, presenter:, presenter_args:, context:, expires_in:) - cache.fetch(contextual_cache_key(object, context), expires_in: expires_in) do - Gitlab::Json.dump(presenter.represent(object, **presenter_args).as_json) - end - end - - # Used for fetching or rendering multiple objects - # - # @param objects [Enumerable<Object>] the objects to render - # @param presenter [Grape::Entity] - # @param presenter_args [Hash] keyword arguments to be passed to the entity - # @param context [Proc] - # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry - # @return [Array<String>] - def cached_collection(collection, presenter:, presenter_args:, context:, expires_in:) - json = fetch_multi(collection, context: context, expires_in: expires_in) do |obj| - Gitlab::Json.dump(presenter.represent(obj, **presenter_args).as_json) - end - - json.values - end - - # An adapted version of ActiveSupport::Cache::Store#fetch_multi. - # - # The original method only provides the missing key to the block, - # not the missing object, so we have to create a map of cache keys - # to the objects to allow us to pass the object to the missing value - # block. - # - # The result is that this is functionally identical to `#fetch`. - def fetch_multi(*objs, context:, **kwargs) - objs.flatten! - map = multi_key_map(objs, context: context) - - # TODO: `contextual_cache_key` should be constructed based on the guideline https://docs.gitlab.com/ee/development/redis.html#multi-key-commands. - Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do - cache.fetch_multi(*map.keys, **kwargs) do |key| - yield map[key] - end - end - end - - # @param objects [Enumerable<Object>] objects which _must_ respond to `#cache_key` - # @param context [Proc] a proc that can be called to help generate each cache key - # @return [Hash] - def multi_key_map(objects, context:) - objects.index_by do |object| - contextual_cache_key(object, context) - end - end end end end diff --git a/lib/api/helpers/groups_helpers.rb b/lib/api/helpers/groups_helpers.rb index 5c5109f3d21..e38213532ba 100644 --- a/lib/api/helpers/groups_helpers.rb +++ b/lib/api/helpers/groups_helpers.rb @@ -30,6 +30,10 @@ module API params :optional_params_ee do end + params :optional_update_params do + optional :prevent_sharing_groups_outside_hierarchy, type: Boolean, desc: 'Prevent sharing groups within this namespace with any groups outside the namespace. Only available on top-level groups.' + end + params :optional_update_params_ee do end diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/integrations_helpers.rb index ca13ea0789a..06539772568 100644 --- a/lib/api/helpers/services_helpers.rb +++ b/lib/api/helpers/integrations_helpers.rb @@ -6,7 +6,7 @@ module API # # The data structures inside this model are returned using class methods, # allowing EE to extend them where necessary. - module ServicesHelpers + module IntegrationsHelpers def self.chat_notification_settings [ { @@ -159,7 +159,7 @@ module API ].freeze end - def self.services + def self.integrations { 'asana' => [ { @@ -772,7 +772,7 @@ module API } end - def self.service_classes + def self.integration_classes [ ::Integrations::Asana, ::Integrations::Assembla, @@ -799,24 +799,24 @@ module API ::Integrations::Packagist, ::Integrations::PipelinesEmail, ::Integrations::Pivotaltracker, + ::Integrations::Prometheus, ::Integrations::Pushover, ::Integrations::Redmine, ::Integrations::Slack, ::Integrations::SlackSlashCommands, ::Integrations::Teamcity, - ::Integrations::Youtrack, - ::PrometheusService + ::Integrations::Youtrack ] end - def self.development_service_classes + def self.development_integration_classes [ ::Integrations::MockCi, - ::MockMonitoringService + ::Integrations::MockMonitoring ] end end end end -API::Helpers::ServicesHelpers.prepend_mod_with('API::Helpers::ServicesHelpers') +API::Helpers::IntegrationsHelpers.prepend_mod_with('API::Helpers::IntegrationsHelpers') diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index 69a83043617..272452bd8db 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -66,6 +66,7 @@ module API optional :autoclose_referenced_issues, type: Boolean, desc: 'Flag indication if referenced issues auto-closing is enabled' optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins' optional :packages_enabled, type: Boolean, desc: 'Enable project packages feature' + optional :squash_option, type: String, values: %w(never always default_on default_off), desc: 'Squash default for project. One of `never`, `always`, `default_on`, or `default_off`.' end params :optional_project_params_ee do @@ -145,6 +146,7 @@ module API :request_access_enabled, :resolve_outdated_diff_discussions, :restrict_user_defined_variables, + :squash_option, :shared_runners_enabled, :snippets_access_level, :tag_list, diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb index 9ec9b5e1e35..a022d1a56ac 100644 --- a/lib/api/helpers/runner.rb +++ b/lib/api/helpers/runner.rb @@ -14,6 +14,10 @@ module API ActiveSupport::SecurityUtils.secure_compare(params[:token], Gitlab::CurrentSettings.runners_registration_token) end + def runner_registrar_valid?(type) + Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?(type) + end + def authenticate_runner! forbidden! unless current_runner diff --git a/lib/api/helpers/snippets_helpers.rb b/lib/api/helpers/snippets_helpers.rb index 42f56680ded..2d8c761101a 100644 --- a/lib/api/helpers/snippets_helpers.rb +++ b/lib/api/helpers/snippets_helpers.rb @@ -72,22 +72,18 @@ module API end def process_create_params(args) - with_api_params do |api_params| - args[:snippet_actions] = args.delete(:files)&.map do |file| - file[:action] = :create - file.symbolize_keys - end - - args.merge(api_params) + args[:snippet_actions] = args.delete(:files)&.map do |file| + file[:action] = :create + file.symbolize_keys end + + args end def process_update_params(args) - with_api_params do |api_params| - args[:snippet_actions] = args.delete(:files)&.map(&:symbolize_keys) + args[:snippet_actions] = args.delete(:files)&.map(&:symbolize_keys) - args.merge(api_params) - end + args end def validate_params_for_multiple_files(snippet) |