onlyoffice-docs_integration_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/lib/onlyoffice/docs_integration_sdk/document_editor/config.rb +1479 -0
- data/lib/onlyoffice/docs_integration_sdk/document_editor/config_test.rb +1713 -0
- data/lib/onlyoffice/docs_integration_sdk/document_editor.rb +29 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/command.rb +417 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/command_test.rb +672 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/conversion.rb +477 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/conversion_test.rb +682 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/healthcheck.rb +101 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/healthcheck_test.rb +209 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/jwt.rb +116 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/jwt_test.rb +70 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/response.rb +73 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/response_test.rb +49 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/service.rb +44 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/ua.rb +31 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client/ua_test.rb +35 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client.rb +321 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server/client_test.rb +1259 -0
- data/lib/onlyoffice/docs_integration_sdk/document_server.rb +29 -0
- data/lib/onlyoffice/docs_integration_sdk/document_storage/callback.rb +276 -0
- data/lib/onlyoffice/docs_integration_sdk/document_storage/callback_test.rb +291 -0
- data/lib/onlyoffice/docs_integration_sdk/document_storage.rb +29 -0
- data/lib/onlyoffice/docs_integration_sdk/jwt.rb +448 -0
- data/lib/onlyoffice/docs_integration_sdk/jwt_test.rb +598 -0
- data/lib/onlyoffice/docs_integration_sdk/test_test.rb +113 -0
- data/lib/onlyoffice/docs_integration_sdk/version.rb +26 -0
- data/lib/onlyoffice/docs_integration_sdk/version_test.rb +33 -0
- data/lib/onlyoffice/docs_integration_sdk.rb +31 -0
- data/lib/onlyoffice.rb +21 -0
- metadata +283 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# (c) Copyright Ascensio System SIA 2025
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
# typed: true
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
require "test/unit"
|
21
|
+
require_relative "ua"
|
22
|
+
|
23
|
+
module Onlyoffice
|
24
|
+
module DocsIntegrationSdk
|
25
|
+
module DocumentServer
|
26
|
+
class Client
|
27
|
+
class UserAgentTest < ::Test::Unit::TestCase
|
28
|
+
def test
|
29
|
+
assert_equal("com.onlyoffice.docs-integration-sdk-ruby #{VERSION}", USER_AGENT)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
#
|
2
|
+
# (c) Copyright Ascensio System SIA 2025
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
# typed: strict
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
require "json"
|
21
|
+
require "net/http"
|
22
|
+
require "sorbet-runtime"
|
23
|
+
require_relative "client/command"
|
24
|
+
require_relative "client/conversion"
|
25
|
+
require_relative "client/healthcheck"
|
26
|
+
require_relative "client/jwt"
|
27
|
+
require_relative "client/response"
|
28
|
+
require_relative "client/service"
|
29
|
+
require_relative "client/ua"
|
30
|
+
|
31
|
+
module Onlyoffice
|
32
|
+
module DocsIntegrationSdk
|
33
|
+
module DocumentServer
|
34
|
+
# Client is a class that provides a way to interact with the Document
|
35
|
+
# Server API. It acts as a wrapper around the Net::HTTP class, offering a
|
36
|
+
# more convenient method for interacting with the API.
|
37
|
+
#
|
38
|
+
# @since 0.1.0
|
39
|
+
class Client
|
40
|
+
extend T::Sig
|
41
|
+
|
42
|
+
# http is a Net::HTTP that is used to make requests to the Document
|
43
|
+
# Server. This should only be used for requests to the Document Server,
|
44
|
+
# because requests may contain a JWT token. It stores a shallow copy of
|
45
|
+
# the original instance.
|
46
|
+
#
|
47
|
+
# @since 0.1.0
|
48
|
+
sig {returns(Net::HTTP)}
|
49
|
+
def http
|
50
|
+
@http.clone
|
51
|
+
end
|
52
|
+
|
53
|
+
# @since 0.1.0
|
54
|
+
sig {returns(Net::HTTP)}
|
55
|
+
protected def http!
|
56
|
+
@http
|
57
|
+
end
|
58
|
+
|
59
|
+
# base_uri is a base URL of the Document Server. It is used to build the
|
60
|
+
# full URL of the request. It stores a shallow copy of the original
|
61
|
+
# instance.
|
62
|
+
#
|
63
|
+
# @since 0.1.0
|
64
|
+
sig {returns(URI::HTTP)}
|
65
|
+
def base_uri
|
66
|
+
@base_uri.clone
|
67
|
+
end
|
68
|
+
|
69
|
+
# user_agent is a User-Agent that is used to make requests to the
|
70
|
+
# Document Server.
|
71
|
+
#
|
72
|
+
# @since 0.1.0
|
73
|
+
sig {returns(String)}
|
74
|
+
def user_agent
|
75
|
+
@user_agent
|
76
|
+
end
|
77
|
+
|
78
|
+
# command is a CommandService that is used to interact with the Command
|
79
|
+
# Service API.
|
80
|
+
#
|
81
|
+
# @since 0.1.0
|
82
|
+
sig {returns(CommandService)}
|
83
|
+
attr_reader :command
|
84
|
+
|
85
|
+
# conversion is a ConversionService that is used to interact with the
|
86
|
+
# Conversion Service API.
|
87
|
+
#
|
88
|
+
# @since 0.1.0
|
89
|
+
sig {returns(ConversionService)}
|
90
|
+
attr_reader :conversion
|
91
|
+
|
92
|
+
# healthcheck is a HealthcheckService that is used to interact with the
|
93
|
+
# Healthcheck Service API.
|
94
|
+
#
|
95
|
+
# @since 0.1.0
|
96
|
+
sig {returns(HealthcheckService)}
|
97
|
+
attr_reader :healthcheck
|
98
|
+
|
99
|
+
# initialize initializes a new Client instance. It requires either http
|
100
|
+
# or base_uri to be provided. If only one of them is provided, the other
|
101
|
+
# one will be built from the provided one. If user_agent is not
|
102
|
+
# provided, it will default to the {USER_AGENT} constant. It makes a
|
103
|
+
# shallow copy of the provided instances.
|
104
|
+
#
|
105
|
+
# @param http
|
106
|
+
# The Net::HTTP instance that is used to make requests to the Document
|
107
|
+
# Server.
|
108
|
+
# @param base_uri
|
109
|
+
# The base URI of the Document Server.
|
110
|
+
# @param user_agent
|
111
|
+
# The User-Agent that is used to make requests to the Document Server.
|
112
|
+
#
|
113
|
+
# @raise [ArgumentError] If neither http nor base_uri is provided.
|
114
|
+
#
|
115
|
+
# @since 0.1.0
|
116
|
+
sig {params(http: T.nilable(Net::HTTP), base_uri: T.nilable(URI::HTTP), user_agent: T.nilable(String)).void}
|
117
|
+
def initialize(http: nil, base_uri: nil, user_agent: nil)
|
118
|
+
if !http && !base_uri
|
119
|
+
raise ArgumentError, "Either http or base_uri must be provided"
|
120
|
+
end
|
121
|
+
|
122
|
+
if http && base_uri
|
123
|
+
@http = T.let(http.clone, Net::HTTP)
|
124
|
+
@base_uri = T.let(base_uri.clone, URI::HTTP)
|
125
|
+
elsif http
|
126
|
+
@http = T.let(http.clone, Net::HTTP)
|
127
|
+
@base_uri = T.let(URI::HTTP.build(host: @http.address, port: @http.port), URI::HTTP)
|
128
|
+
elsif base_uri
|
129
|
+
@http = T.let(Net::HTTP.new(base_uri.host, base_uri.port), Net::HTTP)
|
130
|
+
@base_uri = T.let(base_uri.clone, URI::HTTP)
|
131
|
+
else
|
132
|
+
# :nocov:
|
133
|
+
# unreachable
|
134
|
+
# :nocov:
|
135
|
+
end
|
136
|
+
|
137
|
+
if user_agent
|
138
|
+
@user_agent = T.let(user_agent, String)
|
139
|
+
else
|
140
|
+
@user_agent = T.let(USER_AGENT, String)
|
141
|
+
end
|
142
|
+
|
143
|
+
@command = T.let(CommandService.new(client: self), CommandService)
|
144
|
+
@conversion = T.let(ConversionService.new(client: self), ConversionService)
|
145
|
+
@healthcheck = T.let(HealthcheckService.new(client: self), HealthcheckService)
|
146
|
+
end
|
147
|
+
|
148
|
+
# with_jwt creates a new Client instance with the provided JWT
|
149
|
+
# configuration. It modifies the Net::HTTP#request method to add the JWT
|
150
|
+
# token to the request. The JWT token is added to the request based on
|
151
|
+
# the locations provided in the JWT configuration.
|
152
|
+
#
|
153
|
+
# @param jwt The JWT configuration that is used to sign requests.
|
154
|
+
# @return A new Client instance with the JWT configuration applied.
|
155
|
+
# @since 0.1.0
|
156
|
+
sig {params(jwt: Jwt).returns(Client)}
|
157
|
+
def with_jwt(jwt)
|
158
|
+
# The idea of this approach has its roots in the practice of Go, where
|
159
|
+
# you can implement your own http.Transport. Unfortunately, Ruby does
|
160
|
+
# not have a direct equivalent of http.Transport, so you have to create
|
161
|
+
# a sort of patch for the request method.
|
162
|
+
#
|
163
|
+
# https://pkg.go.dev/net/http@go1.23.5/#Transport
|
164
|
+
# https://github.com/ruby/ruby/blob/v3_4_1/lib/net/http.rb/#L2367
|
165
|
+
|
166
|
+
r = @http.method(:request)
|
167
|
+
c = copy
|
168
|
+
|
169
|
+
c.http!.define_singleton_method(:request) do |req, body = nil, &block|
|
170
|
+
req = T.let(req.clone, Net::HTTPRequest)
|
171
|
+
|
172
|
+
if (req.body || req.body_stream) && body
|
173
|
+
# Leave it untouched so Ruby can raise an error.
|
174
|
+
# https://github.com/ruby/ruby/blob/v3_4_1/lib/net/http/generic_request.rb/#L186
|
175
|
+
elsif req.body
|
176
|
+
if !jwt.locations.empty?
|
177
|
+
b = JSON.parse(req.body)
|
178
|
+
|
179
|
+
if jwt.locations.include?(Jwt::Location::Header)
|
180
|
+
p = jwt.jwt.encode_header(b)
|
181
|
+
req[jwt.header] = "#{jwt.schema} #{p}"
|
182
|
+
end
|
183
|
+
|
184
|
+
if jwt.locations.include?(Jwt::Location::Body)
|
185
|
+
p = jwt.jwt.encode_body(b)
|
186
|
+
req.body = p.to_json
|
187
|
+
end
|
188
|
+
end
|
189
|
+
elsif req.body_stream
|
190
|
+
# There are doubts regarding the necessity of implementing this
|
191
|
+
# branch.
|
192
|
+
elsif body
|
193
|
+
if !jwt.locations.empty?
|
194
|
+
b = JSON.parse(body)
|
195
|
+
|
196
|
+
if jwt.locations.include?(Jwt::Location::Header)
|
197
|
+
p = jwt.jwt.encode_header(b)
|
198
|
+
req[jwt.header] = "#{jwt.schema} #{p}"
|
199
|
+
end
|
200
|
+
|
201
|
+
if jwt.locations.include?(Jwt::Location::Body)
|
202
|
+
p = jwt.jwt.encode_body(b)
|
203
|
+
body = p.to_json
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
r.call(req, body, &block)
|
209
|
+
end
|
210
|
+
|
211
|
+
c
|
212
|
+
end
|
213
|
+
|
214
|
+
# @since 0.1.0
|
215
|
+
sig {returns(Client)}
|
216
|
+
protected def copy
|
217
|
+
self.class.new(
|
218
|
+
base_uri: @base_uri,
|
219
|
+
http: @http,
|
220
|
+
user_agent: @user_agent,
|
221
|
+
)
|
222
|
+
end
|
223
|
+
|
224
|
+
# get makes a GET request to the Document Server. It is a wrapper around
|
225
|
+
# the {uri}, {request} and {do} methods.
|
226
|
+
#
|
227
|
+
# @param p The path to join with the base URI.
|
228
|
+
# @return Inherited from {do}.
|
229
|
+
# @since 0.1.0
|
230
|
+
sig {params(p: String).returns([T.untyped, Response])}
|
231
|
+
def get(p)
|
232
|
+
u = uri(p)
|
233
|
+
r = request(Net::HTTP::Get, u)
|
234
|
+
self.do(r)
|
235
|
+
end
|
236
|
+
|
237
|
+
# post makes a POST request to the Document Server. It is a wrapper
|
238
|
+
# around the {uri}, {request} and {do} methods.
|
239
|
+
#
|
240
|
+
# @param p The path to join with the base URI.
|
241
|
+
# @param b The body of the request.
|
242
|
+
# @return Inherited from {do}
|
243
|
+
# @since 0.1.0
|
244
|
+
sig {params(p: String, b: T.untyped).returns([T.untyped, Response])}
|
245
|
+
def post(p, b = nil)
|
246
|
+
u = uri(p)
|
247
|
+
r = request(Net::HTTP::Post, u, b)
|
248
|
+
self.do(r)
|
249
|
+
end
|
250
|
+
|
251
|
+
# uri creates a new URI::HTTP instance by joining the base URI with the
|
252
|
+
# provided path.
|
253
|
+
#
|
254
|
+
# @param p The path to join with the base URI.
|
255
|
+
# @return A new URI::HTTP instance.
|
256
|
+
# @since 0.1.0
|
257
|
+
sig {params(p: String).returns(URI::HTTP)}
|
258
|
+
def uri(p)
|
259
|
+
# The URI.join returns a URI in the same implementation as the first
|
260
|
+
# argument. Therefore, calling T.cast is safe because the @base_url is a
|
261
|
+
# URI::HTTP and the result will be a URI::HTTP.
|
262
|
+
T.cast(URI.join(@base_uri.to_s, p), URI::HTTP)
|
263
|
+
end
|
264
|
+
|
265
|
+
# request creates a new Net::HTTPRequest instance with the provided
|
266
|
+
# method, URI, and body.
|
267
|
+
#
|
268
|
+
# @param m The method of the request.
|
269
|
+
# @param u The URI of the request.
|
270
|
+
# @param b The body of the request.
|
271
|
+
# @return A new Net::HTTPRequest instance.
|
272
|
+
# @since 0.1.0
|
273
|
+
sig {params(m: T.class_of(Net::HTTPRequest), u: URI::HTTP, b: T.untyped).returns(Net::HTTPRequest)}
|
274
|
+
def request(m, u, b = nil)
|
275
|
+
r = m.new(u)
|
276
|
+
|
277
|
+
r["Accept"] = "application/json"
|
278
|
+
r["User-Agent"] = @user_agent
|
279
|
+
|
280
|
+
if b
|
281
|
+
r["Content-Type"] = "application/json"
|
282
|
+
r.body = b.to_json
|
283
|
+
end
|
284
|
+
|
285
|
+
r
|
286
|
+
end
|
287
|
+
|
288
|
+
# do makes a request to the Document Server. It returns a tuple with the
|
289
|
+
# body of the response and the response instance.
|
290
|
+
#
|
291
|
+
# @param req
|
292
|
+
# The Net::HTTPRequest that is used to make the request.
|
293
|
+
#
|
294
|
+
# @return
|
295
|
+
# A tuple with the body of the response and the response instance.
|
296
|
+
#
|
297
|
+
# @since 0.1.0
|
298
|
+
sig {params(req: Net::HTTPRequest).returns([T.untyped, Response])}
|
299
|
+
def do(req)
|
300
|
+
err = T.let(nil, T.untyped)
|
301
|
+
b = T.let(nil, T.untyped)
|
302
|
+
|
303
|
+
# Document Server always returns a response with the status 200, so
|
304
|
+
# there is no need to check for any other statuses.
|
305
|
+
|
306
|
+
raw = T.let(@http.request(req), Net::HTTPResponse)
|
307
|
+
|
308
|
+
begin
|
309
|
+
b = JSON.parse(raw.body)
|
310
|
+
rescue StandardError => e
|
311
|
+
err = e
|
312
|
+
end
|
313
|
+
|
314
|
+
res = Response.new(request: req, response: raw, error: err)
|
315
|
+
|
316
|
+
[b, res]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|