# frozen_string_literal: true ## # These examples walk you through operations to manage API Keys require_relative 'client_initialization' # Let's setup some test data for this example schema = { 'name' => 'users', 'fields' => [ { 'name' => 'company_id', 'type' => 'int32', 'facet' => false }, { 'name' => 'user_name', 'type' => 'string', 'facet' => false }, { 'name' => 'login_count', 'type' => 'int32', 'facet' => false }, { 'name' => 'country', 'type' => 'string', 'facet' => true } ], 'default_sorting_field' => 'company_id' } # We have four users, belonging to two companies: 124 and 126 documents = [ { 'company_id' => 124, 'user_name' => 'Hilary Bradford', 'login_count' => 10, 'country' => 'USA' }, { 'company_id' => 124, 'user_name' => 'Nile Carty', 'login_count' => 100, 'country' => 'USA' }, { 'company_id' => 126, 'user_name' => 'Tahlia Maxwell', 'login_count' => 1, 'country' => 'France' }, { 'company_id' => 126, 'user_name' => 'Karl Roy', 'login_count' => 2, 'country' => 'Germany' } ] # Delete if the collection already exists from a previous example run begin @typesense.collections['users'].delete rescue Typesense::Error::ObjectNotFound end # create a collection @typesense.collections.create(schema) # Index documents documents.each do |document| @typesense.collections['users'].documents.create(document) end # Generate an API key and restrict it to only allow searches # You want to use this API Key in the browser instead of the master API Key unscoped_search_only_api_key_response = @typesense.keys.create({ 'description' => 'Search-only key.', 'actions' => ['documents:search'], 'collections' => ['*'] }) ap unscoped_search_only_api_key_response # Save the key returned, since this will be the only time the full API Key is returned, for security purposes unscoped_search_only_api_key = unscoped_search_only_api_key_response['value'] # Side note: you can also retrieve metadata of API keys using the ID returned in the above response unscoped_search_only_api_key_response = @typesense.keys[unscoped_search_only_api_key_response['id']].retrieve ap unscoped_search_only_api_key_response # We'll now use this search-only API key to generate a scoped search API key that can only access documents that have company_id:124 # This is useful when you store multi-tenant data in a single Typesense server, but you only want # a particular tenant to access their own data. You'd generate one scoped search key per tenant. # IMPORTANT: scoped search keys should only be generated *server-side*, so as to not leak the unscoped main search key to clients scoped_search_only_api_key = @typesense.keys.generate_scoped_search_key(unscoped_search_only_api_key, { filter_by: 'company_id:124' }) ap "scoped_search_only_api_key: #{scoped_search_only_api_key}" # Now let's search the data using the scoped API Key for company_id:124 # You can do searches with this scoped_search_only_api_key from the server-side or client-side scoped_typesense_client = Typesense::Client.new({ nodes: [{ host: 'localhost', port: '8108', protocol: 'http' }], api_key: scoped_search_only_api_key }) search_results = scoped_typesense_client.collections['users'].documents.search({ 'q' => 'Hilary', 'query_by' => 'user_name' }) ap search_results # Search for a user that exists, but is outside the current key's scope search_results = scoped_typesense_client.collections['users'].documents.search({ q: 'Maxwell', query_by: 'user_name' }) ap search_results # Will return empty result set # Now let's delete the unscoped_search_only_api_key. You'd want to do this when you need to rotate keys for example. results = @typesense.keys[unscoped_search_only_api_key_response['id']].delete ap results