nylas 5.17.0 → 6.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nylas/client.rb +107 -0
  3. data/lib/nylas/config.rb +19 -0
  4. data/lib/nylas/errors.rb +63 -89
  5. data/lib/nylas/handler/api_operations.rb +140 -0
  6. data/lib/nylas/handler/http_client.rb +243 -0
  7. data/lib/nylas/resources/applications.rb +27 -0
  8. data/lib/nylas/resources/attachments.rb +65 -0
  9. data/lib/nylas/resources/auth.rb +211 -0
  10. data/lib/nylas/resources/calendars.rb +101 -0
  11. data/lib/nylas/resources/connectors.rb +80 -0
  12. data/lib/nylas/resources/credentials.rb +75 -0
  13. data/lib/nylas/resources/drafts.rb +91 -0
  14. data/lib/nylas/resources/events.rb +83 -0
  15. data/lib/nylas/resources/folders.rb +73 -0
  16. data/lib/nylas/resources/grants.rb +70 -0
  17. data/lib/nylas/resources/messages.rb +126 -0
  18. data/lib/nylas/resources/redirect_uris.rb +68 -0
  19. data/lib/nylas/resources/resource.rb +18 -0
  20. data/lib/nylas/resources/smart_compose.rb +36 -0
  21. data/lib/nylas/resources/threads.rb +62 -0
  22. data/lib/nylas/resources/webhooks.rb +85 -0
  23. data/lib/nylas/utils/file_utils.rb +49 -0
  24. data/lib/nylas/version.rb +1 -1
  25. data/lib/nylas.rb +30 -148
  26. metadata +87 -247
  27. data/lib/nylas/account.rb +0 -56
  28. data/lib/nylas/api.rb +0 -246
  29. data/lib/nylas/application_details.rb +0 -13
  30. data/lib/nylas/calendar.rb +0 -46
  31. data/lib/nylas/calendar_collection.rb +0 -144
  32. data/lib/nylas/categorize.rb +0 -14
  33. data/lib/nylas/collection.rb +0 -175
  34. data/lib/nylas/component.rb +0 -35
  35. data/lib/nylas/component_collection.rb +0 -10
  36. data/lib/nylas/constraints.rb +0 -56
  37. data/lib/nylas/contact.rb +0 -53
  38. data/lib/nylas/contact_group.rb +0 -23
  39. data/lib/nylas/current_account.rb +0 -23
  40. data/lib/nylas/delta.rb +0 -56
  41. data/lib/nylas/deltas.rb +0 -19
  42. data/lib/nylas/deltas_collection.rb +0 -40
  43. data/lib/nylas/draft.rb +0 -100
  44. data/lib/nylas/email_address.rb +0 -12
  45. data/lib/nylas/event.rb +0 -144
  46. data/lib/nylas/event_collection.rb +0 -15
  47. data/lib/nylas/event_conferencing.rb +0 -12
  48. data/lib/nylas/event_conferencing_autocreate.rb +0 -10
  49. data/lib/nylas/event_conferencing_details.rb +0 -14
  50. data/lib/nylas/event_notification.rb +0 -17
  51. data/lib/nylas/file.rb +0 -75
  52. data/lib/nylas/filter_attributes.rb +0 -25
  53. data/lib/nylas/folder.rb +0 -26
  54. data/lib/nylas/free_busy.rb +0 -13
  55. data/lib/nylas/free_busy_collection.rb +0 -48
  56. data/lib/nylas/http_client.rb +0 -279
  57. data/lib/nylas/im_address.rb +0 -11
  58. data/lib/nylas/job_status.rb +0 -27
  59. data/lib/nylas/job_status_collection.rb +0 -21
  60. data/lib/nylas/label.rb +0 -27
  61. data/lib/nylas/logging.rb +0 -41
  62. data/lib/nylas/message.rb +0 -98
  63. data/lib/nylas/message_headers.rb +0 -27
  64. data/lib/nylas/message_tracking.rb +0 -13
  65. data/lib/nylas/model/attributable.rb +0 -89
  66. data/lib/nylas/model/attribute_definition.rb +0 -24
  67. data/lib/nylas/model/attributes.rb +0 -97
  68. data/lib/nylas/model/list_attribute_definition.rb +0 -39
  69. data/lib/nylas/model/transferable.rb +0 -53
  70. data/lib/nylas/model.rb +0 -217
  71. data/lib/nylas/native_authentication.rb +0 -39
  72. data/lib/nylas/neural.rb +0 -87
  73. data/lib/nylas/neural_categorizer.rb +0 -29
  74. data/lib/nylas/neural_clean_conversation.rb +0 -33
  75. data/lib/nylas/neural_contact_link.rb +0 -11
  76. data/lib/nylas/neural_contact_name.rb +0 -11
  77. data/lib/nylas/neural_message_options.rb +0 -35
  78. data/lib/nylas/neural_ocr.rb +0 -16
  79. data/lib/nylas/neural_sentiment_analysis.rb +0 -17
  80. data/lib/nylas/neural_signature_contact.rb +0 -81
  81. data/lib/nylas/neural_signature_extraction.rb +0 -18
  82. data/lib/nylas/new_message.rb +0 -39
  83. data/lib/nylas/nylas_date.rb +0 -25
  84. data/lib/nylas/open_hours.rb +0 -15
  85. data/lib/nylas/outbox.rb +0 -116
  86. data/lib/nylas/outbox_job_status.rb +0 -19
  87. data/lib/nylas/outbox_message.rb +0 -17
  88. data/lib/nylas/participant.rb +0 -13
  89. data/lib/nylas/phone_number.rb +0 -11
  90. data/lib/nylas/physical_address.rb +0 -17
  91. data/lib/nylas/raw_message.rb +0 -25
  92. data/lib/nylas/recurrence.rb +0 -11
  93. data/lib/nylas/registry.rb +0 -42
  94. data/lib/nylas/room_resource.rb +0 -19
  95. data/lib/nylas/rsvp.rb +0 -24
  96. data/lib/nylas/scheduler.rb +0 -51
  97. data/lib/nylas/scheduler_booking_confirmation.rb +0 -24
  98. data/lib/nylas/scheduler_booking_request.rb +0 -17
  99. data/lib/nylas/scheduler_collection.rb +0 -104
  100. data/lib/nylas/scheduler_config.rb +0 -20
  101. data/lib/nylas/scheduler_time_slot.rb +0 -14
  102. data/lib/nylas/search_collection.rb +0 -10
  103. data/lib/nylas/send_grid_verified_status.rb +0 -12
  104. data/lib/nylas/services/tunnel.rb +0 -128
  105. data/lib/nylas/thread.rb +0 -66
  106. data/lib/nylas/time_slot.rb +0 -16
  107. data/lib/nylas/time_slot_capacity.rb +0 -13
  108. data/lib/nylas/timespan.rb +0 -20
  109. data/lib/nylas/token_info.rb +0 -20
  110. data/lib/nylas/types.rb +0 -168
  111. data/lib/nylas/web_page.rb +0 -11
  112. data/lib/nylas/webhook.rb +0 -111
  113. data/lib/nylas/when.rb +0 -75
@@ -0,0 +1,243 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rest-client"
4
+
5
+ require_relative "../errors"
6
+ require_relative "../version"
7
+
8
+ # Module for working with HTTP Client
9
+ module Nylas
10
+ require "yajl"
11
+ require "base64"
12
+
13
+ # Plain HTTP client that can be used to interact with the Nylas API without any type casting.
14
+ module HttpClient
15
+ protected
16
+
17
+ attr_accessor :api_server
18
+ attr_writer :default_headers
19
+
20
+ # Sends a request to the Nylas API. Returns a successful response if the request succeeds, or a
21
+ # failed response if the request encounters a JSON parse error.
22
+ #
23
+ # @param method [Symbol] HTTP method for the API call. Either :get, :post, :delete, or :patch.
24
+ # @param path [String, nil] Relative path from the API Base. This is the preferred way to execute
25
+ # arbitrary or-not-yet-SDK-ified API commands.
26
+ # @param timeout [Integer, nil] Timeout value to send with the request.
27
+ # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
28
+ # @param query [Hash, {}] Hash of names and values to include in the query section of the URI
29
+ # fragment.
30
+ # @param payload [Hash, nil] Body to send with the request.
31
+ # @param api_key [Hash, nil] API key to send with the request.
32
+ # @return [Object] Parsed JSON response from the API.
33
+ def execute(method:, path:, timeout:, headers: {}, query: {}, payload: nil, api_key: nil)
34
+ request = build_request(method: method, path: path, headers: headers,
35
+ query: query, payload: payload, api_key: api_key, timeout: timeout)
36
+ begin
37
+ rest_client_execute(**request) do |response, _request, result|
38
+ content_type = nil
39
+ if response.headers && response.headers[:content_type]
40
+ content_type = response.headers[:content_type].downcase
41
+ end
42
+
43
+ parse_json_evaluate_error(result.code.to_i, response, path, content_type)
44
+ end
45
+ rescue Timeout::Error => _e
46
+ raise Nylas::NylasSdkTimeoutError.new(request.path, timeout)
47
+ end
48
+ end
49
+
50
+ # Sends a request to the Nylas API, specifically for downloading data.
51
+ # This method supports streaming the response by passing a block, which will be executed
52
+ # with each chunk of the response body as it is read. If no block is provided, the entire
53
+ # response body is returned.
54
+ #
55
+ # @param path [String] Relative path from the API Base. This is the preferred way to execute
56
+ # arbitrary or-not-yet-SDK-ified API commands.
57
+ # @param timeout [Integer] Timeout value to send with the request.
58
+ # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
59
+ # @param query [Hash, {}] Hash of names and values to include in the query section of the URI
60
+ # fragment.
61
+ # @param api_key [Hash, nil] API key to send with the request.
62
+ # @yieldparam chunk [String] A chunk of the response body.
63
+ # @return [nil, String] Returns nil when a block is given (streaming mode).
64
+ # When no block is provided, the return is the entire raw response body.
65
+ def download_request(path:, timeout:, headers: {}, query: {}, api_key: nil, &block)
66
+ request, uri, http = setup_http(path, timeout, headers, query, api_key)
67
+
68
+ begin
69
+ http.start do |setup_http|
70
+ get_request = Net::HTTP::Get.new(uri)
71
+ request[:headers].each { |key, value| get_request[key] = value }
72
+
73
+ handle_response(setup_http, get_request, path, &block)
74
+ end
75
+ rescue Net::OpenTimeout, Net::ReadTimeout
76
+ raise Nylas::NylasSdkTimeoutError.new(request[:url], timeout)
77
+ end
78
+ end
79
+
80
+ # Builds a request sent to the Nylas API.
81
+ #
82
+ # @param method [Symbol] HTTP method for the API call. Either :get, :post, :delete, or :patch.
83
+ # @param path [String, nil] Relative path from the API Base.
84
+ # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
85
+ # @param query [Hash, {}] Hash of names and values to include in the query section of the URI
86
+ # fragment.
87
+ # @param payload [Hash, nil] Body to send with the request.
88
+ # @param timeout [Integer, nil] Timeout value to send with the request.
89
+ # @param api_key [Hash, nil] API key to send with the request.
90
+ # @return [Object] The request information after processing. This includes an updated payload
91
+ # and headers.
92
+ def build_request(
93
+ method:, path: nil, headers: {}, query: {}, payload: nil, timeout: nil, api_key: nil
94
+ )
95
+ url = path
96
+ url = add_query_params_to_url(url, query)
97
+ resulting_headers = default_headers.merge(headers).merge(auth_header(api_key))
98
+ if !payload.nil? && !payload["multipart"]
99
+ payload = payload&.to_json
100
+ resulting_headers["Content-type"] = "application/json"
101
+ elsif !payload.nil? && payload["multipart"]
102
+ payload.delete("multipart")
103
+ end
104
+
105
+ { method: method, url: url, payload: payload, headers: resulting_headers, timeout: timeout }
106
+ end
107
+
108
+ # Sets the default headers for API requests.
109
+ def default_headers
110
+ @default_headers ||= {
111
+ "X-Nylas-API-Wrapper" => "ruby",
112
+ "User-Agent" => "Nylas Ruby SDK #{Nylas::VERSION} - #{RUBY_VERSION}"
113
+ }
114
+ end
115
+
116
+ # Parses the response from the Nylas API.
117
+ def parse_response(response)
118
+ return response if response.is_a?(Enumerable)
119
+
120
+ Yajl::Parser.new(symbolize_names: true).parse(response)
121
+ rescue Yajl::ParseError
122
+ raise Nylas::JsonParseError
123
+ end
124
+
125
+ private
126
+
127
+ # Sends a request to the Nylas REST API.
128
+ #
129
+ # @param method [Symbol] HTTP method for the API call. Either :get, :post, :delete, or :patch.
130
+ # @param url [String] URL for the API call.
131
+ # @param headers [Hash] HTTP headers to include in the payload.
132
+ # @param payload [String, Hash] Body to send with the request.
133
+ # @param timeout [Hash] Timeout value to send with the request.
134
+ def rest_client_execute(method:, url:, headers:, payload:, timeout:, &block)
135
+ ::RestClient::Request.execute(method: method, url: url, payload: payload,
136
+ headers: headers, timeout: timeout, &block)
137
+ end
138
+
139
+ def setup_http(path, timeout, headers, query, api_key)
140
+ request = build_request(method: :get, path: path, headers: headers,
141
+ query: query, api_key: api_key, timeout: timeout)
142
+ uri = URI(request[:url])
143
+ http = Net::HTTP.new(uri.host, uri.port)
144
+ http.use_ssl = true
145
+ http.read_timeout = timeout
146
+ http.open_timeout = timeout
147
+ [request, uri, http]
148
+ end
149
+
150
+ def handle_response(http, get_request, path, &block)
151
+ http.request(get_request) do |response|
152
+ if response.is_a?(Net::HTTPSuccess)
153
+ return response.body unless block_given?
154
+
155
+ response.read_body(&block)
156
+ else
157
+ parse_json_evaluate_error(response.code.to_i, response.body, path, response["Content-Type"])
158
+ break
159
+ end
160
+ end
161
+ end
162
+
163
+ # Parses the response from the Nylas API and evaluates for errors.
164
+ def parse_json_evaluate_error(http_code, response, path, content_type = nil)
165
+ begin
166
+ response = parse_response(response) if content_type == "application/json"
167
+ rescue Nylas::JsonParseError
168
+ handle_failed_response(http_code, response, path)
169
+ raise
170
+ end
171
+
172
+ handle_failed_response(http_code, response, path)
173
+ response
174
+ end
175
+
176
+ # Handles failed responses from the Nylas API.
177
+ def handle_failed_response(http_code, response, path)
178
+ return if HTTP_SUCCESS_CODES.include?(http_code)
179
+
180
+ case response
181
+ when Hash
182
+ raise error_hash_to_exception(response, http_code, path)
183
+ else
184
+ raise NylasApiError.parse_error_response(response, http_code)
185
+ end
186
+ end
187
+
188
+ # Converts error hashes to exceptions.
189
+ def error_hash_to_exception(response, status_code, path)
190
+ return if !response || !response.key?(:error)
191
+
192
+ if %W[#{api_uri}/v3/connect/token #{api_uri}/v3/connect/revoke].include?(path)
193
+ NylasOAuthError.new(response[:error], response[:error_description], response[:error_uri],
194
+ response[:error_code], status_code)
195
+ else
196
+ throw_error(response, status_code)
197
+ end
198
+ end
199
+
200
+ def throw_error(response, status_code)
201
+ error_obj = response[:error]
202
+ provider_error = error_obj.fetch(:provider_error, nil)
203
+
204
+ NylasApiError.new(error_obj[:type], error_obj[:message], status_code, provider_error,
205
+ response[:request_id])
206
+ end
207
+
208
+ # Adds query parameters to a URL.
209
+ #
210
+ # @return [String] Processed URL, including query params.
211
+ def add_query_params_to_url(url, query)
212
+ unless query.nil? || query.empty?
213
+ uri = URI.parse(url)
214
+ query = custom_params(query)
215
+ params = URI.decode_www_form(uri.query || "") + query.to_a
216
+ uri.query = URI.encode_www_form(params)
217
+ url = uri.to_s
218
+ end
219
+
220
+ url
221
+ end
222
+
223
+ # Defines custom parameters for a metadata_pair query.
224
+ #
225
+ # @return [String] Custom parameter in "<key>:<value>" format.
226
+ def custom_params(query)
227
+ # Convert hash to "<key>:<value>" form for metadata_pair query.
228
+ if query.key?(:metadata_pair)
229
+ pairs = query[:metadata_pair].map do |key, value|
230
+ "#{key}:#{value}"
231
+ end
232
+ query[:metadata_pair] = pairs
233
+ end
234
+
235
+ query
236
+ end
237
+
238
+ # Set the authorization header for an API query.
239
+ def auth_header(api_key)
240
+ { "Authorization" => "Bearer #{api_key}" }
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "redirect_uris"
5
+ require_relative "../handler/api_operations"
6
+
7
+ module Nylas
8
+ # Application
9
+ class Applications < Resource
10
+ include ApiOperations::Get
11
+
12
+ attr_reader :redirect_uris
13
+
14
+ # Initializes the application.
15
+ def initialize(sdk_instance)
16
+ super(sdk_instance)
17
+ @redirect_uris = RedirectUris.new(sdk_instance)
18
+ end
19
+
20
+ # Gets the application object.
21
+ #
22
+ # @return [Array(Hash, String)] Application object and API Request ID.
23
+ def info
24
+ get(path: "#{api_uri}/v3/applications")
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+
6
+ module Nylas
7
+ # Nylas Attachment API
8
+ class Attachments < Resource
9
+ include ApiOperations::Get
10
+
11
+ # Return metadata of an attachment.
12
+ #
13
+ # @param identifier [String] Grant ID or email account to query.
14
+ # @param attachment_id [String] The id of the attachment to retrieve.
15
+ # @param query_params [Hash] The query parameters to include in the request.
16
+ # @return [Array(Hash, String)] The attachment and API request ID.
17
+ def find(identifier:, attachment_id:, query_params:)
18
+ get(
19
+ path: "#{api_uri}/v3/grants/#{identifier}/attachments/#{attachment_id}",
20
+ query_params: query_params
21
+ )
22
+ end
23
+
24
+ # Download the attachment data.
25
+ #
26
+ # This method supports streaming the download by passing a block, which will
27
+ # be called with each chunk of the response body as it is read. If no block
28
+ # is given, the entire response will be read into memory and returned (not recommended
29
+ # for large files).
30
+ #
31
+ # @param identifier [String] Grant ID or email account to query.
32
+ # @param attachment_id [String] The ID of the attachment to be downloaded.
33
+ # @param query_params [Hash] The query parameters to include in the request.
34
+ # @yieldparam chunk [String] A chunk of the response body.
35
+ # @return [nil, String] Returns nil when a block is given (streaming mode).
36
+ # When no block is provided, the return is the entire raw response body.
37
+ def download(identifier:, attachment_id:, query_params:, &block)
38
+ download_request(
39
+ path: "#{api_uri}/v3/grants/#{identifier}/attachments/#{attachment_id}/download",
40
+ query: query_params,
41
+ api_key: api_key,
42
+ timeout: timeout,
43
+ &block
44
+ )
45
+ end
46
+
47
+ # Download the attachment as a byte array.
48
+ #
49
+ # @param identifier [String] Grant ID or email account to query.
50
+ # @param attachment_id [String] The ID of the attachment to be downloaded.
51
+ # @param query_params [Hash] The query parameters to include in the request.
52
+ # @return [nil, Array(Integer)] Returns nil when a block is given (streaming mode).
53
+ # When no block is provided, the return is the entire raw response body.
54
+ def download_bytes(identifier:, attachment_id:, query_params:)
55
+ data = download_request(
56
+ path: "#{api_uri}/v3/grants/#{identifier}/attachments/#{attachment_id}/download",
57
+ query: query_params,
58
+ api_key: api_key,
59
+ timeout: timeout
60
+ )
61
+
62
+ data&.bytes
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+ require "base64"
5
+ require "securerandom"
6
+ require "ostruct"
7
+ require "uri"
8
+
9
+ require_relative "resource"
10
+ require_relative "grants"
11
+ require_relative "../handler/api_operations"
12
+
13
+ module Nylas
14
+ # Auth
15
+ class Auth < Resource
16
+ include ApiOperations::Post
17
+ include ApiOperations::Get
18
+
19
+ # Initializes Auth.
20
+ def initialize(sdk_instance)
21
+ super(sdk_instance)
22
+
23
+ @grants = Grants.new(sdk_instance)
24
+ end
25
+
26
+ attr_reader :grants
27
+
28
+ # Builds the URL for authenticating users to your application with OAuth 2.0.
29
+ #
30
+ # @param config [Hash] Configuration for building the URL.
31
+ # @return [String] URL for hosted authentication.
32
+ def url_for_oauth2(config)
33
+ url_auth_builder(config).to_s
34
+ end
35
+
36
+ # Exchanges an authorization code for an access token.
37
+ #
38
+ # @param request [Hash] Code exchange request.
39
+ # @return [Hash] Token object.
40
+ def exchange_code_for_token(request)
41
+ request[:grant_type] = "authorization_code"
42
+
43
+ execute_token_request(request)
44
+ end
45
+
46
+ # Refreshes an access token.
47
+ #
48
+ # @param request [Hash] Code exchange request.
49
+ # @return [Hash] Refreshed token object.
50
+ def refresh_access_token(request)
51
+ request[:grant_type] = "refresh_token"
52
+
53
+ execute_token_request(request)
54
+ end
55
+
56
+ # Builds the URL for authenticating users to your application with OAuth 2.0 and PKCE.
57
+ # IMPORTANT: You must store the 'secret' returned to use it inside the CodeExchange flow.
58
+ #
59
+ # @param config [Hash] Configuration for building the URL.
60
+ # @return [OpenStruct] URL for hosted authentication with the secret and the hashed secret.
61
+ def url_for_oauth2_pkce(config)
62
+ url = url_auth_builder(config)
63
+
64
+ # Generates a secret and hashes it.
65
+ secret = SecureRandom.uuid
66
+ secret_hash = hash_pkce_secret(secret)
67
+
68
+ # Adds code challenge to URL generation.
69
+ url.query = build_query_with_pkce(config, secret_hash)
70
+
71
+ # Returns the URL with secret and hashed secret.
72
+ OpenStruct.new(secret: secret, secret_hash: secret_hash, url: url.to_s)
73
+ end
74
+
75
+ # Builds the URL for admin consent authentication for Microsoft.
76
+ #
77
+ # @param config [Hash] Configuration for the authentication request.
78
+ # @return [String] URL for hosted authentication.
79
+ def url_for_admin_consent(config)
80
+ config_with_provider = config.merge("provider" => "microsoft")
81
+ url = url_auth_builder(config_with_provider)
82
+
83
+ query_params = build_query_with_admin_consent(config)
84
+ url.query = URI.encode_www_form(query_params)
85
+
86
+ url.to_s
87
+ end
88
+
89
+ # Revokes a single access token.
90
+ #
91
+ # @param token [String] Access token to revoke.
92
+ # @return [Boolean] True if the access token was revoked successfully.
93
+ def revoke(token)
94
+ post(
95
+ path: "#{api_uri}/v3/connect/revoke",
96
+ query_params: {
97
+ token: token
98
+ }
99
+ )
100
+ true
101
+ end
102
+
103
+ private
104
+
105
+ # Builds the query with admin consent authentication for Microsoft.
106
+ #
107
+ # @param config [Hash] Configuration for the query.
108
+ # @return [Array(Hash, String)] Updated list of parameters, including those specific to admin
109
+ # consent.
110
+ def build_query_with_admin_consent(config)
111
+ params = build_query(config)
112
+
113
+ # Appends new params specific for admin consent.
114
+ params["response_type"] = "adminconsent"
115
+ params["credential_id"] = config["credentialId"]
116
+
117
+ params
118
+ end
119
+
120
+ # Builds the query with PKCE.
121
+ #
122
+ # @param config [Hash] Configuration for the query.
123
+ # @param secret_hash [Hash] Hashed secret.
124
+ # @return [Array(Hash, String)] Updated list of encoded parameters, including those specific
125
+ # to PKCE.
126
+ def build_query_with_pkce(config, secret_hash)
127
+ params = build_query(config)
128
+
129
+ # Appends new PKCE specific params.
130
+ params["code_challenge_method"] = "s256"
131
+ params["code_challenge"] = secret_hash
132
+
133
+ URI.encode_www_form(params)
134
+ end
135
+
136
+ # Builds the authentication URL.
137
+ #
138
+ # @param config [Hash] Configuration for the query.
139
+ # @return [Array(Hash, String)] List of components for the authentication URL.
140
+ def url_auth_builder(config)
141
+ builder = URI.parse(api_uri)
142
+ builder.path = "/v3/connect/auth"
143
+ builder.query = build_query(config)
144
+
145
+ builder
146
+ end
147
+
148
+ # Builds the query.
149
+ #
150
+ # @param config [Hash] Configuration for the query.
151
+ # @return [Array(Hash, String)] List of encoded parameters for the query.
152
+ def build_query(config)
153
+ params = {
154
+ "client_id" => config[:client_id],
155
+ "redirect_uri" => config[:redirect_uri],
156
+ "access_type" => config[:access_type] || "online",
157
+ "response_type" => "code"
158
+ }
159
+ set_params(config)
160
+
161
+ URI.encode_www_form(params)
162
+ end
163
+
164
+ # Set the parameters for the query
165
+ def set_params(config)
166
+ params["provider"] = config[:provider] if config[:provider]
167
+ set_config_params(config)
168
+ set_more_config(config)
169
+ end
170
+
171
+ # Set login related configurations
172
+ def set_config_params(config)
173
+ if config[:login_hint]
174
+ params["login_hint"] = config[:login_hint]
175
+ params["include_grant_scopes"] = config[:include_grant_scopes].to_s if config[:include_grant_scopes]
176
+ end
177
+ params["scope"] = config[:scope].join(" ") if config[:scope]
178
+ end
179
+
180
+ # More config
181
+ def set_more_config(config)
182
+ params["prompt"] = config[:prompt] if config[:prompt]
183
+ params["metadata"] = config[:metadata] if config[:metadata]
184
+ params["state"] = config[:state] if config[:state]
185
+ end
186
+
187
+ # Hashes the secret for PKCE authentication.
188
+ #
189
+ # @param secret [String] Randomly-generated authentication secret.
190
+ # @return [Hash] Hashed authentication secret.
191
+ def hash_pkce_secret(secret)
192
+ Digest::SHA256.digest(secret).unpack1("H*")
193
+ Base64.strict_encode64(Digest::SHA256.digest(secret))
194
+ end
195
+
196
+ # Sends the token request to the Nylas API.
197
+ #
198
+ # @param request [Hash] Code exchange request.
199
+ def execute_token_request(request)
200
+ execute(
201
+ method: :post,
202
+ path: "#{api_uri}/v3/connect/token",
203
+ query: {},
204
+ payload: request,
205
+ headers: {},
206
+ api_key: api_key,
207
+ timeout: timeout
208
+ )
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+
6
+ module Nylas
7
+ # Nylas Calendar API
8
+ class Calendars < Resource
9
+ include ApiOperations::Get
10
+ include ApiOperations::Post
11
+ include ApiOperations::Put
12
+ include ApiOperations::Delete
13
+
14
+ # Return all calendars.
15
+ #
16
+ # @param identifier [String] Grant ID or email account to query.
17
+ # @param query_params [Hash, nil] Query params to pass to the request.
18
+ # @return [Array(Array(Hash), String)] The list of calendars and API Request ID.
19
+ def list(identifier:, query_params: nil)
20
+ get(
21
+ path: "#{api_uri}/v3/grants/#{identifier}/calendars",
22
+ query_params: query_params
23
+ )
24
+ end
25
+
26
+ # Return a calendar.
27
+ #
28
+ # @param identifier [String] Grant ID or email account to query.
29
+ # @param calendar_id [String] The id of the calendar to return.
30
+ # Use "primary" to refer to the primary calendar associated with grant.
31
+ # @return [Array(Hash, String)] The calendar and API request ID.
32
+ def find(identifier:, calendar_id:)
33
+ get(
34
+ path: "#{api_uri}/v3/grants/#{identifier}/calendars/#{calendar_id}"
35
+ )
36
+ end
37
+
38
+ # Create a calendar.
39
+ #
40
+ # @param identifier [String] Grant ID or email account in which to create the object.
41
+ # @param request_body [Hash] The values to create the calendar with.
42
+ # @return [Array(Hash, String)] The created calendar and API Request ID.
43
+ def create(identifier:, request_body:)
44
+ post(
45
+ path: "#{api_uri}/v3/grants/#{identifier}/calendars",
46
+ request_body: request_body
47
+ )
48
+ end
49
+
50
+ # Update a calendar.
51
+ #
52
+ # @param identifier [String] Grant ID or email account in which to update an object.
53
+ # @param calendar_id [String] The id of the calendar to update.
54
+ # Use "primary" to refer to the primary calendar associated with grant.
55
+ # @param request_body [Hash] The values to update the calendar with
56
+ # @return [Array(Hash, String)] The updated calendar and API Request ID.
57
+ def update(identifier:, calendar_id:, request_body:)
58
+ put(
59
+ path: "#{api_uri}/v3/grants/#{identifier}/calendars/#{calendar_id}",
60
+ request_body: request_body
61
+ )
62
+ end
63
+
64
+ # Delete a calendar.
65
+ #
66
+ # @param identifier [String] Grant ID or email account from which to delete an object.
67
+ # @param calendar_id [String] The id of the calendar to delete.
68
+ # Use "primary" to refer to the primary calendar associated with grant.
69
+ # @return [Array(TrueClass, String)] True and the API Request ID for the delete operation.
70
+ def destroy(identifier:, calendar_id:)
71
+ _, request_id = delete(
72
+ path: "#{api_uri}/v3/grants/#{identifier}/calendars/#{calendar_id}"
73
+ )
74
+
75
+ [true, request_id]
76
+ end
77
+
78
+ # Checks multiple calendars to find available time slots for a single meeting.
79
+ #
80
+ # @param request_body [Hash] Request body to pass to the request.
81
+ # @return [Array(Hash, String)] Availability object and API request ID.
82
+ def get_availability(request_body:)
83
+ post(
84
+ path: "#{api_uri}/v3/calendars/availability",
85
+ request_body: request_body
86
+ )
87
+ end
88
+
89
+ # Get the free/busy schedule for a list of email addresses.
90
+ #
91
+ # @param identifier [str] The identifier of the grant to act upon.
92
+ # @param request_body [Hash] Request body to pass to the request.
93
+ # @return [Array(Array(Hash), String)] The free/busy response.
94
+ def get_free_busy(identifier:, request_body:)
95
+ post(
96
+ path: "#{api_uri}/v3/grants/#{identifier}/calendars/availability",
97
+ request_body: request_body
98
+ )
99
+ end
100
+ end
101
+ end