nylas 6.7.1 → 6.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa916629fd9482f57599bd8cb7887f69575cc12cffd4f2d3d0fa37c5cd163b70
4
- data.tar.gz: 906042891eb1519df1ff287ae27104b5f871edcbb938e25cc23e65a1d71452a0
3
+ metadata.gz: 39fb36891572d67e348da1b79d8d0f73c0c542f073252733a17c7a11ac5f041b
4
+ data.tar.gz: 234c99ad89acd1ef2069bea31a70f7f86e8acf8e5b6a0a38b6000e79e7a570e4
5
5
  SHA512:
6
- metadata.gz: 1f7203ab924ec04f7efda91875003a8ffa10a182800ae7f0ffa8fb1cb7ad01a5cb4403bf99d79d84e58514acd25b45e8446a5522f771b7bd110e1c17595d94c1
7
- data.tar.gz: fb23ac5760b2ed22f253dba8316baf5542ca29f654b1ca5b92345d34918e138065051b207435a62c82d41cefdbb7d3f6ecec0df0eee8294c3471518cc54f3151
6
+ metadata.gz: ae326a217e211366f66a2079cc98990c9ebad04bd0c48a88c6a1634adae55db6d9ee505060655eb4faee1a2deffb7d4447e007a5e5b09a3fdc44157743b20034
7
+ data.tar.gz: b5c494daa9bd4062765eb5182382f550d06abb20ee85d0c890dee54cede76af4ea5650765ebd9bc3bb151d404bb853b409e9695219a5bcf29156d27df6fd696d
data/lib/nylas/client.rb CHANGED
@@ -8,6 +8,7 @@ require_relative "resources/auth"
8
8
  require_relative "resources/webhooks"
9
9
  require_relative "resources/applications"
10
10
  require_relative "resources/folders"
11
+ require_relative "resources/lists"
11
12
  require_relative "resources/notetakers"
12
13
  require_relative "resources/scheduler"
13
14
 
@@ -99,6 +100,13 @@ module Nylas
99
100
  Grants.new(self)
100
101
  end
101
102
 
103
+ # The list resources for your Nylas application.
104
+ #
105
+ # @return [Nylas::Lists] List resources for your Nylas application
106
+ def lists
107
+ Lists.new(self)
108
+ end
109
+
102
110
  # The message resources for your Nylas application.
103
111
  #
104
112
  # @return [Nylas::Messages] Message resources for your Nylas application
@@ -113,6 +121,34 @@ module Nylas
113
121
  Threads.new(self)
114
122
  end
115
123
 
124
+ # The policy resources for your Nylas application.
125
+ #
126
+ # @return [Nylas::Policies] Policy resources for your Nylas application.
127
+ def policies
128
+ Policies.new(self)
129
+ end
130
+
131
+ # The rule resources for your Nylas application.
132
+ #
133
+ # @return [Nylas::Rules] Rule resources for your Nylas application.
134
+ def rules
135
+ Rules.new(self)
136
+ end
137
+
138
+ # The workspace resources for your Nylas application.
139
+ #
140
+ # @return [Nylas::Workspaces] Workspace resources for your Nylas application.
141
+ def workspaces
142
+ Workspaces.new(self)
143
+ end
144
+
145
+ # The domain resources for your Nylas application.
146
+ #
147
+ # @return [Nylas::Domains] Domain resources for your Nylas application.
148
+ def domains
149
+ Domains.new(self)
150
+ end
151
+
116
152
  # The webhook resources for your Nylas application.
117
153
  #
118
154
  # @return [Nylas::Webhooks] Webhook resources for your Nylas application.
@@ -15,9 +15,10 @@ module Nylas
15
15
  #
16
16
  # @param path [String] Destination path for the call.
17
17
  # @param query_params [Hash, {}] Query params to pass to the call.
18
+ # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
18
19
  # @return [Array([Hash, Array], String, Hash)] Nylas data object, API Request ID, and response headers.
19
- def get(path:, query_params: {})
20
- response = get_raw(path: path, query_params: query_params)
20
+ def get(path:, query_params: {}, headers: {})
21
+ response = get_raw(path: path, query_params: query_params, headers: headers)
21
22
 
22
23
  [response[:data], response[:request_id], response[:headers]]
23
24
  end
@@ -26,10 +27,11 @@ module Nylas
26
27
  #
27
28
  # @param path [String] Destination path for the call.
28
29
  # @param query_params [Hash, {}] Query params to pass to the call.
30
+ # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
29
31
  # @return [Array<Array<Hash>, String, String, Hash>]
30
32
  # Nylas data array, API Request ID, next cursor, and response headers.response headers.
31
- def get_list(path:, query_params: {})
32
- response = get_raw(path: path, query_params: query_params)
33
+ def get_list(path:, query_params: {}, headers: {})
34
+ response = get_raw(path: path, query_params: query_params, headers: headers)
33
35
 
34
36
  [response[:data], response[:request_id], response[:next_cursor], response[:headers]]
35
37
  end
@@ -40,16 +42,20 @@ module Nylas
40
42
  #
41
43
  # @param path [String] Destination path for the call.
42
44
  # @param query_params [Hash, {}] Query params to pass to the call.
45
+ # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
43
46
  # @return [Hash] The JSON response from the Nylas API.
44
- def get_raw(path:, query_params: {})
45
- execute(
47
+ def get_raw(path:, query_params: {}, headers: {})
48
+ request = {
46
49
  method: :get,
47
50
  path: path,
48
51
  query: query_params,
49
52
  payload: nil,
50
53
  api_key: api_key,
51
54
  timeout: timeout
52
- )
55
+ }
56
+ request[:headers] = headers unless headers.empty?
57
+
58
+ execute(**request)
53
59
  end
54
60
  end
55
61
 
@@ -63,18 +69,21 @@ module Nylas
63
69
  # @param path [String] Destination path for the call.
64
70
  # @param query_params [Hash, {}] Query params to pass to the call.
65
71
  # @param request_body [Hash, nil] Request body to pass to the call.
72
+ # Defaults to {} when nil to ensure Content-Type: application/json is sent.
66
73
  # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
67
74
  # @return [Array(Hash, String, Hash)] Nylas data object, API Request ID, and response headers.
68
- def post(path:, query_params: {}, request_body: nil, headers: {})
69
- response = execute(
75
+ def post(path:, query_params: {}, request_body: nil, headers: {}, serialized_json_body: nil)
76
+ request = {
70
77
  method: :post,
71
78
  path: path,
72
79
  query: query_params,
73
- payload: request_body,
80
+ payload: request_body || {},
74
81
  headers: headers,
75
82
  api_key: api_key,
76
83
  timeout: timeout
77
- )
84
+ }
85
+ request[:serialized_json_body] = serialized_json_body unless serialized_json_body.nil?
86
+ response = execute(**request)
78
87
 
79
88
  [response[:data], response[:request_id], response[:headers]]
80
89
  end
@@ -90,18 +99,21 @@ module Nylas
90
99
  # @param path [String] Destination path for the call.
91
100
  # @param query_params [Hash, {}] Query params to pass to the call.
92
101
  # @param request_body [Hash, nil] Request body to pass to the call.
102
+ # Defaults to {} when nil to ensure Content-Type: application/json is sent.
93
103
  # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
94
104
  # @return Nylas data object and API Request ID.
95
- def put(path:, query_params: {}, request_body: nil, headers: {})
96
- response = execute(
105
+ def put(path:, query_params: {}, request_body: nil, headers: {}, serialized_json_body: nil)
106
+ request = {
97
107
  method: :put,
98
108
  path: path,
99
109
  query: query_params,
100
- payload: request_body,
110
+ payload: request_body || {},
101
111
  headers: headers,
102
112
  api_key: api_key,
103
113
  timeout: timeout
104
- )
114
+ }
115
+ request[:serialized_json_body] = serialized_json_body unless serialized_json_body.nil?
116
+ response = execute(**request)
105
117
 
106
118
  [response[:data], response[:request_id]]
107
119
  end
@@ -117,18 +129,21 @@ module Nylas
117
129
  # @param path [String] Destination path for the call.
118
130
  # @param query_params [Hash, {}] Query params to pass to the call.
119
131
  # @param request_body [Hash, nil] Request body to pass to the call.
132
+ # Defaults to {} when nil to ensure Content-Type: application/json is sent.
120
133
  # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
121
134
  # @return Nylas data object and API Request ID.
122
- def patch(path:, query_params: {}, request_body: nil, headers: {})
123
- response = execute(
135
+ def patch(path:, query_params: {}, request_body: nil, headers: {}, serialized_json_body: nil)
136
+ request = {
124
137
  method: :patch,
125
138
  path: path,
126
139
  query: query_params,
127
- payload: request_body,
140
+ payload: request_body || {},
128
141
  headers: headers,
129
142
  api_key: api_key,
130
143
  timeout: timeout
131
- )
144
+ }
145
+ request[:serialized_json_body] = serialized_json_body unless serialized_json_body.nil?
146
+ response = execute(**request)
132
147
 
133
148
  [response[:data], response[:request_id]]
134
149
  end
@@ -143,15 +158,17 @@ module Nylas
143
158
  #
144
159
  # @param path [String] Destination path for the call.
145
160
  # @param query_params [Hash, {}] Query params to pass to the call.
161
+ # @param request_body [Hash, nil] Optional request body (e.g. cancellation_reason for bookings).
162
+ # Defaults to {} to ensure Content-Type: application/json is sent.
146
163
  # @param headers [Hash, {}] Additional HTTP headers to include in the payload.
147
164
  # @return Nylas data object and API Request ID.
148
- def delete(path:, query_params: {}, headers: {})
165
+ def delete(path:, query_params: {}, request_body: nil, headers: {})
149
166
  response = execute(
150
167
  method: :delete,
151
168
  path: path,
152
169
  query: query_params,
153
170
  headers: headers,
154
- payload: nil,
171
+ payload: request_body || {},
155
172
  api_key: api_key,
156
173
  timeout: timeout
157
174
  )
@@ -30,11 +30,14 @@ module Nylas
30
30
  # @param query [Hash, {}] Hash of names and values to include in the query section of the URI
31
31
  # fragment.
32
32
  # @param payload [Hash, nil] Body to send with the request.
33
+ # @param serialized_json_body [String, nil] Pre-serialized JSON body to send as-is.
33
34
  # @param api_key [Hash, nil] API key to send with the request.
34
35
  # @return [Object] Parsed JSON response from the API.
35
- def execute(method:, path:, timeout:, headers: {}, query: {}, payload: nil, api_key: nil)
36
+ def execute(method:, path:, timeout:, headers: {}, query: {}, payload: nil, api_key: nil,
37
+ serialized_json_body: nil)
36
38
  request = build_request(method: method, path: path, headers: headers,
37
- query: query, payload: payload, api_key: api_key, timeout: timeout)
39
+ query: query, payload: payload, api_key: api_key, timeout: timeout,
40
+ serialized_json_body: serialized_json_body)
38
41
  begin
39
42
  httparty_execute(**request) do |response, _request, result|
40
43
  content_type = nil
@@ -91,12 +94,14 @@ module Nylas
91
94
  # @param query [Hash, {}] Hash of names and values to include in the query section of the URI
92
95
  # fragment.
93
96
  # @param payload [Hash, nil] Body to send with the request.
97
+ # @param serialized_json_body [String, nil] Pre-serialized JSON body to send as-is.
94
98
  # @param timeout [Integer, nil] Timeout value to send with the request.
95
99
  # @param api_key [Hash, nil] API key to send with the request.
96
100
  # @return [Object] The request information after processing. This includes an updated payload
97
101
  # and headers.
98
102
  def build_request(
99
- method:, path: nil, headers: {}, query: {}, payload: nil, timeout: nil, api_key: nil
103
+ method:, path: nil, headers: {}, query: {}, payload: nil, timeout: nil, api_key: nil,
104
+ serialized_json_body: nil
100
105
  )
101
106
  url = build_url(path, query)
102
107
  resulting_headers = default_headers.merge(headers).merge(auth_header(api_key))
@@ -104,7 +109,10 @@ module Nylas
104
109
  # Check for multipart flag using both string and symbol keys for backwards compatibility
105
110
  is_multipart = !payload.nil? && (payload["multipart"] || payload[:multipart])
106
111
 
107
- if !payload.nil? && !is_multipart
112
+ if !serialized_json_body.nil?
113
+ payload = serialized_json_body
114
+ resulting_headers["Content-type"] = "application/json"
115
+ elsif !payload.nil? && !is_multipart
108
116
  normalize_json_encodings!(payload)
109
117
  payload = payload&.to_json
110
118
  resulting_headers["Content-type"] = "application/json"
@@ -489,6 +497,8 @@ module Nylas
489
497
 
490
498
  # Set the authorization header for an API query.
491
499
  def auth_header(api_key)
500
+ return {} if api_key.nil?
501
+
492
502
  { "Authorization" => "Bearer #{api_key}" }
493
503
  end
494
504
  end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "json"
5
+ require "openssl"
6
+ require "securerandom"
7
+
8
+ module Nylas
9
+ # Builds Nylas Service Account request signing headers for organization admin APIs.
10
+ #
11
+ # @see https://developer.nylas.com/docs/v3/auth/nylas-service-account/
12
+ class ServiceAccountSigner
13
+ NONCE_ALPHABET = ("a".."z").to_a.concat(("A".."Z").to_a, ("0".."9").to_a).freeze
14
+ DEFAULT_NONCE_LENGTH = 20
15
+ SIGNED_BODY_METHODS = %w[post put patch].freeze
16
+
17
+ attr_reader :private_key_id
18
+
19
+ # @param private_key_pem [String] RSA private key in PEM format.
20
+ # @param private_key_id [String] Value for the X-Nylas-Kid header.
21
+ def initialize(private_key_pem:, private_key_id:)
22
+ @private_key = self.class.load_rsa_private_key(private_key_pem)
23
+ @private_key_id = private_key_id
24
+ end
25
+
26
+ # Returns deterministic JSON with keys sorted at every object level and no extra whitespace.
27
+ #
28
+ # @param data [Hash, Array, String, Numeric, true, false, nil] Data to serialize.
29
+ # @return [String] Canonical JSON string.
30
+ def self.canonical_json(data)
31
+ JSON.generate(canonicalize(data))
32
+ end
33
+
34
+ # Loads an RSA private key from a PEM string.
35
+ #
36
+ # @param private_key_pem [String] RSA private key in PEM format.
37
+ # @return [OpenSSL::PKey::RSA]
38
+ def self.load_rsa_private_key(private_key_pem)
39
+ key = OpenSSL::PKey::RSA.new(private_key_pem)
40
+ raise ArgumentError, "Private key must be RSA private key" unless key.private?
41
+ raise ArgumentError, "Private key must be at least 2048 bits" if key.n.num_bits < 2048
42
+
43
+ key
44
+ rescue OpenSSL::PKey::PKeyError
45
+ raise ArgumentError, "Private key must be RSA PEM"
46
+ end
47
+
48
+ # Generates a cryptographically secure alphanumeric nonce.
49
+ #
50
+ # @param length [Integer] Length of the nonce to generate.
51
+ # @return [String] Generated nonce.
52
+ def self.generate_nonce(length = DEFAULT_NONCE_LENGTH)
53
+ Array.new(length) { NONCE_ALPHABET[SecureRandom.random_number(NONCE_ALPHABET.length)] }.join
54
+ end
55
+
56
+ # Builds signed headers and, for JSON body methods, the exact canonical body to send.
57
+ #
58
+ # @param method [String, Symbol] HTTP method.
59
+ # @param path [String] Relative request path, for example "/v3/admin/domains".
60
+ # @param body [Hash, nil] Request body for POST/PUT/PATCH requests.
61
+ # @param timestamp [Integer, nil] Optional Unix timestamp in seconds, mainly for tests.
62
+ # @param nonce [String, nil] Optional nonce, mainly for tests.
63
+ # @return [Array(Hash, String)] Signed headers and optional serialized JSON body.
64
+ def build_headers(method:, path:, body: nil, timestamp: nil, nonce: nil)
65
+ timestamp ||= Time.now.to_i
66
+ nonce ||= self.class.generate_nonce
67
+ method_value = method.to_s.downcase
68
+ serialized_body = nil
69
+
70
+ if SIGNED_BODY_METHODS.include?(method_value) && !body.nil?
71
+ serialized_body = self.class.canonical_json(body)
72
+ end
73
+
74
+ envelope = {
75
+ method: method_value,
76
+ nonce: nonce,
77
+ path: path,
78
+ timestamp: timestamp
79
+ }
80
+ envelope[:payload] = serialized_body if serialized_body
81
+
82
+ signature = @private_key.sign(OpenSSL::Digest.new("SHA256"), self.class.canonical_json(envelope))
83
+
84
+ [
85
+ {
86
+ "X-Nylas-Kid" => private_key_id,
87
+ "X-Nylas-Nonce" => nonce,
88
+ "X-Nylas-Timestamp" => timestamp.to_s,
89
+ "X-Nylas-Signature" => Base64.strict_encode64(signature)
90
+ },
91
+ serialized_body
92
+ ]
93
+ end
94
+
95
+ class << self
96
+ private
97
+
98
+ def canonicalize(value)
99
+ case value
100
+ when Hash
101
+ value.keys.sort_by(&:to_s).each_with_object({}) do |key, result|
102
+ result[key.to_s] = canonicalize(value[key])
103
+ end
104
+ when Array
105
+ value.map { |item| canonicalize(item) }
106
+ else
107
+ value
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -8,6 +8,7 @@ module Nylas
8
8
  # Application
9
9
  class Applications < Resource
10
10
  include ApiOperations::Get
11
+ include ApiOperations::Patch
11
12
 
12
13
  attr_reader :redirect_uris
13
14
 
@@ -23,5 +24,18 @@ module Nylas
23
24
  def get_details
24
25
  get(path: "#{api_uri}/v3/applications")
25
26
  end
27
+
28
+ # Update application details.
29
+ #
30
+ # @param request_body [Hash] The values to update the application with. Include
31
+ # +callback_uris+ entries with +id+ when preserving or updating existing
32
+ # callback URIs.
33
+ # @return [Array(Hash, String)] The updated application details and API Request ID.
34
+ def update(request_body:)
35
+ patch(
36
+ path: "#{api_uri}/v3/applications",
37
+ request_body: request_body
38
+ )
39
+ end
26
40
  end
27
41
  end
@@ -64,11 +64,13 @@ module Nylas
64
64
  # Delete a booking.
65
65
  # @param booking_id [String] The id of the booking to delete.
66
66
  # @param query_params [Hash, nil] Query params to pass to the request.
67
+ # @param request_body [Hash, nil] Optional body params (e.g. cancellation_reason).
67
68
  # @return [Array(TrueClass, String)] True and the API Request ID for the delete operation.
68
- def destroy(booking_id:, query_params: nil)
69
+ def destroy(booking_id:, query_params: nil, request_body: nil)
69
70
  _, request_id = delete(
70
71
  path: "#{api_uri}/v3/scheduling/bookings/#{booking_id}",
71
- query_params: query_params
72
+ query_params: query_params,
73
+ request_body: request_body
72
74
  )
73
75
 
74
76
  [true, request_id]
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+ require_relative "../handler/service_account_signer"
6
+ require "uri"
7
+
8
+ module Nylas
9
+ # Module representing the possible 'type' values in a domain verification request.
10
+ # @see https://developer.nylas.com/docs/reference/api/manage-domains/
11
+ module DomainVerificationRequestType
12
+ OWNERSHIP = "ownership"
13
+ MX = "mx"
14
+ SPF = "spf"
15
+ DKIM = "dkim"
16
+ FEEDBACK = "feedback"
17
+ end
18
+
19
+ # Module representing the possible 'type' values in a domain verification result.
20
+ # @see https://developer.nylas.com/docs/reference/api/manage-domains/
21
+ module DomainVerificationType
22
+ OWNERSHIP = DomainVerificationRequestType::OWNERSHIP
23
+ MX = DomainVerificationRequestType::MX
24
+ SPF = DomainVerificationRequestType::SPF
25
+ DKIM = DomainVerificationRequestType::DKIM
26
+ FEEDBACK = DomainVerificationRequestType::FEEDBACK
27
+ DMARC = "dmarc"
28
+ ARC = "arc"
29
+ end
30
+
31
+ # Module representing the possible 'status' values in a domain verification result.
32
+ module DomainVerificationStatus
33
+ PENDING = "pending"
34
+ DONE = "done"
35
+ FAILED = "failed"
36
+ end
37
+
38
+ # Nylas Manage Domains API
39
+ #
40
+ # These endpoints require Nylas Service Account request signing. Pass headers
41
+ # containing `X-Nylas-Kid`, `X-Nylas-Timestamp`, `X-Nylas-Nonce`, and
42
+ # `X-Nylas-Signature` generated for the exact request being sent.
43
+ class Domains < Resource
44
+ include ApiOperations::Get
45
+ include ApiOperations::Post
46
+ include ApiOperations::Put
47
+ include ApiOperations::Delete
48
+
49
+ REQUIRED_SERVICE_ACCOUNT_HEADERS = %w[
50
+ X-Nylas-Kid
51
+ X-Nylas-Timestamp
52
+ X-Nylas-Nonce
53
+ X-Nylas-Signature
54
+ ].freeze
55
+ DOMAINS_PATH = "/v3/admin/domains"
56
+
57
+ # Return all domains for the caller's organization.
58
+ #
59
+ # @param query_params [Hash, nil] Query params to pass to the request.
60
+ # Supported keys: `limit`, `page_token`.
61
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
62
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
63
+ # @return [Array(Array(Hash), String, String, Hash)]
64
+ # The list of domains, API Request ID, next cursor, and response headers.
65
+ def list(headers: nil, query_params: nil, signer: nil)
66
+ request_headers, = signed_request_headers(method: :get, relative_path: DOMAINS_PATH,
67
+ headers: headers, signer: signer)
68
+
69
+ get_list(
70
+ path: full_path(DOMAINS_PATH),
71
+ query_params: query_params,
72
+ headers: request_headers
73
+ )
74
+ end
75
+
76
+ # Return a domain.
77
+ #
78
+ # @param domain_id [String] The identifier of the domain to return.
79
+ # Accepts either a UUID or a domain address (FQDN/email format).
80
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
81
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
82
+ # @return [Array(Hash, String, Hash)] The domain, API request ID, and response headers.
83
+ def find(domain_id:, headers: nil, signer: nil)
84
+ relative_path = "#{DOMAINS_PATH}/#{encoded_domain_id(domain_id)}"
85
+ request_headers, = signed_request_headers(method: :get, relative_path: relative_path,
86
+ headers: headers, signer: signer)
87
+
88
+ get(
89
+ path: full_path(relative_path),
90
+ headers: request_headers
91
+ )
92
+ end
93
+
94
+ # Create a domain.
95
+ #
96
+ # @param request_body [Hash] The values to create the domain with.
97
+ # Requires `name` and `domain_address`.
98
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
99
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
100
+ # @return [Array(Hash, String, Hash)] The created domain, API Request ID, and response headers.
101
+ def create(request_body:, headers: nil, signer: nil)
102
+ request_headers, serialized_body = signed_request_headers(
103
+ method: :post,
104
+ relative_path: DOMAINS_PATH,
105
+ body: request_body,
106
+ headers: headers,
107
+ signer: signer
108
+ )
109
+
110
+ request = {
111
+ path: full_path(DOMAINS_PATH),
112
+ request_body: serialized_body.nil? ? request_body : nil,
113
+ headers: request_headers
114
+ }
115
+ request[:serialized_json_body] = serialized_body unless serialized_body.nil?
116
+ post(**request)
117
+ end
118
+
119
+ # Update a domain.
120
+ #
121
+ # @param domain_id [String] The identifier of the domain to update.
122
+ # Accepts either a UUID or a domain address (FQDN/email format).
123
+ # @param request_body [Hash] The values to update the domain with.
124
+ # The response echoes only the updated fields, not a full domain object.
125
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
126
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
127
+ # @return [Array(Hash, String)] The updated domain fields and API Request ID.
128
+ def update(domain_id:, request_body:, headers: nil, signer: nil)
129
+ relative_path = "#{DOMAINS_PATH}/#{encoded_domain_id(domain_id)}"
130
+ request_headers, serialized_body = signed_request_headers(
131
+ method: :put,
132
+ relative_path: relative_path,
133
+ body: request_body,
134
+ headers: headers,
135
+ signer: signer
136
+ )
137
+
138
+ request = {
139
+ path: full_path(relative_path),
140
+ request_body: serialized_body.nil? ? request_body : nil,
141
+ headers: request_headers
142
+ }
143
+ request[:serialized_json_body] = serialized_body unless serialized_body.nil?
144
+ put(**request)
145
+ end
146
+
147
+ # Delete a domain.
148
+ #
149
+ # @param domain_id [String] The identifier of the domain to delete.
150
+ # Accepts either a UUID or a domain address (FQDN/email format).
151
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
152
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
153
+ # @return [Array(TrueClass, String)] True and the API Request ID for the delete operation.
154
+ def destroy(domain_id:, headers: nil, signer: nil)
155
+ relative_path = "#{DOMAINS_PATH}/#{encoded_domain_id(domain_id)}"
156
+ request_headers, = signed_request_headers(method: :delete, relative_path: relative_path,
157
+ headers: headers, signer: signer)
158
+
159
+ _, request_id = delete(
160
+ path: full_path(relative_path),
161
+ headers: request_headers
162
+ )
163
+
164
+ [true, request_id]
165
+ end
166
+
167
+ # Get the DNS record info for a domain verification type.
168
+ #
169
+ # @param domain_id [String] The identifier of the domain.
170
+ # Accepts either a UUID or a domain address (FQDN/email format).
171
+ # @param request_body [Hash] The verification attempt values. Requires `type`.
172
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
173
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
174
+ # @return [Array(Hash, String, Hash)]
175
+ # The domain verification result, API Request ID, and response headers.
176
+ def info(domain_id:, request_body:, headers: nil, signer: nil)
177
+ relative_path = "#{DOMAINS_PATH}/#{encoded_domain_id(domain_id)}/info"
178
+ request_headers, serialized_body = signed_request_headers(
179
+ method: :post,
180
+ relative_path: relative_path,
181
+ body: request_body,
182
+ headers: headers,
183
+ signer: signer
184
+ )
185
+
186
+ request = {
187
+ path: full_path(relative_path),
188
+ request_body: serialized_body.nil? ? request_body : nil,
189
+ headers: request_headers
190
+ }
191
+ request[:serialized_json_body] = serialized_body unless serialized_body.nil?
192
+ post(**request)
193
+ end
194
+
195
+ # Trigger a DNS verification check for a domain verification type.
196
+ #
197
+ # @param domain_id [String] The identifier of the domain.
198
+ # Accepts either a UUID or a domain address (FQDN/email format).
199
+ # @param request_body [Hash] The verification attempt values. Requires `type`.
200
+ # @param headers [Hash, nil] Nylas Service Account request signing headers.
201
+ # @param signer [ServiceAccountSigner, nil] Signer to generate Nylas Service Account headers.
202
+ # @return [Array(Hash, String, Hash)]
203
+ # The domain verification result, API Request ID, and response headers.
204
+ def verify(domain_id:, request_body:, headers: nil, signer: nil)
205
+ relative_path = "#{DOMAINS_PATH}/#{encoded_domain_id(domain_id)}/verify"
206
+ request_headers, serialized_body = signed_request_headers(
207
+ method: :post,
208
+ relative_path: relative_path,
209
+ body: request_body,
210
+ headers: headers,
211
+ signer: signer
212
+ )
213
+
214
+ request = {
215
+ path: full_path(relative_path),
216
+ request_body: serialized_body.nil? ? request_body : nil,
217
+ headers: request_headers
218
+ }
219
+ request[:serialized_json_body] = serialized_body unless serialized_body.nil?
220
+ post(**request)
221
+ end
222
+
223
+ private
224
+
225
+ # Manage Domains uses Nylas Service Account signing headers instead of API-key bearer auth.
226
+ def api_key
227
+ nil
228
+ end
229
+
230
+ def full_path(relative_path)
231
+ "#{api_uri}#{relative_path}"
232
+ end
233
+
234
+ def encoded_domain_id(domain_id)
235
+ URI.encode_www_form_component(domain_id)
236
+ end
237
+
238
+ def signed_request_headers(method:, relative_path:, headers:, signer:, body: nil)
239
+ request_headers = headers.nil? ? {} : headers.dup
240
+ serialized_body = body.nil? ? nil : Nylas::ServiceAccountSigner.canonical_json(body)
241
+ if signer
242
+ signer_headers, serialized_body = signer.build_headers(
243
+ method: method,
244
+ path: relative_path,
245
+ body: body
246
+ )
247
+ request_headers.merge!(signer_headers)
248
+ end
249
+
250
+ validate_service_account_headers!(request_headers)
251
+ [request_headers, serialized_body]
252
+ end
253
+
254
+ def validate_service_account_headers!(headers)
255
+ header_values = headers || {}
256
+ normalized_headers = header_values.transform_keys do |key|
257
+ key.to_s.downcase
258
+ end
259
+ missing_headers = REQUIRED_SERVICE_ACCOUNT_HEADERS.select do |header|
260
+ normalized_headers[header.downcase].to_s.empty?
261
+ end
262
+
263
+ return if missing_headers.empty?
264
+
265
+ raise ArgumentError,
266
+ "Missing required service account authentication headers: #{missing_headers.join(', ')}"
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+
6
+ module Nylas
7
+ # Module representing the possible 'type' values for a List.
8
+ module ListType
9
+ DOMAIN = "domain"
10
+ TLD = "tld"
11
+ ADDRESS = "address"
12
+ end
13
+
14
+ # Nylas Lists API
15
+ #
16
+ # Lists are typed collections of domains, TLDs, or email addresses that can
17
+ # be referenced by Rules using the +in_list+ condition operator.
18
+ class Lists < Resource
19
+ include ApiOperations::Post
20
+
21
+ # Create a list for the application.
22
+ #
23
+ # @param request_body [Hash] The public values to create the list with.
24
+ # Supported keys: +name+ (required, 1-256 chars), +type+ (required; one of
25
+ # +domain+, +tld+, or +address+), and +description+ (optional). The server
26
+ # assigns identifiers, item counts, timestamps, and application ownership.
27
+ # @return [Array(Hash, String, Hash)] The created list, API Request ID, and
28
+ # response headers.
29
+ def create(request_body:)
30
+ post(
31
+ path: "#{api_uri}/v3/lists",
32
+ request_body: request_body
33
+ )
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+
6
+ module Nylas
7
+ # Nylas Policies API (beta)
8
+ #
9
+ # Policies define message limits, spam-detection settings, options, and linked
10
+ # rules for Nylas Agent Accounts. `application_id` and `organization_id` are
11
+ # derived from the API key / gateway headers and are read-only.
12
+ #
13
+ # Policy objects (the Hash returned/accepted by these methods) carry these keys:
14
+ # - +id+ [String] Policy UUID. Read-only; server-assigned on create.
15
+ # - +name+ [String] 1-256 chars. Required on create.
16
+ # - +application_id+ [String] Read-only; derived from the API key.
17
+ # - +organization_id+ [String] Read-only; derived from the API key.
18
+ # - +rules+ [Array<String>] Linked rule IDs.
19
+ # - +created_at+ [Integer] Unix timestamp (seconds). Read-only.
20
+ # - +updated_at+ [Integer] Unix timestamp (seconds). Read-only.
21
+ # - +limits+ [Hash] Per-policy limits. Returned as *effective* values resolved
22
+ # against the org's billing plan, which may differ from what was sent. Keys:
23
+ # - +limit_attachment_size_limit+ [Integer] Bytes; >= 0, <= plan max.
24
+ # - +limit_attachment_count_limit+ [Integer] >= 0, <= plan max.
25
+ # - +limit_attachment_allowed_types+ [Array<String>] MIME types from the plan allow-list.
26
+ # - +limit_size_total_mime+ [Integer] Bytes; >= 0, <= plan max.
27
+ # - +limit_storage_total+ [Integer] Bytes. Unlimited-capable: -1 = unlimited.
28
+ # - +limit_count_daily_message_received+ [Integer] Per-grant daily received-message
29
+ # cap. Unlimited-capable: -1 = unlimited.
30
+ # - +limit_count_daily_email_sent+ [Integer] Per-grant daily sent-email cap.
31
+ # Unlimited-capable: -1 = unlimited.
32
+ # - +limit_inbox_retention_period+ [Integer] Days. Unlimited-capable: -1. Must be
33
+ # greater than spam retention when both set.
34
+ # - +limit_spam_retention_period+ [Integer] Days. Unlimited-capable: -1. Must be
35
+ # shorter than inbox retention when both set.
36
+ # - +options+ [Hash] Policy options. Keys:
37
+ # - +additional_folders+ [Array<String>] Only allowed when the plan permits.
38
+ # - +use_cidr_aliasing+ [Boolean] Only allowed when the plan permits.
39
+ # - +spam_detection+ [Hash] Spam-detection settings. Keys:
40
+ # - +use_list_dnsbl+ [Boolean] Always present in responses (false when unset).
41
+ # - +use_header_anomaly_detection+ [Boolean] Always present in responses (false when unset).
42
+ # - +spam_sensitivity+ [Float] 0.1-5.0 inclusive. Default 1.0.
43
+ #
44
+ # The unlimited sentinel for unlimited-capable fields is -1 only; values < -1 are
45
+ # rejected, and -1 is honored only when the plan permits unlimited for that field.
46
+ class Policies < Resource
47
+ include ApiOperations::Get
48
+ include ApiOperations::Post
49
+ include ApiOperations::Put
50
+ include ApiOperations::Delete
51
+
52
+ # Return all policies.
53
+ #
54
+ # The list envelope is flat: the data array is the policies themselves and
55
+ # +next_cursor+ is a top-level sibling. +next_cursor+ is present on every
56
+ # non-empty page (including the last) and is not a has-more flag; page until
57
+ # an empty data array is returned.
58
+ #
59
+ # @param query_params [Hash, nil] Query params to pass to the request
60
+ # (e.g. +limit+ — default 10, no server max; +page_token+ — opaque cursor).
61
+ # @return [Array(Array(Hash), String, String, Hash)] The list of policies,
62
+ # API Request ID, next cursor, and response headers.
63
+ def list(query_params: nil)
64
+ get_list(
65
+ path: "#{api_uri}/v3/policies",
66
+ query_params: query_params
67
+ )
68
+ end
69
+
70
+ # Return a policy.
71
+ #
72
+ # @param policy_id [String] The id of the policy to return.
73
+ # @return [Array(Hash, String, Hash)] The policy, API request ID, and response headers.
74
+ def find(policy_id:)
75
+ get(
76
+ path: "#{api_uri}/v3/policies/#{policy_id}"
77
+ )
78
+ end
79
+
80
+ # Create a policy.
81
+ #
82
+ # @param request_body [Hash] The values to create the policy with. Honored keys:
83
+ # +name+ (required), +options+, +limits+, +rules+, +spam_detection+. Any
84
+ # +id+/+created_at+/+updated_at+/+application_id+/+organization_id+ are ignored.
85
+ # Omitted +limits+/+options+/+spam_detection+ sub-fields fall back to plan defaults.
86
+ # @return [Array(Hash, String, Hash)] The created policy, API Request ID, and response headers.
87
+ def create(request_body:)
88
+ post(
89
+ path: "#{api_uri}/v3/policies",
90
+ request_body: request_body
91
+ )
92
+ end
93
+
94
+ # Update a policy.
95
+ #
96
+ # The route verb is PUT, but the update is a partial nested merge: provided
97
+ # sub-objects (+limits+/+options+/+spam_detection+) are merged field-by-field
98
+ # onto the stored policy. Send only the fields you intend to change.
99
+ #
100
+ # @param policy_id [String] The id of the policy to update.
101
+ # @param request_body [Hash] The values to update the policy with. Honored keys:
102
+ # +name+, +options+, +limits+, +rules+, +spam_detection+. Any
103
+ # +id+/+created_at+/+updated_at+/+application_id+/+organization_id+ are ignored.
104
+ # @return [Array(Hash, String)] The updated policy and API Request ID.
105
+ def update(policy_id:, request_body:)
106
+ put(
107
+ path: "#{api_uri}/v3/policies/#{policy_id}",
108
+ request_body: request_body
109
+ )
110
+ end
111
+
112
+ # Delete a policy.
113
+ #
114
+ # @param policy_id [String] The id of the policy to delete.
115
+ # @return [Array(TrueClass, String)] True and the API Request ID for the delete operation.
116
+ def destroy(policy_id:)
117
+ _, request_id = delete(
118
+ path: "#{api_uri}/v3/policies/#{policy_id}"
119
+ )
120
+
121
+ [true, request_id]
122
+ end
123
+ end
124
+ end
@@ -8,7 +8,7 @@ module Nylas
8
8
  class RedirectUris < Resource
9
9
  include ApiOperations::Get
10
10
  include ApiOperations::Post
11
- include ApiOperations::Put
11
+ include ApiOperations::Patch
12
12
  include ApiOperations::Delete
13
13
 
14
14
  # Return all redirect uris.
@@ -47,7 +47,7 @@ module Nylas
47
47
  # @param request_body [Hash] The values to update the redirect uri with
48
48
  # @return [Array(Hash, String)] The updated redirect uri and API Request ID.
49
49
  def update(redirect_uri_id:, request_body:)
50
- put(
50
+ patch(
51
51
  path: "#{api_uri}/v3/applications/redirect-uris/#{redirect_uri_id}",
52
52
  request_body: request_body
53
53
  )
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+
6
+ module Nylas
7
+ # Module representing the possible 'trigger' values for a Rule.
8
+ module RuleTrigger
9
+ INBOUND = "inbound"
10
+ OUTBOUND = "outbound"
11
+ end
12
+
13
+ # Module representing the possible 'match.operator' values for a Rule.
14
+ module RuleMatchOperator
15
+ ANY = "any"
16
+ ALL = "all"
17
+ end
18
+
19
+ # Module representing the possible condition 'field' values for a Rule.
20
+ module RuleConditionField
21
+ FROM_ADDRESS = "from.address"
22
+ FROM_DOMAIN = "from.domain"
23
+ FROM_TLD = "from.tld"
24
+ RECIPIENT_ADDRESS = "recipient.address"
25
+ RECIPIENT_DOMAIN = "recipient.domain"
26
+ RECIPIENT_TLD = "recipient.tld"
27
+ OUTBOUND_TYPE = "outbound.type"
28
+ end
29
+
30
+ # Module representing the possible condition 'operator' values for a Rule.
31
+ module RuleConditionOperator
32
+ IS = "is"
33
+ IS_NOT = "is_not"
34
+ CONTAINS = "contains"
35
+ IN_LIST = "in_list"
36
+ end
37
+
38
+ # Module representing the possible 'outbound.type' condition values for a Rule.
39
+ module RuleOutboundType
40
+ COMPOSE = "compose"
41
+ REPLY = "reply"
42
+ end
43
+
44
+ # Module representing the possible action 'type' values for a Rule.
45
+ module RuleActionType
46
+ BLOCK = "block"
47
+ MARK_AS_SPAM = "mark_as_spam"
48
+ ASSIGN_TO_FOLDER = "assign_to_folder"
49
+ MARK_AS_READ = "mark_as_read"
50
+ MARK_AS_STARRED = "mark_as_starred"
51
+ ARCHIVE = "archive"
52
+ TRASH = "trash"
53
+ end
54
+
55
+ # Module representing the possible 'evaluation_stage' values in a rule evaluation.
56
+ module RuleEvaluationStage
57
+ SMTP_RCPT = "smtp_rcpt"
58
+ INBOX_PROCESSING = "inbox_processing"
59
+ OUTBOUND_SEND = "outbound_send"
60
+ end
61
+
62
+ # Nylas Rules API
63
+ class Rules < Resource
64
+ include ApiOperations::Get
65
+ include ApiOperations::Post
66
+ include ApiOperations::Put
67
+ include ApiOperations::Delete
68
+
69
+ # Return all rules.
70
+ #
71
+ # The list endpoint returns a nested envelope
72
+ # ({ request_id, data: { items: [...], next_cursor } }), so the items and
73
+ # cursor are unwrapped here defensively rather than via the standard
74
+ # get_list helper, which would mis-read the nested shape.
75
+ #
76
+ # @param query_params [Hash, nil] Query params to pass to the request.
77
+ # @return [Array(Array(Hash), String, String, Hash)]
78
+ # The list of rules, API Request ID, next cursor, and response headers.
79
+ def list(query_params: nil)
80
+ response = get_raw(
81
+ path: "#{api_uri}/v3/rules",
82
+ query_params: query_params
83
+ )
84
+
85
+ data = response[:data]
86
+ # Unwrap only when the envelope actually carries an :items key. Go's
87
+ # ListWithCursorResult serializes a nil slice as "items": null, so coerce
88
+ # that to [] rather than falling back to the envelope hash itself.
89
+ items = if data.is_a?(Hash) && data.key?(:items)
90
+ data[:items] || []
91
+ else
92
+ data
93
+ end
94
+ next_cursor = data.is_a?(Hash) ? data[:next_cursor] : response[:next_cursor]
95
+
96
+ [items, response[:request_id], next_cursor, response[:headers]]
97
+ end
98
+
99
+ # Return a rule.
100
+ #
101
+ # @param rule_id [String] The id of the rule to return.
102
+ # @return [Array(Hash, String, Hash)] The rule, API request ID, and response headers.
103
+ def find(rule_id:)
104
+ get(
105
+ path: "#{api_uri}/v3/rules/#{rule_id}"
106
+ )
107
+ end
108
+
109
+ # Create a rule.
110
+ #
111
+ # @param request_body [Hash] The values to create the rule with.
112
+ # @return [Array(Hash, String)] The created rule and API Request ID.
113
+ def create(request_body:)
114
+ post(
115
+ path: "#{api_uri}/v3/rules",
116
+ request_body: request_body
117
+ )
118
+ end
119
+
120
+ # Update a rule. Only the provided fields are changed (partial update).
121
+ #
122
+ # @param rule_id [String] The id of the rule to update.
123
+ # @param request_body [Hash] The values to update the rule with.
124
+ # @return [Array(Hash, String)] The updated rule and API Request ID.
125
+ def update(rule_id:, request_body:)
126
+ put(
127
+ path: "#{api_uri}/v3/rules/#{rule_id}",
128
+ request_body: request_body
129
+ )
130
+ end
131
+
132
+ # Delete a rule.
133
+ #
134
+ # @param rule_id [String] The id of the rule to delete.
135
+ # @return [Array(TrueClass, String)] True and the API Request ID for the delete operation.
136
+ def destroy(rule_id:)
137
+ _, request_id = delete(
138
+ path: "#{api_uri}/v3/rules/#{rule_id}"
139
+ )
140
+
141
+ [true, request_id]
142
+ end
143
+
144
+ # Return all rule evaluations for a grant.
145
+ #
146
+ # This endpoint returns a flat array with no cursor, so the standard
147
+ # get_list helper is used (next_cursor is always nil).
148
+ #
149
+ # @param grant_id [String] The id of the grant to query rule evaluations for.
150
+ # @param query_params [Hash, nil] Query params to pass to the request.
151
+ # @return [Array(Array(Hash), String, String, Hash)]
152
+ # The list of rule evaluations, API Request ID, next cursor (always nil
153
+ # for this endpoint), and response headers.
154
+ def list_evaluations(grant_id:, query_params: nil)
155
+ get_list(
156
+ path: "#{api_uri}/v3/grants/#{grant_id}/rule-evaluations",
157
+ query_params: query_params
158
+ )
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "resource"
4
+ require_relative "../handler/api_operations"
5
+
6
+ module Nylas
7
+ # Nylas Workspaces API
8
+ #
9
+ # A workspace groups grants in a Nylas application by email domain. Grants can be
10
+ # auto-grouped (by matching email domain) or manually assigned/removed.
11
+ class Workspaces < Resource
12
+ include ApiOperations::Get
13
+ include ApiOperations::Post
14
+ include ApiOperations::Patch
15
+ include ApiOperations::Delete
16
+
17
+ # Return all workspaces for the application.
18
+ #
19
+ # The list endpoint is not paginated; +data+ is a flat array of workspaces.
20
+ #
21
+ # @return [Array(Array(Hash), String, Hash)] The list of workspaces, API Request ID,
22
+ # and response headers.
23
+ def list
24
+ get(
25
+ path: "#{api_uri}/v3/workspaces"
26
+ )
27
+ end
28
+
29
+ # Return a workspace.
30
+ #
31
+ # @param workspace_id [String] The id of the workspace to return. Accepts a workspace
32
+ # UUID or an email domain.
33
+ # @return [Array(Hash, String, Hash)] The workspace, API Request ID, and response headers.
34
+ def find(workspace_id:)
35
+ get(
36
+ path: "#{api_uri}/v3/workspaces/#{workspace_id}"
37
+ )
38
+ end
39
+
40
+ # Create a workspace.
41
+ #
42
+ # @param request_body [Hash] The values to create the workspace with. Only +name+ is
43
+ # required.
44
+ # @return [Array(Hash, String, Hash)] The created workspace, API Request ID, and
45
+ # response headers.
46
+ def create(request_body:)
47
+ post(
48
+ path: "#{api_uri}/v3/workspaces",
49
+ request_body: request_body
50
+ )
51
+ end
52
+
53
+ # Update a workspace.
54
+ #
55
+ # The API exposes update via PATCH only (there is no PUT route). The workspace must be
56
+ # addressed by its UUID; a domain path param is not accepted on update.
57
+ #
58
+ # @param workspace_id [String] The UUID of the workspace to update.
59
+ # @param request_body [Hash] The values to update the workspace with.
60
+ # @return [Array(Hash, String)] The updated workspace and API Request ID.
61
+ def update(workspace_id:, request_body:)
62
+ patch(
63
+ path: "#{api_uri}/v3/workspaces/#{workspace_id}",
64
+ request_body: request_body
65
+ )
66
+ end
67
+
68
+ # Delete a workspace.
69
+ #
70
+ # @param workspace_id [String] The id of the workspace to delete. Accepts a workspace
71
+ # UUID or an email domain.
72
+ # @return [Array(TrueClass, String)] True and the API Request ID for the delete operation.
73
+ def destroy(workspace_id:)
74
+ _, request_id = delete(
75
+ path: "#{api_uri}/v3/workspaces/#{workspace_id}"
76
+ )
77
+
78
+ [true, request_id]
79
+ end
80
+
81
+ # Auto-group grants into workspaces by matching email domain.
82
+ #
83
+ # Runs as a background job and returns immediately with a job ID. Rate limited to one
84
+ # call per minute per application.
85
+ #
86
+ # @param request_body [Hash] Optional filters to scope which grants are grouped,
87
+ # including +after_created_at+, +invalid_also+, and +specific_domain+.
88
+ # @return [Array(Hash, String, Hash)] The job info, API Request ID, and response headers.
89
+ def auto_group(request_body: nil)
90
+ post(
91
+ path: "#{api_uri}/v3/workspaces/auto-group",
92
+ request_body: request_body
93
+ )
94
+ end
95
+
96
+ # Manually assign grants to or remove grants from a workspace.
97
+ #
98
+ # @param workspace_id [String] The id of the workspace to update. Accepts a workspace
99
+ # UUID or an email domain.
100
+ # @param request_body [Hash] The grants to assign and/or remove (+assign_grants+,
101
+ # +remove_grants+).
102
+ # @return [Array(Hash, String, Hash)] The assignment result, API Request ID, and
103
+ # response headers.
104
+ def manual_assign(workspace_id:, request_body:)
105
+ post(
106
+ path: "#{api_uri}/v3/workspaces/#{workspace_id}/manual-assign",
107
+ request_body: request_body
108
+ )
109
+ end
110
+ end
111
+ end
data/lib/nylas/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nylas
4
- VERSION = "6.7.1"
4
+ VERSION = "6.8.0"
5
5
  end
data/lib/nylas.rb CHANGED
@@ -12,6 +12,7 @@ require_relative "nylas/client"
12
12
  require_relative "nylas/config"
13
13
 
14
14
  require_relative "nylas/handler/http_client"
15
+ require_relative "nylas/handler/service_account_signer"
15
16
 
16
17
  require_relative "nylas/resources/applications"
17
18
  require_relative "nylas/resources/attachments"
@@ -24,11 +25,16 @@ require_relative "nylas/resources/drafts"
24
25
  require_relative "nylas/resources/events"
25
26
  require_relative "nylas/resources/folders"
26
27
  require_relative "nylas/resources/grants"
28
+ require_relative "nylas/resources/lists"
27
29
  require_relative "nylas/resources/messages"
28
30
  require_relative "nylas/resources/notetakers"
29
31
  require_relative "nylas/resources/smart_compose"
30
32
  require_relative "nylas/resources/threads"
31
33
  require_relative "nylas/resources/redirect_uris"
34
+ require_relative "nylas/resources/policies"
35
+ require_relative "nylas/resources/rules"
36
+ require_relative "nylas/resources/workspaces"
37
+ require_relative "nylas/resources/domains"
32
38
  require_relative "nylas/resources/webhooks"
33
39
  require_relative "nylas/resources/scheduler"
34
40
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nylas
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.7.1
4
+ version: 6.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nylas, Inc.
@@ -283,6 +283,7 @@ files:
283
283
  - lib/nylas/errors.rb
284
284
  - lib/nylas/handler/api_operations.rb
285
285
  - lib/nylas/handler/http_client.rb
286
+ - lib/nylas/handler/service_account_signer.rb
286
287
  - lib/nylas/resources/applications.rb
287
288
  - lib/nylas/resources/attachments.rb
288
289
  - lib/nylas/resources/auth.rb
@@ -293,19 +294,24 @@ files:
293
294
  - lib/nylas/resources/connectors.rb
294
295
  - lib/nylas/resources/contacts.rb
295
296
  - lib/nylas/resources/credentials.rb
297
+ - lib/nylas/resources/domains.rb
296
298
  - lib/nylas/resources/drafts.rb
297
299
  - lib/nylas/resources/events.rb
298
300
  - lib/nylas/resources/folders.rb
299
301
  - lib/nylas/resources/grants.rb
302
+ - lib/nylas/resources/lists.rb
300
303
  - lib/nylas/resources/messages.rb
301
304
  - lib/nylas/resources/notetakers.rb
305
+ - lib/nylas/resources/policies.rb
302
306
  - lib/nylas/resources/redirect_uris.rb
303
307
  - lib/nylas/resources/resource.rb
308
+ - lib/nylas/resources/rules.rb
304
309
  - lib/nylas/resources/scheduler.rb
305
310
  - lib/nylas/resources/sessions.rb
306
311
  - lib/nylas/resources/smart_compose.rb
307
312
  - lib/nylas/resources/threads.rb
308
313
  - lib/nylas/resources/webhooks.rb
314
+ - lib/nylas/resources/workspaces.rb
309
315
  - lib/nylas/utils/file_utils.rb
310
316
  - lib/nylas/version.rb
311
317
  licenses: