operto 0.3.0 → 0.4.1

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: 31bc34a291dadd87aded5937654fc9824be5cc365e94010724ef763b75169b49
4
- data.tar.gz: 46b42729bb8e8590b02452b56c83fe4387638e5db2bee5b290f6f98040196d63
3
+ metadata.gz: 8844f341cedc86baff27141908730c8dcca2980e4c544855f3542d461335edf2
4
+ data.tar.gz: 2e2854e802788fd252f323f7e41b760fc522a613ef93289c9b88708100e583df
5
5
  SHA512:
6
- metadata.gz: 0cc0aa3b12cb92f0d521dfa5f46e6a834a69ddb047a881f9eb125a12a829bc5ff4ca2b9210a8c18b48f9df761abc81ad7374133fd2bac236dac55d6199cae374
7
- data.tar.gz: 8579d576182fc7598faf1bc8a4fa5e7e166a995def47059412a00a74ab23f5854225ea702468611f4116a76a29db45ab6469a73182437b1e02b5222c449a27fb
6
+ metadata.gz: f9aae9925c322879e23a2a8d6b1f5f1408e368e3c4842b522622f0e611ab5fa38dd6c9c939f58f016d6d72b463675e359edcd631ee9f2636d9baa4984bb3758c
7
+ data.tar.gz: f51faf4e94d597ed1d7032e10b1ea5d19c9ec0eb3e74659e96137b215026335913ede8be5525a87d1e469071ff7d854bee8731fe20f2bf0e003aa7c9d18fb617
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.1 - 2026-10-14
4
+
5
+ - `Tasks::Index`, `Tasks::Show`, `Tasks::Create` and `Tasks::Update` read an out-of-range start or due time (such as `100:100`) as the date with no time instead of failing with `ArgumentError`.
6
+
7
+ ## 0.4.0 - 2026-10-12
8
+
9
+ - When Operto rejects the access token (a `401` or an `auth_token_expired` response), the client clears the token store, renews the token and replays the request once.
10
+ - A host token store's `clear` must retire the token so the next `active` returns `nil`.
11
+ - Retry only idempotent requests, and only on `502`, `503` and `504`. `POST` and `PATCH` requests and `429` responses are no longer retried.
12
+ - `Homes::Index` and `Staff::Index` keep an unparseable create date as the raw value instead of failing with `Date::Error`.
13
+
3
14
  ## 0.3.0 - 2026-09-27
4
15
 
5
16
  - `Tasks::Index` returns the whole task: rule, booking, name, description, start and due times, and the active and completion flags.
data/README.md CHANGED
@@ -9,7 +9,7 @@ framework dependency.
9
9
 
10
10
  ```ruby
11
11
  # Gemfile
12
- gem 'operto', '~> 0.3.0'
12
+ gem 'operto', '~> 0.4.0'
13
13
  ```
14
14
 
15
15
  ```sh
@@ -43,7 +43,7 @@ login/refresh and delegates persistence to it via four methods:
43
43
  | `active` | the current non-expired token, or `nil` |
44
44
  | `refreshable` | a token whose refresh token is still valid, or `nil` |
45
45
  | `save(access_token:, expires_at:, refresh_token: nil, refresh_expires_at: nil)` | persist and return the token |
46
- | `clear` | drop the cached token (called after a `401`) |
46
+ | `clear` | retire the token so the next `active` returns `nil` (called when Operto rejects it, before the renewal) |
47
47
 
48
48
  A token responds to `access_token`, `refresh_token`, `refresh_expires_at`, and
49
49
  `expired?`.
@@ -0,0 +1,30 @@
1
+ module Operto
2
+ # Faraday middleware that signs each request with the stored access token.
3
+ # When Operto rejects the token (a 401 or an auth_token_expired envelope), it
4
+ # clears the store, renews the token and replays the request once.
5
+ class Authorization < Faraday::Middleware
6
+ HEADER = 'Authorization'.freeze
7
+ EXPIRED_REASON = 'auth_token_expired'.freeze
8
+
9
+ def call(env)
10
+ request_body = env.body
11
+ response = @app.call(sign(env))
12
+ return response unless rejected?(response)
13
+
14
+ Operto.config.token_store.clear
15
+ env.body = request_body
16
+ @app.call(sign(env))
17
+ end
18
+
19
+ private
20
+
21
+ def sign(env)
22
+ env.request_headers[HEADER] = "VRS #{Operto::Client.auth_token}"
23
+ env
24
+ end
25
+
26
+ def rejected?(response)
27
+ response.status == 401 || Operto::Client.response_body(response)[:ReasonText].to_s.include?(EXPIRED_REASON)
28
+ end
29
+ end
30
+ end
data/lib/operto/client.rb CHANGED
@@ -10,15 +10,14 @@ module Operto
10
10
  interval: 1.0,
11
11
  interval_randomness: 0.5,
12
12
  backoff_factor: 2,
13
- retry_statuses: [401, 429, 502, 503, 504],
13
+ retry_statuses: [502, 503, 504],
14
14
  exceptions: [*Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed],
15
- methods: [*Faraday::Retry::Middleware::IDEMPOTENT_METHODS, :patch, :post],
16
- retry_block: ->(env:, **) { Operto.config.token_store.clear if env.status == 401 }
15
+ methods: Faraday::Retry::Middleware::IDEMPOTENT_METHODS
17
16
  }.freeze
18
17
 
19
18
  def connection(url: Operto.config.base_url, skip_auth: false)
20
19
  Faraday.new(url:) do |builder|
21
- builder.request :authorization, 'VRS', -> { auth_token } unless skip_auth
20
+ builder.use Operto::Authorization unless skip_auth
22
21
 
23
22
  builder.request :json
24
23
  builder.request :retry, RETRY_OPTIONS
@@ -73,8 +73,11 @@ module Operto
73
73
  def task_time(date, time)
74
74
  return if date.blank?
75
75
 
76
+ day = Time.zone.parse(date.to_s)
76
77
  hour, minute = time.to_s.split(':')
77
- Time.zone.parse(date.to_s).change(hour: hour.to_i, min: minute.to_i)
78
+ day.change(hour: hour.to_i, min: minute.to_i)
79
+ rescue ::ArgumentError
80
+ day
78
81
  end
79
82
 
80
83
  def extract_staff(staff)
@@ -1,3 +1,3 @@
1
1
  module Operto
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.4.1'.freeze
3
3
  end
data/lib/operto.rb CHANGED
@@ -10,6 +10,7 @@ require_relative 'operto/error'
10
10
  require_relative 'operto/memory_token_store'
11
11
  require_relative 'operto/config'
12
12
  require_relative 'operto/operation'
13
+ require_relative 'operto/authorization'
13
14
  require_relative 'operto/client'
14
15
  require_relative 'operto/issue_types'
15
16
  require_relative 'operto/filtered_pagination'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: operto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guestit
@@ -90,6 +90,7 @@ files:
90
90
  - README.md
91
91
  - lib/operto.rb
92
92
  - lib/operto/access_tokens/upsert.rb
93
+ - lib/operto/authorization.rb
93
94
  - lib/operto/client.rb
94
95
  - lib/operto/config.rb
95
96
  - lib/operto/error.rb
@@ -133,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
134
  - !ruby/object:Gem::Version
134
135
  version: '0'
135
136
  requirements: []
136
- rubygems_version: 4.0.20
137
+ rubygems_version: 4.0.21
137
138
  specification_version: 4
138
139
  summary: Client for the Operto Teams API
139
140
  test_files: []