onoffice_sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +200 -0
- data/lib/generators/onoffice_sdk/install/install_generator.rb +25 -0
- data/lib/generators/onoffice_sdk/install/templates/initializer.rb +13 -0
- data/lib/generators/onoffice_sdk/install/templates/service.rb +24 -0
- data/lib/onoffice_sdk/cache/interface.rb +19 -0
- data/lib/onoffice_sdk/cache/rails_cache.rb +44 -0
- data/lib/onoffice_sdk/configuration.rb +57 -0
- data/lib/onoffice_sdk/errors.rb +12 -0
- data/lib/onoffice_sdk/internal/api_action.rb +27 -0
- data/lib/onoffice_sdk/internal/api_call.rb +167 -0
- data/lib/onoffice_sdk/internal/http_fetch.rb +43 -0
- data/lib/onoffice_sdk/internal/request.rb +49 -0
- data/lib/onoffice_sdk/internal/response.rb +25 -0
- data/lib/onoffice_sdk/railtie.rb +36 -0
- data/lib/onoffice_sdk/sdk.rb +73 -0
- data/lib/onoffice_sdk/version.rb +5 -0
- data/lib/onoffice_sdk.rb +23 -0
- metadata +131 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e90e22cbea56ed44b807826226353a8d45bb71269e94579c2e201c68b8513ad0
|
|
4
|
+
data.tar.gz: 8b88aa66df26aa055510af7af24a56495434b18b2d78caef599901985d0275af
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9b6bb076780f3c46930df2ba8c26bbee7d95aa88768d9f04418e8521c5b7558784fafd3943ee08e2cd41c69db56c560469135dbf0f39679b8a5e5292a97b7a35
|
|
7
|
+
data.tar.gz: 944d8601530766b1d2457cbf06aee806f48133e3e704c3190e6ae8f735a8498953d312d076ae4c7877aea515bf549b5e1b6fa2a5e6dc2ec021ae143bda6e3e4b
|
data/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# onoffice_sdk (Ruby)
|
|
2
|
+
|
|
3
|
+
Ruby client for the onOffice API.
|
|
4
|
+
|
|
5
|
+
- HTTP over TLS
|
|
6
|
+
- Token + HMAC (v2) signing per action
|
|
7
|
+
- Batched requests
|
|
8
|
+
- Pluggable cache hooks
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Build and install locally:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
gem build onoffice_sdk.gemspec
|
|
16
|
+
gem install onoffice_sdk-*.gem
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Add to your Gemfile:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
# For local development using this repo
|
|
23
|
+
gem 'onoffice_sdk', path: '.'
|
|
24
|
+
|
|
25
|
+
# Or use the released gem
|
|
26
|
+
# gem 'onoffice_sdk', '~> 0.x'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quickstart
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
require 'onoffice_sdk'
|
|
33
|
+
|
|
34
|
+
sdk = OnOfficeSDK::SDK.new
|
|
35
|
+
sdk.set_api_version('stable')
|
|
36
|
+
|
|
37
|
+
parameters_read_estate = {
|
|
38
|
+
'data' => ['Id', 'kaufpreis', 'lage'],
|
|
39
|
+
'listlimit' => 10,
|
|
40
|
+
'sortby' => { 'kaufpreis' => 'ASC', 'warmmiete' => 'ASC' },
|
|
41
|
+
'filter' => {
|
|
42
|
+
'kaufpreis' => [{ 'op' => '>', 'val' => 300_000 }],
|
|
43
|
+
'status' => [{ 'op' => '=', 'val' => 1 }]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
handle = sdk.call_generic(OnOfficeSDK::SDK::ACTION_ID_READ, 'estate', parameters_read_estate)
|
|
48
|
+
|
|
49
|
+
sdk.send_requests('PUT_TOKEN_HERE', 'PUT_SECRET_HERE')
|
|
50
|
+
|
|
51
|
+
p sdk.get_response_array(handle)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
- `set_api_version(version)` – sets API version (default: `stable`).
|
|
57
|
+
- `set_api_server(url)` – sets base server (default: `https://api.onoffice.de/api/`).
|
|
58
|
+
- `set_http_options(hash)` – Net::HTTP options, e.g., `{ open_timeout: 5, read_timeout: 30 }`.
|
|
59
|
+
- `call_generic(action_id, resource_type, parameters)` – queue an action.
|
|
60
|
+
- `call(action_id, resource_id, identifier, resource_type, parameters)` – queue an action with explicit identifiers.
|
|
61
|
+
- `send_requests(token, secret)` – send all queued actions in a single HTTP request.
|
|
62
|
+
- `get_response_array(handle)` – fetch and remove the response for a prior handle.
|
|
63
|
+
- `add_cache(cache)` / `set_caches([...])` – register cache backends.
|
|
64
|
+
- `remove_cache_instances` – clear all registered caches.
|
|
65
|
+
- `errors` – returns a hash of errors for failed actions.
|
|
66
|
+
|
|
67
|
+
### Cache interface
|
|
68
|
+
|
|
69
|
+
Implementors should respond to:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
class MyCache
|
|
73
|
+
include OnOfficeSDK::Cache::Interface
|
|
74
|
+
|
|
75
|
+
def initialize(options = {}); end
|
|
76
|
+
def get_http_response_by_parameter_array(parameters); end # -> String (JSON) or nil
|
|
77
|
+
def write(parameters, value); end # value is a JSON string
|
|
78
|
+
def cleanup; end
|
|
79
|
+
def clear_all; end
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
When a response is cacheable, the SDK writes a JSON string of the response payload to caches. Reads should return that JSON string for a hit.
|
|
84
|
+
|
|
85
|
+
## Notes
|
|
86
|
+
|
|
87
|
+
- HMAC v2 implemented as Base64.strict_encode64(HMAC-SHA256(secret, timestamp + token + resourcetype + actionid)).
|
|
88
|
+
- Batch request body shape: `{ token, request: { actions: [...] } }`.
|
|
89
|
+
- Response handling uses `status.errorcode`, `data`, and `cacheable`.
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT (see repository LICENSE).
|
|
94
|
+
|
|
95
|
+
## Rails Integration
|
|
96
|
+
|
|
97
|
+
The gem includes a Railtie for auto-configuration, an optional Rails.cache adapter, and a generator.
|
|
98
|
+
|
|
99
|
+
1) Gemfile
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
# For local development using this repo
|
|
103
|
+
gem 'onoffice_sdk', path: '.'
|
|
104
|
+
|
|
105
|
+
# Or use the released gem
|
|
106
|
+
# gem 'onoffice_sdk', '~> 0.x'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
2) Credentials or ENV
|
|
110
|
+
|
|
111
|
+
Set `ONOFFICE_TOKEN` and `ONOFFICE_SECRET` (or use Rails credentials):
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
# .env or deployment env
|
|
115
|
+
ONOFFICE_TOKEN=your_token
|
|
116
|
+
ONOFFICE_SECRET=your_secret
|
|
117
|
+
ONOFFICE_API_VERSION=stable
|
|
118
|
+
ONOFFICE_API_BASE=https://api.onoffice.de/api/
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
3) Initializer (auto-config via Railtie or generator)
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
OnOfficeSDK.configure do |c|
|
|
125
|
+
# c.api_server = ENV.fetch('ONOFFICE_API_BASE', 'https://api.onoffice.de/api/')
|
|
126
|
+
# c.api_version = ENV.fetch('ONOFFICE_API_VERSION', 'stable')
|
|
127
|
+
# c.open_timeout = 5
|
|
128
|
+
# c.read_timeout = 30
|
|
129
|
+
# c.token = Rails.application.credentials.dig(:onoffice, :token)
|
|
130
|
+
# c.secret = Rails.application.credentials.dig(:onoffice, :secret)
|
|
131
|
+
# c.use_rails_cache = true
|
|
132
|
+
# c.rails_cache_ttl = 600
|
|
133
|
+
end
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
4) Use the generator (optional)
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
bin/rails g onoffice_sdk:install
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
This creates `config/initializers/onoffice_sdk.rb` and `app/services/onoffice_client.rb`.
|
|
143
|
+
|
|
144
|
+
5) Example service (app/services/onoffice_client.rb)
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
class OnofficeClient
|
|
148
|
+
def initialize(sdk: OnOfficeSDK.client)
|
|
149
|
+
@sdk = sdk
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def read_estates(limit: 10)
|
|
153
|
+
params = { 'data' => ['Id', 'kaufpreis'], 'listlimit' => limit }
|
|
154
|
+
handle = @sdk.call_generic(OnOfficeSDK::SDK::ACTION_ID_READ, 'estate', params)
|
|
155
|
+
@sdk.send_requests(token, secret)
|
|
156
|
+
@sdk.get_response_array(handle)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
def token
|
|
162
|
+
ENV.fetch('ONOFFICE_TOKEN')
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def secret
|
|
166
|
+
ENV.fetch('ONOFFICE_SECRET')
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
5) Use in a controller
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
class EstatesController < ApplicationController
|
|
175
|
+
def index
|
|
176
|
+
@result = OnofficeClient.new.read_estates(limit: 10)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
6) Optional: Rails.cache adapter
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
require 'digest/md5'
|
|
185
|
+
|
|
186
|
+
Built-in: `OnOfficeSDK::Cache::RailsCache`.
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
# In the initializer
|
|
190
|
+
# OnOfficeSDK.configure do |c|
|
|
191
|
+
# c.use_rails_cache = true
|
|
192
|
+
# c.rails_cache_ttl = 10.minutes
|
|
193
|
+
# end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Notes for Rails
|
|
197
|
+
- The client is stateless; create once and reuse per-process or inject per-request.
|
|
198
|
+
- `send_requests(token, secret)` batches all queued actions; queue multiple calls, then send once.
|
|
199
|
+
- Cache interface expects JSON strings; example above writes/reads raw strings to `Rails.cache`.
|
|
200
|
+
- ActiveSupport::Notifications: emits `onoffice_sdk.request` around each HTTP call.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module OnofficeSdk
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
|
9
|
+
|
|
10
|
+
desc 'Creates an initializer for OnOfficeSDK and an optional service class'
|
|
11
|
+
|
|
12
|
+
class_option :service, type: :boolean, default: true, desc: 'Generate a simple service class using the SDK'
|
|
13
|
+
|
|
14
|
+
def create_initializer
|
|
15
|
+
template 'initializer.rb', 'config/initializers/onoffice_sdk.rb'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_service
|
|
19
|
+
return unless options[:service]
|
|
20
|
+
|
|
21
|
+
template 'service.rb', 'app/services/onoffice_client.rb'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
OnOfficeSDK.configure do |c|
|
|
4
|
+
# Configure via ENV, Rails credentials, or set here
|
|
5
|
+
# c.api_server = ENV.fetch('ONOFFICE_API_BASE', 'https://api.onoffice.de/api/')
|
|
6
|
+
# c.api_version = ENV.fetch('ONOFFICE_API_VERSION', 'stable')
|
|
7
|
+
# c.open_timeout = 5
|
|
8
|
+
# c.read_timeout = 30
|
|
9
|
+
# c.token = Rails.application.credentials.dig(:onoffice, :token)
|
|
10
|
+
# c.secret = Rails.application.credentials.dig(:onoffice, :secret)
|
|
11
|
+
# c.use_rails_cache = true
|
|
12
|
+
# c.rails_cache_ttl = 600
|
|
13
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class OnofficeClient
|
|
4
|
+
def initialize(sdk: OnOfficeSDK.client)
|
|
5
|
+
@sdk = sdk
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def read_estates(limit: 10)
|
|
9
|
+
params = { 'data' => %w[Id kaufpreis], 'listlimit' => limit }
|
|
10
|
+
handle = @sdk.call_generic(OnOfficeSDK::SDK::ACTION_ID_READ, 'estate', params)
|
|
11
|
+
@sdk.send_requests(token, secret)
|
|
12
|
+
@sdk.get_response_array(handle)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def token
|
|
18
|
+
OnOfficeSDK.configuration.token || ENV.fetch('ONOFFICE_TOKEN', nil)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def secret
|
|
22
|
+
OnOfficeSDK.configuration.secret || ENV.fetch('ONOFFICE_SECRET', nil)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnOfficeSDK
|
|
4
|
+
module Cache
|
|
5
|
+
# Informal interface for cache backends.
|
|
6
|
+
# Implementers should provide the following methods:
|
|
7
|
+
# - initialize(options = {})
|
|
8
|
+
# - get_http_response_by_parameter_array(parameters) -> String or nil
|
|
9
|
+
# - write(parameters, value) -> true/false
|
|
10
|
+
# - cleanup
|
|
11
|
+
# - clear_all
|
|
12
|
+
module Interface
|
|
13
|
+
def get_http_response_by_parameter_array(_parameters); end
|
|
14
|
+
def write(_parameters, _value); end
|
|
15
|
+
def cleanup; end
|
|
16
|
+
def clear_all; end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
module OnOfficeSDK
|
|
6
|
+
module Cache
|
|
7
|
+
class RailsCache
|
|
8
|
+
include OnOfficeSDK::Cache::Interface
|
|
9
|
+
|
|
10
|
+
def initialize(options = {})
|
|
11
|
+
@namespace = options[:namespace] || 'onoffice'
|
|
12
|
+
@ttl = options[:ttl] || 300
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get_http_response_by_parameter_array(parameters)
|
|
16
|
+
return nil unless defined?(Rails)
|
|
17
|
+
|
|
18
|
+
Rails.cache.read(key(parameters))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def write(parameters, value)
|
|
22
|
+
return false unless defined?(Rails)
|
|
23
|
+
|
|
24
|
+
Rails.cache.write(key(parameters), value, expires_in: @ttl)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def cleanup; end
|
|
28
|
+
|
|
29
|
+
def clear_all
|
|
30
|
+
return unless defined?(Rails)
|
|
31
|
+
|
|
32
|
+
# Best-effort namespaced clear
|
|
33
|
+
Rails.cache.delete_matched("#{@namespace}:*") if Rails.cache.respond_to?(:delete_matched)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def key(parameters)
|
|
39
|
+
digest = Digest::MD5.hexdigest(Marshal.dump(parameters))
|
|
40
|
+
"#{@namespace}:#{digest}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnOfficeSDK
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_accessor :api_server, :api_version, :open_timeout, :read_timeout,
|
|
6
|
+
:token, :secret, :use_rails_cache, :rails_cache_ttl
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@api_server = 'https://api.onoffice.de/api/'
|
|
10
|
+
@api_version = 'stable'
|
|
11
|
+
@open_timeout = 5
|
|
12
|
+
@read_timeout = 30
|
|
13
|
+
@token = nil
|
|
14
|
+
@secret = nil
|
|
15
|
+
@use_rails_cache = false
|
|
16
|
+
@rails_cache_ttl = 300 # seconds
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def configuration
|
|
22
|
+
@configuration ||= Configuration.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def configure
|
|
26
|
+
yield(configuration)
|
|
27
|
+
refresh_default_client!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def client
|
|
31
|
+
@client ||= build_client_from_config
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def refresh_default_client!
|
|
35
|
+
@client = build_client_from_config
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def build_client_from_config
|
|
41
|
+
sdk = OnOfficeSDK::SDK.new
|
|
42
|
+
cfg = configuration
|
|
43
|
+
sdk.set_api_server(cfg.api_server)
|
|
44
|
+
sdk.set_api_version(cfg.api_version)
|
|
45
|
+
sdk.set_http_options(open_timeout: cfg.open_timeout, read_timeout: cfg.read_timeout)
|
|
46
|
+
if cfg.use_rails_cache && defined?(Rails)
|
|
47
|
+
begin
|
|
48
|
+
require_relative 'cache/rails_cache'
|
|
49
|
+
sdk.add_cache(OnOfficeSDK::Cache::RailsCache.new(ttl: cfg.rails_cache_ttl))
|
|
50
|
+
rescue LoadError
|
|
51
|
+
# ignore if Rails cache adapter not available
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
sdk
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnOfficeSDK
|
|
4
|
+
class SDKError < StandardError; end
|
|
5
|
+
|
|
6
|
+
class ApiCallFaultyResponseError < SDKError; end
|
|
7
|
+
class ApiCallNoActionParametersError < SDKError; end
|
|
8
|
+
|
|
9
|
+
class HttpFetchNoResultError < SDKError
|
|
10
|
+
attr_accessor :errno
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnOfficeSDK
|
|
4
|
+
module Internal
|
|
5
|
+
class ApiAction
|
|
6
|
+
def initialize(action_id, resource_type, parameters, resource_id = '', identifier = '', timestamp = nil)
|
|
7
|
+
sorted_params = parameters.is_a?(Hash) ? parameters.sort.to_h : parameters
|
|
8
|
+
@action_parameters = {
|
|
9
|
+
'actionid' => action_id,
|
|
10
|
+
'identifier' => identifier,
|
|
11
|
+
'parameters' => sorted_params,
|
|
12
|
+
'resourceid' => resource_id,
|
|
13
|
+
'resourcetype' => resource_type,
|
|
14
|
+
'timestamp' => timestamp
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attr_reader :action_parameters
|
|
19
|
+
|
|
20
|
+
def identifier
|
|
21
|
+
# Deterministic identifier for caching
|
|
22
|
+
require 'digest/md5'
|
|
23
|
+
Digest::MD5.hexdigest(Marshal.dump(@action_parameters))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module OnOfficeSDK
|
|
6
|
+
module Internal
|
|
7
|
+
class ApiCall
|
|
8
|
+
def initialize
|
|
9
|
+
@request_queue = {}
|
|
10
|
+
@responses = {}
|
|
11
|
+
@errors = {}
|
|
12
|
+
@api_version = 'stable'
|
|
13
|
+
@caches = []
|
|
14
|
+
@server = nil
|
|
15
|
+
@http_options = {}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def call_by_raw_data(action_id, resource_id, identifier, resource_type, parameters = {})
|
|
19
|
+
p_api_action = ApiAction.new(action_id, resource_type, parameters, resource_id, identifier)
|
|
20
|
+
p_request = Request.new(p_api_action)
|
|
21
|
+
request_id = p_request.request_id
|
|
22
|
+
@request_queue[request_id] = p_request
|
|
23
|
+
request_id
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def send_requests(token, secret, http_fetch = nil)
|
|
27
|
+
collect_or_gather_requests(token, secret, http_fetch)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def set_http_options(opts)
|
|
31
|
+
@http_options = opts || {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get_response(handle)
|
|
35
|
+
if @responses.key?(handle)
|
|
36
|
+
p_response = @responses[handle]
|
|
37
|
+
raise ApiCallFaultyResponseError, "Handle: #{handle}" unless p_response.valid?
|
|
38
|
+
|
|
39
|
+
@responses.delete(handle)
|
|
40
|
+
return p_response.response_data
|
|
41
|
+
end
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def set_api_version(v)
|
|
46
|
+
@api_version = v
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def set_server(server)
|
|
50
|
+
@server = server
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
attr_reader :errors
|
|
54
|
+
|
|
55
|
+
def add_cache(cache)
|
|
56
|
+
@caches << cache
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def remove_cache_instances
|
|
60
|
+
@caches = []
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def collect_or_gather_requests(token, secret, http_fetch)
|
|
66
|
+
action_parameters = []
|
|
67
|
+
action_parameters_order = []
|
|
68
|
+
|
|
69
|
+
@request_queue.each_value do |p_request|
|
|
70
|
+
used_parameters = p_request.api_action.action_parameters
|
|
71
|
+
cached_response = get_from_cache(used_parameters)
|
|
72
|
+
if cached_response.nil?
|
|
73
|
+
parameters_this_action = p_request.create_request(token, secret)
|
|
74
|
+
action_parameters << parameters_this_action
|
|
75
|
+
action_parameters_order << p_request
|
|
76
|
+
else
|
|
77
|
+
@responses[p_request.request_id] = Response.new(p_request, cached_response)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
send_http_requests(token, action_parameters, action_parameters_order, http_fetch)
|
|
82
|
+
@request_queue = {}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def send_http_requests(token, action_parameters, action_parameters_order, http_fetch)
|
|
86
|
+
return if action_parameters.empty?
|
|
87
|
+
|
|
88
|
+
response_http = get_from_http(token, action_parameters, http_fetch)
|
|
89
|
+
result = JSON.parse(response_http)
|
|
90
|
+
raise HttpFetchNoResultError unless result.dig('response', 'results')
|
|
91
|
+
|
|
92
|
+
ids_for_cache = []
|
|
93
|
+
|
|
94
|
+
result['response']['results'].each_with_index do |result_http, request_number|
|
|
95
|
+
p_request = action_parameters_order[request_number]
|
|
96
|
+
request_id = p_request.request_id
|
|
97
|
+
if result_http.dig('status', 'errorcode').to_i.zero?
|
|
98
|
+
@responses[request_id] = Response.new(p_request, result_http)
|
|
99
|
+
ids_for_cache << request_id
|
|
100
|
+
else
|
|
101
|
+
@errors[request_id] = result_http
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
write_cache_for_responses(ids_for_cache)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def get_from_http(token, action_parameters, http_fetch)
|
|
109
|
+
request = {
|
|
110
|
+
'token' => token,
|
|
111
|
+
'request' => { 'actions' => action_parameters }
|
|
112
|
+
}
|
|
113
|
+
if http_fetch.nil?
|
|
114
|
+
http_fetch = HttpFetch.new(api_url, JSON.generate(request))
|
|
115
|
+
http_fetch.http_options = @http_options
|
|
116
|
+
end
|
|
117
|
+
if defined?(ActiveSupport::Notifications)
|
|
118
|
+
ActiveSupport::Notifications.instrument('onoffice_sdk.request',
|
|
119
|
+
url: api_url,
|
|
120
|
+
actions_count: action_parameters.size) do
|
|
121
|
+
http_fetch.send
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
http_fetch.send
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def write_cache_for_responses(response_ids)
|
|
129
|
+
return if @caches.empty?
|
|
130
|
+
|
|
131
|
+
response_objects = @responses.slice(*response_ids).values
|
|
132
|
+
response_objects.each do |p_response|
|
|
133
|
+
next unless p_response.cacheable?
|
|
134
|
+
|
|
135
|
+
response_data = p_response.response_data
|
|
136
|
+
request_parameters = p_response.request.api_action.action_parameters
|
|
137
|
+
write_cache(JSON.generate(response_data), request_parameters)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def write_cache(result, action_parameters)
|
|
142
|
+
@caches.each { |cache| cache.write(action_parameters, result) }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def get_from_cache(parameters)
|
|
146
|
+
@caches.each do |cache|
|
|
147
|
+
result_cache = cache.get_http_response_by_parameter_array(parameters)
|
|
148
|
+
next if result_cache.nil?
|
|
149
|
+
|
|
150
|
+
begin
|
|
151
|
+
return JSON.parse(result_cache)
|
|
152
|
+
rescue JSON::ParserError
|
|
153
|
+
# ignore invalid cache content
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
nil
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def api_url
|
|
160
|
+
raise SDKError, 'Server not set' unless @server
|
|
161
|
+
|
|
162
|
+
base = @server.end_with?('/') ? @server : "#{@server}/"
|
|
163
|
+
"#{base}#{URI.encode_www_form_component(@api_version)}/api.php"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
module OnOfficeSDK
|
|
7
|
+
module Internal
|
|
8
|
+
class HttpFetch
|
|
9
|
+
def initialize(url, post_data)
|
|
10
|
+
@url = url
|
|
11
|
+
@post_data = post_data
|
|
12
|
+
@http_options = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def http_options=(opts)
|
|
16
|
+
@http_options = opts || {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def send
|
|
20
|
+
uri = URI.parse(@url)
|
|
21
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
22
|
+
http.use_ssl = (uri.scheme == 'https')
|
|
23
|
+
# Timeouts / options
|
|
24
|
+
http.open_timeout = @http_options[:open_timeout] if @http_options[:open_timeout]
|
|
25
|
+
http.read_timeout = @http_options[:read_timeout] if @http_options[:read_timeout]
|
|
26
|
+
|
|
27
|
+
req = Net::HTTP::Post.new(uri.request_uri)
|
|
28
|
+
req['Content-Type'] = 'application/json'
|
|
29
|
+
req['Accept-Encoding'] = 'gzip,deflate,br'
|
|
30
|
+
req.body = @post_data
|
|
31
|
+
|
|
32
|
+
res = http.request(req)
|
|
33
|
+
body = res&.body
|
|
34
|
+
unless res.is_a?(Net::HTTPSuccess) && body
|
|
35
|
+
err = HttpFetchNoResultError.new(res&.code.to_s)
|
|
36
|
+
err.errno = nil
|
|
37
|
+
raise err
|
|
38
|
+
end
|
|
39
|
+
body
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'base64'
|
|
5
|
+
require 'openssl'
|
|
6
|
+
|
|
7
|
+
module OnOfficeSDK
|
|
8
|
+
module Internal
|
|
9
|
+
class Request
|
|
10
|
+
@request_id_static = 0
|
|
11
|
+
class << self
|
|
12
|
+
attr_accessor :request_id_static
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(api_action)
|
|
16
|
+
@api_action = api_action
|
|
17
|
+
@request_id = (self.class.request_id_static ||= 0)
|
|
18
|
+
self.class.request_id_static += 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_request(token, secret)
|
|
22
|
+
action_parameters = @api_action.action_parameters.dup
|
|
23
|
+
action_parameters['timestamp'] ||= Time.now.to_i
|
|
24
|
+
action_parameters['hmac_version'] = 2
|
|
25
|
+
|
|
26
|
+
action_id = action_parameters['actionid']
|
|
27
|
+
type = action_parameters['resourcetype']
|
|
28
|
+
hmac = create_hmac2(token, secret, action_parameters['timestamp'], type, action_id)
|
|
29
|
+
action_parameters['hmac'] = hmac
|
|
30
|
+
|
|
31
|
+
action_parameters
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create_hmac2(token, secret, timestamp, type, action_id)
|
|
35
|
+
fields = {
|
|
36
|
+
'timestamp' => timestamp,
|
|
37
|
+
'token' => token,
|
|
38
|
+
'resourcetype' => type,
|
|
39
|
+
'actionid' => action_id
|
|
40
|
+
}
|
|
41
|
+
raw = fields.values.join
|
|
42
|
+
digest = OpenSSL::HMAC.digest('sha256', secret.to_s, raw)
|
|
43
|
+
Base64.strict_encode64(digest)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
attr_reader :request_id, :api_action
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnOfficeSDK
|
|
4
|
+
module Internal
|
|
5
|
+
class Response
|
|
6
|
+
def initialize(request, response_data)
|
|
7
|
+
@request = request
|
|
8
|
+
@response_data = response_data
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def valid?
|
|
12
|
+
@response_data.is_a?(Hash) &&
|
|
13
|
+
@response_data.key?('actionid') &&
|
|
14
|
+
@response_data.key?('resourcetype') &&
|
|
15
|
+
@response_data.key?('data')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def cacheable?
|
|
19
|
+
valid? && @response_data['cacheable']
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :request, :response_data
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/railtie'
|
|
4
|
+
|
|
5
|
+
module OnOfficeSDK
|
|
6
|
+
class Railtie < ::Rails::Railtie
|
|
7
|
+
config.onoffice_sdk = ActiveSupport::OrderedOptions.new
|
|
8
|
+
|
|
9
|
+
initializer 'onoffice_sdk.configure' do |app|
|
|
10
|
+
cfg = app.config.onoffice_sdk
|
|
11
|
+
|
|
12
|
+
OnOfficeSDK.configure do |c|
|
|
13
|
+
c.api_server = cfg.api_server || ENV['ONOFFICE_API_BASE'] || c.api_server
|
|
14
|
+
c.api_version = cfg.api_version || ENV['ONOFFICE_API_VERSION'] || c.api_version
|
|
15
|
+
c.open_timeout = cfg.open_timeout || c.open_timeout
|
|
16
|
+
c.read_timeout = cfg.read_timeout || c.read_timeout
|
|
17
|
+
|
|
18
|
+
c.token = cfg.token || begin
|
|
19
|
+
Rails.application.credentials.dig(:onoffice,
|
|
20
|
+
:token)
|
|
21
|
+
rescue StandardError
|
|
22
|
+
nil
|
|
23
|
+
end || ENV.fetch('ONOFFICE_TOKEN', nil)
|
|
24
|
+
c.secret = cfg.secret || begin
|
|
25
|
+
Rails.application.credentials.dig(:onoffice,
|
|
26
|
+
:secret)
|
|
27
|
+
rescue StandardError
|
|
28
|
+
nil
|
|
29
|
+
end || ENV.fetch('ONOFFICE_SECRET', nil)
|
|
30
|
+
|
|
31
|
+
c.use_rails_cache = cfg.fetch(:use_rails_cache, c.use_rails_cache)
|
|
32
|
+
c.rails_cache_ttl = cfg.rails_cache_ttl || c.rails_cache_ttl
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnOfficeSDK
|
|
4
|
+
# Main SDK client for the onOffice API.
|
|
5
|
+
class SDK
|
|
6
|
+
ACTION_ID_READ = 'urn:onoffice-de-ns:smart:2.5:smartml:action:read'
|
|
7
|
+
ACTION_ID_CREATE = 'urn:onoffice-de-ns:smart:2.5:smartml:action:create'
|
|
8
|
+
ACTION_ID_MODIFY = 'urn:onoffice-de-ns:smart:2.5:smartml:action:modify'
|
|
9
|
+
ACTION_ID_GET = 'urn:onoffice-de-ns:smart:2.5:smartml:action:get'
|
|
10
|
+
ACTION_ID_DO = 'urn:onoffice-de-ns:smart:2.5:smartml:action:do'
|
|
11
|
+
ACTION_ID_DELETE = 'urn:onoffice-de-ns:smart:2.5:smartml:action:delete'
|
|
12
|
+
|
|
13
|
+
RELATION_TYPE_BUYER = 'urn:onoffice-de-ns:smart:2.5:relationTypes:estate:address:buyer'
|
|
14
|
+
RELATION_TYPE_TENANT = 'urn:onoffice-de-ns:smart:2.5:relationTypes:estate:address:renter'
|
|
15
|
+
RELATION_TYPE_OWNER = 'urn:onoffice-de-ns:smart:2.5:relationTypes:estate:address:owner'
|
|
16
|
+
MODULE_ADDRESS = 'address'
|
|
17
|
+
MODULE_ESTATE = 'estate'
|
|
18
|
+
MODULE_SEARCHCRITERIA = 'searchcriteria'
|
|
19
|
+
RELATION_TYPE_CONTACT_BROKER = 'urn:onoffice-de-ns:smart:2.5:relationTypes:estate:address:contactPerson'
|
|
20
|
+
RELATION_TYPE_CONTACT_PERSON = 'urn:onoffice-de-ns:smart:2.5:relationTypes:estate:address:contactPersonAll'
|
|
21
|
+
RELATION_TYPE_COMPLEX_ESTATE_UNITS = 'urn:onoffice-de-ns:smart:2.5:relationTypes:complex:estate:units'
|
|
22
|
+
RELATION_TYPE_ESTATE_ADDRESS_OWNER = 'urn:onoffice-de-ns:smart:2.5:relationTypes:estate:address:owner'
|
|
23
|
+
|
|
24
|
+
def initialize(api_call: nil)
|
|
25
|
+
@api_call = api_call || Internal::ApiCall.new
|
|
26
|
+
@api_call.set_server('https://api.onoffice.de/api/')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def set_api_version(api_version)
|
|
30
|
+
@api_call.set_api_version(api_version)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def set_api_server(server)
|
|
34
|
+
@api_call.set_server(server)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def set_http_options(options)
|
|
38
|
+
@api_call.set_http_options(options)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def call_generic(action_id, resource_type, parameters)
|
|
42
|
+
@api_call.call_by_raw_data(action_id, '', '', resource_type, parameters)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def call(action_id, resource_id, identifier, resource_type, parameters)
|
|
46
|
+
@api_call.call_by_raw_data(action_id, resource_id, identifier, resource_type, parameters)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def send_requests(token, secret)
|
|
50
|
+
@api_call.send_requests(token, secret)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def get_response_array(number)
|
|
54
|
+
@api_call.get_response(number)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def add_cache(cache)
|
|
58
|
+
@api_call.add_cache(cache)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def set_caches(cache_instances)
|
|
62
|
+
Array(cache_instances).each { |c| @api_call.add_cache(c) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def remove_cache_instances
|
|
66
|
+
@api_call.remove_cache_instances
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def errors
|
|
70
|
+
@api_call.errors
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/onoffice_sdk.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require 'uri'
|
|
6
|
+
|
|
7
|
+
require_relative 'onoffice_sdk/version'
|
|
8
|
+
require_relative 'onoffice_sdk/configuration'
|
|
9
|
+
require_relative 'onoffice_sdk/sdk'
|
|
10
|
+
require_relative 'onoffice_sdk/internal/api_call'
|
|
11
|
+
require_relative 'onoffice_sdk/internal/api_action'
|
|
12
|
+
require_relative 'onoffice_sdk/internal/request'
|
|
13
|
+
require_relative 'onoffice_sdk/internal/response'
|
|
14
|
+
require_relative 'onoffice_sdk/internal/http_fetch'
|
|
15
|
+
require_relative 'onoffice_sdk/cache/interface'
|
|
16
|
+
require_relative 'onoffice_sdk/errors'
|
|
17
|
+
|
|
18
|
+
# Auto-load Railtie if in Rails
|
|
19
|
+
begin
|
|
20
|
+
require_relative 'onoffice_sdk/railtie' if defined?(Rails::Railtie)
|
|
21
|
+
rescue LoadError
|
|
22
|
+
# ignore when Rails is not present
|
|
23
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: onoffice_sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- onOffice GmbH
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-11-20 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: json
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rspec
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3.12'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.12'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: simplecov
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.21'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.21'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rubocop
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.48'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.48'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rubocop-rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '2.20'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '2.20'
|
|
83
|
+
description: Lightweight Ruby client to communicate with the onOffice API, supporting
|
|
84
|
+
batched requests, HMAC signing, and pluggable caching.
|
|
85
|
+
email:
|
|
86
|
+
- support@onoffice.de
|
|
87
|
+
executables: []
|
|
88
|
+
extensions: []
|
|
89
|
+
extra_rdoc_files: []
|
|
90
|
+
files:
|
|
91
|
+
- README.md
|
|
92
|
+
- lib/generators/onoffice_sdk/install/install_generator.rb
|
|
93
|
+
- lib/generators/onoffice_sdk/install/templates/initializer.rb
|
|
94
|
+
- lib/generators/onoffice_sdk/install/templates/service.rb
|
|
95
|
+
- lib/onoffice_sdk.rb
|
|
96
|
+
- lib/onoffice_sdk/cache/interface.rb
|
|
97
|
+
- lib/onoffice_sdk/cache/rails_cache.rb
|
|
98
|
+
- lib/onoffice_sdk/configuration.rb
|
|
99
|
+
- lib/onoffice_sdk/errors.rb
|
|
100
|
+
- lib/onoffice_sdk/internal/api_action.rb
|
|
101
|
+
- lib/onoffice_sdk/internal/api_call.rb
|
|
102
|
+
- lib/onoffice_sdk/internal/http_fetch.rb
|
|
103
|
+
- lib/onoffice_sdk/internal/request.rb
|
|
104
|
+
- lib/onoffice_sdk/internal/response.rb
|
|
105
|
+
- lib/onoffice_sdk/railtie.rb
|
|
106
|
+
- lib/onoffice_sdk/sdk.rb
|
|
107
|
+
- lib/onoffice_sdk/version.rb
|
|
108
|
+
homepage: https://apidoc.onoffice.de/
|
|
109
|
+
licenses:
|
|
110
|
+
- MIT
|
|
111
|
+
metadata: {}
|
|
112
|
+
post_install_message:
|
|
113
|
+
rdoc_options: []
|
|
114
|
+
require_paths:
|
|
115
|
+
- lib
|
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - ">="
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: '2.6'
|
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
|
+
requirements:
|
|
123
|
+
- - ">="
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
requirements: []
|
|
127
|
+
rubygems_version: 3.2.3
|
|
128
|
+
signing_key:
|
|
129
|
+
specification_version: 4
|
|
130
|
+
summary: Ruby client for the onOffice API
|
|
131
|
+
test_files: []
|