razorrisk-cassini-common 0.26.24
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/CHANGELOG.md +22 -0
- data/LICENSE +5 -0
- data/README.md +2 -0
- data/Rakefile +102 -0
- data/lib/razor_risk/cassini/applications/microservice.rb +318 -0
- data/lib/razor_risk/cassini/applications/rest_framework/route_verb_dispatcher.rb +120 -0
- data/lib/razor_risk/cassini/applications/rest_framework/verb_handler.rb +117 -0
- data/lib/razor_risk/cassini/applications/route_verb_adaptors/utilities/collection_get_helper.rb +86 -0
- data/lib/razor_risk/cassini/applications/securable_microservice.rb +164 -0
- data/lib/razor_risk/cassini/applications/secured_microservice.rb +63 -0
- data/lib/razor_risk/cassini/applications/unsecured_microservice.rb +77 -0
- data/lib/razor_risk/cassini/authorisation/header_helpers.rb +271 -0
- data/lib/razor_risk/cassini/authorisation/security_model_helpers.rb +93 -0
- data/lib/razor_risk/cassini/authorisation.rb +27 -0
- data/lib/razor_risk/cassini/cli.rb +19 -0
- data/lib/razor_risk/cassini/common/version.rb +44 -0
- data/lib/razor_risk/cassini/common.rb +32 -0
- data/lib/razor_risk/cassini/constants.rb +68 -0
- data/lib/razor_risk/cassini/diagnostics/util_functions.rb +248 -0
- data/lib/razor_risk/cassini/diagnostics/zeroth_include.rb +35 -0
- data/lib/razor_risk/cassini/extensions/libclimate/common_options.rb +267 -0
- data/lib/razor_risk/cassini/extensions/libclimate.rb +26 -0
- data/lib/razor_risk/cassini/header_functions.rb +59 -0
- data/lib/razor_risk/cassini/main.rb +238 -0
- data/lib/razor_risk/cassini/mixin/razor_response_validator.rb +176 -0
- data/lib/razor_risk/cassini/testing/suppress_pantheios_logging.rb +31 -0
- data/lib/razor_risk/cassini/util/conversion_util.rb +176 -0
- data/lib/razor_risk/cassini/util/program_execution_util.rb +379 -0
- data/lib/razor_risk/cassini/util/secrets_util.rb +229 -0
- data/lib/razor_risk/cassini/util/version_util.rb +88 -0
- data/lib/razor_risk/sinatra/helpers/check_auth_helper.rb +209 -0
- data/lib/razor_risk/sinatra/helpers/validate_accept_helper.rb +69 -0
- data/lib/razor_risk/sinatra/helpers/validate_content_type_helper.rb +74 -0
- data/lib/razor_risk/sinatra/helpers/validate_query_parameters_helper.rb +198 -0
- data/test/scratch/cassini/util/convert_XML.rb +54 -0
- data/test/unit/applications/route_verb_adaptors/utilities/tc_collection_get_helper.rb +236 -0
- data/test/unit/applications/tc_verb_handler.rb +130 -0
- data/test/unit/mixin/tc_razor_response_validator.rb +328 -0
- data/test/unit/sinatra/helpers/tc_validate_query_parameters_helper.rb +134 -0
- data/test/unit/tc_authorisation_util.rb +265 -0
- data/test/unit/tc_load_secrets.rb +95 -0
- data/test/unit/util/tc_conversion_util.rb +393 -0
- data/test/unit/util/tc_program_execution_util.rb +462 -0
- metadata +380 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 236c6282305896273a4ec80db78f5455c862c718
|
4
|
+
data.tar.gz: 64be38f9a5b4f4f5ab54d0c0cea21b1166cffe3f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cb2d95a8efe4270026d02f125f237dde0c2eef7865d1e94a0dc84927b3f1393b1e0bfe7803f7f56ba528b6f0a521a3997e618c0b622e5c2c99f22cab619e0cfc
|
7
|
+
data.tar.gz: b361155b9cf118c9de9af6694945384a55e40909eb2165cbff17e44366446a184aee2d44bf6f4163a30ee197953d0a3cd423641225e09b747776c68559052adf
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
## [0.18.1] (2018-06-20)
|
4
|
+
|
5
|
+
**Implemented enhancements:**
|
6
|
+
|
7
|
+
none
|
8
|
+
|
9
|
+
**Fixed defects:**
|
10
|
+
|
11
|
+
none
|
12
|
+
|
13
|
+
**Dependencies and packaging:**
|
14
|
+
|
15
|
+
- separated into own project/repo/package [WEBAPI-138]
|
16
|
+
|
17
|
+
**Merged pull requests:**
|
18
|
+
|
19
|
+
none
|
20
|
+
|
21
|
+
## END OF CHANGE LOG
|
22
|
+
|
data/LICENSE
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# ######################################################################## #
|
5
|
+
#
|
6
|
+
# Copyright (c) 2019 Razor Risk Technologies Pty Limited. All rights reserved.
|
7
|
+
#
|
8
|
+
# ######################################################################## #
|
9
|
+
|
10
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
11
|
+
|
12
|
+
|
13
|
+
# ##########################################################
|
14
|
+
# bundler
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
require 'bundler/setup'
|
18
|
+
|
19
|
+
|
20
|
+
# ######################################################################## #
|
21
|
+
# requires
|
22
|
+
|
23
|
+
require 'razor_risk/razor/control/rake_helpers/diagnostic_tasks'
|
24
|
+
require 'razor_risk/razor/control/rake_helpers/gem_tasks'
|
25
|
+
require 'razor_risk/razor/control/rake_helpers/task_helpers'
|
26
|
+
|
27
|
+
require 'rake'
|
28
|
+
require 'rake/clean'
|
29
|
+
|
30
|
+
|
31
|
+
# ##########################################################
|
32
|
+
# includes
|
33
|
+
|
34
|
+
include ::RazorRisk::Razor::Control
|
35
|
+
include ::Pantheios
|
36
|
+
|
37
|
+
|
38
|
+
# ##########################################################
|
39
|
+
# Constants
|
40
|
+
|
41
|
+
Spec = ::Gem::Specification.load(Dir['*.gemspec'].first)
|
42
|
+
LogDir = 'log'
|
43
|
+
LogThresholds = [ :informational, :informational ]
|
44
|
+
|
45
|
+
|
46
|
+
# ##########################################################
|
47
|
+
# clean/clobber
|
48
|
+
|
49
|
+
Dir[
|
50
|
+
'log',
|
51
|
+
'doc',
|
52
|
+
'test/reports',
|
53
|
+
].each { |f| CLEAN << f }
|
54
|
+
Dir[
|
55
|
+
'.bundle',
|
56
|
+
'vendor',
|
57
|
+
'GEM_HOME',
|
58
|
+
'*.gem',
|
59
|
+
'*.zip',
|
60
|
+
].each { |f| CLOBBER << f }
|
61
|
+
|
62
|
+
|
63
|
+
# ##########################################################
|
64
|
+
# Tasks
|
65
|
+
|
66
|
+
desc 'Run tests'
|
67
|
+
task :test => [ :'gem:unit_test' ]
|
68
|
+
|
69
|
+
desc 'Build gem'
|
70
|
+
task :build_gem, [ :path ] => :'gem:build'
|
71
|
+
|
72
|
+
desc 'Builds the Razor EntityConnector Gem'
|
73
|
+
task :build, [ :path ] => [
|
74
|
+
:build_gem,
|
75
|
+
]
|
76
|
+
|
77
|
+
desc 'Push the gem to the gem server.'
|
78
|
+
task :deploy => :'gem:push'
|
79
|
+
|
80
|
+
|
81
|
+
# ##########################################################
|
82
|
+
# Hooks
|
83
|
+
|
84
|
+
task :default do
|
85
|
+
puts 'Run \'bundler exec rake --tasks\' to see available tasks'
|
86
|
+
end
|
87
|
+
|
88
|
+
task :first do
|
89
|
+
::Rake::Task[:'diagnostics:init'].execute(
|
90
|
+
name: Spec.name,
|
91
|
+
version: Spec.version.to_s,
|
92
|
+
directory: LogDir,
|
93
|
+
thresholds: LogThresholds,
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
RakeHelpers::TaskHelpers.add_hooks
|
98
|
+
|
99
|
+
|
100
|
+
# ############################## end of file ############################# #
|
101
|
+
|
102
|
+
|
@@ -0,0 +1,318 @@
|
|
1
|
+
|
2
|
+
#############################################################################
|
3
|
+
# File: lib/razor_risk/cassini/applications/microservice.rb
|
4
|
+
#
|
5
|
+
# Purpose: Define the Microservice base class
|
6
|
+
#
|
7
|
+
# Author: Matthew Wilson
|
8
|
+
#
|
9
|
+
# Copyright (c) 2017, Razor Risk Technologies Pty Ltd
|
10
|
+
# All rights reserved
|
11
|
+
#
|
12
|
+
# ##########################################################################
|
13
|
+
|
14
|
+
|
15
|
+
require 'pantheios'
|
16
|
+
require 'xqsr3/quality/parameter_checking'
|
17
|
+
|
18
|
+
require 'razor_risk/cassini/constants'
|
19
|
+
|
20
|
+
require 'razor_risk/sinatra/helpers/validate_accept_helper'
|
21
|
+
require 'razor_risk/sinatra/helpers/validate_content_type_helper'
|
22
|
+
require 'razor_risk/sinatra/helpers/validate_query_parameters_helper'
|
23
|
+
require 'razor_risk/core/diagnostics/logger'
|
24
|
+
|
25
|
+
require 'sinatra/base'
|
26
|
+
|
27
|
+
require 'socket'
|
28
|
+
|
29
|
+
module RazorRisk
|
30
|
+
module Cassini
|
31
|
+
module Applications
|
32
|
+
|
33
|
+
# Common base-class for all microservices
|
34
|
+
#
|
35
|
+
# === Notable features:
|
36
|
+
# - provide class attribute +full_description+, which assumes the deriving
|
37
|
+
# class has defined the constants +FULL_DESIGNATION+ +SERVICE_TYPE+ and
|
38
|
+
# +SHORT_DESIGNATION+, that obtains a human-readable "full Cassini'
|
39
|
+
# service description
|
40
|
+
# - provides class method +init_base_service+ that is used to initialise the
|
41
|
+
# microservice class. It must be called within a class initialiser of a
|
42
|
+
# derived class
|
43
|
+
# - provides class method +run!+ that ensures class initialisation (by a
|
44
|
+
# derived microservice class) has been performed
|
45
|
+
# - provides global 'before' handler that:
|
46
|
+
# * trace
|
47
|
+
# * log of request details
|
48
|
+
# * before handle that:
|
49
|
+
# + sets 'Content-Type' to 'text/plain'
|
50
|
+
#
|
51
|
+
#
|
52
|
+
class Microservice < ::Sinatra::Base
|
53
|
+
|
54
|
+
include ::Xqsr3::Quality::ParameterChecking
|
55
|
+
include ::RazorRisk::Core::Diagnostics::Logger
|
56
|
+
|
57
|
+
helpers ::RazorRisk::Sinatra::Helpers::ValidateAcceptHelper
|
58
|
+
helpers ::RazorRisk::Sinatra::Helpers::ValidateContentTypeHelper
|
59
|
+
helpers ::RazorRisk::Sinatra::Helpers::ValidateQueryParametersHelper
|
60
|
+
|
61
|
+
private
|
62
|
+
def self.to_nil *a; end
|
63
|
+
def to_nil *a; end
|
64
|
+
|
65
|
+
def self.init_base_service_ \
|
66
|
+
host,
|
67
|
+
port,
|
68
|
+
options
|
69
|
+
|
70
|
+
trace
|
71
|
+
|
72
|
+
# Will raise Errno::EADDRINUSE if port is in use
|
73
|
+
TCPServer.new(host, port).close
|
74
|
+
|
75
|
+
# Default to 'production' rather than 'development' (default from
|
76
|
+
# Sinatra. 'APP_ENV' is a Sinatra environment variable that needs to
|
77
|
+
# be checked first (note this isn't introduced to Sinatra until 2.0).
|
78
|
+
if ENV['APP_ENV']
|
79
|
+
set :environment, ENV['APP_ENV']
|
80
|
+
elsif $DEBUG or Constants::RZ_EXPOSE_MICROSERVICE_EXCEPTIONS
|
81
|
+
set :environment, 'development'
|
82
|
+
else
|
83
|
+
set :environment, 'production'
|
84
|
+
end
|
85
|
+
|
86
|
+
# Call error handlers even in testing.
|
87
|
+
configure :test do
|
88
|
+
set :show_exceptions, :after_handler
|
89
|
+
end
|
90
|
+
|
91
|
+
# Call error handlers even in development.
|
92
|
+
configure :development do
|
93
|
+
set :show_exceptions, :after_handler
|
94
|
+
end
|
95
|
+
|
96
|
+
configure :production do
|
97
|
+
|
98
|
+
# Don't print the stack trace to the console.
|
99
|
+
disable :dump_errors
|
100
|
+
|
101
|
+
# Error handler for all uncaught exceptions when in production.
|
102
|
+
error Exception do
|
103
|
+
x = env['sinatra.error']
|
104
|
+
log :violation, "unexpected exception (#{x.class}): '#{x}'"
|
105
|
+
error 500, "Oops! Something went wrong!"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
set :bind, host unless host.nil?
|
110
|
+
set :port, port
|
111
|
+
set :server, options[:web_server] if options[:web_server]
|
112
|
+
|
113
|
+
if options[:tls_certificate_file]
|
114
|
+
|
115
|
+
cts = {
|
116
|
+
|
117
|
+
certificate_file: options[:tls_certificate_file],
|
118
|
+
public_key_file: options[:tls_public_key_file],
|
119
|
+
}
|
120
|
+
|
121
|
+
set :cassini_tls_settings, cts
|
122
|
+
end
|
123
|
+
|
124
|
+
set :microservice_base_is_initialised, Time.now
|
125
|
+
|
126
|
+
if self.respond_to? :on_init_service
|
127
|
+
|
128
|
+
self.on_init_service options
|
129
|
+
end
|
130
|
+
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
public
|
135
|
+
|
136
|
+
# Provides a full description of an including type, which must have the
|
137
|
+
# constants +FULL_DESIGNATION+, +SERVICE_TYPE+, and +SHORT_DESIGNATION+.
|
138
|
+
def self.full_description
|
139
|
+
|
140
|
+
"#{self::FULL_DESIGNATION} #{self::SERVICE_TYPE.to_s.capitalize} (#{self::SHORT_DESIGNATION})"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Defines catch-all handlers for all available verbs
|
144
|
+
#
|
145
|
+
# Unless given a block, it will create catch-all handlers with a basic
|
146
|
+
# message and obtaining a 404. If a block given, it will be invoked with
|
147
|
+
# two parameters - the method name symbol and an options hash within
|
148
|
+
# which are the options +:env+, +:params+, +:request+, and +:response+ -
|
149
|
+
# and should return an array consisting of the HTTP status code and the
|
150
|
+
# body message.
|
151
|
+
#
|
152
|
+
# NOTE: Must be the last component defining the application!
|
153
|
+
def self.define_catch_all_handlers
|
154
|
+
|
155
|
+
methods = %i(delete get head link options patch post put unlink)
|
156
|
+
|
157
|
+
if block_given?
|
158
|
+
|
159
|
+
methods.each do |method|
|
160
|
+
|
161
|
+
send method, // do
|
162
|
+
|
163
|
+
yield method, env: env, params: params, request: request, response: response
|
164
|
+
end
|
165
|
+
end
|
166
|
+
else
|
167
|
+
|
168
|
+
methods.each do |method|
|
169
|
+
|
170
|
+
send method, // do
|
171
|
+
|
172
|
+
[ 404, "'#{env['PATH_INFO']}' [#{method.to_s.upcase}] not found" ]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# This must be invoked prior to activation of the application
|
179
|
+
#
|
180
|
+
# === Signature
|
181
|
+
#
|
182
|
+
# * *Parameters:*
|
183
|
+
# - +host+:: [String] The host to which the application binds. May be:
|
184
|
+
# +nil+, in which case no binding is performed and the Sinatra
|
185
|
+
# defaults are observed; +'0.0.0.0', in which case the server will
|
186
|
+
# listen on all available interfaces; a specific IP addres, in which
|
187
|
+
# case the server will listen only on that address. It is recommend
|
188
|
+
# that a specific address is used. Required
|
189
|
+
# - +port+:: [Integer] The port on which to activate. Required
|
190
|
+
def self.init_base_service \
|
191
|
+
host: to_nil(host_not_given_ = true),
|
192
|
+
port: to_nil(port_not_given_ = true),
|
193
|
+
**options
|
194
|
+
|
195
|
+
trace ParamNames[ :host, :port, :options ], host, port, options
|
196
|
+
|
197
|
+
raise ArgumentError, 'missing keyword: host' if host_not_given_
|
198
|
+
|
199
|
+
raise ArgumentError, 'missing keyword: port' if port_not_given_
|
200
|
+
check_parameter port, 'port', type: Integer
|
201
|
+
|
202
|
+
init_base_service_ host, port, options
|
203
|
+
end
|
204
|
+
|
205
|
+
# Refinement of +::Sinatra::Base.run!+ that ensures that the
|
206
|
+
# microservice class has been initialised
|
207
|
+
def self.run!(options = {}, &block)
|
208
|
+
|
209
|
+
trace
|
210
|
+
|
211
|
+
# TODO: Change this to use proper exception
|
212
|
+
unless settings.respond_to?(:microservice_is_initialised) &&
|
213
|
+
settings.respond_to?(:microservice_base_is_initialised)
|
214
|
+
|
215
|
+
raise ArgumentError, "#{self} microservice application class is not initialised. Must first call #{self}.init_service()"
|
216
|
+
end
|
217
|
+
|
218
|
+
# Configures settings in backend service (e.g. thin, webrick)
|
219
|
+
begin
|
220
|
+
|
221
|
+
super do |server|
|
222
|
+
|
223
|
+
# Set the timeout for the backend service. This prevents thin
|
224
|
+
# from closing connections
|
225
|
+
server.timeout = nil if server.respond_to? :timeout
|
226
|
+
|
227
|
+
# This configures ssl in the backend service, which must be
|
228
|
+
# thin.
|
229
|
+
if settings.respond_to? :cassini_tls_settings
|
230
|
+
|
231
|
+
cts = settings.cassini_tls_settings
|
232
|
+
ssl_opts = {
|
233
|
+
|
234
|
+
cert_chain_file: cts[:tls_certificate_file],
|
235
|
+
private_key_file: cts[:tls_private_key_file],
|
236
|
+
verify_peer: false,
|
237
|
+
}
|
238
|
+
server.ssl = true
|
239
|
+
server.ssl_options = ssl_opts
|
240
|
+
end
|
241
|
+
end
|
242
|
+
rescue ::ArgumentError, ::NameError, ::NoMethodError, ::TypeError => x
|
243
|
+
|
244
|
+
log :violation, "unexpected exception (#{x.class}): '#{x.message}': #{x.backtrace}"
|
245
|
+
raise
|
246
|
+
rescue => x
|
247
|
+
|
248
|
+
log :alert, "exception (#{x.class}): '#{x.message}': #{x.backtrace}"
|
249
|
+
raise
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
before do
|
254
|
+
|
255
|
+
trace
|
256
|
+
|
257
|
+
# benchmarking (if enabled)
|
258
|
+
|
259
|
+
@before_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_ = Time.now if severity_logged? :benchmark
|
260
|
+
|
261
|
+
# log the request information
|
262
|
+
|
263
|
+
log :informational, 'handling ', request.path_info, ' [', request.request_method, ']'
|
264
|
+
|
265
|
+
if severity_logged? :debug2
|
266
|
+
|
267
|
+
prefix = ?\t
|
268
|
+
|
269
|
+
e = env.map { |k, v| "#{prefix}'#{k}' : '#{v}'" }.sort.join("\n")
|
270
|
+
|
271
|
+
log :debug2, "ENV for #{request.path_info} [#{request.request_method}] :\n#{e}"
|
272
|
+
end
|
273
|
+
|
274
|
+
if severity_logged? :debug3
|
275
|
+
|
276
|
+
request.body.rewind
|
277
|
+
|
278
|
+
b = request.body.read.strip
|
279
|
+
|
280
|
+
request.body.rewind
|
281
|
+
|
282
|
+
log :debug3, "body for #{request.path_info} [#{request.request_method}] :", b.empty? ? 'no body' : ?\n + b
|
283
|
+
end
|
284
|
+
|
285
|
+
# general (shared) logical actions
|
286
|
+
|
287
|
+
# by default, all handlers return 'text/plain'
|
288
|
+
content_type 'text/plain'
|
289
|
+
end
|
290
|
+
|
291
|
+
after do
|
292
|
+
|
293
|
+
trace
|
294
|
+
|
295
|
+
log :informational, 'handled ', request.path_info, ' [', request.request_method, ']'
|
296
|
+
|
297
|
+
# benchmarking (if enabled)
|
298
|
+
|
299
|
+
if @before_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_ && severity_logged?(:benchmark)
|
300
|
+
|
301
|
+
after_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_ = Time.now
|
302
|
+
|
303
|
+
delta_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_ = after_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_ - @before_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_
|
304
|
+
delta_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_ *= 1000
|
305
|
+
|
306
|
+
log :benchmark, "execution of HTTP(S) request - '#{request.path_info}' - (in #{self.class}): dt=#{delta_time_01dd7eef998dwfh_23hfsdfh_777_ashdf732bf_}ms"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
end # class Microservice
|
311
|
+
|
312
|
+
end # module Applications
|
313
|
+
end # module Cassini
|
314
|
+
end # module RazorRisk
|
315
|
+
|
316
|
+
# ############################## end of file ############################# #
|
317
|
+
|
318
|
+
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# ######################################################################## #
|
4
|
+
# File: razor_risk/cassini/applications/rest_framework/route_verb_dispatcher.rb
|
5
|
+
#
|
6
|
+
# Purpose: Adaptor for Portfolios microservice's collection GET verb
|
7
|
+
#
|
8
|
+
# Author: Matthew Wilson
|
9
|
+
#
|
10
|
+
# Copyright (c) 2018, Razor Risk Technologies Pty Ltd
|
11
|
+
# All rights reserved.
|
12
|
+
#
|
13
|
+
# ######################################################################## #
|
14
|
+
|
15
|
+
|
16
|
+
# ##########################################################################
|
17
|
+
# requires
|
18
|
+
|
19
|
+
require 'razor_risk/razor/connectivity/razor_3/razor_requester'
|
20
|
+
|
21
|
+
require 'razor_risk/cassini/constants'
|
22
|
+
|
23
|
+
require 'pantheios'
|
24
|
+
require 'xqsr3/quality/parameter_checking'
|
25
|
+
|
26
|
+
module RazorRisk
|
27
|
+
module Cassini
|
28
|
+
module Applications
|
29
|
+
module RESTFramework
|
30
|
+
|
31
|
+
# ##########################################################################
|
32
|
+
# modules
|
33
|
+
|
34
|
+
module RouteVerbDispatch
|
35
|
+
|
36
|
+
include ::Pantheios
|
37
|
+
include ::Xqsr3::Quality::ParameterChecking
|
38
|
+
|
39
|
+
def dispatch supplier, *args, **options
|
40
|
+
|
41
|
+
trace ParamNames[ :supplier, :args, :options ], supplier, args, options
|
42
|
+
|
43
|
+
if ::Class === supplier
|
44
|
+
|
45
|
+
supplier_class = supplier
|
46
|
+
supplier = supplier_class.new(self, self.class, *args, **options)
|
47
|
+
else
|
48
|
+
|
49
|
+
supplier_class = supplier.class
|
50
|
+
end
|
51
|
+
|
52
|
+
if $PARAMETER_CHECKING
|
53
|
+
|
54
|
+
check_parameter supplier, 'supplier', responds_to: :handle
|
55
|
+
end
|
56
|
+
|
57
|
+
verb = (options[:verb] || request.request_method).to_s.downcase.to_sym
|
58
|
+
|
59
|
+
# validate 'Accept'
|
60
|
+
|
61
|
+
validate_accept(request, supplier_class::HTTP_ACCEPTS) if supplier_class.const_defined?(:HTTP_ACCEPTS)
|
62
|
+
|
63
|
+
# validate 'Content-Type'
|
64
|
+
|
65
|
+
validate_content_type(request, supplier_class::HTTP_CONTENT_TYPES) if supplier_class.const_defined?(:HTTP_CONTENT_TYPES)
|
66
|
+
|
67
|
+
# validate query parameters
|
68
|
+
|
69
|
+
validated_params = validate_query_parameters(params, supplier_class.const_defined?(:QUERY_PARAMETERS) ? supplier_class::QUERY_PARAMETERS : nil, supplier_class.const_defined?(:ROUTE_VARIABLES) ? supplier_class::ROUTE_VARIABLES : nil)
|
70
|
+
|
71
|
+
# handle base-64 for all params
|
72
|
+
|
73
|
+
validated_params = validated_params.merge(validated_params) do |k, o, n|
|
74
|
+
|
75
|
+
case n
|
76
|
+
when ::String
|
77
|
+
|
78
|
+
s = n.strip
|
79
|
+
|
80
|
+
if /^===(.+)===$/ =~ s
|
81
|
+
|
82
|
+
e = $1
|
83
|
+
|
84
|
+
begin
|
85
|
+
|
86
|
+
Base64.strict_decode64(e).chomp
|
87
|
+
rescue ::ArgumentError => x
|
88
|
+
|
89
|
+
halt(*[ 422, {}, "value for query parameter '#{k}' is malformed Base-64: a valid Base-64 string must be prefixed and suffixed by '==='" ])
|
90
|
+
end
|
91
|
+
else
|
92
|
+
|
93
|
+
n
|
94
|
+
end
|
95
|
+
else
|
96
|
+
|
97
|
+
n
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# execute handler
|
102
|
+
resp = supplier.handle(env, validated_params, request, response)
|
103
|
+
|
104
|
+
# TODO: post-process result, in terms of converting to 'Accept' type
|
105
|
+
# and calling halt / status appropriately
|
106
|
+
|
107
|
+
resp
|
108
|
+
end
|
109
|
+
|
110
|
+
end # module RouteVerbDispatch
|
111
|
+
|
112
|
+
|
113
|
+
end # module RESTFramework
|
114
|
+
end # module Applications
|
115
|
+
end # module Cassini
|
116
|
+
end # module RazorRisk
|
117
|
+
|
118
|
+
# ############################## end of file ############################# #
|
119
|
+
|
120
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# ######################################################################## #
|
4
|
+
# File: razor_risk/cassini/applications/rest_framework/verb_handler.rb
|
5
|
+
#
|
6
|
+
# Purpose: Root (abstract) verb-handler class
|
7
|
+
#
|
8
|
+
# Author: Matthew Wilson
|
9
|
+
#
|
10
|
+
# Copyright (c) 2018, Razor Risk Technologies Pty Ltd
|
11
|
+
# All rights reserved.
|
12
|
+
#
|
13
|
+
# ######################################################################## #
|
14
|
+
|
15
|
+
|
16
|
+
# ##########################################################################
|
17
|
+
# requires
|
18
|
+
|
19
|
+
require 'razor_risk/cassini/authorisation/security_model_helpers'
|
20
|
+
|
21
|
+
require 'razor_risk/extensions/rack/utils/http_status_names'
|
22
|
+
|
23
|
+
require 'pantheios'
|
24
|
+
require 'xqsr3/quality/parameter_checking'
|
25
|
+
|
26
|
+
module RazorRisk
|
27
|
+
module Cassini
|
28
|
+
module Applications
|
29
|
+
module RESTFramework
|
30
|
+
|
31
|
+
# ##########################################################################
|
32
|
+
# classes
|
33
|
+
|
34
|
+
class VerbHandler
|
35
|
+
|
36
|
+
|
37
|
+
# ##########################################################
|
38
|
+
# includes
|
39
|
+
|
40
|
+
include ::RazorRisk::Cassini::Authorisation::SecurityModelHelpers
|
41
|
+
|
42
|
+
include ::Pantheios
|
43
|
+
include ::Xqsr3::Quality::ParameterChecking
|
44
|
+
|
45
|
+
|
46
|
+
# ##########################################################
|
47
|
+
# constants
|
48
|
+
|
49
|
+
HTTP_STATUS_NAMES = ::Rack::Utils::HTTP_STATUS_NAMES
|
50
|
+
|
51
|
+
|
52
|
+
# ##########################################################
|
53
|
+
# methods
|
54
|
+
|
55
|
+
def initialize app, settings = nil, **options
|
56
|
+
|
57
|
+
check_parameter app, 'app'
|
58
|
+
|
59
|
+
settings ||= app.class
|
60
|
+
|
61
|
+
@app = app
|
62
|
+
@settings = settings
|
63
|
+
@options = options
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :app
|
67
|
+
attr_reader :settings
|
68
|
+
|
69
|
+
def content_type *args
|
70
|
+
|
71
|
+
@app.content_type(*args)
|
72
|
+
end
|
73
|
+
|
74
|
+
def halt *args
|
75
|
+
|
76
|
+
@app.halt(*args)
|
77
|
+
end
|
78
|
+
|
79
|
+
def error *args
|
80
|
+
|
81
|
+
@app.error(*args)
|
82
|
+
end
|
83
|
+
|
84
|
+
def status *args
|
85
|
+
|
86
|
+
@app.status(*args)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Obtains a credentials-hash, which will be empty if no authentication
|
90
|
+
# is being used, or will contain +:username+ and, optionally,
|
91
|
+
# +:password+ and/or +:domain+, depending on the authentication scheme
|
92
|
+
# being used
|
93
|
+
def get_required_credentials
|
94
|
+
|
95
|
+
if settings.respond_to?(:authentication_scheme)
|
96
|
+
|
97
|
+
razor_requester_credentials_options(
|
98
|
+
settings.authentication_scheme,
|
99
|
+
app.credentials,
|
100
|
+
auth_test_mode: settings.auth_test_mode
|
101
|
+
)
|
102
|
+
else
|
103
|
+
|
104
|
+
Hash.new
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end # class VerbHandler
|
108
|
+
|
109
|
+
|
110
|
+
end # module RESTFramework
|
111
|
+
end # module Applications
|
112
|
+
end # module Cassini
|
113
|
+
end # module RazorRisk
|
114
|
+
|
115
|
+
# ############################## end of file ############################# #
|
116
|
+
|
117
|
+
|