knockapi 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: df2a97ad8702bbb6843e12eeca370179e4ce14e1c591312d8bc6462c9114fd07
4
+ data.tar.gz: bdaae5b1b47ef4e022ff4fa81f59250705880801ef6075af337b41ee657ef79a
5
+ SHA512:
6
+ metadata.gz: 799e436d7ca5514f82b76f789f7fcf031fb67ed1d5f2705b34c9313c3a9369b04b450bd72e4e18c1d29d4119cf65a353729a5102fabfb1be3ef3ade48a9bd047
7
+ data.tar.gz: aec1077db54be921685100263417cc360af0ede27c382282a0f117bf59bce26d41d1af7db4775dadfb7b19b27e3b53ceae1fab1c8b4c73b43f56dbd045ebc3a8
data/.gitignore ADDED
@@ -0,0 +1,49 @@
1
+ *.gem
2
+ *.rbc
3
+ *.DS_Store
4
+ /.config
5
+ /coverage/
6
+ /InstalledFiles
7
+ /pkg/
8
+ /spec/reports/
9
+ /spec/examples.txt
10
+ /test/tmp/
11
+ /test/version_tmp/
12
+ /tmp/
13
+
14
+ # Used by dotenv library to load environment variables.
15
+ # .env
16
+
17
+ # Ignore Byebug command history file.
18
+ .byebug_history
19
+
20
+ ## Specific to RubyMotion (use of CocoaPods):
21
+ #
22
+ # We recommend against adding the Pods directory to your .gitignore. However
23
+ # you should judge for yourself, the pros and cons are mentioned at:
24
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
25
+ #
26
+ # vendor/Pods/
27
+
28
+ ## Documentation cache and generated files:
29
+ /.yardoc/
30
+ /_yardoc/
31
+ /doc/
32
+ /rdoc/
33
+
34
+ ## Environment normalization:
35
+ /.bundle/
36
+ /vendor/bundle
37
+ /lib/bundler/man/
38
+
39
+ # for a library or gem, you might want to ignore these files since the code is
40
+ # intended to run in multiple environments; otherwise, check them in:
41
+ # Gemfile.lock
42
+ # .ruby-version
43
+ # .ruby-gemset
44
+
45
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
46
+ .rvmrc
47
+
48
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
49
+ # .rubocop-https?--*
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.2
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ knockapi (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ parallel (1.20.1)
11
+ parser (3.0.2.0)
12
+ ast (~> 2.4.1)
13
+ rainbow (3.0.0)
14
+ rake (13.0.6)
15
+ regexp_parser (2.1.1)
16
+ rexml (3.2.5)
17
+ rubocop (1.18.4)
18
+ parallel (~> 1.10)
19
+ parser (>= 3.0.0.0)
20
+ rainbow (>= 2.2.2, < 4.0)
21
+ regexp_parser (>= 1.8, < 3.0)
22
+ rexml
23
+ rubocop-ast (>= 1.8.0, < 2.0)
24
+ ruby-progressbar (~> 1.7)
25
+ unicode-display_width (>= 1.4.0, < 3.0)
26
+ rubocop-ast (1.10.0)
27
+ parser (>= 3.0.1.1)
28
+ rubocop-performance (1.11.4)
29
+ rubocop (>= 1.7.0, < 2.0)
30
+ rubocop-ast (>= 0.4.0)
31
+ ruby-progressbar (1.11.0)
32
+ standard (1.1.7)
33
+ rubocop (= 1.18.4)
34
+ rubocop-performance (= 1.11.4)
35
+ unicode-display_width (2.0.0)
36
+
37
+ PLATFORMS
38
+ x86_64-darwin-19
39
+
40
+ DEPENDENCIES
41
+ bundler (>= 2.0.1)
42
+ knockapi!
43
+ rake
44
+ standard
45
+
46
+ BUNDLED WITH
47
+ 2.2.22
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Knock Labs, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Knock Ruby library
2
+
3
+ Knock API access for applications written in Ruby.
4
+
5
+ ## Documentation
6
+
7
+ See the documentation for Ruby usage examples.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ gem install knockapi
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ To use the library you must provide a secret API key, provided in the Knock dashboard.
18
+
19
+ You can set it as an environment variable:
20
+
21
+ ```bash
22
+ KNOCK_API_KEY="sk_12345"
23
+ ```
24
+
25
+ Or, you may set the key yourself in an initializer:
26
+
27
+ ```ruby
28
+ # /config/initializers/knock.rb
29
+ Knock.key = 'sk_12345'
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ### Identifying users
35
+
36
+ ```ruby
37
+ require "knockapi"
38
+
39
+ Knock.key = "sk_12345"
40
+
41
+ Knock::Users.identify(
42
+ id: "jhammond",
43
+ data: {
44
+ name: "John Hammond",
45
+ email: "jhammond@ingen.net",
46
+ }
47
+ )
48
+ ```
49
+
50
+ ### Sending notifies (triggering workflows)
51
+
52
+ ```ruby
53
+ require "knockapi"
54
+
55
+ Knock.key = "sk_12345"
56
+
57
+ # The key of the workflow (from Knock dashboard)
58
+ Knock::Workflows.trigger(
59
+ key: "dinosaurs-loose",
60
+ # user id of who performed the action
61
+ actor: "dnedry",
62
+ # list of user ids for who should receive the notif
63
+ recipients: ["jhammond", "agrant", "imalcolm", "esattler"],
64
+ # data payload to send through
65
+ data: {
66
+ type: "trex",
67
+ priority: 1,
68
+ },
69
+ # an optional key to provide to cancel a notify
70
+ cancellation_key: trigger_alert.id,
71
+ )
72
+ ```
73
+
74
+ ### Retrieving users
75
+
76
+ ```ruby
77
+ require "knockapi"
78
+
79
+ Knock.key = "sk_12345"
80
+
81
+ Knock::Users.get(id: "jhammond")
82
+ ```
83
+
84
+ ### Deleting users
85
+
86
+ ```ruby
87
+ require "knockapi"
88
+
89
+ Knock.key = "sk_12345"
90
+
91
+ Knock::Users.delete(id: "jhammond")
92
+ ```
93
+
94
+ ### Preferences
95
+
96
+ ```ruby
97
+ require "knockapi"
98
+ Knock.key = "sk_12345"
99
+
100
+ # Set an entire preference set
101
+ Knock::Preferences.set(
102
+ user_id: "jhammond",
103
+ channel_types: { email: true, sms: false },
104
+ workflows: {
105
+ 'dinosaurs-loose': {
106
+ channel_types: { email: false, in_app_feed: false }
107
+ }
108
+ }
109
+ )
110
+
111
+ # Get an entire preference set
112
+ Knock::Preferences.get(user_id: "jhammond")
113
+ ```
114
+
115
+ ### Cancelling workflows
116
+
117
+ ```ruby
118
+ require "knockapi"
119
+ Knock.key = "sk_12345"
120
+
121
+ Knock::Workflows.cancel(
122
+ key: "dinosaurs-loose",
123
+ cancellation_key: trigger_alert.id,
124
+ # Optionally, you can provide recipients to cancel for
125
+ recipients: ["jhammond"]
126
+ )
127
+ ```
128
+
129
+ ### Signing JWTs
130
+
131
+ You can use the `jwt` gem to sign JWTs easily. You will need to generate an environment specific signing key, which you can find in the Knock dashboard.
132
+
133
+ If you're using a signing token you will need to pass this to your client to perform authentication. You can read more about [clientside authentication here](https://docs.knock.app/client-integration/authenticating-users).
134
+
135
+ ```ruby
136
+ require 'jwt'
137
+
138
+ secret = ENV['KNOCK_SIGNING_KEY']
139
+ now = Time.now.to_i
140
+
141
+ payload = {
142
+ # The subject of the token
143
+ sub: 'jhammond',
144
+ # When the token was issued
145
+ iat: now,
146
+ # Expire the token in 1 week
147
+ exp: now + (24 * 7 * 3600)
148
+ }
149
+
150
+ JWT.encode(payload, secret, 'RS256')
151
+ ```
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "knock"
5
+
6
+ require "irb"
7
+ IRB.start(__FILE__)
data/knockapi.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "knock/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "knockapi"
9
+ spec.version = Knock::VERSION
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
+ spec.metadata = {
17
+ "documentation_uri" => "https://docs.knock.app"
18
+ }
19
+
20
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", ">= 2.0.1"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "standard"
28
+
29
+ spec.required_ruby_version = ">= 2.5"
30
+ end
data/lib/knock.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "knock/version"
4
+ require "json"
5
+
6
+ module Knock
7
+ API_HOSTNAME = ENV["KNOCK_API_HOSTNAME"] || "api.knock.app"
8
+
9
+ def self.key=(value)
10
+ Base.key = value
11
+ end
12
+
13
+ def self.key
14
+ Base.key
15
+ end
16
+
17
+ def self.key!
18
+ key || raise("Knock.key not set")
19
+ end
20
+
21
+ autoload :Base, "knock/base"
22
+ autoload :Client, "knock/client"
23
+
24
+ # Resources
25
+ autoload :Preferences, "knock/preferences"
26
+ autoload :Users, "knock/users"
27
+ autoload :Workflows, "knock/workflows"
28
+
29
+ # Errors
30
+ autoload :APIError, "knock/errors"
31
+ autoload :AuthenticationError, "knock/errors"
32
+ autoload :InvalidRequestError, "knock/errors"
33
+
34
+ key = ENV["KNOCK_API_KEY"]
35
+ Knock.key = key unless key.nil?
36
+
37
+ # Triggers the workflow with the given key
38
+ #
39
+ # @param [String] key The workflow key
40
+ # @param [String] actor The actor ID
41
+ # @param [Array<String>] recipients The recipient IDs
42
+ # @param [Hash] data The data to pass to the workflow
43
+ # @param [String] cancellation_key An optional key to identify this workflow
44
+ # invocation for cancelling
45
+ # @param [String] tenant An optional tenant identifier
46
+ #
47
+ # @return [Hash] A workflow trigger result
48
+ def self.notify(**args)
49
+ Knock::Workflows.trigger(**args)
50
+ end
51
+ end
data/lib/knock/base.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Knock
2
+ ## The Base class handles setting and reading the Knock API Key for authentication
3
+ module Base
4
+ attr_accessor :key
5
+
6
+ class << self
7
+ attr_writer :key
8
+ attr_reader :key
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,116 @@
1
+ module Knock
2
+ # A Net::HTTP based API client for interacting with the Knock API
3
+ module Client
4
+ include Kernel
5
+
6
+ def client
7
+ return @client if defined?(@client)
8
+
9
+ @client = Net::HTTP.new(Knock::API_HOSTNAME, 443)
10
+ @client.use_ssl = true
11
+
12
+ @client
13
+ end
14
+
15
+ def execute_request(request:)
16
+ response = client.request(request)
17
+
18
+ http_status = response.code.to_i
19
+ handle_error_response(response: response) if http_status >= 400
20
+
21
+ JSON.parse(response.body)
22
+ end
23
+
24
+ def get_request(path:, auth: false, params: {}, access_token: nil)
25
+ uri = URI(path)
26
+ uri.query = URI.encode_www_form(params) if params
27
+
28
+ request = Net::HTTP::Get.new(
29
+ uri.to_s,
30
+ "Content-Type" => "application/json"
31
+ )
32
+
33
+ request["Authorization"] = "Bearer #{access_token || Knock.key!}" if auth
34
+ request["User-Agent"] = user_agent
35
+ request
36
+ end
37
+
38
+ def post_request(path:, auth: false, idempotency_key: nil, body: nil)
39
+ request = Net::HTTP::Post.new(path, "Content-Type" => "application/json")
40
+ request.body = body.to_json if body
41
+ request["Authorization"] = "Bearer #{Knock.key!}" if auth
42
+ request["User-Agent"] = user_agent
43
+ request
44
+ end
45
+
46
+ def delete_request(path:, auth: false, params: {})
47
+ uri = URI(path)
48
+ uri.query = URI.encode_www_form(params) if params
49
+
50
+ request = Net::HTTP::Delete.new(
51
+ uri.to_s,
52
+ "Content-Type" => "application/json"
53
+ )
54
+
55
+ request["Authorization"] = "Bearer #{Knock.key!}" if auth
56
+ request["User-Agent"] = user_agent
57
+ request
58
+ end
59
+
60
+ def put_request(path:, auth: false, idempotency_key: nil, body: nil)
61
+ request = Net::HTTP::Put.new(path, "Content-Type" => "application/json")
62
+ request.body = body.to_json if body
63
+ request["Authorization"] = "Bearer #{Knock.key!}" if auth
64
+ request["User-Agent"] = user_agent
65
+ request
66
+ end
67
+
68
+ def user_agent
69
+ "Knock Ruby - v#{Knock::VERSION}"
70
+ end
71
+
72
+ def handle_error_response(response:)
73
+ http_status = response.code.to_i
74
+ json = JSON.parse(response.body)
75
+
76
+ case http_status
77
+ when 400
78
+ raise InvalidRequestError.new(
79
+ message: json["message"],
80
+ http_status: http_status,
81
+ request_id: response["x-request-id"]
82
+ )
83
+ when 401
84
+ raise AuthenticationError.new(
85
+ message: json["message"],
86
+ http_status: http_status,
87
+ request_id: response["x-request-id"]
88
+ )
89
+ when 404
90
+ raise APIError.new(
91
+ message: json["message"],
92
+ http_status: http_status,
93
+ request_id: response["x-request-id"]
94
+ )
95
+ when 422
96
+ message = json["message"]
97
+ errors = extract_error(json["errors"]) if json["errors"]
98
+ message += " (#{errors})" if errors
99
+
100
+ raise InvalidRequestError.new(
101
+ message: message,
102
+ http_status: http_status,
103
+ request_id: response["x-request-id"]
104
+ )
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def extract_error(errors)
111
+ errors.map do |error|
112
+ "#{error["field"]}: #{error["message"]} (#{error["type"]})"
113
+ end.join("; ")
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,42 @@
1
+ module Knock
2
+ class KnockError < StandardError
3
+ attr_reader :http_status
4
+ attr_reader :request_id
5
+
6
+ def initialize(message: nil, error: nil, error_description: nil, http_status: nil, request_id: nil)
7
+ @message = message
8
+ @error = error
9
+ @error_description = error_description
10
+ @http_status = http_status
11
+ @request_id = request_id
12
+ end
13
+
14
+ def to_s
15
+ status_string = @http_status.nil? ? "" : "Status #{@http_status}, "
16
+ id_string = @request_id.nil? ? "" : " - request ID: #{@request_id}"
17
+
18
+ if @error && @error_description
19
+ error_string = "error: #{@error}, error_description: #{@error_description}"
20
+ "#{status_string}#{error_string}#{id_string}"
21
+ elsif @error
22
+ "#{status_string}#{@error}#{id_string}"
23
+ else
24
+ "#{status_string}#{@message}#{id_string}"
25
+ end
26
+ end
27
+ end
28
+
29
+ # APIError is a generic error that may be raised in cases where none of the
30
+ # other named errors cover the problem. It could also be raised in the case
31
+ # that a new error has been introduced in the API, but this version of the
32
+ # Ruby SDK doesn't know how to handle it.
33
+ class APIError < KnockError; end
34
+
35
+ # AuthenticationError is raised when invalid credentials are used to connect
36
+ # to Knock's servers.
37
+ class AuthenticationError < KnockError; end
38
+
39
+ # InvalidRequestError is raised when a request is initiated with invalid
40
+ # parameters.
41
+ class InvalidRequestError < KnockError; end
42
+ end
@@ -0,0 +1,141 @@
1
+ require "net/http"
2
+ require "uri"
3
+
4
+ module Knock
5
+ # Provides convienience methods for working with preferences
6
+ module Preferences
7
+ class << self
8
+ include Base
9
+ include Client
10
+
11
+ DEFAULT_SET_ID = "default"
12
+
13
+ # Returns all preference sets for the user
14
+ #
15
+ # @param [String] user_id The ID of the user to retrieve preferences for
16
+ #
17
+ # @return [Hash] The preference sets
18
+ def get_all(user_id:)
19
+ endpoint = "/v1/users/#{user_id}/preferences"
20
+
21
+ request = get_request(
22
+ auth: true,
23
+ path: endpoint
24
+ )
25
+
26
+ execute_request(request: request)
27
+ end
28
+
29
+ # Gets a single preference set, defaults to the 'default' set
30
+ # for the user given.
31
+ #
32
+ # @param [String] user_id The ID of the user to retrieve preferences for
33
+ # @param [String] preference_set The preference set ID (defaults to `default`)
34
+ #
35
+ # @return [Hash] The preference set (if it exists)
36
+ def get(user_id:, preference_set: DEFAULT_SET_ID)
37
+ endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}"
38
+
39
+ request = get_request(
40
+ auth: true,
41
+ path: endpoint
42
+ )
43
+
44
+ execute_request(request: request)
45
+ end
46
+
47
+ # Sets multiple preferences at once for the preference set.
48
+ #
49
+ # @param [String] user_id The ID of the user to set preferences for
50
+ # @param [String] preference_set The preference set ID (defaults to `default`)
51
+ # @param [Hash] preferences The preferences hash to set
52
+ #
53
+ #  @return [Hash] The preference set
54
+ def update(
55
+ user_id:,
56
+ channel_types: nil,
57
+ workflows: nil,
58
+ categories: nil,
59
+ preference_set: DEFAULT_SET_ID
60
+ )
61
+ endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}"
62
+
63
+ request = put_request(
64
+ auth: true,
65
+ path: endpoint,
66
+ body: {
67
+ channel_types: channel_types,
68
+ workflows: workflows,
69
+ categories: categories
70
+ }
71
+ )
72
+
73
+ execute_request(request: request)
74
+ end
75
+
76
+ # Sets preferences for the given channel type
77
+ #
78
+ # @param [String] user_id The ID of the user to set preferences for
79
+ # @param [String] preference_set The preference set ID (defaults to `default`)
80
+ # @param [String] channel_type The channel type to set
81
+ # @param [Bool] setting Whether the channel type is enabled or not
82
+ #
83
+ #  @return [Hash] The preference set
84
+ def set_channel_type(user_id:, channel_type:, setting:, preference_set: DEFAULT_SET_ID)
85
+ endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}/channel_types/#{channel_type}"
86
+
87
+ request = put_request(
88
+ auth: true,
89
+ path: endpoint,
90
+ body: {subscribed: setting}
91
+ )
92
+
93
+ execute_request(request: request)
94
+ end
95
+
96
+ # Sets preferences for the given workflow
97
+ #
98
+ # @param [String] user_id The ID of the user to set preferences for
99
+ # @param [String] preference_set The preference set ID (defaults to `default`)
100
+ # @param [String] workflow The workflow to set preferences for
101
+ # @param [Bool | Hash] setting Either a boolean to indicate if the type is enabled
102
+ # or a hash containing channel types and settings
103
+ #
104
+ #  @return [Hash] The preference set
105
+ def set_workflow(user_id:, workflow:, setting:, preference_set: DEFAULT_SET_ID)
106
+ params = setting.is_a?(Hash) ? setting : {subscribed: setting}
107
+ endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}/workflows/#{workflow}"
108
+
109
+ request = put_request(
110
+ auth: true,
111
+ path: endpoint,
112
+ body: params
113
+ )
114
+
115
+ execute_request(request: request)
116
+ end
117
+
118
+ # Sets preferences for the given category
119
+ #
120
+ # @param [String] user_id The ID of the user to set preferences for
121
+ # @param [String] preference_set The preference set ID (defaults to `default`)
122
+ # @param [String] category The category to set preferences for
123
+ # @param [Bool | Hash] setting Either a boolean to indicate if the type is enabled
124
+ # or a hash containing channel types and settings
125
+ #
126
+ #  @return [Hash] The preference set
127
+ def set_category(user_id:, category:, setting:, preference_set: DEFAULT_SET_ID)
128
+ params = setting.is_a?(Hash) ? setting : {subscribed: setting}
129
+ endpoint = "/v1/users/#{user_id}/preferences/#{preference_set}/categories/#{category}"
130
+
131
+ request = put_request(
132
+ auth: true,
133
+ path: endpoint,
134
+ body: params
135
+ )
136
+
137
+ execute_request(request: request)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,56 @@
1
+ require "net/http"
2
+ require "uri"
3
+
4
+ module Knock
5
+ # Provides convienience methods for working with users
6
+ module Users
7
+ class << self
8
+ include Base
9
+ include Client
10
+
11
+ # Identifies the user
12
+ #
13
+ # @param [String] id The user ID
14
+ # @param [Hash] data The traits to attach to the user
15
+ #
16
+ # @return [Hash] The user
17
+ def identify(id:, data: {})
18
+ request = put_request(
19
+ auth: true,
20
+ path: "/v1/users/#{id}",
21
+ body: data
22
+ )
23
+
24
+ execute_request(request: request)
25
+ end
26
+
27
+ # Retrieves the given user
28
+ #
29
+ # @param [String] id The user ID
30
+ #
31
+ # @return [Hash] The user
32
+ def get(id:)
33
+ request = get_request(
34
+ auth: true,
35
+ path: "/v1/users/#{id}"
36
+ )
37
+
38
+ execute_request(request: request)
39
+ end
40
+
41
+ # Deletes the user
42
+ #
43
+ # @param [String] id the user ID
44
+ #
45
+ # @return [Hash] the user
46
+ def delete(id:)
47
+ request = delete_request(
48
+ auth: true,
49
+ path: "/v1/users/#{id}"
50
+ )
51
+
52
+ execute_request(request: request)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Knock
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,63 @@
1
+ require "net/http"
2
+ require "uri"
3
+
4
+ module Knock
5
+ # Methods for interacting with workflows in Knock
6
+ module Workflows
7
+ class << self
8
+ include Base
9
+ include Client
10
+
11
+ # Triggers the workflow with the given key
12
+ #
13
+ # @param [String] key The workflow key
14
+ # @param [String] actor The actor ID
15
+ # @param [Array<String>] recipients The recipient IDs
16
+ # @param [Hash] data The data to pass to the workflow
17
+ # @param [String] cancellation_key An optional key to identify this workflow
18
+ # invocation for cancelling
19
+ # @param [String] tenant An optional tenant identifier
20
+ #
21
+ # @return [Hash] A workflow trigger result
22
+ def trigger(key:, actor:, recipients:, data: {}, cancellation_key: nil, tenant: nil)
23
+ attrs = {
24
+ actor: actor,
25
+ recipients: recipients,
26
+ data: data,
27
+ cancellation_key: cancellation_key,
28
+ tenant: tenant
29
+ }
30
+
31
+ request = post_request(
32
+ auth: true,
33
+ path: "/v1/workflows/#{key}/trigger",
34
+ body: attrs
35
+ )
36
+
37
+ execute_request(request: request)
38
+ end
39
+
40
+ # Cancels the workflow with the given key and cancellation key
41
+ #
42
+ # @param [String] key The workflow key
43
+ # @param [String] cancellation_key The cancellation key
44
+ # @param [Array<String>] recipients The recipient IDs to cancel for
45
+ #
46
+ # @return [Hash] - Cancellation result
47
+ def cancel(key:, cancellation_key:, recipients: nil)
48
+ attrs = {
49
+ cancellation_key: cancellation_key,
50
+ recipients: recipients
51
+ }
52
+
53
+ request = post_request(
54
+ auth: true,
55
+ path: "/v1/workflows/#{key}/cancel",
56
+ body: attrs
57
+ )
58
+
59
+ execute_request(request: request)
60
+ end
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knockapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Knock Labs, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.1
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: standard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: API client for Knock
56
+ email:
57
+ - support@knock.app
58
+ executables:
59
+ - console
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".ruby-version"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE
68
+ - README.md
69
+ - bin/console
70
+ - knockapi.gemspec
71
+ - lib/knock.rb
72
+ - lib/knock/base.rb
73
+ - lib/knock/client.rb
74
+ - lib/knock/errors.rb
75
+ - lib/knock/preferences.rb
76
+ - lib/knock/users.rb
77
+ - lib/knock/version.rb
78
+ - lib/knock/workflows.rb
79
+ homepage: https://github.com/knocklabs/knock-ruby
80
+ licenses:
81
+ - MIT
82
+ metadata:
83
+ documentation_uri: https://docs.knock.app
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '2.5'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubygems_version: 3.2.22
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: API client for Knock
103
+ test_files: []