typesense 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c74454a48a4f170bbb99bb5e382199c8842e84ec5d2fbd6198106df89b45977
4
- data.tar.gz: ca4772c87e84fabe0cef3af42bfb6e1bb889e305b402d9a2e2f83b10bdbe6d1b
3
+ metadata.gz: ec69deb240d0c343346d128161aa74fe12ab18e7f79007dfa24ac16738c46237
4
+ data.tar.gz: e681fcd5f9b1241054f3c786ee5e6eebad45c1ddc1705311bf7a45ea6551a23f
5
5
  SHA512:
6
- metadata.gz: d1ab99d6e52d15257c8e664d765b1debb063d151d364916b273cef1658537dadcd0241e76fffa5807be50b15c83891b76c2aaef7105c875be2c3bb70728b88e0
7
- data.tar.gz: db20bce0c42a7713a3c5fa25ca1c7a17bb6724bd8949b5dc16202d11538b348d806d960f0def0712e118d856184da8650a3b12ba861037754e20e172856d38c0
6
+ metadata.gz: f6dd0dfd751499e1ec32cfd45935038df7ad219c498f433745fd8855439ef5136a7df7c47491f37fa9940d8bc1f1d02cfcc5aa77f6c4a154256f6ebe4dcb5c32
7
+ data.tar.gz: 7ef2d64aa701054a756222bc18dc19c9b3e282dbb6cc8789a47fe901d5716d67faaacf0c8fe1ed5b3de7cf1f06a1af11621e77ec633a4dfb6722e5bb0ed6908f
@@ -11,3 +11,6 @@ Metrics/BlockLength:
11
11
  - 'spec/**/*'
12
12
  - 'Gemfile'
13
13
  - 'typesense.gemspec'
14
+
15
+ Style/Documentation:
16
+ Enabled: false
@@ -17,6 +17,7 @@ Lint/SuppressedException:
17
17
  Exclude:
18
18
  - 'examples/collections_and_documents.rb'
19
19
  - 'examples/search.rb'
20
+ - 'examples/keys.rb'
20
21
 
21
22
  # Offense count: 3
22
23
  # Configuration parameters: IgnoredMethods.
@@ -49,6 +50,8 @@ RSpec/ExampleLength:
49
50
  Exclude:
50
51
  - 'spec/typesense/alias_spec.rb'
51
52
  - 'spec/typesense/aliases_spec.rb'
53
+ - 'spec/typesense/key_spec.rb'
54
+ - 'spec/typesense/keys_spec.rb'
52
55
  - 'spec/typesense/api_call_spec.rb'
53
56
  - 'spec/typesense/collection_spec.rb'
54
57
  - 'spec/typesense/collections_spec.rb'
data/README.md CHANGED
@@ -33,8 +33,9 @@ Tests are also a good place to know how the the library works internally: [spec]
33
33
 
34
34
  | Typesense Server | typesense-ruby |
35
35
  |------------------|----------------|
36
+ | \>= v0.12.1 | \>= v0.5.0 |
37
+ | \>= v0.12.0 | \>= v0.4.0 |
36
38
  | <= v0.11 | <= v0.3.0 |
37
- | \>= v0.12 | \>= v0.4.0 |
38
39
 
39
40
  ## Development
40
41
 
@@ -11,7 +11,7 @@ AwesomePrint.defaults = {
11
11
  ## Setup
12
12
  #
13
13
  ### Option 1: Start a single-node cluster
14
- # $ docker run -i -p 8108:8108 -v/tmp/typesense-server-data-1b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.rc9 --data-dir /data --api-key=xyz --search-only-api-key=abcd --listen-port 8108 --enable-cors
14
+ # $ docker run -i -p 8108:8108 -v/tmp/typesense-server-data-1b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 8108 --enable-cors
15
15
  #
16
16
  ### Option 2: Start a 3-node cluster
17
17
  #
@@ -19,13 +19,13 @@ AwesomePrint.defaults = {
19
19
  # $ echo '172.17.0.2:8107:8108,172.17.0.3:7107:7108,172.17.0.4:9107:9108' > `pwd`/typesense-server-peers
20
20
  #
21
21
  # Start node 1:
22
- # $ docker run -i -p 8108:8108 -p 8107:8107 -v/tmp/typesense-server-data-1b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.rc9 --data-dir /data --api-key=xyz --search-only-api-key=abcd --listen-port 8108 --peering-port 8107 --enable-cors --nodes=/typesense-server-peers
22
+ # $ docker run -i -p 8108:8108 -p 8107:8107 -v/tmp/typesense-server-data-1b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 8108 --peering-port 8107 --enable-cors --nodes=/typesense-server-peers
23
23
  #
24
24
  # Start node 2:
25
- # $ docker run -i -p 7108:7108 -p 7107:7107 -v/tmp/.typesense-server-data-2b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.rc9 --data-dir /data --api-key=xyz --search-only-api-key=abcd --listen-port 7108 --peering-port 7107 --enable-cors --nodes=/typesense-server-peers
25
+ # $ docker run -i -p 7108:7108 -p 7107:7107 -v/tmp/.typesense-server-data-2b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 7108 --peering-port 7107 --enable-cors --nodes=/typesense-server-peers
26
26
  #
27
27
  # Start node 3:
28
- # $ docker run -i -p 9108:9108 -p 9107:9107 -v/tmp/.typesense-server-data-3b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.rc9 --data-dir /data --api-key=xyz --search-only-api-key=abcd --listen-port 9108 --peering-port 9107 --enable-cors --nodes=/typesense-server-peers
28
+ # $ docker run -i -p 9108:9108 -p 9107:9107 -v/tmp/.typesense-server-data-3b/:/data -v`pwd`/typesense-server-peers:/typesense-server-peers typesense/typesense:0.12.1.rc1 --data-dir /data --api-key=xyz --listen-port 9108 --peering-port 9107 --enable-cors --nodes=/typesense-server-peers
29
29
  #
30
30
  # Note: Be sure to add `--license-key=<>` at the end when starting a Typesense Premium server
31
31
 
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # These examples walk you through operations to manage API Keys
5
+
6
+ require_relative './client_initialization'
7
+
8
+ # Let's setup some test data for this example
9
+ schema = {
10
+ 'name' => 'users',
11
+ 'fields' => [
12
+ {
13
+ 'name' => 'company_id',
14
+ 'type' => 'int32',
15
+ 'facet' => false
16
+ },
17
+ {
18
+ 'name' => 'user_name',
19
+ 'type' => 'string',
20
+ 'facet' => false
21
+ },
22
+ {
23
+ 'name' => 'login_count',
24
+ 'type' => 'int32',
25
+ 'facet' => false
26
+ },
27
+ {
28
+ 'name' => 'country',
29
+ 'type' => 'string',
30
+ 'facet' => true
31
+ }
32
+ ],
33
+ 'default_sorting_field' => 'company_id'
34
+ }
35
+
36
+ # We have four users, belonging to two companies: 124 and 126
37
+ documents = [
38
+ {
39
+ 'company_id' => 124,
40
+ 'user_name' => 'Hilary Bradford',
41
+ 'login_count' => 10,
42
+ 'country' => 'USA'
43
+ },
44
+ {
45
+ 'company_id' => 124,
46
+ 'user_name' => 'Nile Carty',
47
+ 'login_count' => 100,
48
+ 'country' => 'USA'
49
+ },
50
+ {
51
+ 'company_id' => 126,
52
+ 'user_name' => 'Tahlia Maxwell',
53
+ 'login_count' => 1,
54
+ 'country' => 'France'
55
+ },
56
+ {
57
+ 'company_id' => 126,
58
+ 'user_name' => 'Karl Roy',
59
+ 'login_count' => 2,
60
+ 'country' => 'Germany'
61
+ }
62
+ ]
63
+
64
+ # Delete if the collection already exists from a previous example run
65
+ begin
66
+ @typesense.collections['users'].delete
67
+ rescue Typesense::Error::ObjectNotFound
68
+ end
69
+
70
+ # create a collection
71
+ @typesense.collections.create(schema)
72
+
73
+ # Index documents
74
+ documents.each do |document|
75
+ @typesense.collections['users'].documents.create(document)
76
+ end
77
+
78
+ # Generate an API key and restrict it to only allow searches
79
+ # You want to use this API Key in the browser instead of the master API Key
80
+ unscoped_search_only_api_key_response = @typesense.keys.create({
81
+ 'description' => 'Search-only key.',
82
+ 'actions' => ['documents:search'],
83
+ 'collections' => ['*']
84
+ })
85
+ ap unscoped_search_only_api_key_response
86
+
87
+ # Save the key returned, since this will be the only time the full API Key is returned, for security purposes
88
+ unscoped_search_only_api_key = unscoped_search_only_api_key_response['value']
89
+
90
+ # Side note: you can also retrieve metadata of API keys using the ID returned in the above response
91
+ unscoped_search_only_api_key_response = @typesense.keys[unscoped_search_only_api_key_response['id']].retrieve
92
+ ap unscoped_search_only_api_key_response
93
+
94
+ # 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
95
+ # This is useful when you store multi-tenant data in a single Typesense server, but you only want
96
+ # a particular tenant to access their own data. You'd generate one scoped search key per tenant.
97
+ # IMPORTANT: scoped search keys should only be generated *server-side*, so as to not leak the unscoped main search key to clients
98
+ scoped_search_only_api_key = @typesense.keys.generate_scoped_search_key(unscoped_search_only_api_key, { 'filter_by': 'company_id:124' })
99
+ ap "scoped_search_only_api_key: #{scoped_search_only_api_key}"
100
+
101
+ # Now let's search the data using the scoped API Key for company_id:124
102
+ # You can do searches with this scoped_search_only_api_key from the server-side or client-side
103
+ scoped_typesense_client = Typesense::Client.new({
104
+ 'nodes': [{
105
+ 'host': 'localhost',
106
+ 'port': '8108',
107
+ 'protocol': 'http'
108
+ }],
109
+ 'api_key': scoped_search_only_api_key
110
+ })
111
+
112
+ search_results = scoped_typesense_client.collections['users'].documents.search({
113
+ 'q' => 'Hilary',
114
+ 'query_by' => 'user_name'
115
+ })
116
+ ap search_results
117
+
118
+ # Search for a user that exists, but is outside the current key's scope
119
+ search_results = scoped_typesense_client.collections['users'].documents.search({
120
+ 'q': 'Maxwell',
121
+ 'query_by': 'user_name'
122
+ })
123
+ ap search_results # Will return empty result set
124
+
125
+ # Now let's delete the unscoped_search_only_api_key. You'd want to do this when you need to rotate keys for example.
126
+ results = @typesense.keys[unscoped_search_only_api_key_response['id']].delete
127
+ ap results
@@ -15,5 +15,7 @@ require_relative 'typesense/overrides'
15
15
  require_relative 'typesense/override'
16
16
  require_relative 'typesense/aliases'
17
17
  require_relative 'typesense/alias'
18
+ require_relative 'typesense/keys'
19
+ require_relative 'typesense/key'
18
20
  require_relative 'typesense/debug'
19
21
  require_relative 'typesense/error'
@@ -5,6 +5,7 @@ module Typesense
5
5
  attr_reader :configuration
6
6
  attr_reader :collections
7
7
  attr_reader :aliases
8
+ attr_reader :keys
8
9
  attr_reader :debug
9
10
 
10
11
  def initialize(options = {})
@@ -12,6 +13,7 @@ module Typesense
12
13
  @api_call = ApiCall.new(@configuration)
13
14
  @collections = Collections.new(@api_call)
14
15
  @aliases = Aliases.new(@api_call)
16
+ @keys = Keys.new(@api_call)
15
17
  @debug = Debug.new(@api_call)
16
18
  end
17
19
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Typesense
4
+ class Key
5
+ def initialize(id, api_call)
6
+ @id = id
7
+ @api_call = api_call
8
+ end
9
+
10
+ def retrieve
11
+ @api_call.get(endpoint_path)
12
+ end
13
+
14
+ def delete
15
+ @api_call.delete(endpoint_path)
16
+ end
17
+
18
+ private
19
+
20
+ def endpoint_path
21
+ "#{Keys::RESOURCE_PATH}/#{@id}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module Typesense
6
+ class Keys
7
+ RESOURCE_PATH = '/keys'
8
+
9
+ def initialize(api_call)
10
+ @api_call = api_call
11
+ @keys = {}
12
+ end
13
+
14
+ def create(parameters)
15
+ @api_call.post(RESOURCE_PATH, parameters)
16
+ end
17
+
18
+ def retrieve
19
+ @api_call.get(RESOURCE_PATH)
20
+ end
21
+
22
+ def generate_scoped_search_key(search_key, parameters)
23
+ parameters_json = JSON.dump(parameters)
24
+ digest = Base64.encode64(OpenSSL::HMAC.digest('sha256', search_key, parameters_json)).gsub("\n", '')
25
+ key_prefix = search_key[0...4]
26
+ raw_scoped_key = "#{digest}#{key_prefix}#{parameters_json}"
27
+ Base64.encode64(raw_scoped_key).gsub("\n", '')
28
+ end
29
+
30
+ def [](id)
31
+ @keys[id] ||= Key.new(id, @api_call)
32
+ end
33
+ end
34
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Typesense
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typesense
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Typesense, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-23 00:00:00.000000000 Z
11
+ date: 2020-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -229,6 +229,7 @@ files:
229
229
  - examples/aliases.rb
230
230
  - examples/client_initialization.rb
231
231
  - examples/collections_and_documents.rb
232
+ - examples/keys.rb
232
233
  - examples/overrides.rb
233
234
  - examples/search.rb
234
235
  - lib/typesense.rb
@@ -243,6 +244,8 @@ files:
243
244
  - lib/typesense/document.rb
244
245
  - lib/typesense/documents.rb
245
246
  - lib/typesense/error.rb
247
+ - lib/typesense/key.rb
248
+ - lib/typesense/keys.rb
246
249
  - lib/typesense/override.rb
247
250
  - lib/typesense/overrides.rb
248
251
  - lib/typesense/version.rb