oklog-api 1.0.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/LICENSE +19 -0
- data/README.markdown +0 -0
- data/lib/generators/oklog_api/install/USAGE +2 -0
- data/lib/generators/oklog_api/install/install_generator.rb +13 -0
- data/lib/generators/oklog_api/install/templates/oklog_api.rb +24 -0
- data/lib/generators/oklog_api/install/templates/oklog_api.yml +24 -0
- data/lib/oklog-api/api_request.rb +427 -0
- data/lib/oklog-api/rail_locator_api_error.rb +29 -0
- data/lib/oklog-api/request.rb +161 -0
- data/lib/oklog-api/response.rb +11 -0
- data/lib/oklog-api/version.rb +3 -0
- data/lib/oklog-api.rb +91 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2ade0502599e017e35719e5ab72d43a7d496c1cbe831f4de48dba5096d103ea7
|
4
|
+
data.tar.gz: d2c926c063c82f889ecaaebe78cbd1e165d77d655d048e0e4362402a2f98d0ef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 01535c9bc906254cbea3ad0664bdaeb306ca6db8c999dc0f275b9b12cd6539e9552519206d411000db5f6188fd20340a8990666f984f76a80f1e95283fce3b2f
|
7
|
+
data.tar.gz: 4832f39fb0f6e4bae1141ff181b3e15df4d0657f5e17b03e95e3c885ba1169acdb429280c15c56a12f92e2623c70737cfbc478a2e64a39067e7813e8baba8101
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.markdown
ADDED
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OklogApi
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
6
|
+
|
7
|
+
def generate_install
|
8
|
+
copy_file 'oklog_api.yml', 'config/oklog_api.yml'
|
9
|
+
copy_file 'oklog_api.rb', 'config/initializers/oklog_api.rb'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'oklog-api'
|
2
|
+
|
3
|
+
OklogApi.setup do |config|
|
4
|
+
if File.exist?('config/oklog_api.yml')
|
5
|
+
processed = YAML.load('config/oklog_api.yml', aliases: true)[Rails.env]
|
6
|
+
|
7
|
+
processed.each do |k, v|
|
8
|
+
config::register k.underscore.to_sym, v
|
9
|
+
end
|
10
|
+
|
11
|
+
#config::Request.api_key ||= ENV['API_KEY']
|
12
|
+
|
13
|
+
config::Request.api_user_email ||= ENV['API_USER_EMAIL']
|
14
|
+
config::Request.api_user_password ||= ENV['API_USER_PASSWORD']
|
15
|
+
|
16
|
+
config::Request.timeout = 60
|
17
|
+
config::Request.open_timeout = 60
|
18
|
+
config::Request.symbolize_keys = true
|
19
|
+
config::Request.debug = false
|
20
|
+
config::Request.debug_options = { headers: true, bodies: false, errors: false, log_level: :info } # https://lostisland.github.io/faraday/middleware/logger
|
21
|
+
|
22
|
+
config::Request.language = defined?(I18n) ? I18n.locale : :ru
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
API_ENDPOINT: "https://rail-scan.com"
|
3
|
+
UNION_ENDPOINT: "http://192.168.88.38:8000"
|
4
|
+
NOTIFY_ENDPOINT: "http://192.168.1.153:3003"
|
5
|
+
|
6
|
+
API_AUTH_METHOD: "api_key"
|
7
|
+
API_KEY: "***"
|
8
|
+
|
9
|
+
API_USER_EMAIL: ""
|
10
|
+
API_USER_PASSWORD: ""
|
11
|
+
|
12
|
+
KEYCLOAK_TOKEN_URL: "https://iam.ctm.ru/auth/realms/ctm/protocol/openid-connect/token"
|
13
|
+
KEYCLOAK_GRANT_TYPE: "password"
|
14
|
+
KEYCLOAK_CLIENT_ID: "client_id"
|
15
|
+
KEYCLOAK_CLIENT_SECRET: "client_secret"
|
16
|
+
KEYCLOAK_REDIRECT_URI: "http://yousite.ru/callback"
|
17
|
+
production:
|
18
|
+
<<: *defaults
|
19
|
+
UNION_ENDPOINT: "http://192.168.1.88:3500"
|
20
|
+
NOTIFY_ENDPOINT: "http://192.168.1.153:3003"
|
21
|
+
development:
|
22
|
+
<<: *defaults
|
23
|
+
test:
|
24
|
+
<<: *defaults
|
@@ -0,0 +1,427 @@
|
|
1
|
+
module OklogApi
|
2
|
+
class APIRequest
|
3
|
+
|
4
|
+
def initialize(builder: nil)
|
5
|
+
@request_builder = builder
|
6
|
+
end
|
7
|
+
|
8
|
+
def post(params: nil, headers: nil, format: nil, body: {})
|
9
|
+
validate_api_key
|
10
|
+
begin
|
11
|
+
headers ||= {}
|
12
|
+
if is_multipart?(body)
|
13
|
+
if self.api_auth_method == :base64
|
14
|
+
headers['Authorization'] = "Basic " + Base64::encode64("#{self.api_user_email}:#{self.api_user_password}")
|
15
|
+
end
|
16
|
+
if [:keycloak].include?(self.api_auth_method)
|
17
|
+
unless OklogApi::Request.token_alive?(OklogApi::Request.access_token)
|
18
|
+
if OklogApi::Request.token_alive?(OklogApi::Request.refresh_token)
|
19
|
+
response = OklogApi.refresh_access_token
|
20
|
+
OklogApi::Request.access_token = response.try(:dig, "access_token")
|
21
|
+
OklogApi::Request.refresh_token = response.try(:dig, "refresh_token")
|
22
|
+
else
|
23
|
+
error_params = { title: "UNAUTHORIZED", status_code: 401 }
|
24
|
+
error = OklogApiError.new("Token is unavailable", error_params)
|
25
|
+
raise error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
headers['Authorization'] = "Bearer #{OklogApi::Request.access_token}"
|
29
|
+
end
|
30
|
+
if [:api_key].include?(self.api_auth_method)
|
31
|
+
request.headers['X-Api-Key'] = "#{OklogApi::Request.api_key}"
|
32
|
+
if self.api_user_id.present?
|
33
|
+
request.headers['X-User-Id'] = self.api_user_id.to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
headers['User-Agent'] = "OklogApi/#{OklogApi::VERSION} Ruby gem"
|
37
|
+
headers['Accept-Language'] = OklogApi::Request.language.to_s
|
38
|
+
if @request_builder.without_ratelimit
|
39
|
+
headers['X-Is-Request-Without-RateLimit'] = "true"
|
40
|
+
end
|
41
|
+
if @request_builder.is_allow_access_to_coordinates
|
42
|
+
headers['X-Is-Allow-Access-To-Coordinates'] = "true"
|
43
|
+
end
|
44
|
+
url = URI("#{self.api_url}#{format.present? ? ".#{format}": ""}")
|
45
|
+
http = Net::HTTP.new(url.host, url.port);
|
46
|
+
request = Net::HTTP::Post.new(url, headers)
|
47
|
+
request.set_form body.to_params, 'multipart/form-data'
|
48
|
+
if @request_builder.debug
|
49
|
+
p request
|
50
|
+
end
|
51
|
+
http.request(request)
|
52
|
+
else
|
53
|
+
response = self.rest_client(format).post do |request|
|
54
|
+
configure_request(request: request, params: params, headers: headers, body: body)
|
55
|
+
end
|
56
|
+
if [nil, 'json'].include?(format)
|
57
|
+
parse_response(response)
|
58
|
+
else
|
59
|
+
response
|
60
|
+
end
|
61
|
+
end
|
62
|
+
rescue => e
|
63
|
+
handle_error(e)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get(params: nil, headers: nil, format: nil, body: {})
|
68
|
+
validate_api_key
|
69
|
+
|
70
|
+
begin
|
71
|
+
response = self.rest_client(format).get do |request|
|
72
|
+
configure_request(request: request, params: params, headers: headers, body: body)
|
73
|
+
end
|
74
|
+
if [nil, 'json'].include?(format)
|
75
|
+
parse_response(response)
|
76
|
+
else
|
77
|
+
response
|
78
|
+
end
|
79
|
+
rescue => e
|
80
|
+
handle_error(e)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete(params: nil, headers: nil, format: nil, body: {})
|
85
|
+
validate_api_key
|
86
|
+
begin
|
87
|
+
response = self.rest_client(format).delete do |request|
|
88
|
+
configure_request(request: request, params: params, headers: headers, body: body)
|
89
|
+
end
|
90
|
+
if [nil, 'json'].include?(format)
|
91
|
+
parse_response(response)
|
92
|
+
else
|
93
|
+
response
|
94
|
+
end
|
95
|
+
rescue => e
|
96
|
+
handle_error(e)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def patch(params: nil, headers: nil, format: nil, body: {})
|
101
|
+
validate_api_key
|
102
|
+
begin
|
103
|
+
response = self.rest_client(format).patch do |request|
|
104
|
+
configure_request(request: request, params: params, headers: headers, body: body)
|
105
|
+
end
|
106
|
+
if [nil, 'json'].include?(format)
|
107
|
+
parse_response(response)
|
108
|
+
else
|
109
|
+
response
|
110
|
+
end
|
111
|
+
rescue => e
|
112
|
+
handle_error(e)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def put(params: nil, headers: nil, format: nil, body: {})
|
117
|
+
validate_api_key
|
118
|
+
begin
|
119
|
+
response = self.rest_client(format).put do |request|
|
120
|
+
configure_request(request: request, params: params, headers: headers, body: body)
|
121
|
+
end
|
122
|
+
if [nil, 'json'].include?(format)
|
123
|
+
parse_response(response)
|
124
|
+
else
|
125
|
+
response
|
126
|
+
end
|
127
|
+
rescue => e
|
128
|
+
handle_error(e)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
protected
|
133
|
+
|
134
|
+
# Convenience accessors
|
135
|
+
|
136
|
+
def access_token
|
137
|
+
@request_builder.access_token
|
138
|
+
end
|
139
|
+
|
140
|
+
def refresh_token
|
141
|
+
@request_builder.refresh_token
|
142
|
+
end
|
143
|
+
|
144
|
+
def api_user_id
|
145
|
+
@request_builder.api_user_id
|
146
|
+
end
|
147
|
+
|
148
|
+
def api_key
|
149
|
+
@request_builder.api_key
|
150
|
+
end
|
151
|
+
|
152
|
+
def api_user_email
|
153
|
+
@request_builder.api_user_email
|
154
|
+
end
|
155
|
+
|
156
|
+
def api_user_password
|
157
|
+
@request_builder.api_user_password
|
158
|
+
end
|
159
|
+
|
160
|
+
def api_auth_method
|
161
|
+
@request_builder.api_auth_method
|
162
|
+
end
|
163
|
+
|
164
|
+
def api_endpoint
|
165
|
+
@request_builder.api_endpoint
|
166
|
+
end
|
167
|
+
|
168
|
+
def union_endpoint
|
169
|
+
@request_builder.union_endpoint
|
170
|
+
end
|
171
|
+
|
172
|
+
def notify_endpoint
|
173
|
+
@request_builder.notify_endpoint
|
174
|
+
end
|
175
|
+
|
176
|
+
def timeout
|
177
|
+
@request_builder.timeout
|
178
|
+
end
|
179
|
+
|
180
|
+
def open_timeout
|
181
|
+
@request_builder.open_timeout
|
182
|
+
end
|
183
|
+
|
184
|
+
def proxy
|
185
|
+
@request_builder.proxy
|
186
|
+
end
|
187
|
+
|
188
|
+
def ssl_options
|
189
|
+
@request_builder.ssl_options
|
190
|
+
end
|
191
|
+
|
192
|
+
def adapter
|
193
|
+
@request_builder.faraday_adapter
|
194
|
+
end
|
195
|
+
|
196
|
+
def symbolize_keys
|
197
|
+
@request_builder.symbolize_keys
|
198
|
+
end
|
199
|
+
|
200
|
+
# Helpers
|
201
|
+
|
202
|
+
def handle_error(error)
|
203
|
+
error_params = {}
|
204
|
+
|
205
|
+
begin
|
206
|
+
if error.is_a?(Faraday::ClientError) && error.response
|
207
|
+
error_params[:status_code] = error.response[:status]
|
208
|
+
error_params[:raw_body] = error.response[:body]
|
209
|
+
|
210
|
+
parsed_response = MultiJson.load(error.response[:body], symbolize_keys: symbolize_keys)
|
211
|
+
|
212
|
+
if parsed_response
|
213
|
+
error_params[:body] = parsed_response
|
214
|
+
|
215
|
+
title_key = symbolize_keys ? :title : "title"
|
216
|
+
detail_key = symbolize_keys ? :detail : "detail"
|
217
|
+
|
218
|
+
error_params[:title] = parsed_response[title_key] if parsed_response[title_key]
|
219
|
+
error_params[:detail] = parsed_response[detail_key] if parsed_response[detail_key]
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
rescue MultiJson::ParseError
|
224
|
+
end
|
225
|
+
|
226
|
+
error_to_raise = OklogApiError.new(error.message, error_params)
|
227
|
+
|
228
|
+
raise error_to_raise
|
229
|
+
end
|
230
|
+
|
231
|
+
def configure_request(request: nil, params: nil, headers: nil, body: nil)
|
232
|
+
if request
|
233
|
+
request.params.merge!(params) if params
|
234
|
+
request.headers ||= {}
|
235
|
+
request.headers['Content-Type'] = 'application/json'
|
236
|
+
if self.api_auth_method == :base64
|
237
|
+
request.headers['Authorization'] = "Basic " + Base64::encode64("#{self.api_user_email}:#{self.api_user_password}")
|
238
|
+
end
|
239
|
+
if [:keycloak].include?(self.api_auth_method)
|
240
|
+
unless OklogApi::Request.token_alive?(OklogApi::Request.access_token)
|
241
|
+
if OklogApi::Request.token_alive?(OklogApi::Request.refresh_token)
|
242
|
+
response = OklogApi.refresh_access_token
|
243
|
+
OklogApi::Request.access_token = response.try(:dig, "access_token")
|
244
|
+
OklogApi::Request.refresh_token = response.try(:dig, "refresh_token")
|
245
|
+
else
|
246
|
+
error_params = { title: "UNAUTHORIZED", status_code: 401 }
|
247
|
+
error = OklogApiError.new("Token is unavailable", error_params)
|
248
|
+
raise error
|
249
|
+
end
|
250
|
+
end
|
251
|
+
request.headers['Authorization'] = "Bearer #{OklogApi::Request.access_token}"
|
252
|
+
end
|
253
|
+
if [:api_key].include?(self.api_auth_method)
|
254
|
+
request.headers['X-Api-Key'] = "#{OklogApi::Request.api_key}"
|
255
|
+
if self.api_user_id.present?
|
256
|
+
request.headers['X-User-Id'] = self.api_user_id.to_s
|
257
|
+
end
|
258
|
+
end
|
259
|
+
request.headers['User-Agent'] = "OklogApi/#{OklogApi::VERSION} Ruby gem"
|
260
|
+
request.headers['Accept-Language'] = OklogApi::Request.language.to_s
|
261
|
+
if @request_builder.without_ratelimit
|
262
|
+
request.headers['X-Is-Request-Without-RateLimit'] = "true"
|
263
|
+
end
|
264
|
+
if @request_builder.is_allow_access_to_coordinates
|
265
|
+
request.headers['X-Is-Allow-Access-To-Coordinates'] = "true"
|
266
|
+
end
|
267
|
+
request.headers.merge!(headers) if headers
|
268
|
+
|
269
|
+
request.body = MultiJson.dump(body) if body && request.headers['Content-Type'] == 'application/json'
|
270
|
+
|
271
|
+
request.options.timeout = self.timeout
|
272
|
+
request.options.open_timeout = self.open_timeout
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def is_multipart?(body, result=false)
|
277
|
+
return false if body == {}
|
278
|
+
if body.is_a?(Hash)
|
279
|
+
body.inject({}) do |acc, kv|
|
280
|
+
result = is_multipart?(kv.last, result)
|
281
|
+
end
|
282
|
+
elsif body.is_a?(Array)
|
283
|
+
body.map do |item|
|
284
|
+
result = is_multipart?(item, result)
|
285
|
+
end
|
286
|
+
result
|
287
|
+
elsif [ActionDispatch::Http::UploadedFile, StringIO, Tempfile, File].include?(body.class)
|
288
|
+
return true
|
289
|
+
else
|
290
|
+
result || false
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def rest_client(format=nil)
|
295
|
+
client = Faraday.new("#{self.api_url}#{format.present? ? ".#{format}": ""}", proxy: self.proxy,
|
296
|
+
ssl: self.ssl_options) do |faraday|
|
297
|
+
faraday.request :gzip
|
298
|
+
faraday.response :raise_error
|
299
|
+
faraday.adapter adapter
|
300
|
+
if @request_builder.debug
|
301
|
+
faraday.response :logger, @request_builder.logger, @request_builder.debug_options
|
302
|
+
end
|
303
|
+
end
|
304
|
+
client
|
305
|
+
end
|
306
|
+
|
307
|
+
def parse_response(response)
|
308
|
+
parsed_response = nil
|
309
|
+
|
310
|
+
if response.body && !response.body.empty?
|
311
|
+
begin
|
312
|
+
headers = response.headers
|
313
|
+
body = MultiJson.load(response.body, symbolize_keys: symbolize_keys)
|
314
|
+
parsed_response = Response.new(headers: headers, body: body, status_code: response.env.status)
|
315
|
+
rescue MultiJson::ParseError
|
316
|
+
error_params = { title: "UNPARSEABLE_RESPONSE", status_code: 500 }
|
317
|
+
error = OklogApiError.new("Unparseable response: #{response.body}", error_params)
|
318
|
+
raise error
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
parsed_response
|
323
|
+
end
|
324
|
+
|
325
|
+
def validate_api_key
|
326
|
+
case self.api_auth_method
|
327
|
+
when :api_key
|
328
|
+
unless self.api_key# && self.api_endpoint
|
329
|
+
raise OklogApi::OklogApiError, "You must set an api_key prior to making a call #{self.api_key} #{self.api_endpoint}"
|
330
|
+
end
|
331
|
+
when :base64
|
332
|
+
unless self.api_user_email && self.api_user_password
|
333
|
+
raise OklogApi::OklogApiError, "You must set an api_user_email and an api_user_password prior to making a call #{self.api_user_email} #{self.api_user_password} #{self.api_endpoint}"
|
334
|
+
end
|
335
|
+
when :keycloak
|
336
|
+
unless self.access_token || self.refresh_token
|
337
|
+
raise OklogApi::OklogApiError, "You must set an access_token or a refresh_token prior to making a call #{self.access_token} #{self.refresh_token} #{self.api_endpoint}"
|
338
|
+
end
|
339
|
+
else
|
340
|
+
raise OklogApi::OklogApiError, "You must set an api_auth_method prior to making a call #{self.api_auth_method} #{self.api_endpoint}"
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
def api_url
|
345
|
+
first_path = @request_builder.path_parts.first
|
346
|
+
url = case @request_builder.path_parts.first
|
347
|
+
when "lk"
|
348
|
+
lk_api_url
|
349
|
+
when "notify"
|
350
|
+
notify_api_url
|
351
|
+
when "app"
|
352
|
+
app_api_url
|
353
|
+
when "union"
|
354
|
+
union_api_url
|
355
|
+
else
|
356
|
+
base_api_url
|
357
|
+
end
|
358
|
+
@request_builder.path_parts.shift if %w[union notify].include?(first_path)
|
359
|
+
url + @request_builder.path
|
360
|
+
end
|
361
|
+
|
362
|
+
def base_api_url
|
363
|
+
"#{OklogApi.api_endpoint}/api/v2.0/"
|
364
|
+
end
|
365
|
+
|
366
|
+
def lk_api_url
|
367
|
+
"https://rail-scan.com/"
|
368
|
+
end
|
369
|
+
|
370
|
+
def app_api_url
|
371
|
+
"https://rail-scan.com/"
|
372
|
+
end
|
373
|
+
|
374
|
+
def union_api_url
|
375
|
+
"#{OklogApi.union_endpoint}/api/v1.0/"
|
376
|
+
end
|
377
|
+
|
378
|
+
def notify_api_url
|
379
|
+
"#{OklogApi.notify_endpoint}/"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
class Hash
|
385
|
+
def to_params(namespace = nil)
|
386
|
+
query = []
|
387
|
+
each do |key, value|
|
388
|
+
if value.present?
|
389
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
390
|
+
query += value.to_params(namespace ? "#{namespace}[#{key}]" : key)
|
391
|
+
else
|
392
|
+
query << value.to_params(namespace ? "#{namespace}[#{key}]" : key)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
query
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
class Object
|
401
|
+
def to_params(key)
|
402
|
+
if self.is_a? ActionDispatch::Http::UploadedFile
|
403
|
+
[key.to_param, File.open(self.path),
|
404
|
+
{
|
405
|
+
:filename => self.original_filename,
|
406
|
+
:content_type => self.content_type
|
407
|
+
}
|
408
|
+
]
|
409
|
+
elsif %w[File Tempfile StringIO].include?(self.class.name)
|
410
|
+
self
|
411
|
+
else
|
412
|
+
[key.to_param, to_param.to_s]
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
class Array
|
418
|
+
def to_params(key)
|
419
|
+
prefix = "#{key}[]"
|
420
|
+
|
421
|
+
if empty?
|
422
|
+
nil.to_params(prefix)
|
423
|
+
else
|
424
|
+
collect { |value| value.to_params(prefix) }
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module OklogApi
|
2
|
+
class OklogApiError < StandardError
|
3
|
+
attr_reader :title, :detail, :body, :raw_body, :status_code
|
4
|
+
|
5
|
+
def initialize(message = "", params = {})
|
6
|
+
@title = params[:title]
|
7
|
+
@detail = params[:detail]
|
8
|
+
@body = params[:body]
|
9
|
+
@raw_body = params[:raw_body]
|
10
|
+
@status_code = params[:status_code]
|
11
|
+
|
12
|
+
super(message)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
super + " " + instance_variables_to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def instance_variables_to_s
|
22
|
+
[:title, :detail, :body, :raw_body, :status_code].map do |attr|
|
23
|
+
attr_value = send(attr)
|
24
|
+
|
25
|
+
"@#{attr}=#{attr_value.inspect}"
|
26
|
+
end.join(", ")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module OklogApi
|
2
|
+
class Request
|
3
|
+
attr_accessor :access_token, :refresh_token, :api_user_id, :api_key, :api_user_email, :api_user_password,
|
4
|
+
:api_auth_method, :api_endpoint, :union_endpoint, :notify_endpoint,
|
5
|
+
:timeout, :open_timeout, :proxy, :ssl_options, :faraday_adapter, :symbolize_keys, :debug, :debug_options,
|
6
|
+
:without_ratelimit, :is_allow_access_to_coordinates, :logger, :test, :language
|
7
|
+
|
8
|
+
AUTH_METHODS = [:keycloak, :api_key, :base64]
|
9
|
+
DEFAULT_AUTH_METHOD = :api_key
|
10
|
+
DEFAULT_TIMEOUT = 60
|
11
|
+
DEFAULT_OPEN_TIMEOUT = 60
|
12
|
+
DEFAULT_LANGUAGE = :ru
|
13
|
+
|
14
|
+
def initialize(access_token: nil, refresh_token: nil, api_user_id: nil, api_key: nil, api_user_email: nil, api_user_password: nil,
|
15
|
+
api_endpoint: nil, union_endpoint: nil, api_auth_method: nil, timeout: nil, open_timeout: nil, proxy: nil, ssl_options: nil,
|
16
|
+
faraday_adapter: nil, symbolize_keys: false, debug: false,
|
17
|
+
debug_options: { headers: true, bodies: false, errors: false, log_level: :info },
|
18
|
+
without_ratelimit: false, is_allow_access_to_coordinates: false,
|
19
|
+
logger: nil, test: false, language: DEFAULT_LANGUAGE)
|
20
|
+
|
21
|
+
@path_parts = []
|
22
|
+
@api_key = api_key || self.class.api_key || ENV['RAIL_LOCATOR_API_KEY']
|
23
|
+
@api_key = @api_key.strip if @api_key
|
24
|
+
|
25
|
+
@api_user_id = api_user_id
|
26
|
+
|
27
|
+
if @api_key == :keycloak
|
28
|
+
@access_token = access_token || self.class.access_token || OklogApi.generate_access_token.try(:dig, "access_token")
|
29
|
+
@access_token = @access_token.strip if @access_token
|
30
|
+
@refresh_token = refresh_token || self.class.refresh_token
|
31
|
+
@refresh_token = @refresh_token.strip if @refresh_token
|
32
|
+
else
|
33
|
+
@access_token = ""
|
34
|
+
@refresh_token = ""
|
35
|
+
end
|
36
|
+
|
37
|
+
@api_user_email = api_user_email || ENV['API_USER_EMAIL'] || ""
|
38
|
+
@api_user_password = api_user_password || ENV['API_USER_PASSWORD'] || ""
|
39
|
+
|
40
|
+
@api_endpoint = api_endpoint || self.class.api_endpoint
|
41
|
+
@api_endpoint = OklogApi::api_endpoint if @api_endpoint.nil?
|
42
|
+
@union_endpoint = union_endpoint || self.class.union_endpoint
|
43
|
+
@union_endpoint = OklogApi::union_endpoint if @union_endpoint.nil?
|
44
|
+
|
45
|
+
@api_auth_method = api_auth_method || OklogApi::api_auth_method || DEFAULT_AUTH_METHOD
|
46
|
+
@timeout = timeout || self.class.timeout || DEFAULT_TIMEOUT
|
47
|
+
@open_timeout = open_timeout || self.class.open_timeout || DEFAULT_OPEN_TIMEOUT
|
48
|
+
@proxy = proxy || self.class.proxy || ENV['RAIL_LOCATOR_API_PROXY']
|
49
|
+
@ssl_options = ssl_options || self.class.ssl_options || { version: "TLSv1_2" }
|
50
|
+
@faraday_adapter = faraday_adapter || self.class.faraday_adapter || Faraday.default_adapter
|
51
|
+
@symbolize_keys = symbolize_keys || self.class.symbolize_keys || false
|
52
|
+
@debug = debug || self.class.debug || false
|
53
|
+
@debug_options = debug_options || self.class.debug_options || { headers: true, bodies: false, errors: false, log_level: :info }
|
54
|
+
@without_ratelimit = without_ratelimit || self.class.without_ratelimit
|
55
|
+
@is_allow_access_to_coordinates = is_allow_access_to_coordinates || self.class.is_allow_access_to_coordinates
|
56
|
+
@test = test || self.class.test || false
|
57
|
+
@language = language || DEFAULT_LANGUAGE
|
58
|
+
@logger = logger || self.class.logger || ::Logger.new(STDOUT)
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing(method, *args)
|
62
|
+
@path_parts << method.to_s.downcase
|
63
|
+
@path_parts << args if args.length > 0
|
64
|
+
@path_parts.flatten!
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def respond_to_missing?(method_name, include_private = false)
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def send(*args)
|
73
|
+
if args.length == 0
|
74
|
+
method_missing(:send, args)
|
75
|
+
else
|
76
|
+
__send__(*args)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def path_parts
|
81
|
+
@path_parts
|
82
|
+
end
|
83
|
+
|
84
|
+
def path
|
85
|
+
@path_parts.join('/')
|
86
|
+
end
|
87
|
+
|
88
|
+
def create(params: nil, headers: nil, body: {}, format: nil)
|
89
|
+
APIRequest.new(builder: self).post(params: params, headers: headers, body: body, format: format)
|
90
|
+
ensure
|
91
|
+
reset
|
92
|
+
end
|
93
|
+
|
94
|
+
def update(params: nil, headers: nil, body: {}, format: nil)
|
95
|
+
APIRequest.new(builder: self).patch(params: params, headers: headers, body: body, format: format)
|
96
|
+
ensure
|
97
|
+
reset
|
98
|
+
end
|
99
|
+
|
100
|
+
def insert(params: nil, headers: nil, body: {}, format: nil)
|
101
|
+
APIRequest.new(builder: self).put(params: params, headers: headers, body: body, format: format)
|
102
|
+
ensure
|
103
|
+
reset
|
104
|
+
end
|
105
|
+
|
106
|
+
def retrieve(params: nil, headers: nil, body: {}, format: nil)
|
107
|
+
APIRequest.new(builder: self).get(params: params, headers: headers, body: body, format: format)
|
108
|
+
ensure
|
109
|
+
reset
|
110
|
+
end
|
111
|
+
|
112
|
+
def delete(params: nil, headers: nil, body: {})
|
113
|
+
APIRequest.new(builder: self).delete(params: params, headers: headers, body: body)
|
114
|
+
ensure
|
115
|
+
reset
|
116
|
+
end
|
117
|
+
|
118
|
+
def token_alive?(token, jwt_secret_code=OklogApi.keycloak_client_secret)
|
119
|
+
begin
|
120
|
+
return false if token.nil?
|
121
|
+
exp = JWT.decode(token, jwt_secret_code, false).try(:first).try(:dig, "exp")
|
122
|
+
return false if exp.nil?
|
123
|
+
Time.at(exp) > Time.now + 30.second
|
124
|
+
rescue => e
|
125
|
+
#Sentry.capture_exception(e)
|
126
|
+
false
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
protected
|
131
|
+
|
132
|
+
def reset
|
133
|
+
@path_parts = []
|
134
|
+
end
|
135
|
+
|
136
|
+
class << self
|
137
|
+
attr_accessor :access_token, :refresh_token, :api_user_id, :api_key, :api_user_email, :api_user_password, :api_auth_method,
|
138
|
+
:timeout, :open_timeout, :api_endpoint, :union_endpoint, :notify_endpoint,
|
139
|
+
:proxy, :ssl_options, :faraday_adapter, :symbolize_keys,
|
140
|
+
:debug, :debug_options, :without_ratelimit, :is_allow_access_to_coordinates, :logger, :test, :language
|
141
|
+
|
142
|
+
def method_missing(sym, *args, &block)
|
143
|
+
new(access_token: self.access_token, refresh_token: self.refresh_token,
|
144
|
+
api_user_id: self.api_user_id,
|
145
|
+
api_key: self.api_key,
|
146
|
+
api_user_email: self.api_user_email, api_user_password: self.api_user_password,
|
147
|
+
api_auth_method: self.api_auth_method, api_endpoint: self.api_endpoint, union_endpoint: self.union_endpoint,
|
148
|
+
timeout: self.timeout, open_timeout: self.open_timeout, faraday_adapter: self.faraday_adapter,
|
149
|
+
symbolize_keys: self.symbolize_keys, debug: self.debug, debug_options: self.debug_options,
|
150
|
+
without_ratelimit: self.without_ratelimit,
|
151
|
+
is_allow_access_to_coordinates: self.is_allow_access_to_coordinates,
|
152
|
+
proxy: self.proxy, ssl_options: self.ssl_options, logger: self.logger,
|
153
|
+
test: self.test, language: self.language).send(sym, *args, &block)
|
154
|
+
end
|
155
|
+
|
156
|
+
def respond_to_missing?(method_name, include_private = false)
|
157
|
+
true
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/oklog-api.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday/gzip'
|
3
|
+
require 'net/http/post/multipart'
|
4
|
+
require 'multi_json'
|
5
|
+
require 'oklog-api/version'
|
6
|
+
require 'oklog-api/oklog_api_error'
|
7
|
+
require 'oklog-api/request'
|
8
|
+
require 'oklog-api/api_request'
|
9
|
+
require 'oklog-api/response'
|
10
|
+
|
11
|
+
module OklogApi
|
12
|
+
class << self
|
13
|
+
def generate_access_token(code=nil)
|
14
|
+
if OklogApi.keycloak_grant_type == "password"
|
15
|
+
payload = "grant_type=#{OklogApi.keycloak_grant_type}&client_id=#{OklogApi.keycloak_client_id}&username=#{OklogApi.api_user_email}&password=#{OklogApi.api_user_password}"
|
16
|
+
else
|
17
|
+
payload = "grant_type=#{OklogApi.keycloak_grant_type}&client_id=#{OklogApi.keycloak_client_id}&client_secret=#{OklogApi.keycloak_client_secret}&code=#{code ||OklogApi::Request.access_token}&redirect_uri=#{OklogApi.keycloak_redirect_uri}"
|
18
|
+
end
|
19
|
+
connection = Faraday.new(OklogApi.keycloak_token_url, proxy: nil,
|
20
|
+
ssl: OklogApi::Request.ssl_options || { version: "TLSv1_2" }) do |faraday|
|
21
|
+
faraday.adapter Faraday.default_adapter
|
22
|
+
faraday.response :logger, ::Logger.new(STDOUT), bodies: true
|
23
|
+
end
|
24
|
+
|
25
|
+
response = connection.post OklogApi.keycloak_token_url, payload do |request|
|
26
|
+
request.headers['accept'] = 'application/json'
|
27
|
+
end
|
28
|
+
|
29
|
+
JSON.parse(response.body)
|
30
|
+
end
|
31
|
+
|
32
|
+
def refresh_access_token
|
33
|
+
payload = "grant_type=refresh_token&client_id=#{OklogApi.keycloak_client_id}&client_secret=#{OklogApi.keycloak_client_secret}&refresh_token=#{OklogApi::Request.refresh_token}&redirect_uri=#{OklogApi.keycloak_redirect_uri}"
|
34
|
+
connection = Faraday.new(OklogApi.keycloak_token_url, proxy: nil,
|
35
|
+
ssl: OklogApi::Request.ssl_options || { version: "TLSv1_2" }) do |faraday|
|
36
|
+
faraday.adapter Faraday.default_adapter
|
37
|
+
faraday.response :logger, ::Logger.new(STDOUT), bodies: true
|
38
|
+
end
|
39
|
+
|
40
|
+
response = connection.post OklogApi.keycloak_token_url, payload do |request|
|
41
|
+
request.headers['accept'] = 'application/json'
|
42
|
+
end
|
43
|
+
|
44
|
+
JSON.parse(response.body)
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup
|
48
|
+
yield self
|
49
|
+
end
|
50
|
+
|
51
|
+
def register(name, value, type = nil)
|
52
|
+
cattr_accessor "#{name}_setting".to_sym
|
53
|
+
|
54
|
+
add_reader(name)
|
55
|
+
add_writer(name, type)
|
56
|
+
send "#{name}=", value
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_reader(name)
|
60
|
+
define_singleton_method(name) do |*args|
|
61
|
+
send("#{name}_setting").value(*args)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_writer(name, type)
|
66
|
+
define_singleton_method("#{name}=") do |value|
|
67
|
+
send("#{name}_setting=", DynamicSetting.build(value, type))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class DynamicSetting
|
73
|
+
def self.build(setting, type)
|
74
|
+
(type ? klass(type) : self).new(setting)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.klass(type)
|
78
|
+
klass = "#{type.to_s.camelcase}Setting"
|
79
|
+
raise ArgumentError, "Unknown type: #{type}" unless OklogApi.const_defined?(klass)
|
80
|
+
OklogApi.const_get(klass)
|
81
|
+
end
|
82
|
+
|
83
|
+
def initialize(setting)
|
84
|
+
@setting = setting
|
85
|
+
end
|
86
|
+
|
87
|
+
def value(*_args)
|
88
|
+
@setting
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oklog-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pavel Osetrov
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-07-25 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: faraday
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 2.0.0
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 2.0.0
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: faraday-gzip
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.1.0
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: multi_json
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.11.0
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.11.0
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: irb
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.3.6
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.3.6
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: jwt
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: multipart-post
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :runtime
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: psych
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 4.0.0
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 4.0.0
|
110
|
+
description: ''
|
111
|
+
email: p.osetrov@daobit.ru
|
112
|
+
executables: []
|
113
|
+
extensions: []
|
114
|
+
extra_rdoc_files: []
|
115
|
+
files:
|
116
|
+
- LICENSE
|
117
|
+
- README.markdown
|
118
|
+
- lib/generators/oklog_api/install/USAGE
|
119
|
+
- lib/generators/oklog_api/install/install_generator.rb
|
120
|
+
- lib/generators/oklog_api/install/templates/oklog_api.rb
|
121
|
+
- lib/generators/oklog_api/install/templates/oklog_api.yml
|
122
|
+
- lib/oklog-api.rb
|
123
|
+
- lib/oklog-api/api_request.rb
|
124
|
+
- lib/oklog-api/rail_locator_api_error.rb
|
125
|
+
- lib/oklog-api/request.rb
|
126
|
+
- lib/oklog-api/response.rb
|
127
|
+
- lib/oklog-api/version.rb
|
128
|
+
homepage: https://oklog.ru
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '2.5'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubygems_version: 3.6.3
|
147
|
+
specification_version: 4
|
148
|
+
summary: OkLog API
|
149
|
+
test_files: []
|