algoliasearch 1.2.4 → 1.2.5
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 +4 -4
- data/ChangeLog +5 -0
- data/README.md +52 -2
- data/algoliasearch.gemspec +2 -2
- data/lib/algolia/client.rb +26 -2
- data/lib/algolia/version.rb +1 -1
- data/spec/client_spec.rb +14 -0
- metadata +27 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffcea70e1e16052463f966167245f0d0412bb1d1
|
4
|
+
data.tar.gz: a37adf050adb92682c8ddd48990b093606ba800d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc1fbead2ee31e7e503b7864d7779c9455d99f1925de7f5ca765c0a0229dc0c4b81680a9b814c029a0b06152b8729565dae1f8ecb342a07c46f650771ec4df07
|
7
|
+
data.tar.gz: 79a73010bbaa3b99227c9693ea9f71ba9c6627b02faf4dd4a9f772bef98b0cb9af637e67e65049fa797d056bd22cafa6415b6a28db23164a1810c1e7a3a3288f
|
data/ChangeLog
CHANGED
data/README.md
CHANGED
@@ -295,6 +295,8 @@ The server response will look like:
|
|
295
295
|
|
296
296
|
|
297
297
|
|
298
|
+
|
299
|
+
|
298
300
|
Get an object
|
299
301
|
-------------
|
300
302
|
|
@@ -494,13 +496,18 @@ You can also create an API Key with advanced restrictions:
|
|
494
496
|
Note: If you are sending the query through your servers, you must use the `Algolia.with_rate_limits("EndUserIP", "APIKeyWithRateLimit") do ... end` block to enable rate-limit.
|
495
497
|
|
496
498
|
* Specify the maximum number of hits this API key can retrieve in one call. Defaults to 0 (unlimited). This parameter can be used to protect you from attempts at retrieving your entire content by massively querying the index.
|
499
|
+
* Specify the list of targeted indexes. Defaults to all indexes if empty of blank.
|
497
500
|
|
498
501
|
```ruby
|
499
502
|
# Creates a new global API key that is valid for 300 seconds
|
500
503
|
res = Algolia.add_user_key(["search"], 300)
|
501
504
|
puts res['key']
|
502
|
-
# Creates a new index specific API key
|
503
|
-
|
505
|
+
# Creates a new index specific API key:
|
506
|
+
# - valid for 300 seconds
|
507
|
+
# - rate limit of 100 calls per hour per IP
|
508
|
+
# - maximum of 20 hits
|
509
|
+
# - valid on 'my_index1' and 'my_index2'
|
510
|
+
res = index.add_user_key(["search"], 300, 100, 20, ['my_index1', 'my_index2'])
|
504
511
|
puts res['key']
|
505
512
|
```
|
506
513
|
|
@@ -520,6 +527,49 @@ Algolia.delete_user_key("f420238212c54dcfad07ea0aa6d5c45f")
|
|
520
527
|
index.delete_user_key("71671c38001bf3ac857bc82052485107")
|
521
528
|
```
|
522
529
|
|
530
|
+
You may have a single index containing per-user data. In that case, all records should be tagged with their associated user_id in order to add a `tagFilters=(public,user_42)` filter at query time to retrieve only what a user has access to. If you're using the [JavaScript client](http://github.com/algolia/algoliasearch-client-js), it will result in a security breach since the user is able to modify the `tagFilters` you've set modifying the code from the browser. To keep using the JavaScript client (recommended for optimal latency) and target secured records, you can generate secured API key from your backend:
|
531
|
+
|
532
|
+
```ruby
|
533
|
+
# generate a public API key for user 42. Here, records are tagged with:
|
534
|
+
# - 'public' if they are visible by all users
|
535
|
+
# - 'user_XXXX' if they are visible by user XXXX
|
536
|
+
public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', '(public,user_42)'
|
537
|
+
```
|
538
|
+
|
539
|
+
This public API key must then be used in your JavaScript code as follow:
|
540
|
+
|
541
|
+
```javascript
|
542
|
+
<script type="text/javascript">
|
543
|
+
var algolia = new AlgoliaSearch('YourApplicationID', '<%= public_api_key %>');
|
544
|
+
algolia.setSecurityTags('(public,user_42)'); // must be same than those used at generation-time
|
545
|
+
algolia.initIndex('YourIndex').search($('#q').val(), function(success, content) {
|
546
|
+
// [...]
|
547
|
+
});
|
548
|
+
</script>
|
549
|
+
```
|
550
|
+
|
551
|
+
You can mix rate limits and secured API keys setting an extra `user_token` attribute both at API key generation-time and query-time. When set, a uniq user will be identified by her `IP + user_token` instead of only her `IP`. It allows you to restrict a single user to perform maximum `N` API calls per hour, even if she share her `IP` with another user.
|
552
|
+
|
553
|
+
```ruby
|
554
|
+
# generate a public API key for user 42. Here, records are tagged with:
|
555
|
+
# - 'public' if they are visible by all users
|
556
|
+
# - 'user_XXXX' if they are visible by user XXXX
|
557
|
+
public_key = Algolia.generate_secured_api_key 'YourRateLimitedApiKey', '(public,user_42)', 'user_42'
|
558
|
+
```
|
559
|
+
|
560
|
+
This public API key must then be used in your JavaScript code as follow:
|
561
|
+
|
562
|
+
```javascript
|
563
|
+
<script type="text/javascript">
|
564
|
+
var algolia = new AlgoliaSearch('YourApplicationID', '<%= public_api_key %>');
|
565
|
+
algolia.setSecurityTags('(public,user_42)'); // must be same than those used at generation-time
|
566
|
+
algolia.setUserToken('user_42') // must be same than the one used at generation-time
|
567
|
+
algolia.initIndex('YourIndex').search($('#q').val(), function(success, content) {
|
568
|
+
// [...]
|
569
|
+
});
|
570
|
+
</script>
|
571
|
+
```
|
572
|
+
|
523
573
|
Copy or rename an index
|
524
574
|
-------------
|
525
575
|
|
data/algoliasearch.gemspec
CHANGED
@@ -6,12 +6,12 @@
|
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "algoliasearch"
|
9
|
-
s.version = "1.2.
|
9
|
+
s.version = "1.2.5"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Algolia"]
|
14
|
-
s.date = "2014-02-
|
14
|
+
s.date = "2014-02-24"
|
15
15
|
s.description = "A simple Ruby client for the algolia.com REST API"
|
16
16
|
s.email = "contact@algolia.com"
|
17
17
|
s.extra_rdoc_files = [
|
data/lib/algolia/client.rb
CHANGED
@@ -148,6 +148,22 @@ module Algolia
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
+
#
|
152
|
+
# Generate a secured and public API Key from a list of tagFilters and an
|
153
|
+
# optional user token identifying the current user
|
154
|
+
#
|
155
|
+
# @param private_api_key your private API Key
|
156
|
+
# @param tag_filters the list of tags applied to the query (used as security)
|
157
|
+
# @param user_token an optional token identifying the current user
|
158
|
+
#
|
159
|
+
def Algolia.generate_secured_api_key(private_api_key, tag_filters, user_token = nil)
|
160
|
+
if tag_filters.is_a?(Array)
|
161
|
+
tag_filters = tag_filters.map { |t| t.is_a?(Array) ? "(#{t.join(',')})" : t }.join(',')
|
162
|
+
end
|
163
|
+
raise ArgumentError.new('Attribute "tag_filters" must be a list of tags') if !tag_filters.is_a?(String)
|
164
|
+
Digest::SHA256.hexdigest "#{private_api_key}#{tag_filters}#{user_token.to_s}"
|
165
|
+
end
|
166
|
+
|
151
167
|
#
|
152
168
|
# List all existing indexes
|
153
169
|
# return an Answer object with answer in the form
|
@@ -213,9 +229,17 @@ module Algolia
|
|
213
229
|
# @param validity the number of seconds after which the key will be automatically removed (0 means no time limit for this key)
|
214
230
|
# @param maxQueriesPerIPPerHour the maximum number of API calls allowed from an IP address per hour (0 means unlimited)
|
215
231
|
# @param maxHitsPerQuery the maximum number of hits this API key can retrieve in one call (0 means unlimited)
|
232
|
+
# @param indexes the optional list of targeted indexes
|
216
233
|
#
|
217
|
-
def Algolia.add_user_key(acls, validity = 0, maxQueriesPerIPPerHour = 0, maxHitsPerQuery = 0)
|
218
|
-
|
234
|
+
def Algolia.add_user_key(acls, validity = 0, maxQueriesPerIPPerHour = 0, maxHitsPerQuery = 0, indexes = nil)
|
235
|
+
params = {
|
236
|
+
:acl => acls,
|
237
|
+
:validity => validity.to_i,
|
238
|
+
:maxQueriesPerIPPerHour => maxQueriesPerIPPerHour.to_i,
|
239
|
+
:maxHitsPerQuery => maxHitsPerQuery.to_i
|
240
|
+
}
|
241
|
+
params[:indexes] = indexes if indexes
|
242
|
+
Algolia.client.post(Protocol.keys_uri, params.to_json)
|
219
243
|
end
|
220
244
|
|
221
245
|
# Delete an existing user key
|
data/lib/algolia/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -214,6 +214,9 @@ describe 'Client' do
|
|
214
214
|
end
|
215
215
|
|
216
216
|
it "should get logs" do
|
217
|
+
host = Algolia.client.send(:thread_local_hosts).first
|
218
|
+
puts host[:session].get(host[:base_url] + Algolia::Protocol.logs(0, 10), { :header => Algolia.client.headers }).content
|
219
|
+
|
217
220
|
res = Algolia.get_logs
|
218
221
|
|
219
222
|
res['logs'].size.should > 0
|
@@ -561,4 +564,15 @@ describe 'Client' do
|
|
561
564
|
logs['logs'][0].should have_key('sha1')
|
562
565
|
logs['logs'][0]['sha1'].should be_a(String)
|
563
566
|
end
|
567
|
+
|
568
|
+
it 'should generate secured api keys' do
|
569
|
+
key = Algolia.generate_secured_api_key('my_api_key', '(public,user1)')
|
570
|
+
key.should eq(Digest::SHA256.hexdigest 'my_api_key(public,user1)')
|
571
|
+
key = Algolia.generate_secured_api_key('my_api_key', '(public,user1)', 42)
|
572
|
+
key.should eq(Digest::SHA256.hexdigest 'my_api_key(public,user1)42')
|
573
|
+
key = Algolia.generate_secured_api_key('my_api_key', ['public'])
|
574
|
+
key.should eq(Digest::SHA256.hexdigest 'my_api_keypublic')
|
575
|
+
key = Algolia.generate_secured_api_key('my_api_key', ['public', ['premium','vip']])
|
576
|
+
key.should eq(Digest::SHA256.hexdigest 'my_api_keypublic,(premium,vip)')
|
577
|
+
end
|
564
578
|
end
|
metadata
CHANGED
@@ -1,85 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: algoliasearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Algolia
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
15
|
-
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2.3'
|
20
|
-
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
23
21
|
requirements:
|
24
22
|
- - ~>
|
25
23
|
- !ruby/object:Gem::Version
|
26
24
|
version: '2.3'
|
25
|
+
prerelease: false
|
26
|
+
type: :runtime
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
|
-
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.5.1
|
34
|
-
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
37
35
|
requirements:
|
38
36
|
- - '>='
|
39
37
|
- !ruby/object:Gem::Version
|
40
38
|
version: 1.5.1
|
39
|
+
prerelease: false
|
40
|
+
type: :runtime
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: travis
|
43
|
-
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
51
49
|
requirements:
|
52
50
|
- - '>='
|
53
51
|
- !ruby/object:Gem::Version
|
54
52
|
version: '0'
|
53
|
+
prerelease: false
|
54
|
+
type: :development
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
|
-
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
65
63
|
requirements:
|
66
64
|
- - '>='
|
67
65
|
- !ruby/object:Gem::Version
|
68
66
|
version: '0'
|
67
|
+
prerelease: false
|
68
|
+
type: :development
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rdoc
|
71
|
-
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
|
-
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
79
77
|
requirements:
|
80
78
|
- - '>='
|
81
79
|
- !ruby/object:Gem::Version
|
82
80
|
version: '0'
|
81
|
+
prerelease: false
|
82
|
+
type: :development
|
83
83
|
description: A simple Ruby client for the algolia.com REST API
|
84
84
|
email: contact@algolia.com
|
85
85
|
executables: []
|
@@ -115,7 +115,7 @@ homepage: http://github.com/algolia/algoliasearch-client-ruby
|
|
115
115
|
licenses:
|
116
116
|
- MIT
|
117
117
|
metadata: {}
|
118
|
-
post_install_message:
|
118
|
+
post_install_message:
|
119
119
|
rdoc_options: []
|
120
120
|
require_paths:
|
121
121
|
- lib
|
@@ -130,9 +130,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
requirements: []
|
133
|
-
rubyforge_project:
|
134
|
-
rubygems_version: 2.1
|
135
|
-
signing_key:
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.2.1
|
135
|
+
signing_key:
|
136
136
|
specification_version: 4
|
137
137
|
summary: A simple Ruby client for the algolia.com REST API
|
138
138
|
test_files: []
|