keen 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea225965754dd52560665211c578bd3793bde5e2
4
- data.tar.gz: 167256828b0989a4543a9c2ad8f6400dab0c565a
3
+ metadata.gz: 065f80ef6be231a709d26afe30ae76a8a1138812
4
+ data.tar.gz: d6a07538cff945becfa38fc12015f1e0244d9032
5
5
  SHA512:
6
- metadata.gz: 272b9dab9b16c0cb8d6c9aa6e4a1caf40bff0e4e807619c3f884b814bbd0cf926d6cd6416a1dd337299b63c8ee99813649022f07a37d6347b75a60a0a98e3201
7
- data.tar.gz: 1df6f05bb56a255fcc463b7bfe4420fc15e2c32bc38bb389d6ecdbd48f753cbf9a963d9c644e92121e8b36e6b4d4e2fd6abe3abbafff1ae675fece9f87f9cbef
6
+ metadata.gz: 40e792c1cd92e85b901b365ad3f27a146e964094cb25475a252b36f903760eb319055d620eb2ceee371ccb7fbb3bc7bfddb306c0b871b07b50d96e741f2f4a5e
7
+ data.tar.gz: 5b65635514c0be2d55107f3d1aa3a532a2d502f3b9599817daa691e9adcfb6f1e3ff8505e9ad74b6ee2d296fef8f099e4a67080e7717a0a0dbb577c602d44201
data/README.md CHANGED
@@ -355,6 +355,8 @@ This is helpful for tracking email clickthroughs. See the [redirect documentatio
355
355
 
356
356
  #### Generating scoped keys
357
357
 
358
+ Note, Scoped Keys are now *deprecated* in favor of [access keys](https://keen.io/docs/api/#access-keys?s=gh-gem).
359
+
358
360
  A [scoped key](https://keen.io/docs/security/#scoped-key?s=gh-gem) is a string, generated with your API Key, that represents some encrypted authentication and query options.
359
361
  Use them to control what data queries have access to.
360
362
 
@@ -369,6 +371,34 @@ scoped_key = Keen::ScopedKey.new("my-api-key", { "filters" => [{
369
371
 
370
372
  You can use the scoped key created in Ruby for API requests from any client. Scoped keys are commonly used in JavaScript, where credentials are visible and need to be protected.
371
373
 
374
+ #### Access Keys
375
+
376
+ You can use access keys to restrict the functionality of a key you use with the Keen API. Access keys can also enrich events that you send.
377
+
378
+ [Read up](https://keen.io/docs/api/#access-keys?s=gh-gem) on the full key body options.
379
+
380
+ Create a key that automatically adds information to each event published with that key:
381
+
382
+ ``` ruby
383
+ key_body = {
384
+ "name" => "autofill foo",
385
+ "is_active" => true,
386
+ "permitted" => ["writes"],
387
+ "options" => {
388
+ "writes" => {
389
+ "autofill": {
390
+ "foo": "bar"
391
+ }
392
+ }
393
+ }
394
+ }
395
+
396
+ new_key = client.access_keys.create(key_body)
397
+ autofill_write_key = new_key["key"]
398
+ ```
399
+
400
+ You can `revoke` and `unrevoke` keys to disable or enable access. `all` will return all current keys for the project, while `get("key-value-here")` will return info for a single key. You can also `update` and `delete` keys.
401
+
372
402
  ### Additional options
373
403
 
374
404
  ##### HTTP Read Timeout
@@ -417,6 +447,11 @@ If you want some bot protection, check out the [Voight-Kampff](https://github.co
417
447
 
418
448
  ### Changelog
419
449
 
450
+ ##### 1.1.0
451
+ + Add support for access keys
452
+ + Move saved queries into the Keen namespace
453
+ + Deprecate scoped keys in favor of access keys
454
+
420
455
  ##### 1.0.0
421
456
  + Remove support for ruby 1.9.3
422
457
  + Update a few dependencies
@@ -1,7 +1,9 @@
1
1
  require 'logger'
2
2
  require 'forwardable'
3
3
 
4
+ require 'keen/access_keys'
4
5
  require 'keen/client'
6
+ require 'keen/saved_queries'
5
7
  require 'keen/scoped_key'
6
8
 
7
9
  module Keen
@@ -52,7 +54,8 @@ module Keen
52
54
  :project_info,
53
55
  :query_url,
54
56
  :query,
55
- :saved_queries
57
+ :saved_queries,
58
+ :access_keys
56
59
 
57
60
  attr_writer :logger
58
61
 
@@ -0,0 +1,93 @@
1
+ require 'multi_json'
2
+
3
+ module Keen
4
+ class AccessKeys
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ def get(key)
10
+ client.ensure_master_key!
11
+ path = "/#{key}"
12
+
13
+ response = access_keys_get(client.master_key, path)
14
+ client.process_response(response.code.to_i, response.body)
15
+ end
16
+
17
+ def all()
18
+ client.ensure_master_key!
19
+
20
+ response = access_keys_get(client.master_key)
21
+ client.process_response(response.code.to_i, response.body)
22
+ end
23
+
24
+ # For information on the format of the key_body, see
25
+ # https://keen.io/docs/api/#access-keys
26
+ def create(key_body)
27
+ client.ensure_master_key!
28
+
29
+ path = ""
30
+ response = access_keys_post(client.master_key, path, key_body)
31
+ client.process_response(response.code.to_i, response.body)
32
+ end
33
+
34
+ def update(key, key_body)
35
+ client.ensure_master_key!
36
+
37
+ path = "/#{key}"
38
+ response = access_keys_post(client.master_key, path, key_body)
39
+ client.process_response(response.code.to_i, response.body)
40
+ end
41
+
42
+ def revoke(key)
43
+ client.ensure_master_key!
44
+
45
+ path = "/#{key}/revoke"
46
+ response = access_keys_post(client.master_key, path)
47
+ client.process_response(response.code.to_i, response.body)
48
+ end
49
+
50
+ def unrevoke(key)
51
+ client.ensure_master_key!
52
+
53
+ path = "/#{key}/unrevoke"
54
+ response = access_keys_post(client.master_key, path)
55
+ client.process_response(response.code.to_i, response.body)
56
+ end
57
+
58
+ def delete(key)
59
+ client.ensure_master_key!
60
+
61
+ response = Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).delete(
62
+ path: access_keys_base_url + "/#{key}",
63
+ headers: client.api_headers(client.master_key, "sync")
64
+ )
65
+
66
+ client.process_response(response.code.to_i, response.body)
67
+ end
68
+
69
+ def access_keys_base_url
70
+ client.ensure_project_id!
71
+ "/#{client.api_version}/projects/#{client.project_id}/keys"
72
+ end
73
+
74
+ private
75
+
76
+ attr_reader :client
77
+
78
+ def access_keys_get(api_key, path = "")
79
+ Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).get(
80
+ path: access_keys_base_url + path,
81
+ headers: client.api_headers(api_key, "sync")
82
+ )
83
+ end
84
+
85
+ def access_keys_post(api_key, path = "", body = "")
86
+ Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).post(
87
+ path: access_keys_base_url + path,
88
+ headers: client.api_headers(api_key, "sync"),
89
+ body: MultiJson.dump(body)
90
+ )
91
+ end
92
+ end
93
+ end
@@ -3,7 +3,6 @@ require 'keen/version'
3
3
  require 'keen/client/publishing_methods'
4
4
  require 'keen/client/querying_methods'
5
5
  require 'keen/client/maintenance_methods'
6
- require 'keen/client/saved_queries'
7
6
  require 'keen/version'
8
7
  require 'openssl'
9
8
  require 'multi_json'
@@ -62,7 +61,9 @@ module Keen
62
61
  @saved_queries ||= SavedQueries.new(self)
63
62
  end
64
63
 
65
- private
64
+ def access_keys
65
+ @access_keys ||= AccessKeys.new(self)
66
+ end
66
67
 
67
68
  def process_response(status_code, response_body)
68
69
  case status_code.to_i
@@ -102,6 +103,8 @@ module Keen
102
103
  raise ConfigurationError, "Read Key must be set for this operation" unless self.read_key
103
104
  end
104
105
 
106
+ private
107
+
105
108
  def api_event_collection_resource_path(event_collection)
106
109
  encoded_collection_name = Addressable::URI.encode_component(event_collection.to_s)
107
110
  encoded_collection_name.gsub! '/', '%2F'
@@ -0,0 +1,83 @@
1
+ require 'keen/version'
2
+ require "json"
3
+
4
+ module Keen
5
+ class SavedQueries
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def all
11
+ client.ensure_master_key!
12
+
13
+ response = saved_query_response(client.master_key)
14
+ client.process_response(response.code.to_i, response.body)
15
+ end
16
+
17
+ def get(saved_query_name, results = false)
18
+ saved_query_path = "/#{saved_query_name}"
19
+ if results
20
+ client.ensure_read_key!
21
+ saved_query_path += "/result"
22
+ # The results path should use the READ KEY
23
+ api_key = client.read_key
24
+ else
25
+ client.ensure_master_key!
26
+ api_key = client.master_key
27
+ end
28
+
29
+ response = saved_query_response(api_key, saved_query_path)
30
+ client.process_response(response.code.to_i, response.body)
31
+ end
32
+
33
+ def create(saved_query_name, saved_query_body)
34
+ client.ensure_master_key!
35
+
36
+ response = Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).put(
37
+ path: "#{saved_query_base_url}/#{saved_query_name}",
38
+ headers: api_headers(client.master_key, "sync"),
39
+ body: saved_query_body
40
+ )
41
+ client.process_response(response.code.to_i, response.body)
42
+ end
43
+ alias_method :update, :create
44
+
45
+ def delete(saved_query_name)
46
+ client.ensure_master_key!
47
+
48
+ response = Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).delete(
49
+ path: "#{saved_query_base_url}/#{saved_query_name}",
50
+ headers: api_headers(client.master_key, "sync")
51
+ )
52
+ client.process_response(response.code.to_i, response.body)
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :client
58
+
59
+ def saved_query_response(api_key, path = "")
60
+ Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).get(
61
+ path: saved_query_base_url + path,
62
+ headers: api_headers(api_key, "sync")
63
+ )
64
+ end
65
+
66
+ def saved_query_base_url
67
+ client.ensure_project_id!
68
+ "/#{client.api_version}/projects/#{client.project_id}/queries/saved"
69
+ end
70
+
71
+ def api_headers(authorization, sync_type)
72
+ user_agent = "keen-gem, v#{Keen::VERSION}, #{sync_type}"
73
+ user_agent += ", #{RUBY_VERSION}, #{RUBY_PLATFORM}, #{RUBY_PATCHLEVEL}"
74
+ if defined?(RUBY_ENGINE)
75
+ user_agent += ", #{RUBY_ENGINE}"
76
+ end
77
+ { "Content-Type" => "application/json",
78
+ "User-Agent" => user_agent,
79
+ "Authorization" => authorization,
80
+ "Keen-Sdk" => "ruby-#{Keen::VERSION}" }
81
+ end
82
+ end
83
+ end
@@ -3,6 +3,7 @@ require 'keen/aes_helper'
3
3
  require 'keen/aes_helper_old'
4
4
 
5
5
  module Keen
6
+ # <b>DEPRECATED:</b> Please use <tt>access keys</tt> instead.
6
7
  class ScopedKey
7
8
 
8
9
  attr_accessor :api_key
@@ -26,6 +27,8 @@ module Keen
26
27
  end
27
28
 
28
29
  def encrypt!(iv = nil)
30
+ warn "[DEPRECATION] Scoped keys are deprecated. Please use `access_keys` instead."
31
+
29
32
  json_str = MultiJson.dump(self.data)
30
33
  if self.api_key.length == 64
31
34
  Keen::AESHelper.aes256_encrypt(self.api_key, json_str, iv)
@@ -1,3 +1,3 @@
1
1
  module Keen
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -0,0 +1,70 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe "Access Keys" do
4
+ let(:project_id) { ENV["KEEN_PROJECT_ID"] }
5
+ let(:master_key) { ENV["KEEN_MASTER_KEY"] }
6
+ let(:client) { Keen::Client.new(project_id: project_id, master_key: master_key) }
7
+
8
+ describe "#all" do
9
+ it "gets all access keys" do
10
+ expect(client.access_keys.all).to be_instance_of(Array)
11
+ end
12
+ end
13
+
14
+ describe "#create" do
15
+ it "creates a key" do
16
+ key_body = {
17
+ "name" => "integration test key",
18
+ "is_active" => true,
19
+ "permitted" => ["queries"],
20
+ "options" => {}
21
+ }
22
+
23
+ create_result = client.access_keys.create(key_body)
24
+ expect(create_result["name"]).to eq(key_body["name"])
25
+ end
26
+ end
27
+
28
+ describe "#get" do
29
+ it "gets a single access key" do
30
+ all_keys = client.access_keys.all
31
+
32
+ access_key = client.access_keys.get(all_keys.first["key"])
33
+
34
+ expect(access_key["name"]).to eq(all_keys.first["name"])
35
+ end
36
+ end
37
+
38
+ describe "#revoke" do
39
+ it "sets the is_active to false" do
40
+ all_keys = client.access_keys.all
41
+ key = all_keys.first["key"]
42
+
43
+ client.access_keys.revoke(key)
44
+ new_key = client.access_keys.get(key)
45
+ expect(new_key["is_active"]).to be_falsey
46
+ end
47
+ end
48
+
49
+ describe "#unrevoke" do
50
+ it "sets the is_active to true" do
51
+ all_keys = client.access_keys.all
52
+ key = all_keys.first["key"]
53
+
54
+ client.access_keys.unrevoke(key)
55
+ new_key = client.access_keys.get(key)
56
+ expect(new_key["is_active"]).to be_truthy
57
+ end
58
+ end
59
+
60
+ describe "#delete" do
61
+ it "deletes a key" do
62
+ all_keys = client.access_keys.all
63
+ key = all_keys.first["key"]
64
+
65
+ client.access_keys.delete(key)
66
+ all_keys = client.access_keys.all
67
+ expect(all_keys).to eq([])
68
+ end
69
+ end
70
+ end
@@ -7,7 +7,7 @@ describe "Keen IO API" do
7
7
  def wait_for_count(event_collection, count)
8
8
  attempts = 0
9
9
  while attempts < 30
10
- break if Keen.count(event_collection) == count
10
+ break if Keen.count(event_collection, {:timeframe => "this_2_hours"}) == count
11
11
  attempts += 1
12
12
  sleep(1)
13
13
  end
@@ -20,7 +20,7 @@ describe "Keen IO API" do
20
20
 
21
21
  describe "success" do
22
22
  it "should return a created status for a valid post" do
23
- Keen.publish(collection, event_properties).should == api_success
23
+ expect(Keen.publish(collection, event_properties)).to eq(api_success)
24
24
  end
25
25
  end
26
26
 
@@ -33,7 +33,7 @@ describe "Keen IO API" do
33
33
  end
34
34
 
35
35
  it "should succeed if a non-url-safe event collection is specified" do
36
- Keen.publish("infinite possibilities", event_properties).should == api_success
36
+ expect(Keen.publish("infinite possibilities", event_properties)).to eq(api_success)
37
37
  end
38
38
  end
39
39
 
@@ -45,7 +45,7 @@ describe "Keen IO API" do
45
45
  EM.run {
46
46
  Keen.publish_async(collection, event_properties).callback { |response|
47
47
  begin
48
- response.should == api_success
48
+ expect(response).to eq(api_success)
49
49
  ensure
50
50
  EM.stop
51
51
  end
@@ -60,7 +60,7 @@ describe "Keen IO API" do
60
60
  EM.run {
61
61
  Keen.publish_async("foo bar", event_properties).callback { |response|
62
62
  begin
63
- response.should == api_success
63
+ expect(response).to eq(api_success)
64
64
  ensure
65
65
  EM.stop
66
66
  end
@@ -72,7 +72,7 @@ describe "Keen IO API" do
72
72
 
73
73
  describe "batch" do
74
74
  it "should publish a batch of events" do
75
- Keen.publish_batch(
75
+ expect(Keen.publish_batch(
76
76
  :batch_signups => [
77
77
  { :name => "bob" },
78
78
  { :name => "ted" }
@@ -81,7 +81,7 @@ describe "Keen IO API" do
81
81
  { :price => 30 },
82
82
  { :price => 40 }
83
83
  ]
84
- ).should == {
84
+ )).to eq({
85
85
  "batch_purchases" => [
86
86
  { "success" => true },
87
87
  { "success" => true }
@@ -89,7 +89,7 @@ describe "Keen IO API" do
89
89
  "batch_signups" => [
90
90
  { "success" => true },
91
91
  { "success"=>true }
92
- ]}
92
+ ]})
93
93
  end
94
94
  end
95
95
  end
@@ -110,7 +110,7 @@ describe "Keen IO API" do
110
110
  { :price => 40 }
111
111
  ]).callback { |response|
112
112
  begin
113
- response.should == api_success
113
+ expect(response).to eq(api_success)
114
114
  ensure
115
115
  EM.stop
116
116
  end
@@ -151,111 +151,115 @@ describe "Keen IO API" do
151
151
  end
152
152
 
153
153
  it "should return a valid count_unique" do
154
- Keen.count_unique(event_collection, :target_property => "price").should == 2
154
+ expect(Keen.count_unique(event_collection, :timeframe => "this_2_hours", :target_property => "price")).to eq(2)
155
155
  end
156
156
 
157
157
  it "should return a valid count with group_by" do
158
- response = Keen.average(event_collection, :group_by => "username", :target_property => "price")
158
+ response = Keen.average(event_collection, :timeframe => "this_2_hours", :group_by => "username", :target_property => "price")
159
159
  bobs_response = response.select { |result| result["username"] == "bob" }.first
160
- bobs_response["result"].should == 10
160
+ expect(bobs_response["result"]).to eq(10)
161
161
  teds_response = response.select { |result| result["username"] == "ted" }.first
162
- teds_response["result"].should == 20
162
+ expect(teds_response["result"]).to eq(20)
163
163
  end
164
164
 
165
165
  it "should return a valid count with multi-group_by" do
166
- response = Keen.average(event_collection, :group_by => ["username", "price"], :target_property => "price")
166
+ response = Keen.average(event_collection, :timeframe => "this_2_hours", :group_by => ["username", "price"], :target_property => "price")
167
167
  bobs_response = response.select { |result| result["username"] == "bob" }.first
168
- bobs_response["result"].should == 10
169
- bobs_response["price"].should == 10
168
+ expect(bobs_response["result"]).to eq(10)
169
+ expect(bobs_response["price"]).to eq(10)
170
170
  teds_response = response.select { |result| result["username"] == "ted" }.first
171
- teds_response["result"].should == 20
172
- teds_response["price"].should == 20
171
+ expect(teds_response["result"]).to eq(20)
172
+ expect(teds_response["price"]).to eq(20)
173
173
  end
174
174
 
175
175
  it "should return a valid sum" do
176
- Keen.sum(event_collection, :target_property => "price").should == 30
176
+ expect(Keen.sum(event_collection, :timeframe => "this_2_hours", :target_property => "price")).to eq(30)
177
177
  end
178
178
 
179
179
  it "should return a valid minimum" do
180
- Keen.minimum(event_collection, :target_property => "price").should == 10
180
+ expect(Keen.minimum(event_collection, :timeframe => "this_2_hours", :target_property => "price")).to eq(10)
181
181
  end
182
182
 
183
183
  it "should return a valid maximum" do
184
- Keen.maximum(event_collection, :target_property => "price").should == 20
184
+ expect(Keen.maximum(event_collection, :timeframe => "this_2_hours", :target_property => "price")).to eq(20)
185
185
  end
186
186
 
187
187
  it "should return a valid average" do
188
- Keen.average(event_collection, :target_property => "price").should == 15
188
+ expect(Keen.average(event_collection, :timeframe => "this_2_hours", :target_property => "price")).to eq(15)
189
189
  end
190
190
 
191
191
  it "should return a valid median" do
192
- Keen.median(event_collection, :target_property => "price").should == 10
192
+ expect(Keen.median(event_collection, :timeframe => "this_2_hours", :target_property => "price")).to eq(10)
193
193
  end
194
194
 
195
195
  it "should return a valid percentile" do
196
- Keen.percentile(event_collection, :target_property => "price", :percentile => 50).should == 10
197
- Keen.percentile(event_collection, :target_property => "price", :percentile => 100).should == 20
196
+ expect(Keen.percentile(event_collection, :timeframe => "this_2_hours", :target_property => "price", :percentile => 50)).to eq(10)
197
+ expect(Keen.percentile(event_collection, :timeframe => "this_2_hours", :target_property => "price", :percentile => 100)).to eq(20)
198
198
  end
199
199
 
200
200
  it "should return a valid select_unique" do
201
- results = Keen.select_unique(event_collection, :target_property => "price")
202
- results.sort.should == [10, 20].sort
201
+ results = Keen.select_unique(event_collection, :timeframe => "this_2_hours", :target_property => "price")
202
+ expect(results.sort).to eq([10, 20].sort)
203
203
  end
204
204
 
205
205
  it "should return a valid extraction" do
206
- results = Keen.extraction(event_collection)
207
- results.length.should == 2
208
- results.all? { |result| result["keen"] }.should be_true
209
- results.map { |result| result["price"] }.sort.should == [10, 20]
210
- results.map { |result| result["username"] }.sort.should == ["bob", "ted"]
206
+ results = Keen.extraction(event_collection, :timeframe => "this_2_hours")
207
+ expect(results.length).to eq(2)
208
+ expect(results.all? { |result| result["keen"] }).to be_truthy
209
+ expect(results.map { |result| result["price"] }.sort).to eq([10, 20])
210
+ expect(results.map { |result| result["username"] }.sort).to eq(["bob", "ted"])
211
211
  end
212
212
 
213
213
  it "should return a valid extraction of one property name" do
214
- results = Keen.extraction(event_collection, :property_names => "price")
215
- results.length.should == 2
216
- results.any? { |result| result["keen"] }.should be_false
217
- results.map { |result| result["price"] }.sort.should == [10, 20]
218
- results.map { |result| result["username"] }.sort.should == [nil, nil]
214
+ results = Keen.extraction(event_collection, :timeframe => "this_2_hours", :property_names => "price")
215
+ expect(results.length).to eq(2)
216
+ expect(results.any? { |result| result["keen"] }).to be_falsey
217
+ expect(results.map { |result| result["price"] }.sort).to eq([10, 20])
218
+ expect(results.map { |result| result["username"] }.sort).to eq([nil, nil])
219
219
  end
220
220
 
221
221
  it "should return a valid extraction of more than one property name" do
222
- results = Keen.extraction(event_collection, :property_names => ["price", "username"])
223
- results.length.should == 2
224
- results.any? { |result| result["keen"] }.should be_false
225
- results.map { |result| result["price"] }.sort.should == [10, 20]
226
- results.map { |result| result["username"] }.sort.should == ["bob", "ted"]
222
+ results = Keen.extraction(event_collection, :timeframe => "this_2_hours", :property_names => ["price", "username"])
223
+ expect(results.length).to eq(2)
224
+ expect(results.any? { |result| result["keen"] }).to be_falsey
225
+ expect(results.map { |result| result["price"] }.sort).to eq([10, 20])
226
+ expect(results.map { |result| result["username"] }.sort).to eq(["bob", "ted"])
227
227
  end
228
228
 
229
229
  it "should return a valid funnel" do
230
230
  steps = [{
231
231
  :event_collection => event_collection,
232
- :actor_property => "username"
232
+ :actor_property => "username",
233
+ :timeframe => "this_2_hours"
233
234
  }, {
234
235
  :event_collection => @returns_event_collection,
235
- :actor_property => "username"
236
+ :actor_property => "username",
237
+ :timeframe => "this_2_hours"
236
238
  }]
237
239
  results = Keen.funnel(:steps => steps)
238
- results.should == [2, 1]
240
+ expect(results).to eq([2, 1])
239
241
  end
240
242
 
241
243
  it "should return all keys of valid funnel if full result option is passed" do
242
244
  steps = [{
245
+ :timeframe => "this_2_hours",
243
246
  :event_collection => event_collection,
244
247
  :actor_property => "username"
245
248
  }, {
249
+ :timeframe => "this_2_hours",
246
250
  :event_collection => @returns_event_collection,
247
251
  :actor_property => "username"
248
252
  }]
249
253
  results = Keen.funnel({ :steps => steps }, { :response => :all_keys })
250
- results["result"].should == [2, 1]
254
+ expect(results["result"]).to eq([2, 1])
251
255
  end
252
256
 
253
257
  it "should apply filters" do
254
- Keen.count(event_collection, :filters => [{
258
+ expect(Keen.count(event_collection, :timeframe => "this_2_hours", :filters => [{
255
259
  :property_name => "username",
256
260
  :operator => "eq",
257
261
  :property_value => "ted"
258
- }]).should == 1
262
+ }])).to eq(1)
259
263
  end
260
264
  end
261
265
 
@@ -273,9 +277,9 @@ describe "Keen IO API" do
273
277
  { :property_name => "delete", :operator => "eq", :property_value => "me" }
274
278
  ])
275
279
  wait_for_count(event_collection, 1)
276
- results = Keen.extraction(event_collection)
277
- results.length.should == 1
278
- results.first["delete"].should == "you"
280
+ results = Keen.extraction(event_collection, :timeframe => "this_2_hours")
281
+ expect(results.length).to eq(1)
282
+ expect(results.first["delete"]).to eq("you")
279
283
  end
280
284
  end
281
285
 
@@ -286,21 +290,13 @@ describe "Keen IO API" do
286
290
  # requires a project with at least 1 collection
287
291
  it "should return the project's collections as JSON" do
288
292
  first_collection = Keen.event_collections.first
289
- first_collection["properties"]["keen.timestamp"].should == "datetime"
290
- end
291
- end
292
-
293
- describe "event_collection" do
294
- # requires a project with at least 1 collection
295
- it "should return the project's named collection as JSON" do
296
- first_collection = Keen.event_collection(:event_collection)
297
- first_collection["properties"]["keen.timestamp"].should == "datetime"
293
+ expect(first_collection["properties"]["keen.timestamp"]).to eq("datetime")
298
294
  end
299
295
  end
300
296
 
301
297
  describe "project_info" do
302
298
  it "should return the project info as JSON" do
303
- Keen.project_info["url"].should =~ Regexp.new(project_id)
299
+ expect(Keen.project_info["url"]).to include(project_id)
304
300
 
305
301
  end
306
302
  end
@@ -0,0 +1,113 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe Keen do
4
+ let(:client) do
5
+ Keen::Client.new(
6
+ project_id: "12341234",
7
+ master_key: "abcdef",
8
+ api_url: "https://notreal.keen.io"
9
+ )
10
+ end
11
+
12
+ describe "#access_keys" do
13
+ describe "#all" do
14
+
15
+ it "returns all access keys" do
16
+ all_access_keys = [
17
+ key_object()
18
+ ]
19
+
20
+ stub_keen_get(access_keys_endpoint, 200, all_access_keys)
21
+
22
+ all_access_keys_response = client.access_keys.all
23
+
24
+ expect(all_access_keys_response).to eq(all_access_keys)
25
+ end
26
+ end
27
+
28
+ describe "#get" do
29
+ it "returns a specific access key given a key" do
30
+ key = key_object()
31
+
32
+ stub_keen_get(
33
+ access_keys_endpoint + "/#{key["key"]}",
34
+ 200,
35
+ key
36
+ )
37
+
38
+ access_key_response = client.access_keys.get(key["key"])
39
+
40
+ expect(access_key_response).to eq(key)
41
+ end
42
+ end
43
+
44
+ describe "#create" do
45
+ it "returns the created saved query when creation is successful" do
46
+ key = key_object()
47
+
48
+ stub_keen_post(
49
+ access_keys_endpoint, 201, key
50
+ )
51
+
52
+ access_keys_response = client.access_keys.create(key)
53
+
54
+ expect(access_keys_response).to eq(key)
55
+ end
56
+ end
57
+
58
+ describe "#update" do
59
+ it "returns the updated access key when update is successful" do
60
+ key = key_object()
61
+
62
+ stub_keen_post(
63
+ access_keys_endpoint + "/#{key["key"]}", 200, key
64
+ )
65
+
66
+ access_keys_response = client.access_keys.update(key["key"], key)
67
+
68
+ expect(access_keys_response).to eq(key)
69
+ end
70
+ end
71
+
72
+ describe "#delete" do
73
+ it "returns true with deletion is successful" do
74
+ key = "asdf1234"
75
+
76
+ stub_keen_delete(
77
+ access_keys_endpoint + "/#{key}", 204
78
+ )
79
+
80
+ access_keys_response = client.access_keys.delete(key)
81
+
82
+ expect(access_keys_response).to eq(true)
83
+ end
84
+ end
85
+ end
86
+
87
+ def access_keys_endpoint
88
+ client.api_url + "/#{client.api_version}/projects/#{client.project_id}/keys"
89
+ end
90
+
91
+ def key_object(name = "Test Access Key")
92
+ {
93
+ "key" => "SDKFJSDKFJSDKFJSDKFJDSK",
94
+ "name" => name,
95
+ "is_active" => true,
96
+ "permitted" => ["queries", "cached_queries"],
97
+ "options" => {
98
+ "queries" => {
99
+ "filters" => [
100
+ {
101
+ "property_name" => "customer.id",
102
+ "operator" => "eq",
103
+ "property_value" => "asdf12345z"
104
+ }
105
+ ]
106
+ },
107
+ "cached_queries" => {
108
+ "allowed" => ["my_cached_query"]
109
+ }
110
+ }
111
+ }
112
+ end
113
+ end
@@ -14,18 +14,18 @@ describe Keen do
14
14
 
15
15
  it "returns all saved queries" do
16
16
  all_saved_queries = [ {
17
- refresh_rate: 0,
18
- last_modified_date: "2015-10-19T20:14:29.797000+00:00",
19
- query_name: "Analysis-API-Calls-this-1-day",
20
- query: {
21
- filters: [],
22
- analysis_type: "count",
23
- timezone: "UTC",
24
- timeframe: "this_1_days",
25
- event_collection: "analysis_api_call"
17
+ "refresh_rate" => 0,
18
+ "last_modified_date" => "2015-10-19T20:14:29.797000+00:00",
19
+ "query_name" => "Analysis-API-Calls-this-1-day",
20
+ "query" => {
21
+ "filters" => [],
22
+ "analysis_type" => "count",
23
+ "timezone" => "UTC",
24
+ "timeframe" => "this_1_days",
25
+ "event_collection" => "analysis_api_call"
26
26
  },
27
- metadata: {
28
- visualization: { chart_type: "metric"}
27
+ "metadata" => {
28
+ "visualization" => { "chart_type" => "metric"}
29
29
  }
30
30
  } ]
31
31
  stub_keen_get(saved_query_endpoint, 200, all_saved_queries)
@@ -39,22 +39,22 @@ describe Keen do
39
39
  describe "#get" do
40
40
  it "returns a specific saved query given a query id" do
41
41
  saved_query = {
42
- refresh_rate: 0,
43
- last_modified_date: "2015-10-19T20:14:29.797000+00:00",
44
- query_name: "Analysis-API-Calls-this-1-day",
45
- query: {
46
- filters: [],
47
- analysis_type: "count",
48
- timezone: "UTC",
49
- timeframe: "this_1_days",
50
- event_collection: "analysis_api_call"
42
+ "refresh_rate" => 0,
43
+ "last_modified_date" => "2015-10-19T20:14:29.797000+00:00",
44
+ "query_name" => "Analysis-API-Calls-this-1-day",
45
+ "query" => {
46
+ "filters" => [],
47
+ "analysis_type" => "count",
48
+ "timezone" => "UTC",
49
+ "timeframe" => "this_1_days",
50
+ "event_collection" => "analysis_api_call"
51
51
  },
52
- metadata: {
53
- visualization: { chart_type: "metric"}
52
+ "metadata" => {
53
+ "visualization" => { "chart_type" => "metric"}
54
54
  }
55
55
  }
56
56
  stub_keen_get(
57
- saved_query_endpoint + "/#{saved_query[:query_name]}",
57
+ saved_query_endpoint + "/#{saved_query["query_name"]}",
58
58
  200,
59
59
  saved_query
60
60
  )
@@ -84,18 +84,18 @@ describe Keen do
84
84
  describe "#create" do
85
85
  it "returns the created saved query when creation is successful" do
86
86
  saved_query = {
87
- refresh_rate: 0,
88
- last_modified_date: "2015-10-19T20:14:29.797000+00:00",
89
- query_name: "new-query",
90
- query: {
91
- filters: [],
92
- analysis_type: "count",
93
- timezone: "UTC",
94
- timeframe: "this_1_days",
95
- event_collection: "analysis_api_call"
87
+ "refresh_rate" => 0,
88
+ "last_modified_date" => "2015-10-19T20:14:29.797000+00:00",
89
+ "query_name" => "new-query",
90
+ "query" => {
91
+ "filters" => [],
92
+ "analysis_type" => "count",
93
+ "timezone" => "UTC",
94
+ "timeframe" => "this_1_days",
95
+ "event_collection" => "analysis_api_call"
96
96
  },
97
- metadata: {
98
- visualization: { chart_type: "metric"}
97
+ "metadata" => {
98
+ "visualization" => { "chart_type" => "metric"}
99
99
  }
100
100
  }
101
101
  stub_keen_put(
@@ -121,18 +121,18 @@ describe Keen do
121
121
  describe "#update" do
122
122
  it "returns the created saved query when update is successful" do
123
123
  saved_query = {
124
- refresh_rate: 0,
125
- last_modified_date: "2015-10-19T20:14:29.797000+00:00",
126
- query_name: "new-query",
127
- query: {
128
- filters: [],
129
- analysis_type: "count",
130
- timezone: "UTC",
131
- timeframe: "this_1_days",
132
- event_collection: "analysis_api_call"
124
+ "refresh_rate" => 0,
125
+ "last_modified_date" => "2015-10-19T20:14:29.797000+00:00",
126
+ "query_name" => "new-query",
127
+ "query" => {
128
+ "filters" => [],
129
+ "analysis_type" => "count",
130
+ "timezone" => "UTC",
131
+ "timeframe" => "this_1_days",
132
+ "event_collection" => "analysis_api_call"
133
133
  },
134
- metadata: {
135
- visualization: { chart_type: "metric"}
134
+ "metadata" => {
135
+ "visualization" => { "chart_type" => "metric"}
136
136
  }
137
137
  }
138
138
  stub_keen_put(
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kleissner
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-05-15 00:00:00.000000000 Z
12
+ date: 2017-06-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -154,19 +154,22 @@ files:
154
154
  - config/cacert.pem
155
155
  - keen.gemspec
156
156
  - lib/keen.rb
157
+ - lib/keen/access_keys.rb
157
158
  - lib/keen/aes_helper.rb
158
159
  - lib/keen/aes_helper_old.rb
159
160
  - lib/keen/client.rb
160
161
  - lib/keen/client/maintenance_methods.rb
161
162
  - lib/keen/client/publishing_methods.rb
162
163
  - lib/keen/client/querying_methods.rb
163
- - lib/keen/client/saved_queries.rb
164
164
  - lib/keen/http.rb
165
+ - lib/keen/saved_queries.rb
165
166
  - lib/keen/scoped_key.rb
166
167
  - lib/keen/version.rb
168
+ - spec/integration/access_keys_spec.rb
167
169
  - spec/integration/api_spec.rb
168
170
  - spec/integration/saved_query_spec.rb
169
171
  - spec/integration/spec_helper.rb
172
+ - spec/keen/access_keys_spec.rb
170
173
  - spec/keen/client/maintenance_methods_spec.rb
171
174
  - spec/keen/client/publishing_methods_spec.rb
172
175
  - spec/keen/client/querying_methods_spec.rb
@@ -204,9 +207,11 @@ signing_key:
204
207
  specification_version: 4
205
208
  summary: Keen IO API Client
206
209
  test_files:
210
+ - spec/integration/access_keys_spec.rb
207
211
  - spec/integration/api_spec.rb
208
212
  - spec/integration/saved_query_spec.rb
209
213
  - spec/integration/spec_helper.rb
214
+ - spec/keen/access_keys_spec.rb
210
215
  - spec/keen/client/maintenance_methods_spec.rb
211
216
  - spec/keen/client/publishing_methods_spec.rb
212
217
  - spec/keen/client/querying_methods_spec.rb
@@ -1,88 +0,0 @@
1
- require 'keen/version'
2
- require "json"
3
-
4
- class SavedQueries
5
- def initialize(client)
6
- @client = client
7
- end
8
-
9
- def all
10
- process_response(saved_query_response(client.master_key))
11
- end
12
-
13
- def get(saved_query_name, results = false)
14
- saved_query_path = "/#{saved_query_name}"
15
- api_key = client.master_key
16
- if results
17
- saved_query_path += "/result"
18
- # The results path should use the READ KEY
19
- api_key = client.read_key
20
- end
21
-
22
- response = saved_query_response(api_key, saved_query_path)
23
- response_body = JSON.parse(response.body, symbolize_names: true)
24
- process_response(response)
25
- end
26
-
27
- def create(saved_query_name, saved_query_body)
28
- response = Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).put(
29
- path: "#{saved_query_base_url}/#{saved_query_name}",
30
- headers: api_headers(client.master_key, "sync"),
31
- body: saved_query_body
32
- )
33
- process_response(response)
34
- end
35
- alias_method :update, :create
36
-
37
- def delete(saved_query_name)
38
- response = Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).delete(
39
- path: "#{saved_query_base_url}/#{saved_query_name}",
40
- headers: api_headers(client.master_key, "sync")
41
- )
42
- process_response(response)
43
- end
44
-
45
- private
46
-
47
- attr_reader :client
48
-
49
- def saved_query_response(api_key, path = "")
50
- Keen::HTTP::Sync.new(client.api_url, client.proxy_url, client.read_timeout, client.open_timeout).get(
51
- path: saved_query_base_url + path,
52
- headers: api_headers(api_key, "sync")
53
- )
54
- end
55
-
56
- def saved_query_base_url
57
- "/#{client.api_version}/projects/#{client.project_id}/queries/saved"
58
- end
59
-
60
- def api_headers(authorization, sync_type)
61
- user_agent = "keen-gem, v#{Keen::VERSION}, #{sync_type}"
62
- user_agent += ", #{RUBY_VERSION}, #{RUBY_PLATFORM}, #{RUBY_PATCHLEVEL}"
63
- if defined?(RUBY_ENGINE)
64
- user_agent += ", #{RUBY_ENGINE}"
65
- end
66
- { "Content-Type" => "application/json",
67
- "User-Agent" => user_agent,
68
- "Authorization" => authorization,
69
- "Keen-Sdk" => "ruby-#{Keen::VERSION}" }
70
- end
71
-
72
- def process_response(response)
73
- case response.code.to_i
74
- when 204
75
- true
76
- when 200..299
77
- JSON.parse(response.body, symbolize_names: true)
78
- when 400
79
- raise Keen::BadRequestError.new(response.body)
80
- when 401
81
- raise Keen::AuthenticationError.new(response.body)
82
- when 404
83
- raise Keen::NotFoundError.new(response.body)
84
- else
85
- raise Keen::HttpError.new(response.body)
86
- end
87
- end
88
- end