From 0ab0f558209abba729d34f8c1dad3205ce56915c Mon Sep 17 00:00:00 2001 From: Pierre Millot Date: Wed, 12 Jun 2024 10:21:03 +0200 Subject: [PATCH] feat(clients): add generate_secured_api_key to ruby --- .../lib/algolia/transport/transport.rb | 16 +++---- templates/ruby/api.mustache | 5 ++ templates/ruby/search_helpers.mustache | 48 +++++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/clients/algoliasearch-client-ruby/lib/algolia/transport/transport.rb b/clients/algoliasearch-client-ruby/lib/algolia/transport/transport.rb index 447432a2e2..a49274905a 100644 --- a/clients/algoliasearch-client-ruby/lib/algolia/transport/transport.rb +++ b/clients/algoliasearch-client-ruby/lib/algolia/transport/transport.rb @@ -9,6 +9,13 @@ def self.encode_uri(uri) CGI.escape(uri).gsub('+', '%20') end + def self.stringify_query_params(query_params) + query_params.to_h do |key, value| + value = value.join(',') if value.is_a?(Array) + [encode_uri(key.to_s).to_sym, encode_uri(value.to_s)] + end + end + class Transport include RetryOutcomeType include CallType @@ -79,7 +86,7 @@ def build_request(method, path, body, request_options) request[:method] = method.downcase request[:path] = path request[:body] = build_body(body, request_options) - request[:query_params] = stringify_query_params(request_options.query_params) + request[:query_params] = Algolia::Transport.stringify_query_params(request_options.query_params) request[:header_params] = generate_header_params(body, request_options) request[:timeout] = request_options.timeout request[:connect_timeout] = request_options.connect_timeout @@ -128,13 +135,6 @@ def get_timeout(call_type) @config.write_timeout end end - - def stringify_query_params(query_params) - query_params.to_h do |key, value| - value = value.join(',') if value.is_a?(Array) - [Algolia::Transport.encode_uri(key.to_s).to_sym, Algolia::Transport.encode_uri(value.to_s)] - end - end end end end diff --git a/templates/ruby/api.mustache b/templates/ruby/api.mustache index 97a55758b4..c7d6d81f05 100644 --- a/templates/ruby/api.mustache +++ b/templates/ruby/api.mustache @@ -1,5 +1,10 @@ # {{{generationBanner}}} +{{#isSearchClient}} +require 'openssl' +require 'base64' +{{/isSearchClient}} + module {{moduleName}} {{#operations}} class {{classname}} diff --git a/templates/ruby/search_helpers.mustache b/templates/ruby/search_helpers.mustache index 6433ac8bdf..1365ed44dd 100644 --- a/templates/ruby/search_helpers.mustache +++ b/templates/ruby/search_helpers.mustache @@ -157,3 +157,51 @@ def browse_synonyms(index_name, search_synonyms_params = Search::SearchSynonymsP synonyms unless block_given? end + +# Helper: Generates a secured API key based on the given `parent_api_key` and given `restrictions`. +# +# @param parent_api_key [String] Parent API key used the generate the secured key +# @param restrictions [SecuredApiKeyRestrictions] Restrictions to apply on the secured key +# +# @return [String] +# +def generate_secured_api_key(parent_api_key, restrictions = {}) + restrictions = restrictions.to_hash + if restrictions.key?(:searchParams) + # merge searchParams with the root of the restrictions + + restrictions.merge!(restrictions[:searchParams]) + restrictions.delete(:searchParams) + end + + url_encoded_restrictions = Algolia::Transport.stringify_query_params(restrictions).sort.to_h.map do |key, value| + "#{key}=#{value}" + end.join('&') + + hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), parent_api_key, url_encoded_restrictions) + + puts "hmac: #{hmac}" + puts "url_encoded_restrictions: #{url_encoded_restrictions}" + Base64.encode64("#{hmac}#{url_encoded_restrictions}").gsub("\n", '') +end + +# Helper: Retrieves the remaining validity of the previous generated `secured_api_key`, the `validUntil` parameter must have been provided. +# +# @param secured_api_key [String] +# +# @return [Integer] +# +def get_secured_api_key_remaining_validity(secured_api_key) + now = Time.now.to_i + decoded_key = Base64.decode64(secured_api_key) + regex = 'validUntil=(\d+)' + matches = decoded_key.match(regex) + + if matches.nil? + raise AlgoliaError, 'The SecuredApiKey doesn\'t have a validUntil parameter.' + end + + valid_until = matches[1].to_i + + valid_until - now +end \ No newline at end of file