knockapi 0.4.1 → 0.4.4
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/.github/workflows/ruby.yml +52 -0
- data/.rubocop.yml +8 -0
- data/Gemfile +5 -1
- data/Gemfile.lock +16 -1
- data/bin/console +5 -4
- data/knockapi.gemspec +15 -15
- data/lib/knock/base.rb +3 -2
- data/lib/knock/bulk_operations.rb +4 -2
- data/lib/knock/client.rb +32 -26
- data/lib/knock/errors.rb +7 -4
- data/lib/knock/messages.rb +89 -0
- data/lib/knock/objects.rb +191 -7
- data/lib/knock/preferences.rb +5 -3
- data/lib/knock/tenants.rb +73 -0
- data/lib/knock/users.rb +53 -15
- data/lib/knock/version.rb +1 -1
- data/lib/knock/workflows.rb +5 -3
- data/lib/knock.rb +18 -15
- data/spec/tenants_spec.rb +66 -0
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d0a730346c7c39ec862f160ac31fd80844b3f0907129a02ad320bf724e74888
|
4
|
+
data.tar.gz: bab747c80c86891e7e5d8135748deec4cd8c6bee1b20fbddf19546aefebe5646
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7e879b66a557daac3950155ec7429cbfe72b7f6d7f2491eb440f92cf1b1f620753a2dab325751bdb704933df7be8c598b9b47c67b191c7659dbd9470c888f2c
|
7
|
+
data.tar.gz: 689dba9548ddba6fe5e2e90fb339eb2dee6c23f9c8d51ce878d4d163da70453482a1fae0806c7fa56638e3dec9aa0cf38f3c5669c657b11768d7e1087a57dd47
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ "main" ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ "main" ]
|
15
|
+
|
16
|
+
permissions:
|
17
|
+
contents: read
|
18
|
+
|
19
|
+
jobs:
|
20
|
+
test:
|
21
|
+
|
22
|
+
runs-on: ubuntu-latest
|
23
|
+
strategy:
|
24
|
+
matrix:
|
25
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
26
|
+
|
27
|
+
steps:
|
28
|
+
- uses: actions/checkout@v3
|
29
|
+
- name: Set up Ruby
|
30
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
31
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
32
|
+
# uses: ruby/setup-ruby@v1
|
33
|
+
uses: ruby/setup-ruby@2b019609e2b0f1ea1a2bc8ca11cb82ab46ada124
|
34
|
+
with:
|
35
|
+
ruby-version: ${{ matrix.ruby-version }}
|
36
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
37
|
+
- name: Run tests
|
38
|
+
run: bundle exec rspec spec
|
39
|
+
|
40
|
+
lint:
|
41
|
+
|
42
|
+
runs-on: ubuntu-latest
|
43
|
+
steps:
|
44
|
+
- name: Checkout code
|
45
|
+
uses: actions/checkout@v3
|
46
|
+
- name: Install Ruby and gems
|
47
|
+
uses: ruby/setup-ruby@8f312efe1262fb463d906e9bf040319394c18d3e # v1.92
|
48
|
+
with:
|
49
|
+
bundler-cache: true
|
50
|
+
# Add or replace any other lints here
|
51
|
+
- name: Lint Ruby files
|
52
|
+
run: bundle exec rubocop
|
data/.rubocop.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
knockapi (0.4.
|
4
|
+
knockapi (0.4.4)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ast (2.4.2)
|
10
|
+
diff-lcs (1.5.0)
|
10
11
|
parallel (1.20.1)
|
11
12
|
parser (3.0.2.0)
|
12
13
|
ast (~> 2.4.1)
|
@@ -14,6 +15,19 @@ GEM
|
|
14
15
|
rake (13.0.6)
|
15
16
|
regexp_parser (2.1.1)
|
16
17
|
rexml (3.2.5)
|
18
|
+
rspec (3.11.0)
|
19
|
+
rspec-core (~> 3.11.0)
|
20
|
+
rspec-expectations (~> 3.11.0)
|
21
|
+
rspec-mocks (~> 3.11.0)
|
22
|
+
rspec-core (3.11.0)
|
23
|
+
rspec-support (~> 3.11.0)
|
24
|
+
rspec-expectations (3.11.0)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.11.0)
|
27
|
+
rspec-mocks (3.11.1)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.11.0)
|
30
|
+
rspec-support (3.11.0)
|
17
31
|
rubocop (1.18.4)
|
18
32
|
parallel (~> 1.10)
|
19
33
|
parser (>= 3.0.0.0)
|
@@ -42,6 +56,7 @@ DEPENDENCIES
|
|
42
56
|
bundler (>= 2.0.1)
|
43
57
|
knockapi!
|
44
58
|
rake
|
59
|
+
rspec (~> 3.11)
|
45
60
|
standard
|
46
61
|
|
47
62
|
BUNDLED WITH
|
data/bin/console
CHANGED
data/knockapi.gemspec
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require 'knock/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = 'knockapi'
|
9
9
|
spec.version = Knock::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
12
|
-
spec.description =
|
13
|
-
spec.summary =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
10
|
+
spec.authors = ['Knock Labs, Inc.']
|
11
|
+
spec.email = ['support@knock.app']
|
12
|
+
spec.description = 'API client for Knock'
|
13
|
+
spec.summary = 'API client for Knock'
|
14
|
+
spec.homepage = 'https://github.com/knocklabs/knock-ruby'
|
15
|
+
spec.license = 'MIT'
|
16
16
|
spec.metadata = {
|
17
|
-
|
17
|
+
'documentation_uri' => 'https://docs.knock.app'
|
18
18
|
}
|
19
19
|
|
20
20
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
21
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
-
spec.require_paths = [
|
23
|
+
spec.require_paths = ['lib']
|
24
24
|
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency 'bundler', '>= 2.0.1'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'standard'
|
28
28
|
|
29
|
-
spec.required_ruby_version =
|
29
|
+
spec.required_ruby_version = '>= 2.5'
|
30
30
|
end
|
data/lib/knock/base.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Knock
|
2
4
|
## The Base class handles setting and reading the Knock API Key for authentication
|
3
5
|
module Base
|
4
6
|
attr_accessor :key
|
5
7
|
|
6
8
|
class << self
|
7
|
-
|
8
|
-
attr_reader :key
|
9
|
+
attr_accessor :key
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
data/lib/knock/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Knock
|
2
4
|
# A Net::HTTP based API client for interacting with the Knock API
|
3
5
|
module Client
|
@@ -18,7 +20,7 @@ module Knock
|
|
18
20
|
http_status = response.code.to_i
|
19
21
|
handle_error_response(response: response) if http_status >= 400
|
20
22
|
|
21
|
-
JSON.parse(response.body)
|
23
|
+
JSON.parse(response.body) if response.body && (response.body != '')
|
22
24
|
end
|
23
25
|
|
24
26
|
def get_request(path:, auth: false, params: {}, access_token: nil)
|
@@ -27,19 +29,19 @@ module Knock
|
|
27
29
|
|
28
30
|
request = Net::HTTP::Get.new(
|
29
31
|
uri.to_s,
|
30
|
-
|
32
|
+
'Content-Type' => 'application/json'
|
31
33
|
)
|
32
34
|
|
33
|
-
request[
|
34
|
-
request[
|
35
|
+
request['Authorization'] = "Bearer #{access_token || Knock.key!}" if auth
|
36
|
+
request['User-Agent'] = user_agent
|
35
37
|
request
|
36
38
|
end
|
37
39
|
|
38
|
-
def post_request(path:, auth: false,
|
39
|
-
request = Net::HTTP::Post.new(path,
|
40
|
+
def post_request(path:, auth: false, _idempotency_key: nil, body: nil)
|
41
|
+
request = Net::HTTP::Post.new(path, 'Content-Type' => 'application/json')
|
40
42
|
request.body = body.to_json if body
|
41
|
-
request[
|
42
|
-
request[
|
43
|
+
request['Authorization'] = "Bearer #{Knock.key!}" if auth
|
44
|
+
request['User-Agent'] = user_agent
|
43
45
|
request
|
44
46
|
end
|
45
47
|
|
@@ -49,19 +51,19 @@ module Knock
|
|
49
51
|
|
50
52
|
request = Net::HTTP::Delete.new(
|
51
53
|
uri.to_s,
|
52
|
-
|
54
|
+
'Content-Type' => 'application/json'
|
53
55
|
)
|
54
56
|
|
55
|
-
request[
|
56
|
-
request[
|
57
|
+
request['Authorization'] = "Bearer #{Knock.key!}" if auth
|
58
|
+
request['User-Agent'] = user_agent
|
57
59
|
request
|
58
60
|
end
|
59
61
|
|
60
|
-
def put_request(path:, auth: false,
|
61
|
-
request = Net::HTTP::Put.new(path,
|
62
|
+
def put_request(path:, auth: false, _idempotency_key: nil, body: nil)
|
63
|
+
request = Net::HTTP::Put.new(path, 'Content-Type' => 'application/json')
|
62
64
|
request.body = body.to_json if body
|
63
|
-
request[
|
64
|
-
request[
|
65
|
+
request['Authorization'] = "Bearer #{Knock.key!}" if auth
|
66
|
+
request['User-Agent'] = user_agent
|
65
67
|
request
|
66
68
|
end
|
67
69
|
|
@@ -69,6 +71,8 @@ module Knock
|
|
69
71
|
"Knock Ruby - v#{Knock::VERSION}"
|
70
72
|
end
|
71
73
|
|
74
|
+
# rubocop:disable Metrics/AbcSize
|
75
|
+
|
72
76
|
def handle_error_response(response:)
|
73
77
|
http_status = response.code.to_i
|
74
78
|
json = JSON.parse(response.body)
|
@@ -76,41 +80,43 @@ module Knock
|
|
76
80
|
case http_status
|
77
81
|
when 400
|
78
82
|
raise InvalidRequestError.new(
|
79
|
-
message: json[
|
83
|
+
message: json['message'],
|
80
84
|
http_status: http_status,
|
81
|
-
request_id: response[
|
85
|
+
request_id: response['x-request-id']
|
82
86
|
)
|
83
87
|
when 401
|
84
88
|
raise AuthenticationError.new(
|
85
|
-
message: json[
|
89
|
+
message: json['message'],
|
86
90
|
http_status: http_status,
|
87
|
-
request_id: response[
|
91
|
+
request_id: response['x-request-id']
|
88
92
|
)
|
89
93
|
when 404
|
90
94
|
raise APIError.new(
|
91
|
-
message: json[
|
95
|
+
message: json['message'],
|
92
96
|
http_status: http_status,
|
93
|
-
request_id: response[
|
97
|
+
request_id: response['x-request-id']
|
94
98
|
)
|
95
99
|
when 422
|
96
|
-
message = json[
|
97
|
-
errors = extract_error(json[
|
100
|
+
message = json['message']
|
101
|
+
errors = extract_error(json['errors']) if json['errors']
|
98
102
|
message += " (#{errors})" if errors
|
99
103
|
|
100
104
|
raise InvalidRequestError.new(
|
101
105
|
message: message,
|
102
106
|
http_status: http_status,
|
103
|
-
request_id: response[
|
107
|
+
request_id: response['x-request-id']
|
104
108
|
)
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
112
|
+
# rubocop:enable Metrics/AbcSize
|
113
|
+
|
108
114
|
private
|
109
115
|
|
110
116
|
def extract_error(errors)
|
111
117
|
errors.map do |error|
|
112
|
-
"#{error[
|
113
|
-
end.join(
|
118
|
+
"#{error['field']}: #{error['message']} (#{error['type']})"
|
119
|
+
end.join('; ')
|
114
120
|
end
|
115
121
|
end
|
116
122
|
end
|
data/lib/knock/errors.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Knock
|
4
|
+
# Knock specific errors
|
2
5
|
class KnockError < StandardError
|
3
|
-
attr_reader :http_status
|
4
|
-
attr_reader :request_id
|
6
|
+
attr_reader :http_status, :request_id
|
5
7
|
|
6
8
|
def initialize(message: nil, error: nil, error_description: nil, http_status: nil, request_id: nil)
|
9
|
+
super
|
7
10
|
@message = message
|
8
11
|
@error = error
|
9
12
|
@error_description = error_description
|
@@ -12,8 +15,8 @@ module Knock
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def to_s
|
15
|
-
status_string = @http_status.nil? ?
|
16
|
-
id_string = @request_id.nil? ?
|
18
|
+
status_string = @http_status.nil? ? '' : "Status #{@http_status}, "
|
19
|
+
id_string = @request_id.nil? ? '' : " - request ID: #{@request_id}"
|
17
20
|
|
18
21
|
if @error && @error_description
|
19
22
|
error_string = "error: #{@error}, error_description: #{@error_description}"
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Knock
|
7
|
+
# Methods for interacting with messages in Knock
|
8
|
+
module Messages
|
9
|
+
class << self
|
10
|
+
include Base
|
11
|
+
include Client
|
12
|
+
|
13
|
+
# Retrieves a paginated list of messages for the provided environment
|
14
|
+
#
|
15
|
+
# @param [Hash] options Options to pass to the messages endpoint query
|
16
|
+
#
|
17
|
+
# @return [Hash] Paginated list of Message records
|
18
|
+
def list(options: {})
|
19
|
+
request = get_request(
|
20
|
+
auth: true,
|
21
|
+
path: '/v1/messages',
|
22
|
+
params: options
|
23
|
+
)
|
24
|
+
|
25
|
+
execute_request(request: request)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Retrieves a Message
|
29
|
+
#
|
30
|
+
# @param [String] id The message id
|
31
|
+
#
|
32
|
+
# @return [Hash] The Message
|
33
|
+
def get(id:)
|
34
|
+
request = get_request(
|
35
|
+
auth: true,
|
36
|
+
path: "/v1/messages/#{id}"
|
37
|
+
)
|
38
|
+
|
39
|
+
execute_request(request: request)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get a Message's content
|
43
|
+
#
|
44
|
+
# @param [String] id The message id
|
45
|
+
#
|
46
|
+
# @return [Hash] The Message content
|
47
|
+
def get_content(id:)
|
48
|
+
request = get_request(
|
49
|
+
auth: true,
|
50
|
+
path: "/v1/messages/#{id}/content"
|
51
|
+
)
|
52
|
+
|
53
|
+
execute_request(request: request)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get a Message's activities
|
57
|
+
#
|
58
|
+
# @param [String] id The message id
|
59
|
+
# @param [Hash] options Options to pass to the paginated activities endpoint query
|
60
|
+
#
|
61
|
+
# @return [Hash] Paginated Message's activities
|
62
|
+
def get_activities(id:, options: {})
|
63
|
+
request = get_request(
|
64
|
+
auth: true,
|
65
|
+
path: "/v1/messages/#{id}/activities",
|
66
|
+
params: options
|
67
|
+
)
|
68
|
+
|
69
|
+
execute_request(request: request)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Get a Message's events
|
73
|
+
#
|
74
|
+
# @param [String] id The message id
|
75
|
+
# @param [Hash] options Options to pass to the paginated events endpoint query
|
76
|
+
#
|
77
|
+
# @return [Hash] Paginated Message's events
|
78
|
+
def get_events(id:, options: {})
|
79
|
+
request = get_request(
|
80
|
+
auth: true,
|
81
|
+
path: "/v1/messages/#{id}/events",
|
82
|
+
params: options
|
83
|
+
)
|
84
|
+
|
85
|
+
execute_request(request: request)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/knock/objects.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
3
5
|
|
4
6
|
module Knock
|
5
|
-
#
|
7
|
+
# Methods for interacting with objects in Knock
|
8
|
+
# rubocop:disable Metrics/ModuleLength
|
6
9
|
module Objects
|
7
10
|
class << self
|
8
11
|
include Base
|
9
12
|
include Client
|
10
13
|
|
14
|
+
DEFAULT_PREFERENCE_SET_ID = 'default'
|
15
|
+
|
11
16
|
# Retrieves an Object in a collection
|
12
17
|
#
|
13
18
|
# @param [String] collection The collection the object is in
|
@@ -50,7 +55,7 @@ module Knock
|
|
50
55
|
request = post_request(
|
51
56
|
auth: true,
|
52
57
|
path: "/v1/objects/#{collection}/bulk/set",
|
53
|
-
body: {objects: objects}
|
58
|
+
body: { objects: objects }
|
54
59
|
)
|
55
60
|
|
56
61
|
execute_request(request: request)
|
@@ -81,7 +86,7 @@ module Knock
|
|
81
86
|
request = post_request(
|
82
87
|
auth: true,
|
83
88
|
path: "/v1/objects/#{collection}/bulk/delete",
|
84
|
-
body: {object_ids: object_ids}
|
89
|
+
body: { object_ids: object_ids }
|
85
90
|
)
|
86
91
|
|
87
92
|
execute_request(request: request)
|
@@ -111,15 +116,194 @@ module Knock
|
|
111
116
|
# @param [Hash] channel_data channel data
|
112
117
|
#
|
113
118
|
# @return [Hash] channel data
|
114
|
-
def set_channel_data(id:, channel_id:, channel_data:)
|
119
|
+
def set_channel_data(collection:, id:, channel_id:, channel_data:)
|
115
120
|
request = put_request(
|
116
121
|
auth: true,
|
117
122
|
path: "/v1/objects/#{collection}/#{id}/channel_data/#{channel_id}",
|
118
|
-
body: {data: channel_data}
|
123
|
+
body: { data: channel_data }
|
124
|
+
)
|
125
|
+
|
126
|
+
execute_request(request: request)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Unsets object channel data for the given channel id
|
130
|
+
#
|
131
|
+
# @param [String] collection The collection the object is in
|
132
|
+
# @param [String] id The object id
|
133
|
+
# @param [String] channel_id target channel ID
|
134
|
+
#
|
135
|
+
# @return [Hash] channel data
|
136
|
+
def unset_channel_data(collection:, id:, channel_id:)
|
137
|
+
request = delete_request(
|
138
|
+
auth: true,
|
139
|
+
path: "/v1/objects/#{collection}/#{id}/channel_data/#{channel_id}"
|
140
|
+
)
|
141
|
+
|
142
|
+
execute_request(request: request)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Get object's messages
|
146
|
+
#
|
147
|
+
# @param [String] collection The collection the object is in
|
148
|
+
# @param [String] id The object id
|
149
|
+
# @param [Hash] options Options to pass to the messages endpoint query
|
150
|
+
#
|
151
|
+
# @return [Hash] Paginated messages response
|
152
|
+
def get_messages(collection:, id:, options: {})
|
153
|
+
request = get_request(
|
154
|
+
auth: true,
|
155
|
+
path: "/v1/objects/#{collection}/#{id}/messages",
|
156
|
+
params: options
|
157
|
+
)
|
158
|
+
|
159
|
+
execute_request(request: request)
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Preferences
|
164
|
+
##
|
165
|
+
|
166
|
+
# Returns all preference sets for the object
|
167
|
+
#
|
168
|
+
# @param [String] collection The collection the object is in
|
169
|
+
# @param [String] id The object id
|
170
|
+
#
|
171
|
+
# @return [Array] The preference sets
|
172
|
+
def get_all_preferences(collection:, id:)
|
173
|
+
endpoint = "/v1/objects/#{collection}/#{id}/preferences"
|
174
|
+
|
175
|
+
request = get_request(
|
176
|
+
auth: true,
|
177
|
+
path: endpoint
|
178
|
+
)
|
179
|
+
|
180
|
+
execute_request(request: request)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Gets a single preference set, defaults to the 'default' set
|
184
|
+
# for the object given.
|
185
|
+
#
|
186
|
+
# @param [String] collection The collection the object is in
|
187
|
+
# @param [String] id The object id
|
188
|
+
# @param [String] preference_set The preference set ID (defaults to `default`)
|
189
|
+
#
|
190
|
+
# @return [Hash] The preference set (if it exists)
|
191
|
+
def get_preferences(collection:, id:, preference_set: DEFAULT_PREFERENCE_SET_ID)
|
192
|
+
endpoint = "/v1/objects/#{collection}/#{id}/preferences/#{preference_set}"
|
193
|
+
|
194
|
+
request = get_request(
|
195
|
+
auth: true,
|
196
|
+
path: endpoint
|
197
|
+
)
|
198
|
+
|
199
|
+
execute_request(request: request)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Sets multiple preferences at once for the preference set.
|
203
|
+
#
|
204
|
+
# @param [String] collection The collection the object is in
|
205
|
+
# @param [String] id The object id
|
206
|
+
# @param [String] preference_set The preference set ID (defaults to `default`)
|
207
|
+
# @param [Hash] channel_types The channel_types hash to set
|
208
|
+
# @param [Hash] workflows The workflows hash to set
|
209
|
+
# @param [Hash] categories The categories hash to set
|
210
|
+
#
|
211
|
+
# @return [Hash] The preference set
|
212
|
+
|
213
|
+
def set_preferences(
|
214
|
+
collection:,
|
215
|
+
id:,
|
216
|
+
channel_types: nil,
|
217
|
+
workflows: nil,
|
218
|
+
categories: nil,
|
219
|
+
preference_set: DEFAULT_PREFERENCE_SET_ID
|
220
|
+
)
|
221
|
+
endpoint = "/v1/objects/#{collection}/#{id}/preferences/#{preference_set}"
|
222
|
+
|
223
|
+
request = put_request(
|
224
|
+
auth: true,
|
225
|
+
path: endpoint,
|
226
|
+
body: {
|
227
|
+
channel_types: channel_types,
|
228
|
+
workflows: workflows,
|
229
|
+
categories: categories
|
230
|
+
}
|
231
|
+
)
|
232
|
+
|
233
|
+
execute_request(request: request)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Sets preferences for the given channel type
|
237
|
+
#
|
238
|
+
# @param [String] collection The collection the object is in
|
239
|
+
# @param [String] id The object id
|
240
|
+
# @param [String] preference_set The preference set ID (defaults to `default`)
|
241
|
+
# @param [String] channel_type The channel type to set
|
242
|
+
# @param [Bool] setting Whether the channel type is enabled or not
|
243
|
+
#
|
244
|
+
# @return [Hash] The preference set
|
245
|
+
def set_channel_type_preferences(collection:,
|
246
|
+
id:,
|
247
|
+
channel_type:,
|
248
|
+
setting:,
|
249
|
+
preference_set: DEFAULT_PREFERENCE_SET_ID)
|
250
|
+
endpoint = "/v1/objects/#{collection}/#{id}/preferences/#{preference_set}/channel_types/#{channel_type}"
|
251
|
+
|
252
|
+
request = put_request(
|
253
|
+
auth: true,
|
254
|
+
path: endpoint,
|
255
|
+
body: { subscribed: setting }
|
256
|
+
)
|
257
|
+
|
258
|
+
execute_request(request: request)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Sets preferences for the given workflow
|
262
|
+
#
|
263
|
+
# @param [String] collection The collection the object is in
|
264
|
+
# @param [String] id The object id
|
265
|
+
# @param [String] preference_set The preference set ID (defaults to `default`)
|
266
|
+
# @param [String] workflow The workflow to set preferences for
|
267
|
+
# @param [Bool | Hash] setting Either a boolean to indicate if the type is enabled
|
268
|
+
# or a hash containing channel types and settings
|
269
|
+
#
|
270
|
+
# @return [Hash] The preference set
|
271
|
+
def set_workflow_preferences(collection:, id:, workflow:, setting:, preference_set: DEFAULT_PREFERENCE_SET_ID)
|
272
|
+
params = setting.is_a?(Hash) ? setting : { subscribed: setting }
|
273
|
+
endpoint = "/v1/objects/#{collection}/#{id}/preferences/#{preference_set}/workflows/#{workflow}"
|
274
|
+
|
275
|
+
request = put_request(
|
276
|
+
auth: true,
|
277
|
+
path: endpoint,
|
278
|
+
body: params
|
279
|
+
)
|
280
|
+
|
281
|
+
execute_request(request: request)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Sets preferences for the given category
|
285
|
+
#
|
286
|
+
# @param [String] collection The collection the object is in
|
287
|
+
# @param [String] id The object id
|
288
|
+
# @param [String] preference_set The preference set ID (defaults to `default`)
|
289
|
+
# @param [String] category The category to set preferences for
|
290
|
+
# @param [Bool | Hash] setting Either a boolean to indicate if the type is enabled
|
291
|
+
# or a hash containing channel types and settings
|
292
|
+
#
|
293
|
+
# @return [Hash] The preference set
|
294
|
+
def set_category_preferences(collection:, id:, category:, setting:, preference_set: DEFAULT_PREFERENCE_SET_ID)
|
295
|
+
params = setting.is_a?(Hash) ? setting : { subscribed: setting }
|
296
|
+
endpoint = "/v1/objects/#{collection}/#{id}/preferences/#{preference_set}/categories/#{category}"
|
297
|
+
|
298
|
+
request = put_request(
|
299
|
+
auth: true,
|
300
|
+
path: endpoint,
|
301
|
+
body: params
|
119
302
|
)
|
120
303
|
|
121
304
|
execute_request(request: request)
|
122
305
|
end
|
123
306
|
end
|
124
307
|
end
|
308
|
+
# rubocop:enable Metrics/ModuleLength
|
125
309
|
end
|
data/lib/knock/preferences.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
3
5
|
|
4
6
|
module Knock
|
5
7
|
# Provides convienience methods for working with preferences (deprecated)
|
@@ -36,7 +38,7 @@ module Knock
|
|
36
38
|
# @param [String] preference_set The preference set ID (defaults to `default`)
|
37
39
|
# @param [Hash] preferences The preferences hash to set
|
38
40
|
#
|
39
|
-
#
|
41
|
+
# @return [Hash] The preference set
|
40
42
|
# @deprecated Please use {#Knock::Users.set_preferences} instead
|
41
43
|
def update(
|
42
44
|
user_id:,
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Knock
|
7
|
+
# Methods for interacting with tenants in Knock
|
8
|
+
module Tenants
|
9
|
+
class << self
|
10
|
+
include Base
|
11
|
+
include Client
|
12
|
+
|
13
|
+
# Retrieves all Tenants in environment
|
14
|
+
#
|
15
|
+
# @param [Hash] options Options to pass to the tenants endpoint query
|
16
|
+
#
|
17
|
+
# @return [Hash] Paginated list of Tenant records
|
18
|
+
def list(options: {})
|
19
|
+
request = get_request(
|
20
|
+
auth: true,
|
21
|
+
path: '/v1/tenants',
|
22
|
+
params: options
|
23
|
+
)
|
24
|
+
|
25
|
+
execute_request(request: request)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Retrieves a Tenant
|
29
|
+
#
|
30
|
+
# @param [String] id The Tenant id
|
31
|
+
#
|
32
|
+
# @return [Hash] The Tenant
|
33
|
+
def get(id:)
|
34
|
+
request = get_request(
|
35
|
+
auth: true,
|
36
|
+
path: "/v1/tenants/#{id}"
|
37
|
+
)
|
38
|
+
|
39
|
+
execute_request(request: request)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Upserts a Tenant
|
43
|
+
#
|
44
|
+
# @param [String] id The Tenant id
|
45
|
+
# @param [Hash] tenant_data The data to set on the Tenant
|
46
|
+
#
|
47
|
+
# @return [Hash] The Tenant
|
48
|
+
def set(id:, tenant_data: {})
|
49
|
+
request = put_request(
|
50
|
+
auth: true,
|
51
|
+
path: "/v1/tenants/#{id}",
|
52
|
+
body: tenant_data
|
53
|
+
)
|
54
|
+
|
55
|
+
execute_request(request: request)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Deletes a Tenant
|
59
|
+
#
|
60
|
+
# @param [String] id The Tenant id
|
61
|
+
#
|
62
|
+
# @return [nil] Nothing
|
63
|
+
def delete(id:)
|
64
|
+
request = delete_request(
|
65
|
+
auth: true,
|
66
|
+
path: "/v1/tenants/#{id}"
|
67
|
+
)
|
68
|
+
|
69
|
+
execute_request(request: request)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/knock/users.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
3
5
|
|
4
6
|
module Knock
|
5
7
|
# Provides convienience methods for working with users
|
8
|
+
# rubocop:disable Metrics/ModuleLength
|
6
9
|
module Users
|
7
10
|
class << self
|
8
11
|
include Base
|
9
12
|
include Client
|
10
13
|
|
11
|
-
DEFAULT_PREFERENCE_SET_ID =
|
14
|
+
DEFAULT_PREFERENCE_SET_ID = 'default'
|
12
15
|
|
13
16
|
# Identifies the user
|
14
17
|
#
|
@@ -34,8 +37,8 @@ module Knock
|
|
34
37
|
def bulk_identify(users: [])
|
35
38
|
request = post_request(
|
36
39
|
auth: true,
|
37
|
-
path:
|
38
|
-
body: {users: users}
|
40
|
+
path: '/v1/users/bulk/identify',
|
41
|
+
body: { users: users }
|
39
42
|
)
|
40
43
|
|
41
44
|
execute_request(request: request)
|
@@ -77,8 +80,8 @@ module Knock
|
|
77
80
|
def bulk_delete(user_ids: [])
|
78
81
|
request = post_request(
|
79
82
|
auth: true,
|
80
|
-
path:
|
81
|
-
body: {user_ids: user_ids}
|
83
|
+
path: '/v1/users/bulk/delete',
|
84
|
+
body: { user_ids: user_ids }
|
82
85
|
)
|
83
86
|
|
84
87
|
execute_request(request: request)
|
@@ -198,12 +201,10 @@ module Knock
|
|
198
201
|
preferences: {},
|
199
202
|
preference_set: DEFAULT_PREFERENCE_SET_ID
|
200
203
|
)
|
201
|
-
endpoint =
|
204
|
+
endpoint = '/v1/users/bulk/preferences'
|
202
205
|
|
203
206
|
# Put the preference set id if it doesn't already exist
|
204
|
-
unless preferences.has_key(
|
205
|
-
preferences["id"] = preference_set
|
206
|
-
end
|
207
|
+
preferences['id'] = preference_set unless preferences.has_key('id')
|
207
208
|
|
208
209
|
request = put_request(
|
209
210
|
auth: true,
|
@@ -231,7 +232,7 @@ module Knock
|
|
231
232
|
request = put_request(
|
232
233
|
auth: true,
|
233
234
|
path: endpoint,
|
234
|
-
body: {subscribed: setting}
|
235
|
+
body: { subscribed: setting }
|
235
236
|
)
|
236
237
|
|
237
238
|
execute_request(request: request)
|
@@ -247,7 +248,7 @@ module Knock
|
|
247
248
|
#
|
248
249
|
# @return [Hash] The preference set
|
249
250
|
def set_workflow_preferences(user_id:, workflow:, setting:, preference_set: DEFAULT_PREFERENCE_SET_ID)
|
250
|
-
params = setting.is_a?(Hash) ? setting : {subscribed: setting}
|
251
|
+
params = setting.is_a?(Hash) ? setting : { subscribed: setting }
|
251
252
|
endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}/workflows/#{workflow}"
|
252
253
|
|
253
254
|
request = put_request(
|
@@ -269,7 +270,7 @@ module Knock
|
|
269
270
|
#
|
270
271
|
# @return [Hash] The preference set
|
271
272
|
def set_category_preferences(user_id:, category:, setting:, preference_set: DEFAULT_PREFERENCE_SET_ID)
|
272
|
-
params = setting.is_a?(Hash) ? setting : {subscribed: setting}
|
273
|
+
params = setting.is_a?(Hash) ? setting : { subscribed: setting }
|
273
274
|
endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}/categories/#{category}"
|
274
275
|
|
275
276
|
request = put_request(
|
@@ -311,11 +312,48 @@ module Knock
|
|
311
312
|
request = put_request(
|
312
313
|
auth: true,
|
313
314
|
path: "/v1/users/#{id}/channel_data/#{channel_id}",
|
314
|
-
body: {data: channel_data}
|
315
|
+
body: { data: channel_data }
|
316
|
+
)
|
317
|
+
|
318
|
+
execute_request(request: request)
|
319
|
+
end
|
320
|
+
|
321
|
+
# Unsets user's channel data for the given channel id
|
322
|
+
#
|
323
|
+
# @param [String] id the user ID
|
324
|
+
# @param [String] channel_id target channel ID
|
325
|
+
# @param [Hash] channel_data channel data
|
326
|
+
#
|
327
|
+
# @return [Hash] channel data
|
328
|
+
def unset_channel_data(id:, channel_id:)
|
329
|
+
request = delete_request(
|
330
|
+
auth: true,
|
331
|
+
path: "/v1/users/#{id}/channel_data/#{channel_id}"
|
332
|
+
)
|
333
|
+
|
334
|
+
execute_request(request: request)
|
335
|
+
end
|
336
|
+
|
337
|
+
##
|
338
|
+
# Messages
|
339
|
+
##
|
340
|
+
|
341
|
+
# Get user's messages
|
342
|
+
#
|
343
|
+
# @param [String] id the user ID
|
344
|
+
# @param [Hash] options Options to pass to the messages endpoint query
|
345
|
+
#
|
346
|
+
# @return [Hash] Paginated messages response
|
347
|
+
def get_messages(id:, options: {})
|
348
|
+
request = get_request(
|
349
|
+
auth: true,
|
350
|
+
path: "/v1/users/#{id}/messages",
|
351
|
+
params: options
|
315
352
|
)
|
316
353
|
|
317
354
|
execute_request(request: request)
|
318
355
|
end
|
319
356
|
end
|
320
357
|
end
|
358
|
+
# rubocop:enable Metrics/ModuleLength
|
321
359
|
end
|
data/lib/knock/version.rb
CHANGED
data/lib/knock/workflows.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
3
5
|
|
4
6
|
module Knock
|
5
7
|
# Methods for interacting with workflows in Knock
|
@@ -11,7 +13,7 @@ module Knock
|
|
11
13
|
# Triggers the workflow with the given key
|
12
14
|
#
|
13
15
|
# @param [String] key The workflow key
|
14
|
-
# @param [String, Hash] actor The actor identifier
|
16
|
+
# @param [String, Hash] actor The actor identifier (optional)
|
15
17
|
# @param [Array<String, Hash>] recipients The recipient identifiers
|
16
18
|
# @param [Hash] data The data to pass to the workflow
|
17
19
|
# @param [String] cancellation_key An optional key to identify this workflow
|
data/lib/knock.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'knock/version'
|
4
|
+
require 'json'
|
5
5
|
|
6
|
+
# Setup for Knock client
|
6
7
|
module Knock
|
7
|
-
API_HOSTNAME = ENV[
|
8
|
+
API_HOSTNAME = ENV['KNOCK_API_HOSTNAME'] || 'api.knock.app'
|
8
9
|
|
9
10
|
def self.key=(value)
|
10
11
|
Base.key = value
|
@@ -15,25 +16,27 @@ module Knock
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def self.key!
|
18
|
-
key || raise(
|
19
|
+
key || raise('Knock.key not set')
|
19
20
|
end
|
20
21
|
|
21
|
-
autoload :Base,
|
22
|
-
autoload :Client,
|
22
|
+
autoload :Base, 'knock/base'
|
23
|
+
autoload :Client, 'knock/client'
|
23
24
|
|
24
25
|
# Resources
|
25
|
-
autoload :Preferences,
|
26
|
-
autoload :Users,
|
27
|
-
autoload :Workflows,
|
28
|
-
autoload :BulkOperations,
|
29
|
-
autoload :Objects,
|
26
|
+
autoload :Preferences, 'knock/preferences'
|
27
|
+
autoload :Users, 'knock/users'
|
28
|
+
autoload :Workflows, 'knock/workflows'
|
29
|
+
autoload :BulkOperations, 'knock/bulk_operations'
|
30
|
+
autoload :Objects, 'knock/objects'
|
31
|
+
autoload :Tenants, 'knock/tenants'
|
32
|
+
autoload :Messages, 'knock/messages'
|
30
33
|
|
31
34
|
# Errors
|
32
|
-
autoload :APIError,
|
33
|
-
autoload :AuthenticationError,
|
34
|
-
autoload :InvalidRequestError,
|
35
|
+
autoload :APIError, 'knock/errors'
|
36
|
+
autoload :AuthenticationError, 'knock/errors'
|
37
|
+
autoload :InvalidRequestError, 'knock/errors'
|
35
38
|
|
36
|
-
key = ENV[
|
39
|
+
key = ENV['KNOCK_API_KEY']
|
37
40
|
Knock.key = key unless key.nil?
|
38
41
|
|
39
42
|
# Triggers the workflow with the given key
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../lib/knock'
|
4
|
+
# rubocop:disable Metrics/BlockLength
|
5
|
+
describe 'tenant tests' do
|
6
|
+
before do
|
7
|
+
allow_any_instance_of(Knock::Client)
|
8
|
+
.to receive(:execute_request)
|
9
|
+
.with({ request: 'request' })
|
10
|
+
.and_return('ok')
|
11
|
+
end
|
12
|
+
describe '#list' do
|
13
|
+
before do
|
14
|
+
allow_any_instance_of(Knock::Client)
|
15
|
+
.to receive(:get_request)
|
16
|
+
.with({ auth: true,
|
17
|
+
path: '/v1/tenants',
|
18
|
+
params: {} })
|
19
|
+
.and_return('request')
|
20
|
+
end
|
21
|
+
it 'sends the correct parameters to the tenants API' do
|
22
|
+
Knock::Tenants.list(options: {})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#get' do
|
27
|
+
before do
|
28
|
+
allow_any_instance_of(Knock::Client)
|
29
|
+
.to receive(:get_request)
|
30
|
+
.with({ auth: true,
|
31
|
+
path: '/v1/tenants/tenant_id' })
|
32
|
+
.and_return('request')
|
33
|
+
end
|
34
|
+
it 'sends the correct parameters to the tenants API' do
|
35
|
+
Knock::Tenants.get(id: 'tenant_id')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#delete' do
|
40
|
+
before do
|
41
|
+
allow_any_instance_of(Knock::Client)
|
42
|
+
.to receive(:delete_request)
|
43
|
+
.with({ auth: true,
|
44
|
+
path: '/v1/tenants/tenant_id' })
|
45
|
+
.and_return('request')
|
46
|
+
end
|
47
|
+
it 'sends the correct parameters to the tenants API' do
|
48
|
+
Knock::Tenants.delete(id: 'tenant_id')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#set' do
|
53
|
+
before do
|
54
|
+
body = { name: 'My tenant', settings: { branding: { primary_color: '#FFFFFF' } } }
|
55
|
+
allow_any_instance_of(Knock::Client).to receive(:put_request)
|
56
|
+
.with({ auth: true,
|
57
|
+
body: body, path: '/v1/tenants/tenant_id' })
|
58
|
+
.and_return('request')
|
59
|
+
end
|
60
|
+
it 'sends the correct parameters to the tenants API' do
|
61
|
+
tenant_data = { name: 'My tenant', settings: { branding: { primary_color: '#FFFFFF' } } }
|
62
|
+
Knock::Tenants.set(id: 'tenant_id', tenant_data: tenant_data)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
# rubocop:enable Metrics/BlockLength
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knockapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Knock Labs, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -62,7 +62,9 @@ extensions: []
|
|
62
62
|
extra_rdoc_files: []
|
63
63
|
files:
|
64
64
|
- ".github/workflows/publish.yml"
|
65
|
+
- ".github/workflows/ruby.yml"
|
65
66
|
- ".gitignore"
|
67
|
+
- ".rubocop.yml"
|
66
68
|
- ".ruby-version"
|
67
69
|
- Gemfile
|
68
70
|
- Gemfile.lock
|
@@ -76,11 +78,14 @@ files:
|
|
76
78
|
- lib/knock/bulk_operations.rb
|
77
79
|
- lib/knock/client.rb
|
78
80
|
- lib/knock/errors.rb
|
81
|
+
- lib/knock/messages.rb
|
79
82
|
- lib/knock/objects.rb
|
80
83
|
- lib/knock/preferences.rb
|
84
|
+
- lib/knock/tenants.rb
|
81
85
|
- lib/knock/users.rb
|
82
86
|
- lib/knock/version.rb
|
83
87
|
- lib/knock/workflows.rb
|
88
|
+
- spec/tenants_spec.rb
|
84
89
|
homepage: https://github.com/knocklabs/knock-ruby
|
85
90
|
licenses:
|
86
91
|
- MIT
|
@@ -101,8 +106,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
106
|
- !ruby/object:Gem::Version
|
102
107
|
version: '0'
|
103
108
|
requirements: []
|
104
|
-
rubygems_version: 3.3.
|
109
|
+
rubygems_version: 3.3.7
|
105
110
|
signing_key:
|
106
111
|
specification_version: 4
|
107
112
|
summary: API client for Knock
|
108
|
-
test_files:
|
113
|
+
test_files:
|
114
|
+
- spec/tenants_spec.rb
|