cronofy 0.36.0 → 0.37.3

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: e085c07872654ff1e239fcdce81beeb212856ce2ff7d9c3168e71c3f2778e6d5
4
- data.tar.gz: 0ce2421b8e0aa2b39c76a72eaeeddd4a474573690a6d3ccdf437c1d57dbf0028
3
+ metadata.gz: f398fb44b861ba5df84e244632877a53b050f584c08d15a815cb0e4abaae13bc
4
+ data.tar.gz: 8cea161bbef6df1b41a3ff52b29984c9ccd3f713abe279a7137e1e0be89cd7d7
5
5
  SHA512:
6
- metadata.gz: 8df4506dfe09d4454c8901e312dbda5d03a27d1ec8a0cb28506327f8802a691fa5abf00abd8028ee6f04d9c09eae73f3a0ea417409e7164b2fa1e0e4530bb2a3
7
- data.tar.gz: fe07ce98f72073fa8c0254510a089fbf04d37d5da2a12b7c12d1de77e19e1666c394d14aca6d32d96ad2ee7093b1e276ad5571f0ffcfd615a4d269e70031e07b
6
+ metadata.gz: 5961670573669f876d06f772a1c96175ac2e37a06fb3b3c6a1c677da86f5cbcb50820aa1e71897b7e8379ec556b55f9b56751efb51037d2f642284e72f0f07ed
7
+ data.tar.gz: 7bf5e28b6786f2fee081d09562e9e2dd57a90652994d1755a13b76c9ad9484cb50ef9dce1784fd6921372a3f6b5b29888c2274e99ed13bdb196aa42036133233
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [0.37.3]
2
+
3
+ * Support `hmac_valid` as well as the original `hmac_match` for Client to verify a HMAC from a push notification using the client's secret.[#95]
4
+
5
+ ## [0.37.2]
6
+
7
+ * Support `query_periods` as well as the original `available_periods` for Availability Query and Sequenced Availability [#91]
8
+
9
+ ## [0.37.1]
10
+
11
+ * Rename `data_centre` to `data_centre` (with aliases for backwards compatibility) [#90]
12
+
13
+ ## [0.37.0]
14
+
15
+ * Add `revoke_by_token` and `revoke_by_sub` to the Client [#86]
16
+
17
+ ## [0.36.1]
18
+
19
+ * Loosen the version requirement on Hashie to allow 4.X
20
+
1
21
  ## [0.36.0]
2
22
 
3
23
  * Add support for Available Periods [#81]
@@ -167,6 +187,11 @@
167
187
  [0.34.0]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.34.0
168
188
  [0.35.0]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.35.0
169
189
  [0.36.0]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.36.0
190
+ [0.36.1]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.36.1
191
+ [0.37.0]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.37.0
192
+ [0.37.1]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.37.1
193
+ [0.37.2]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.37.2
194
+ [0.37.3]: https://github.com/cronofy/cronofy-ruby/releases/tag/v0.37.3
170
195
 
171
196
  [#13]: https://github.com/cronofy/cronofy-ruby/pull/13
172
197
  [#16]: https://github.com/cronofy/cronofy-ruby/pull/16
@@ -207,3 +232,8 @@
207
232
  [#75]: https://github.com/cronofy/cronofy-ruby/pull/75
208
233
  [#77]: https://github.com/cronofy/cronofy-ruby/pull/77
209
234
  [#81]: https://github.com/cronofy/cronofy-ruby/pull/81
235
+ [#85]: https://github.com/cronofy/cronofy-ruby/pull/85
236
+ [#86]: https://github.com/cronofy/cronofy-ruby/pull/86
237
+ [#90]: https://github.com/cronofy/cronofy-ruby/pull/90
238
+ [#91]: https://github.com/cronofy/cronofy-ruby/pull/91
239
+ [#95]: https://github.com/cronofy/cronofy-ruby/pull/95
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Cronofy
2
2
 
3
- [![Build Status](https://travis-ci.org/cronofy/cronofy-ruby.svg?branch=master)](https://travis-ci.org/cronofy/cronofy-ruby)
3
+ [![ruby CI](https://github.com/cronofy/cronofy-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/cronofy/cronofy-ruby/actions/workflows/ci.yml)
4
4
  [![Gem Version](https://badge.fury.io/rb/cronofy.svg)](http://badge.fury.io/rb/cronofy)
5
5
 
6
- [Cronofy](https://www.cronofy.com) - one API for all the calendars (Google, iCloud, Exchange, Office 365, Outlook.com)
6
+ [Cronofy](https://www.cronofy.com) - the scheduling platform for business
7
7
 
8
8
  ## Installation
9
9
 
@@ -23,22 +23,21 @@ bundle install
23
23
 
24
24
  In order to use the Cronofy API you will need to [create a developer account](https://app.cronofy.com/sign_up/new).
25
25
 
26
- From there you can [use your Calendar Sandbox](https://app.cronofy.com/oauth/sandbox)
27
- to access your own calendars, or you can [create an OAuth application](https://app.cronofy.com/oauth/applications/new)
28
- to obtain an OAuth `client_id` and `client_secret` to be able to use the full
29
- API.
26
+ From there you can [create an OAuth application](https://app.cronofy.com/oauth/applications/new)
27
+ to obtain an OAuth `client_id` and `client_secret` to be able to use the full API.
30
28
 
31
29
  ## Creating a client
32
30
 
33
31
  To make calls to the Cronofy API you must create a `Cronofy::Client`. This takes
34
- four keyword arguments, all of which are optional:
32
+ five keyword arguments, all of which are optional:
35
33
 
36
34
  ```ruby
37
35
  cronofy = Cronofy::Client.new(
38
36
  client_id: 'CLIENT_ID',
39
37
  client_secret: 'CLIENT_SECRET',
40
38
  access_token: 'ACCESS_TOKEN',
41
- refresh_token: 'REFRESH_TOKEN'
39
+ refresh_token: 'REFRESH_TOKEN',
40
+ data_center: :de
42
41
  )
43
42
  ```
44
43
 
@@ -53,6 +52,8 @@ If `client_id` and `client_secret` are not specified explicitly the values from
53
52
  the environment variables `CRONOFY_CLIENT_ID` and `CRONOFY_CLIENT_SECRET` will
54
53
  be used if present.
55
54
 
55
+ `data_center` is the two-letter designation for the data center you want to operate against - for example `:de` for Germany, or `:au` for Australia. When omitted, this defaults to the US data center.
56
+
56
57
  ## Authorization
57
58
 
58
59
  [API documentation](https://www.cronofy.com/developers/api/#authorization)
@@ -133,6 +134,15 @@ To delete an event from user's calendar:
133
134
  cronofy.delete_event(calendar_id, 'uniq-id')
134
135
  ```
135
136
 
137
+ ## A feature I want is not in the SDK, how do I get it?
138
+
139
+ We add features to this SDK as they are requested, to focus on developing the Cronofy API.
140
+
141
+ If you're comfortable contributing support for an endpoint or attribute, then we love to receive pull requests!
142
+ Please create a PR mentioning the feature/API endpoint you’ve added and we’ll review it as soon as we can.
143
+
144
+ If you would like to request a feature is added by our team then please let us know by getting in touch via [support@cronofy.com](mailto:support@cronofy.com).
145
+
136
146
  ## Links
137
147
 
138
148
  * [API documentation](https://www.cronofy.com/developers/api)
data/cronofy.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |spec|
5
5
  spec.version = Cronofy::VERSION
6
6
  spec.authors = ["Sergii Paryzhskyi", "Garry Shutler"]
7
7
  spec.email = ["parizhskiy@gmail.com", "garry@cronofy.com"]
8
- spec.summary = %q{Cronofy - one API for all the calendars}
8
+ spec.summary = %q{Cronofy - the scheduling platform for business}
9
9
  spec.description = %q{Ruby wrapper for Cronofy's unified calendar API}
10
10
  spec.homepage = "https://github.com/cronofy/cronofy-ruby"
11
11
  spec.license = "MIT"
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.files += Dir['spec/**/*.rb']
18
18
  spec.test_files = Dir['spec/**/*.rb']
19
19
 
20
+ spec.add_runtime_dependency "hashie", ">= 2.1", "< 5"
20
21
  spec.add_runtime_dependency "oauth2", "~> 1.0"
21
- spec.add_runtime_dependency "hashie", ">= 2.1", "< 4"
22
22
 
23
23
  spec.add_development_dependency "bundler", ">= 1.6", "< 3"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
data/lib/cronofy.rb CHANGED
@@ -13,18 +13,26 @@ require 'openssl'
13
13
 
14
14
  module Cronofy
15
15
  def self.default_data_centre
16
- @default_data_centre || ENV['CRONOFY_DATA_CENTRE']
16
+ default_data_center
17
17
  end
18
18
 
19
19
  def self.default_data_centre=(value)
20
- @default_data_centre = value
20
+ default_data_center= value
21
21
  end
22
22
 
23
- def self.api_url(data_centre_override)
24
- if data_centre_override
25
- api_url_for_data_centre(data_centre_override)
23
+ def self.default_data_center
24
+ @default_data_center || ENV['CRONOFY_DATA_CENTER'] || ENV['CRONOFY_DATA_CENTRE']
25
+ end
26
+
27
+ def self.default_data_center=(value)
28
+ @default_data_center = value
29
+ end
30
+
31
+ def self.api_url(data_center_override)
32
+ if data_center_override
33
+ api_url_for_data_center(data_center_override)
26
34
  else
27
- ENV['CRONOFY_API_URL'] || api_url_for_data_centre(default_data_centre)
35
+ ENV['CRONOFY_API_URL'] || api_url_for_data_center(default_data_center)
28
36
  end
29
37
  end
30
38
 
@@ -32,7 +40,11 @@ module Cronofy
32
40
  @api_url = value
33
41
  end
34
42
 
35
- def self.api_url_for_data_centre(dc)
43
+ def self.api_url_for_data_centre
44
+ api_url_for_data_center
45
+ end
46
+
47
+ def self.api_url_for_data_center(dc)
36
48
  @api_urls ||= Hash.new do |hash, key|
37
49
  if key.nil? || key.to_sym == :us
38
50
  url = "https://api.cronofy.com"
@@ -46,11 +58,11 @@ module Cronofy
46
58
  @api_urls[dc]
47
59
  end
48
60
 
49
- def self.app_url(data_centre_override)
50
- if data_centre_override
51
- app_url_for_data_centre(data_centre_override)
61
+ def self.app_url(data_center_override)
62
+ if data_center_override
63
+ app_url_for_data_center(data_center_override)
52
64
  else
53
- ENV['CRONOFY_APP_URL'] || app_url_for_data_centre(default_data_centre)
65
+ ENV['CRONOFY_APP_URL'] || app_url_for_data_center(default_data_center)
54
66
  end
55
67
  end
56
68
 
@@ -59,6 +71,10 @@ module Cronofy
59
71
  end
60
72
 
61
73
  def self.app_url_for_data_centre(dc)
74
+ app_url_for_data_center(dc)
75
+ end
76
+
77
+ def self.app_url_for_data_center(dc)
62
78
  @app_urls ||= Hash.new do |hash, key|
63
79
  if key.nil? || key.to_sym == :us
64
80
  url = "https://app.cronofy.com"
data/lib/cronofy/auth.rb CHANGED
@@ -11,13 +11,13 @@ module Cronofy
11
11
  access_token = options[:access_token]
12
12
  client_id = options[:client_id]
13
13
  client_secret = options[:client_secret]
14
- data_centre = options[:data_centre]
14
+ data_center = options[:data_center]
15
15
  refresh_token = options[:refresh_token]
16
16
 
17
17
  @client_credentials_missing = blank?(client_id) || blank?(client_secret)
18
18
 
19
- @auth_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.app_url(data_centre), connection_opts: { headers: { "User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}" } })
20
- @api_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.api_url(data_centre), connection_opts: { headers: { "User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}" } })
19
+ @auth_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.app_url(data_center), connection_opts: { headers: { "User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}" } })
20
+ @api_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.api_url(data_center), connection_opts: { headers: { "User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}" } })
21
21
 
22
22
  set_access_token(access_token, refresh_token) if access_token || refresh_token
23
23
  set_api_key(client_secret) if client_secret
@@ -118,20 +118,50 @@ module Cronofy
118
118
  def revoke!
119
119
  raise CredentialsMissingError.new("No credentials to revoke") unless access_token
120
120
 
121
+ token = access_token.refresh_token || access_token.token
122
+ revoke_by_token(token)
123
+ @access_token = nil
124
+ end
125
+
126
+ # Internal: Revokes an authorization by the sub
127
+ #
128
+ # Returns nothing.
129
+ #
130
+ # Raises Cronofy::CredentialsMissingError if no credentials available.
131
+ def revoke_by_sub(sub)
132
+ do_revoke(sub: sub)
133
+ end
134
+
135
+ # Internal: Revokes an authorization via the token
136
+ #
137
+ # Returns nothing.
138
+ #
139
+ # Raises Cronofy::CredentialsMissingError if no credentials available.
140
+ def revoke_by_token(token)
141
+ do_revoke(token: token)
142
+ end
143
+
144
+ private
145
+
146
+ def do_revoke(token: nil, sub: nil)
147
+ raise CredentialsMissingError.new("No credentials to revoke") unless token || sub
148
+
121
149
  do_request do
122
150
  body = {
123
151
  client_id: @api_client.id,
124
152
  client_secret: @api_client.secret,
125
- token: access_token.refresh_token || access_token.token,
126
153
  }
127
154
 
155
+ if token
156
+ body.merge!(token: token)
157
+ else
158
+ body.merge!(sub: sub)
159
+ end
160
+
128
161
  @api_client.request(:post, "/oauth/token/revoke", body: body)
129
- @access_token = nil
130
162
  end
131
163
  end
132
164
 
133
- private
134
-
135
165
  def do_request(&block)
136
166
  if @client_credentials_missing
137
167
  raise CredentialsMissingError.new("OAuth client_id and client_secret must be set")
@@ -27,22 +27,22 @@ module Cronofy
27
27
  # ENV["CRONOFY_CLIENT_SECRET"]).
28
28
  # :refresh_token - An existing refresh token String for the user's
29
29
  # account (optional).
30
- # :data_centre - An identifier to override the default data
31
- # centre (optional).
30
+ # :data_center - An identifier to override the default data
31
+ # center (optional).
32
32
  def initialize(options = {})
33
33
  access_token = options[:access_token]
34
34
  refresh_token = options[:refresh_token]
35
35
 
36
36
  @client_id = options.fetch(:client_id, ENV["CRONOFY_CLIENT_ID"])
37
37
  @client_secret = options.fetch(:client_secret, ENV["CRONOFY_CLIENT_SECRET"])
38
- @data_centre = options[:data_centre]
38
+ @data_center = options[:data_center] || options[:data_centre]
39
39
 
40
40
  @auth = Auth.new(
41
41
  client_id: @client_id,
42
42
  client_secret: @client_secret,
43
43
  access_token: access_token,
44
44
  refresh_token: refresh_token,
45
- data_centre: @data_centre,
45
+ data_center: @data_center
46
46
  )
47
47
  end
48
48
 
@@ -471,24 +471,33 @@ module Cronofy
471
471
  parse_json(Channel, "channel", response)
472
472
  end
473
473
 
474
+ # DEPRECATED: Please use hmac_valid instead.
475
+ def hmac_match?(args)
476
+ warn "[DEPRECATION] `hmac_match?` is deprecated. Please use `hmac_valid?` instead."
477
+ hmac_valid?(args)
478
+ end
479
+
474
480
  # Public: Verifies a HMAC from a push notification using the client secret.
475
481
  #
476
482
  # args - A Hash containing the details of the push notification:
477
483
  # :body - A String of the body of the notification.
478
- # :hmac - A String of the HMAC of the notification taken from the
484
+ # :hmac - A String containing comma-separated values describing HMACs of the notification taken from the
479
485
  # Cronofy-HMAC-SHA256 header.
480
486
  #
481
- # Returns true if the HMAC provided matches the one calculated using the
487
+ # Returns true if one of the HMAC provided matches the one calculated using the
482
488
  # client secret, otherwise false.
483
- def hmac_match?(args)
489
+ def hmac_valid?(args)
484
490
  body = args[:body]
485
491
  hmac = args[:hmac]
486
492
 
493
+ return false if hmac.nil? || hmac.empty?
494
+
487
495
  sha256 = OpenSSL::Digest.new('sha256')
488
496
  digest = OpenSSL::HMAC.digest(sha256, @client_secret, body)
489
497
  calculated = Base64.encode64(digest).strip
490
498
 
491
- calculated == hmac
499
+ hmac_list = hmac.split(',')
500
+ hmac_list.include?(calculated)
492
501
  end
493
502
 
494
503
  # Public: Lists all the notification channels for the account.
@@ -737,6 +746,14 @@ module Cronofy
737
746
  @auth.revoke!
738
747
  end
739
748
 
749
+ def revoke_by_sub(sub)
750
+ @auth.revoke_by_sub(sub)
751
+ end
752
+
753
+ def revoke_by_token(token)
754
+ @auth.revoke_by_token(token)
755
+ end
756
+
740
757
  # Public: Requests elevated permissions for a set of calendars.
741
758
  #
742
759
  # args - A Hash of options used to initialize the request (default: {}):
@@ -795,7 +812,7 @@ module Cronofy
795
812
  # for a single participant group.
796
813
  # :required_duration - An Integer representing the minimum number
797
814
  # of minutes of availability required.
798
- # :available_periods - An Array of available time periods Hashes,
815
+ # :query_periods - An Array of available time periods Hashes,
799
816
  # each must specify a start and end Time.
800
817
  # :start_interval - An Integer representing the start interval
801
818
  # of minutes for the availability query.
@@ -825,7 +842,7 @@ module Cronofy
825
842
  options[:buffer] = map_availability_buffer(buffer)
826
843
  end
827
844
 
828
- translate_available_periods(options[:available_periods])
845
+ translate_available_periods(options[:query_periods] || options[:available_periods])
829
846
 
830
847
  response = post("/v1/availability", options)
831
848
 
@@ -839,7 +856,7 @@ module Cronofy
839
856
  # Public: Performs an sequenced availability query.
840
857
  #
841
858
  # options - The Hash options used to refine the selection (default: {}):
842
- # :sequence - An Array of sequence defintions containing
859
+ # :sequence - An Array of sequence defintions containing
843
860
  # a Hash of:
844
861
  # :sequence_id - A String to uniquely identify this part
845
862
  # of the proposed sequence.
@@ -853,7 +870,7 @@ module Cronofy
853
870
  # of minutes for the availability query.
854
871
  # :buffer - An Hash containing the buffer to apply to
855
872
  # the availability query.
856
- # :available_periods - An Array of available time periods Hashes,
873
+ # :query_periods - An Array of available time periods Hashes,
857
874
  # each must specify a start and end Time.
858
875
  #
859
876
  # Returns an Array of Sequences.
@@ -870,7 +887,7 @@ module Cronofy
870
887
  def sequenced_availability(options = {})
871
888
  options[:sequence] = map_availability_sequence(options[:sequence])
872
889
 
873
- translate_available_periods(options[:available_periods])
890
+ translate_available_periods(options[:query_periods] || options[:available_periods])
874
891
 
875
892
  response = post("/v1/sequenced_availability", options)
876
893
  parse_collection(Sequence, "sequences", response)
@@ -1881,7 +1898,7 @@ module Cronofy
1881
1898
  end
1882
1899
 
1883
1900
  def api_url
1884
- ::Cronofy.api_url(@data_centre)
1901
+ ::Cronofy.api_url(@data_center)
1885
1902
  end
1886
1903
  end
1887
1904
 
@@ -1,3 +1,3 @@
1
1
  module Cronofy
2
- VERSION = "0.36.0".freeze
2
+ VERSION = "0.37.3".freeze
3
3
  end
@@ -92,7 +92,7 @@ describe Cronofy::Auth do
92
92
  let(:scheme) { 'https' }
93
93
  let(:host) { 'app.cronofy.com' }
94
94
  let(:path) { '/oauth/authorize' }
95
- let(:data_centre_override) { nil }
95
+ let(:data_center_override) { nil }
96
96
  let(:default_params) do
97
97
  {
98
98
  'client_id' => client_id,
@@ -106,7 +106,7 @@ describe Cronofy::Auth do
106
106
  Cronofy::Auth.new(
107
107
  client_id: client_id,
108
108
  client_secret: client_secret,
109
- data_centre: data_centre_override,
109
+ data_center: data_center_override,
110
110
  )
111
111
  end
112
112
 
@@ -156,8 +156,8 @@ describe Cronofy::Auth do
156
156
  it_behaves_like 'a user auth link provider'
157
157
  end
158
158
 
159
- context 'when data centre overridden' do
160
- let(:data_centre_override) { :de }
159
+ context 'when data center overridden' do
160
+ let(:data_center_override) { :de }
161
161
  let(:host) { 'app-de.cronofy.com' }
162
162
  let(:params) { default_params }
163
163
 
@@ -204,13 +204,13 @@ describe Cronofy::Auth do
204
204
  end
205
205
 
206
206
  describe '#get_token_from_code' do
207
- let(:data_centre_override) { nil }
207
+ let(:data_center_override) { nil }
208
208
 
209
209
  subject do
210
210
  Cronofy::Auth.new(
211
211
  client_id: client_id,
212
212
  client_secret: client_secret,
213
- data_centre: data_centre_override,
213
+ data_center: data_center_override,
214
214
  ).get_token_from_code(code, redirect_uri)
215
215
  end
216
216
 
@@ -236,7 +236,7 @@ describe Cronofy::Auth do
236
236
  end
237
237
 
238
238
  describe '#application_calendar' do
239
- let(:data_centre_override) { nil }
239
+ let(:data_center_override) { nil }
240
240
 
241
241
  let(:application_calendar_id) { "my-application-calendar" }
242
242
  let(:cronofy_application_calendar_id) { "apc_54475485743" }
@@ -273,7 +273,7 @@ describe Cronofy::Auth do
273
273
  Cronofy::Auth.new(
274
274
  client_id: client_id,
275
275
  client_secret: client_secret,
276
- data_centre: data_centre_override,
276
+ data_center: data_center_override,
277
277
  ).application_calendar(application_calendar_id)
278
278
  end
279
279
 
@@ -308,8 +308,8 @@ describe Cronofy::Auth do
308
308
  end
309
309
  end
310
310
 
311
- context "with data centre overridden" do
312
- let(:data_centre_override) { :de }
311
+ context "with data center overridden" do
312
+ let(:data_center_override) { :de }
313
313
  let(:api_token_url) { "https://api-de.cronofy.com/oauth/token" }
314
314
  let(:app_token_url) { "https://app-de.cronofy.com/oauth/token" }
315
315
 
@@ -372,14 +372,14 @@ describe Cronofy::Auth do
372
372
  it_behaves_like 'an authorization request'
373
373
  end
374
374
 
375
- context "with data centre overridden" do
375
+ context "with data center overridden" do
376
376
  subject do
377
377
  Cronofy::Auth.new(
378
378
  client_id: client_id,
379
379
  client_secret: client_secret,
380
380
  access_token: access_token,
381
381
  refresh_token: refresh_token,
382
- data_centre: :de,
382
+ data_center: :de,
383
383
  ).refresh!
384
384
  end
385
385
 
@@ -476,4 +476,84 @@ describe Cronofy::Auth do
476
476
  end
477
477
  end
478
478
  end
479
+
480
+ describe "#revoke_by_sub" do
481
+ let(:auth) do
482
+ Cronofy::Auth.new(
483
+ client_id: client_id,
484
+ client_secret: client_secret,
485
+ access_token: access_token,
486
+ refresh_token: refresh_token,
487
+ )
488
+ end
489
+
490
+ let!(:revocation_request) do
491
+ stub_request(:post, "https://api.cronofy.com/oauth/token/revoke")
492
+ .with(
493
+ body: {
494
+ client_id: client_id,
495
+ client_secret: client_secret,
496
+ sub: sub,
497
+ },
498
+ headers: {
499
+ 'Content-Type' => 'application/x-www-form-urlencoded',
500
+ 'User-Agent' => "Cronofy Ruby #{Cronofy::VERSION}",
501
+ }
502
+ ).to_return(status: response_status)
503
+ end
504
+
505
+ let(:sub) { "random_sub_value" }
506
+
507
+ before do
508
+ auth.revoke_by_sub(sub)
509
+ end
510
+
511
+ it "does not unset the access token for the current auth" do
512
+ expect(auth.access_token).not_to be_nil
513
+ end
514
+
515
+ it "makes the revocation request" do
516
+ expect(revocation_request).to have_been_requested
517
+ end
518
+ end
519
+
520
+ describe "#revoke_by_token" do
521
+ let(:auth) do
522
+ Cronofy::Auth.new(
523
+ client_id: client_id,
524
+ client_secret: client_secret,
525
+ access_token: access_token,
526
+ refresh_token: refresh_token,
527
+ )
528
+ end
529
+
530
+ let!(:revocation_request) do
531
+ stub_request(:post, "https://api.cronofy.com/oauth/token/revoke")
532
+ .with(
533
+ body: {
534
+ client_id: client_id,
535
+ client_secret: client_secret,
536
+ token: token,
537
+ },
538
+ headers: {
539
+ 'Content-Type' => 'application/x-www-form-urlencoded',
540
+ 'User-Agent' => "Cronofy Ruby #{Cronofy::VERSION}",
541
+ }
542
+ ).to_return(status: response_status)
543
+ end
544
+
545
+ let(:token) { "random_token_value" }
546
+
547
+ before do
548
+ auth.revoke_by_token(token)
549
+ end
550
+
551
+ it "does not unset the access token for the current auth" do
552
+ expect(auth.access_token).not_to be_nil
553
+ end
554
+
555
+ it "makes the revocation request" do
556
+ expect(revocation_request).to have_been_requested
557
+ end
558
+ end
479
559
  end
@@ -266,6 +266,7 @@ describe Cronofy::Client do
266
266
  ],
267
267
  }
268
268
  end
269
+
269
270
  let(:request_body) do
270
271
  {
271
272
  :event_id => "qTtZdczOccgaPncGJaCiLg",
@@ -1718,6 +1719,57 @@ describe Cronofy::Client do
1718
1719
  it_behaves_like 'a Cronofy request'
1719
1720
  it_behaves_like 'a Cronofy request with mapped return value'
1720
1721
  end
1722
+
1723
+ context "when given query_periods instead of available_periods" do
1724
+ let(:participants) do
1725
+ { members: %w{acc_567236000909002 acc_678347111010113} }
1726
+ end
1727
+
1728
+ let(:required_duration) { 60 }
1729
+
1730
+ let(:query_periods) do
1731
+ [
1732
+ { start: Time.parse("2017-01-03T09:00:00Z"), end: Time.parse("2017-01-03T18:00:00Z") },
1733
+ { start: Time.parse("2017-01-04T09:00:00Z"), end: Time.parse("2017-01-04T18:00:00Z") },
1734
+ ]
1735
+ end
1736
+
1737
+ let(:request_body) do
1738
+ {
1739
+ "participants" => [
1740
+ {
1741
+ "members" => [
1742
+ { "sub" => "acc_567236000909002" },
1743
+ { "sub" => "acc_678347111010113" }
1744
+ ],
1745
+ "required" => "all"
1746
+ }
1747
+ ],
1748
+ "query_periods" => [
1749
+ {
1750
+ "start" => "2017-01-03T09:00:00Z",
1751
+ "end" => "2017-01-03T18:00:00Z"
1752
+ },
1753
+ {
1754
+ "start" => "2017-01-04T09:00:00Z",
1755
+ "end" => "2017-01-04T18:00:00Z"
1756
+ }
1757
+ ],
1758
+ "required_duration" => { "minutes" => 60 },
1759
+ }
1760
+ end
1761
+
1762
+ subject do
1763
+ client.availability(
1764
+ participants: participants,
1765
+ required_duration: required_duration,
1766
+ query_periods: query_periods
1767
+ )
1768
+ end
1769
+
1770
+ it_behaves_like 'a Cronofy request'
1771
+ it_behaves_like 'a Cronofy request with mapped return value'
1772
+ end
1721
1773
  end
1722
1774
  end
1723
1775
 
@@ -1873,6 +1925,18 @@ describe Cronofy::Client do
1873
1925
 
1874
1926
  it_behaves_like 'a Cronofy request'
1875
1927
  it_behaves_like 'a Cronofy request with mapped return value'
1928
+
1929
+ context "when passing query_periods instead" do
1930
+ before do
1931
+ args[:query_periods] = args[:available_periods]
1932
+ args.delete(:available_periods)
1933
+ request_body["query_periods"] = request_body["available_periods"]
1934
+ request_body.delete("available_periods")
1935
+ end
1936
+
1937
+ it_behaves_like 'a Cronofy request'
1938
+ it_behaves_like 'a Cronofy request with mapped return value'
1939
+ end
1876
1940
  end
1877
1941
  end
1878
1942
 
@@ -2325,8 +2389,8 @@ describe Cronofy::Client do
2325
2389
 
2326
2390
  end
2327
2391
 
2328
- describe "Specified data centre" do
2329
- let(:data_centre) { :de }
2392
+ describe "specifying data_centre" do
2393
+ let(:data_center) { :de }
2330
2394
 
2331
2395
  let(:client) do
2332
2396
  Cronofy::Client.new(
@@ -2334,12 +2398,52 @@ describe Cronofy::Client do
2334
2398
  client_secret: 'client_secret_456',
2335
2399
  access_token: token,
2336
2400
  refresh_token: 'refresh_token_456',
2337
- data_centre: data_centre,
2401
+ data_centre: data_center,
2338
2402
  )
2339
2403
  end
2340
2404
 
2341
2405
  describe "Userinfo" do
2342
- let(:request_url) { "https://api-#{data_centre}.cronofy.com/v1/userinfo" }
2406
+ let(:request_url) { "https://api-#{data_center}.cronofy.com/v1/userinfo" }
2407
+
2408
+ describe "#userinfo" do
2409
+ let(:method) { :get }
2410
+
2411
+ let(:correct_response_code) { 200 }
2412
+ let(:correct_response_body) do
2413
+ {
2414
+ "sub" => "ser_5700a00eb0ccd07000000000",
2415
+ "cronofy.type" => "service_account",
2416
+ "cronofy.service_account.domain" => "example.com"
2417
+ }
2418
+ end
2419
+
2420
+ let(:correct_mapped_result) do
2421
+ Cronofy::UserInfo.new(correct_response_body)
2422
+ end
2423
+
2424
+ subject { client.userinfo }
2425
+
2426
+ it_behaves_like "a Cronofy request"
2427
+ it_behaves_like "a Cronofy request with mapped return value"
2428
+ end
2429
+ end
2430
+ end
2431
+
2432
+ describe "specifying data_center" do
2433
+ let(:data_center) { :au }
2434
+
2435
+ let(:client) do
2436
+ Cronofy::Client.new(
2437
+ client_id: 'client_id_123',
2438
+ client_secret: 'client_secret_456',
2439
+ access_token: token,
2440
+ refresh_token: 'refresh_token_456',
2441
+ data_center: data_center,
2442
+ )
2443
+ end
2444
+
2445
+ describe "Userinfo" do
2446
+ let(:request_url) { "https://api-#{data_center}.cronofy.com/v1/userinfo" }
2343
2447
 
2344
2448
  describe "#userinfo" do
2345
2449
  let(:method) { :get }
@@ -2377,11 +2481,27 @@ describe Cronofy::Client do
2377
2481
  let(:body) { "{\"example\":\"well-known\"}" }
2378
2482
 
2379
2483
  it "verifies the correct HMAC" do
2380
- expect(client.hmac_match?(body: body, hmac: "6r2/HjBkqymGegX0wOfifieeUXbbHwtV/LohHS+jv6c=")).to be true
2484
+ expect(client.hmac_valid?(body: body, hmac: "6r2/HjBkqymGegX0wOfifieeUXbbHwtV/LohHS+jv6c=")).to be true
2381
2485
  end
2382
2486
 
2383
2487
  it "rejects an incorrect HMAC" do
2384
- expect(client.hmac_match?(body: body, hmac: "something-else")).to be false
2488
+ expect(client.hmac_valid?(body: body, hmac: "something-else")).to be false
2489
+ end
2490
+
2491
+ it "verifies the correct HMAC when one of the multiple HMACs splitted by ',' match" do
2492
+ expect(client.hmac_valid?(body: body, hmac: "6r2/HjBkqymGegX0wOfifieeUXbbHwtV/LohHS+jv6c=,something-else")).to be true
2493
+ end
2494
+
2495
+ it "rejects incorrect when multiple HMACs splitted by ',' don't match" do
2496
+ expect(client.hmac_valid?(body: body, hmac: "something-else,something-else2")).to be false
2497
+ end
2498
+
2499
+ it "rejects if empty HMAC" do
2500
+ expect(client.hmac_valid?(body: body, hmac: "")).to be false
2501
+ end
2502
+
2503
+ it "rejects if nil HMAC" do
2504
+ expect(client.hmac_valid?(body: body, hmac: nil)).to be false
2385
2505
  end
2386
2506
  end
2387
2507
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cronofy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.36.0
4
+ version: 0.37.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergii Paryzhskyi
@@ -9,22 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-09-23 00:00:00.000000000 Z
12
+ date: 2021-07-02 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: oauth2
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '1.0'
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: '1.0'
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: hashie
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -34,7 +20,7 @@ dependencies:
34
20
  version: '2.1'
35
21
  - - "<"
36
22
  - !ruby/object:Gem::Version
37
- version: '4'
23
+ version: '5'
38
24
  type: :runtime
39
25
  prerelease: false
40
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,7 +30,21 @@ dependencies:
44
30
  version: '2.1'
45
31
  - - "<"
46
32
  - !ruby/object:Gem::Version
47
- version: '4'
33
+ version: '5'
34
+ - !ruby/object:Gem::Dependency
35
+ name: oauth2
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: bundler
50
50
  requirement: !ruby/object:Gem::Requirement
@@ -156,10 +156,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
156
  - !ruby/object:Gem::Version
157
157
  version: '0'
158
158
  requirements: []
159
- rubygems_version: 3.1.2
159
+ rubygems_version: 3.2.20
160
160
  signing_key:
161
161
  specification_version: 4
162
- summary: Cronofy - one API for all the calendars
162
+ summary: Cronofy - the scheduling platform for business
163
163
  test_files:
164
164
  - spec/spec_helper.rb
165
165
  - spec/response_parser_spec.rb