hoodoo 1.0.2
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/bin/hoodoo +5 -0
- data/lib/hoodoo.rb +27 -0
- data/lib/hoodoo/active.rb +32 -0
- data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
- data/lib/hoodoo/active/active_record/base.rb +81 -0
- data/lib/hoodoo/active/active_record/creator.rb +134 -0
- data/lib/hoodoo/active/active_record/dated.rb +343 -0
- data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
- data/lib/hoodoo/active/active_record/finder.rb +606 -0
- data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
- data/lib/hoodoo/active/active_record/secure.rb +431 -0
- data/lib/hoodoo/active/active_record/support.rb +106 -0
- data/lib/hoodoo/active/active_record/translated.rb +87 -0
- data/lib/hoodoo/active/active_record/uuid.rb +80 -0
- data/lib/hoodoo/active/active_record/writer.rb +321 -0
- data/lib/hoodoo/client.rb +23 -0
- data/lib/hoodoo/client/augmented_array.rb +29 -0
- data/lib/hoodoo/client/augmented_base.rb +168 -0
- data/lib/hoodoo/client/augmented_hash.rb +23 -0
- data/lib/hoodoo/client/client.rb +354 -0
- data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
- data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
- data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
- data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
- data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
- data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
- data/lib/hoodoo/client/headers.rb +269 -0
- data/lib/hoodoo/communicators.rb +23 -0
- data/lib/hoodoo/communicators/fast.rb +44 -0
- data/lib/hoodoo/communicators/pool.rb +601 -0
- data/lib/hoodoo/communicators/slow.rb +84 -0
- data/lib/hoodoo/data.rb +51 -0
- data/lib/hoodoo/data/resources/caller.rb +39 -0
- data/lib/hoodoo/data/resources/errors.rb +28 -0
- data/lib/hoodoo/data/resources/log.rb +31 -0
- data/lib/hoodoo/data/resources/session.rb +26 -0
- data/lib/hoodoo/data/types/error_primitive.rb +27 -0
- data/lib/hoodoo/data/types/permissions.rb +40 -0
- data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
- data/lib/hoodoo/data/types/permissions_full.rb +28 -0
- data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
- data/lib/hoodoo/discovery.rb +20 -0
- data/lib/hoodoo/errors.rb +19 -0
- data/lib/hoodoo/errors/error_descriptions.rb +229 -0
- data/lib/hoodoo/errors/errors.rb +322 -0
- data/lib/hoodoo/generator.rb +139 -0
- data/lib/hoodoo/logger.rb +23 -0
- data/lib/hoodoo/logger/fast_writer.rb +27 -0
- data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
- data/lib/hoodoo/logger/logger.rb +387 -0
- data/lib/hoodoo/logger/slow_writer.rb +49 -0
- data/lib/hoodoo/logger/writer_mixin.rb +52 -0
- data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
- data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
- data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
- data/lib/hoodoo/middleware.rb +33 -0
- data/lib/hoodoo/presenters.rb +45 -0
- data/lib/hoodoo/presenters/base.rb +281 -0
- data/lib/hoodoo/presenters/base_dsl.rb +519 -0
- data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
- data/lib/hoodoo/presenters/embedding.rb +232 -0
- data/lib/hoodoo/presenters/types/array.rb +118 -0
- data/lib/hoodoo/presenters/types/boolean.rb +26 -0
- data/lib/hoodoo/presenters/types/date.rb +26 -0
- data/lib/hoodoo/presenters/types/date_time.rb +26 -0
- data/lib/hoodoo/presenters/types/decimal.rb +47 -0
- data/lib/hoodoo/presenters/types/enum.rb +55 -0
- data/lib/hoodoo/presenters/types/field.rb +158 -0
- data/lib/hoodoo/presenters/types/float.rb +26 -0
- data/lib/hoodoo/presenters/types/hash.rb +361 -0
- data/lib/hoodoo/presenters/types/integer.rb +26 -0
- data/lib/hoodoo/presenters/types/object.rb +117 -0
- data/lib/hoodoo/presenters/types/string.rb +53 -0
- data/lib/hoodoo/presenters/types/tags.rb +24 -0
- data/lib/hoodoo/presenters/types/text.rb +26 -0
- data/lib/hoodoo/presenters/types/uuid.rb +54 -0
- data/lib/hoodoo/services.rb +34 -0
- data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
- data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
- data/lib/hoodoo/services/discovery/discovery.rb +186 -0
- data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
- data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
- data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
- data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
- data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
- data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
- data/lib/hoodoo/services/middleware/interaction.rb +127 -0
- data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
- data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
- data/lib/hoodoo/services/services/context.rb +153 -0
- data/lib/hoodoo/services/services/implementation.rb +132 -0
- data/lib/hoodoo/services/services/interface.rb +934 -0
- data/lib/hoodoo/services/services/permissions.rb +250 -0
- data/lib/hoodoo/services/services/request.rb +189 -0
- data/lib/hoodoo/services/services/response.rb +316 -0
- data/lib/hoodoo/services/services/service.rb +141 -0
- data/lib/hoodoo/services/services/session.rb +729 -0
- data/lib/hoodoo/utilities.rb +12 -0
- data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
- data/lib/hoodoo/utilities/utilities.rb +380 -0
- data/lib/hoodoo/utilities/uuid.rb +44 -0
- data/lib/hoodoo/version.rb +17 -0
- data/spec/active/active_record/base_spec.rb +57 -0
- data/spec/active/active_record/creator_spec.rb +88 -0
- data/spec/active/active_record/dated_spec.rb +248 -0
- data/spec/active/active_record/error_mapping_spec.rb +360 -0
- data/spec/active/active_record/finder_spec.rb +744 -0
- data/spec/active/active_record/search_helper_spec.rb +384 -0
- data/spec/active/active_record/secure_spec.rb +435 -0
- data/spec/active/active_record/support_spec.rb +225 -0
- data/spec/active/active_record/translated_spec.rb +19 -0
- data/spec/active/active_record/uuid_spec.rb +72 -0
- data/spec/active/active_record/writer_spec.rb +272 -0
- data/spec/alchemy/alchemy-amq.rb +33 -0
- data/spec/client/augmented_array_spec.rb +15 -0
- data/spec/client/augmented_base_spec.rb +50 -0
- data/spec/client/augmented_hash_spec.rb +15 -0
- data/spec/client/client_spec.rb +955 -0
- data/spec/client/endpoint/endpoint_spec.rb +70 -0
- data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
- data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
- data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
- data/spec/client/headers_spec.rb +172 -0
- data/spec/communicators/fast_spec.rb +9 -0
- data/spec/communicators/pool_spec.rb +339 -0
- data/spec/communicators/slow_spec.rb +15 -0
- data/spec/data/resources/caller_spec.rb +156 -0
- data/spec/data/resources/errors_spec.rb +22 -0
- data/spec/data/resources/log_spec.rb +20 -0
- data/spec/data/resources/session_spec.rb +15 -0
- data/spec/data/types/error_primitive_spec.rb +15 -0
- data/spec/data/types/permissions_defaults_spec.rb +25 -0
- data/spec/data/types/permissions_full_spec.rb +44 -0
- data/spec/data/types/permissions_resources_spec.rb +34 -0
- data/spec/data/types/permissions_spec.rb +37 -0
- data/spec/errors/error_descriptions_spec.rb +98 -0
- data/spec/errors/errors_spec.rb +346 -0
- data/spec/integration/service_actions_spec.rb +112 -0
- data/spec/logger/fast_writer_spec.rb +18 -0
- data/spec/logger/logger_spec.rb +259 -0
- data/spec/logger/slow_writer_spec.rb +144 -0
- data/spec/logger/writers/file_writer_spec.rb +37 -0
- data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
- data/spec/logger/writers/stream_writer_spec.rb +38 -0
- data/spec/presenters/base_dsl_spec.rb +111 -0
- data/spec/presenters/base_spec.rb +871 -0
- data/spec/presenters/common_resource_fields_spec.rb +30 -0
- data/spec/presenters/embedding_spec.rb +87 -0
- data/spec/presenters/types/array_spec.rb +249 -0
- data/spec/presenters/types/boolean_spec.rb +51 -0
- data/spec/presenters/types/date_spec.rb +57 -0
- data/spec/presenters/types/date_time_spec.rb +59 -0
- data/spec/presenters/types/decimal_spec.rb +58 -0
- data/spec/presenters/types/enum_spec.rb +71 -0
- data/spec/presenters/types/field_spec.rb +77 -0
- data/spec/presenters/types/float_spec.rb +50 -0
- data/spec/presenters/types/hash_spec.rb +1069 -0
- data/spec/presenters/types/integer_spec.rb +50 -0
- data/spec/presenters/types/object_spec.rb +177 -0
- data/spec/presenters/types/string_spec.rb +65 -0
- data/spec/presenters/types/tags_spec.rb +56 -0
- data/spec/presenters/types/text_spec.rb +50 -0
- data/spec/presenters/types/uuid_spec.rb +46 -0
- data/spec/presenters/walk_spec.rb +198 -0
- data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
- data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
- data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
- data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
- data/spec/services/discovery/discovery_spec.rb +73 -0
- data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
- data/spec/services/discovery/results/for_http_spec.rb +37 -0
- data/spec/services/discovery/results/for_local_spec.rb +21 -0
- data/spec/services/discovery/results/for_remote_spec.rb +15 -0
- data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
- data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
- data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
- data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
- data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
- data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
- data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
- data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
- data/spec/services/middleware/middleware_cors_spec.rb +93 -0
- data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
- data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
- data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
- data/spec/services/middleware/middleware_logging_spec.rb +356 -0
- data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
- data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
- data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
- data/spec/services/middleware/middleware_public_spec.rb +238 -0
- data/spec/services/middleware/middleware_spec.rb +1569 -0
- data/spec/services/middleware/string_inquirer_spec.rb +30 -0
- data/spec/services/services/application_spec.rb +74 -0
- data/spec/services/services/context_spec.rb +48 -0
- data/spec/services/services/implementation_spec.rb +45 -0
- data/spec/services/services/interface_spec.rb +262 -0
- data/spec/services/services/permissions_spec.rb +249 -0
- data/spec/services/services/request_spec.rb +95 -0
- data/spec/services/services/response_spec.rb +250 -0
- data/spec/services/services/session_spec.rb +432 -0
- data/spec/spec_helper.rb +298 -0
- data/spec/utilities/utilities_spec.rb +537 -0
- data/spec/utilities/uuid_spec.rb +20 -0
- metadata +615 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: slow_writer.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Base class for slow log writers.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 16-Dec-2014 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
module Hoodoo
|
11
|
+
class Logger
|
12
|
+
|
13
|
+
# Log writer classes are used through the Hoodoo::Logger class.
|
14
|
+
#
|
15
|
+
# Subclass SlowWriter if you are writing a log data output mechanism which
|
16
|
+
# does not respond very quickly. File output might fall into this category
|
17
|
+
# depending upon target deployment infrastructure; exporting logs to a
|
18
|
+
# remote logging service over the network would certainly qualify.
|
19
|
+
#
|
20
|
+
# The subclass only needs to implement
|
21
|
+
# Hoodoo::Logger::WriterMixin#report.
|
22
|
+
#
|
23
|
+
# If a slow writer cannot keep up with a high rate of log messages, some
|
24
|
+
# may be dropped. A +:warn+ level message is reported automatically for
|
25
|
+
# such cases, describing the number of dropped messages, once the slow
|
26
|
+
# writer has caught up.
|
27
|
+
#
|
28
|
+
# *IMPORTANT*: If you use ActiveRecord in a slow writer class, beware that
|
29
|
+
# your writer runs in a ruby Thread. Unless you take steps to prevent it,
|
30
|
+
# ActiveRecord will implicitly check out a connection which stays with
|
31
|
+
# your Thread forever. This steals a connection from the pool. To prevent
|
32
|
+
# this issue, you must use the following pattern:
|
33
|
+
#
|
34
|
+
# def report( log_level, component, code, data )
|
35
|
+
# ActiveRecord::Base.connection_pool.with_connection do
|
36
|
+
# # ...Any AciveRecord code goes here...
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# Code within the +with_connection+ block uses a temporary connection from
|
41
|
+
# the pool which is returned once the block has finished processing. Even
|
42
|
+
# if exceptions occur within your ActiveRecord code, the connection is
|
43
|
+
# still correctly returned to the pool using the above approach.
|
44
|
+
#
|
45
|
+
class SlowWriter
|
46
|
+
include Hoodoo::Logger::WriterMixin
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: writer_mixin.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Common code for fast and slow log writer base classes.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 16-Dec-2014 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
module Hoodoo
|
11
|
+
class Logger
|
12
|
+
|
13
|
+
# This mixin is used by Hoodoo::Logger::FastWriter and
|
14
|
+
# Hoodoo::Logger::SlowWriter. See those two classes for details.
|
15
|
+
#
|
16
|
+
module WriterMixin
|
17
|
+
|
18
|
+
# Hoodoo::Logger::FastWriter and Hoodoo::Logger::SlowWriter
|
19
|
+
# subclasses implement this method.
|
20
|
+
#
|
21
|
+
# Write a structured log message. Writers sending data somewhere with no
|
22
|
+
# structure support will need to serialize/flatten the message; others
|
23
|
+
# should retain data structures like hashes or arrays.
|
24
|
+
#
|
25
|
+
# The #report method is only invoked if the logging threshold level of
|
26
|
+
# the owning logger is set to an equal or lower level. Implementations
|
27
|
+
# do not, therefore, need to check this themselves.
|
28
|
+
#
|
29
|
+
# +log_level+:: Log level as a symbol - one of, from most trivial to most
|
30
|
+
# severe, +:debug+, +:info+, +:warn+ or +:error+.
|
31
|
+
#
|
32
|
+
# +component+:: Component - for example, a resource name for a specific
|
33
|
+
# service implementation, 'Middleware' for Hoodoo itself,
|
34
|
+
# or some other name you think is useful. String or Symbol.
|
35
|
+
#
|
36
|
+
# +code+:: Component-defined code. Think of this in a manner similar
|
37
|
+
# to platform error codes, appearing after the "."; messages
|
38
|
+
# related to the same thing should share the same code. The
|
39
|
+
# intent is to produce log data that someone can filter on
|
40
|
+
# code to get useful information about that specific aspect
|
41
|
+
# of a service implementation's behaviour.
|
42
|
+
#
|
43
|
+
# +data+:: A Hash containing the level, component and code-dependent
|
44
|
+
# payload data to be logged. Converted to a string with
|
45
|
+
# +inspect+ for flat output use in an unstructured context.
|
46
|
+
#
|
47
|
+
def report( log_level, component, code, data )
|
48
|
+
raise( 'Subclasses must implement #report' )
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: file_writer.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Write flat log messages to a file.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 16-Dec-2014 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
module Hoodoo
|
11
|
+
class Logger
|
12
|
+
|
13
|
+
# Writes unstructured messages to a file. Hoodoo::Logger::SlowWriter
|
14
|
+
# subclass. See also Hoodoo::Logger.
|
15
|
+
#
|
16
|
+
class FileWriter < Hoodoo::Logger::SlowWriter
|
17
|
+
|
18
|
+
include Hoodoo::Logger::FlattenerMixin
|
19
|
+
|
20
|
+
# Create a file writer instance. Files are written by opening,
|
21
|
+
# adding a log message and closing again, to provide reliability.
|
22
|
+
# For this reason, this is a Hoodoo::Logger::SlowWriter subclass.
|
23
|
+
#
|
24
|
+
# If you want faster file access at the expense of immediate updates
|
25
|
+
# / reliability due to buffering, open a file externally to create an
|
26
|
+
# I/O stream and pass this persistently-open file's stream to an
|
27
|
+
# Hoodoo::Logger::StreamWriter class instead.
|
28
|
+
#
|
29
|
+
# +pathname+:: Full pathname of a file that can be opened in "ab"
|
30
|
+
# (append for writing at end-of-file) mode.
|
31
|
+
#
|
32
|
+
def initialize( pathname )
|
33
|
+
@pathname = pathname
|
34
|
+
end
|
35
|
+
|
36
|
+
# See Hoodoo::Logger::WriterMixin#report.
|
37
|
+
#
|
38
|
+
def report( log_level, component, code, data )
|
39
|
+
File.open( @pathname, 'ab' ) do | file |
|
40
|
+
file.puts( flatten( log_level, component, code, data ) )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: log_entries_dot_com_writer.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Write structured log messages logentries.com.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 08-Jan-2015 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
require 'json'
|
11
|
+
|
12
|
+
module Hoodoo
|
13
|
+
class Logger
|
14
|
+
|
15
|
+
begin # Exception handler as 'le' gem inclusion is optional.
|
16
|
+
require 'le' # Might raise LoadError; that's allowed.
|
17
|
+
|
18
|
+
# Writes structured messages to logentries.com via the "le" gem,
|
19
|
+
# which uses its own asynchronous worker thread for network data.
|
20
|
+
# Thus, a Hoodoo::Logger::FastWriter subclass. See also
|
21
|
+
# Hoodoo::Logger.
|
22
|
+
#
|
23
|
+
class LogEntriesDotComWriter < Hoodoo::Logger::FastWriter
|
24
|
+
|
25
|
+
# Create a log writer instance.
|
26
|
+
#
|
27
|
+
# +token+:: Your logentries.com API token.
|
28
|
+
#
|
29
|
+
def initialize( token )
|
30
|
+
@@logger ||= Le.new( token, :ssl => true )
|
31
|
+
end
|
32
|
+
|
33
|
+
# See Hoodoo::Logger::WriterMixin#report.
|
34
|
+
#
|
35
|
+
def report( log_level, component, code, data )
|
36
|
+
method = case log_level
|
37
|
+
when :debug, :info, :warn, :error
|
38
|
+
log_level
|
39
|
+
else
|
40
|
+
:unknown
|
41
|
+
end
|
42
|
+
|
43
|
+
message = {
|
44
|
+
:level => log_level,
|
45
|
+
:component => component,
|
46
|
+
:code => code,
|
47
|
+
:data => data
|
48
|
+
}
|
49
|
+
|
50
|
+
# This method is only called if the log level set elsewhere
|
51
|
+
# is already appropriate; always make sure that the 'LE' class
|
52
|
+
# logging level is as low as possible so it doesn't filter any
|
53
|
+
# additional messages accidentally.
|
54
|
+
|
55
|
+
@@logger.level = ::Logger::DEBUG
|
56
|
+
@@logger.send( method, ::JSON.generate( message ) )
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
rescue LoadError # From "require 'le'"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: file_writer.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Write flat log messages to an I/O stream - STDOUT by
|
6
|
+
# default.
|
7
|
+
# ----------------------------------------------------------------------
|
8
|
+
# 16-Dec-2014 (ADH): Created.
|
9
|
+
########################################################################
|
10
|
+
|
11
|
+
module Hoodoo
|
12
|
+
class Logger
|
13
|
+
|
14
|
+
# Writes unstructured messages to (presumed) fast output streams such as
|
15
|
+
# <tt>$stdout</tt>. Hoodoo::Logger::FastWriter subclass. See also
|
16
|
+
# Hoodoo::Logger.
|
17
|
+
#
|
18
|
+
class StreamWriter < Hoodoo::Logger::FastWriter
|
19
|
+
|
20
|
+
include Hoodoo::Logger::FlattenerMixin
|
21
|
+
|
22
|
+
# Create a stream writer instance. Although you could initialize this
|
23
|
+
# class with a slow output stream, they're expected to be fast (e.g.
|
24
|
+
# terminal output) as this is a Hoodoo::Logger::FastWriter subclass.
|
25
|
+
#
|
26
|
+
# For reliable file writing, use the Hoodoo::Logger::FileWriter class
|
27
|
+
# instead.
|
28
|
+
#
|
29
|
+
# +output_stream+:: Optional I/O stream instance; default is +$stdout+.
|
30
|
+
# The instance must provide a +puts+ implementation.
|
31
|
+
#
|
32
|
+
def initialize( output_stream = $stdout )
|
33
|
+
@output_stream = output_stream
|
34
|
+
end
|
35
|
+
|
36
|
+
# See Hoodoo::Logger::WriterMixin#report.
|
37
|
+
#
|
38
|
+
def report( log_level, component, code, data )
|
39
|
+
@output_stream.puts( flatten( log_level, component, code, data ) )
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: middleware.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Include code implementing the Rack service middleware.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 26-Jan-2015 (ADH): Split from top-level inclusion file.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
# Dependencies
|
11
|
+
|
12
|
+
require 'hoodoo/utilities'
|
13
|
+
require 'hoodoo/errors'
|
14
|
+
require 'hoodoo/communicators'
|
15
|
+
require 'hoodoo/logger'
|
16
|
+
require 'hoodoo/discovery'
|
17
|
+
require 'hoodoo/client'
|
18
|
+
require 'hoodoo/presenters'
|
19
|
+
|
20
|
+
# Middleware
|
21
|
+
|
22
|
+
require 'hoodoo/services/middleware/rack_monkey_patch'
|
23
|
+
require 'hoodoo/services/middleware/amqp_log_message'
|
24
|
+
require 'hoodoo/services/middleware/amqp_log_writer'
|
25
|
+
require 'hoodoo/services/middleware/interaction'
|
26
|
+
require 'hoodoo/services/middleware/endpoints/inter_resource_remote'
|
27
|
+
require 'hoodoo/services/middleware/endpoints/inter_resource_local'
|
28
|
+
require 'hoodoo/services/middleware/middleware'
|
29
|
+
|
30
|
+
require 'hoodoo/services/middleware/exception_reporting/exception_reporting'
|
31
|
+
require 'hoodoo/services/middleware/exception_reporting/base_reporter'
|
32
|
+
require 'hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter'
|
33
|
+
require 'hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: presenters.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Include the schema based data validation and rendering code.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 26-Jan-2015 (ADH): Split from top-level inclusion file.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
module Hoodoo
|
11
|
+
|
12
|
+
# Module providing a namespace for schema-based data rendering and
|
13
|
+
# validation code.
|
14
|
+
#
|
15
|
+
module Presenters
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Dependencies
|
20
|
+
|
21
|
+
require 'hoodoo/utilities'
|
22
|
+
|
23
|
+
# Presenters
|
24
|
+
|
25
|
+
require 'hoodoo/presenters/base'
|
26
|
+
require 'hoodoo/presenters/base_dsl'
|
27
|
+
require 'hoodoo/presenters/embedding'
|
28
|
+
|
29
|
+
require 'hoodoo/presenters/types/field'
|
30
|
+
require 'hoodoo/presenters/types/object'
|
31
|
+
require 'hoodoo/presenters/types/array'
|
32
|
+
require 'hoodoo/presenters/types/hash'
|
33
|
+
require 'hoodoo/presenters/types/string'
|
34
|
+
require 'hoodoo/presenters/types/text'
|
35
|
+
require 'hoodoo/presenters/types/enum'
|
36
|
+
require 'hoodoo/presenters/types/boolean'
|
37
|
+
require 'hoodoo/presenters/types/float'
|
38
|
+
require 'hoodoo/presenters/types/integer'
|
39
|
+
require 'hoodoo/presenters/types/decimal'
|
40
|
+
require 'hoodoo/presenters/types/date'
|
41
|
+
require 'hoodoo/presenters/types/date_time'
|
42
|
+
require 'hoodoo/presenters/types/tags'
|
43
|
+
require 'hoodoo/presenters/types/uuid'
|
44
|
+
|
45
|
+
require 'hoodoo/presenters/common_resource_fields'
|
@@ -0,0 +1,281 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: base_presenter.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Schema-based data rendering and validation.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 02-Dec-2014 (ADH): Merge of DocumentedPresenter code into
|
8
|
+
# Base.
|
9
|
+
########################################################################
|
10
|
+
|
11
|
+
module Hoodoo
|
12
|
+
module Presenters
|
13
|
+
|
14
|
+
# Base functionality for JSON validation and presenter (rendering) layers.
|
15
|
+
# Subclass this to define a schema against which validation of inbound data
|
16
|
+
# or rendering of outbound data can be performed. Call #schema in the
|
17
|
+
# subclass to declare, via the DSL, the shape of the schema.
|
18
|
+
#
|
19
|
+
class Base
|
20
|
+
|
21
|
+
# Define the JSON schema for validation.
|
22
|
+
#
|
23
|
+
# &block:: Block that makes calls to the DSL defined in
|
24
|
+
# Hoodoo::Presenters::BaseDSL in order to define the schema.
|
25
|
+
#
|
26
|
+
def self.schema( &block )
|
27
|
+
@schema = Hoodoo::Presenters::Object.new
|
28
|
+
@schema.instance_eval( &block )
|
29
|
+
@schema_definition = block
|
30
|
+
end
|
31
|
+
|
32
|
+
# Given some data that should conform to the subclass presenter's schema,
|
33
|
+
# render it to go from the input Ruby Hash, to an output Ruby Hash which
|
34
|
+
# will include default values - if any - present in the schema and will
|
35
|
+
# drop input fields not present in that schema. In essence, this takes
|
36
|
+
# data which may have been programatically generated and sanitises it to
|
37
|
+
# produce valid, with-defaults guaranteed valid output.
|
38
|
+
#
|
39
|
+
# Field +kind+ is taken from the class name. If concerned about clashes
|
40
|
+
# between resource names and ActiveRecord model names, put your resource
|
41
|
+
# classes inside a module for namespacing - for example:
|
42
|
+
#
|
43
|
+
# module Resources
|
44
|
+
# class Product < Hoodoo::Presenters::Base
|
45
|
+
# schema do
|
46
|
+
# ...
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# Only the class "leaf" name is used to infer the resource kind - in the
|
52
|
+
# above case, that's +Product+.
|
53
|
+
#
|
54
|
+
# Any field with a schema giving a default value will only appear should
|
55
|
+
# a value for that field be _omitted_ in the input data. If the data
|
56
|
+
# provides, for example, an explicit +nil+ value then a corresponding
|
57
|
+
# explicit +nil+ will be rendered, regardless of defaults.
|
58
|
+
#
|
59
|
+
# For belt-and-braces, unless subsequent profiling shows performance
|
60
|
+
# issues, callers should call #validate first to self-check their internal
|
61
|
+
# data against the schema prior to rendering. That way, coding errors
|
62
|
+
# will be discovered immediately, rather than hidden / obscured by the
|
63
|
+
# rendered sanitisation.
|
64
|
+
#
|
65
|
+
# Since rendering top-level +nil+ is not valid JSON, should +nil+ be
|
66
|
+
# provided as input, it'll be treated as an empty hash ("{}") instead.
|
67
|
+
#
|
68
|
+
# This is quite a low-level call. For a higher level renderer which
|
69
|
+
# Hoodoo service resource implementations will probably want to use for
|
70
|
+
# returning resource representations in responses, see ::render_in.
|
71
|
+
#
|
72
|
+
# +data+:: Hash to be represented. Data within this is compared
|
73
|
+
# against the schema being called to ensure that correct
|
74
|
+
# information is returned and unknown data is ignored.
|
75
|
+
#
|
76
|
+
# +uuid+:: Unique ID of the resource instance that is to be
|
77
|
+
# represented. If nil / omitted, this is assumed to be
|
78
|
+
# a rendering of a type or other non-resource like item.
|
79
|
+
# Otherwise the field is mandatory.
|
80
|
+
#
|
81
|
+
# +created_at+:: Date/Time of instance creation. Only required if UUID
|
82
|
+
# has been provided. This is a Ruby DateTime instance or
|
83
|
+
# similar, _NOT_ a string!
|
84
|
+
#
|
85
|
+
# +language+:: Optional language. If the type/resource being rendered
|
86
|
+
# is internationalised but this is omitted, then a value
|
87
|
+
# of "en-nz" is used as a default.
|
88
|
+
#
|
89
|
+
def self.render( data, uuid = nil, created_at = nil, language = 'en-nz' )
|
90
|
+
target = {}
|
91
|
+
data = data || {}
|
92
|
+
|
93
|
+
@schema.render( data, target )
|
94
|
+
|
95
|
+
# Common fields are added after rendering the data in case there are
|
96
|
+
# any same-named field collisions - platform defaults should take
|
97
|
+
# precedence, overwriting previous definitions intentionally.
|
98
|
+
|
99
|
+
unless ( uuid.nil? )
|
100
|
+
|
101
|
+
raise "Can't render a Resource with a nil 'created_at'" if created_at.nil?
|
102
|
+
|
103
|
+
# Field "kind" is taken from the class name; this is a class method
|
104
|
+
# so "self.name" yields "Hoodoo::Data::Resources::..." or similar.
|
105
|
+
# We could just use "split", but that creates an intermediate Array
|
106
|
+
# which uses more RAM and is about half the speed (or worse) of the
|
107
|
+
# following alternative (it turns out ActiveSupport 4's #demodulize
|
108
|
+
# uses much the same approach).
|
109
|
+
|
110
|
+
name = self.name
|
111
|
+
index = ( name.rindex( '::' ) || -2 ) + 2
|
112
|
+
kind = name[ index .. -1 ]
|
113
|
+
|
114
|
+
target.merge!( {
|
115
|
+
'id' => uuid,
|
116
|
+
'kind' => kind,
|
117
|
+
'created_at' => Time.parse( created_at.to_s ).utc.iso8601
|
118
|
+
} )
|
119
|
+
|
120
|
+
target[ 'language' ] = language if self.is_internationalised?()
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
return target
|
125
|
+
end
|
126
|
+
|
127
|
+
# A higher level version of ::render, typically called from Hoodoo
|
128
|
+
# services in their resource implementation code.
|
129
|
+
#
|
130
|
+
# As with ::render, data is rendered according to the schema of the
|
131
|
+
# object the ::render_in message is sent to. Options specify things like
|
132
|
+
# UUID and created-at date. Language information for internationalised
|
133
|
+
# fields can be given, but if omitted comes from the given request
|
134
|
+
# context data.
|
135
|
+
#
|
136
|
+
# Additional facilites exist over and above ::render - security scoping
|
137
|
+
# information in the resource via its +secured_with+ field is made
|
138
|
+
# available through options (see below), along with support for embedded
|
139
|
+
# or referenced resource information.
|
140
|
+
#
|
141
|
+
# +context+:: A Hoodoo::Services::Context instance, which is usually the
|
142
|
+
# value passed to a service implementation in calls like
|
143
|
+
# Hoodoo::Services::Implementation#list or
|
144
|
+
# Hoodoo::Services::Implementation#show.
|
145
|
+
#
|
146
|
+
# +data+:: Hash to be represented. Data within this is compared
|
147
|
+
# against the schema being called to ensure that correct
|
148
|
+
# information is returned and unknown data is ignored.
|
149
|
+
#
|
150
|
+
# +options+:: Options hash, see below.
|
151
|
+
#
|
152
|
+
# The options keys are Symbols, used as follows:
|
153
|
+
#
|
154
|
+
# +uuid+:: Same as the +uuid+ parameter to ::render, except
|
155
|
+
# mandatory.
|
156
|
+
#
|
157
|
+
# +created_at+:: Same as the +created_at+ parameter to ::render, except
|
158
|
+
# mandatory.
|
159
|
+
#
|
160
|
+
# +language+:: Optional value for resource's +language+ field; taken
|
161
|
+
# from the +context+ parameter if omitted.
|
162
|
+
#
|
163
|
+
# +embeds+:: A Hoodoo::Presenters::Embedding::Embeds instance that
|
164
|
+
# contains (fully rendered) resources which are to be
|
165
|
+
# embedded in this rendered representation. Optional.
|
166
|
+
#
|
167
|
+
# +references+:: A Hoodoo::Presenters::Embedding::References instance
|
168
|
+
# that contains UUIDs which are to be embedded in this
|
169
|
+
# rendered representation as references. Optional.
|
170
|
+
#
|
171
|
+
# +secured_with+:: An ActiveRecord::Base subclass instance where the
|
172
|
+
# model class includes a +secure_with+ declaration. As
|
173
|
+
# per documentation for
|
174
|
+
# Hoodoo::ActiveRecord::Secure::ClassMethods#secure and
|
175
|
+
# Hoodoo::ActiveRecord::Secure::ClassMethods#secure_with,
|
176
|
+
# this leads (potentially) to the generation of the
|
177
|
+
# +secured_with+ field and object value in the rendered
|
178
|
+
# resource data.
|
179
|
+
#
|
180
|
+
def self.render_in( context, data, options = {} )
|
181
|
+
uuid = options[ :uuid ]
|
182
|
+
created_at = options[ :created_at ]
|
183
|
+
language = options[ :language ] || context.request.locale
|
184
|
+
secured_with = options[ :secured_with ]
|
185
|
+
embeds = options[ :embeds ]
|
186
|
+
references = options[ :references ]
|
187
|
+
|
188
|
+
target = self.render( data, uuid, created_at, language )
|
189
|
+
|
190
|
+
if secured_with.is_a?( ::ActiveRecord::Base )
|
191
|
+
result_hash = {}
|
192
|
+
extra_scope_map = secured_with.class.secured_with()
|
193
|
+
|
194
|
+
extra_scope_map.each do | model_field_name, key_or_options |
|
195
|
+
resource_field = if key_or_options.is_a?( ::Hash )
|
196
|
+
next if key_or_options[ :hide_from_resource ] == true
|
197
|
+
key_or_options[ :resource_field_name ] || model_field_name
|
198
|
+
else
|
199
|
+
model_field_name
|
200
|
+
end
|
201
|
+
|
202
|
+
result_hash[ resource_field.to_s ] = secured_with.send( model_field_name )
|
203
|
+
end unless extra_scope_map.nil?
|
204
|
+
|
205
|
+
target[ 'secured_with' ] = result_hash unless result_hash.empty?
|
206
|
+
end
|
207
|
+
|
208
|
+
target[ '_embed' ] = embeds.retrieve() unless embeds.nil?
|
209
|
+
target[ '_reference' ] = references.retrieve() unless references.nil?
|
210
|
+
|
211
|
+
return target
|
212
|
+
end
|
213
|
+
|
214
|
+
# Is the given rendering of a resource valid? Returns an array of
|
215
|
+
# Error Primitive types (as hashes); this will be empty if the data
|
216
|
+
# given is valid.
|
217
|
+
#
|
218
|
+
# +data+:: Ruby Hash representation of JSON data that is to be validated
|
219
|
+
# against 'this' schema. Keys must be Strings, not Symbols.
|
220
|
+
#
|
221
|
+
# +as_resource+:: Check Resource common fields - +id+, +kind+,
|
222
|
+
# +created_at+ and (for an internationalised resource)
|
223
|
+
# +language+. Otherwise, only basic data schema is
|
224
|
+
# examined. Optional; default is +false+.
|
225
|
+
#
|
226
|
+
def self.validate( data, as_resource = false )
|
227
|
+
errors = @schema.validate( data )
|
228
|
+
|
229
|
+
if as_resource
|
230
|
+
common_fields = {
|
231
|
+
'id' => data[ :id ],
|
232
|
+
'created_at' => data[ :created_at ],
|
233
|
+
'kind' => data[ :kind ]
|
234
|
+
}
|
235
|
+
|
236
|
+
if self.is_internationalised?
|
237
|
+
common_fields[ 'internationalised' ] = data[ 'internationalised' ]
|
238
|
+
Hoodoo::Presenters::CommonResourceFields.get_schema.properties[ 'language' ].required = true
|
239
|
+
end
|
240
|
+
|
241
|
+
errors.merge!( Hoodoo::Presenters::CommonResourceFields.validate( data, false ) )
|
242
|
+
|
243
|
+
Hoodoo::Presenters::CommonResourceFields.get_schema.properties[ 'language' ].required = false
|
244
|
+
end
|
245
|
+
|
246
|
+
return errors
|
247
|
+
end
|
248
|
+
|
249
|
+
# Walk the schema graph and invoke the given block on each field within
|
250
|
+
# it, passing the field instances to the block for each call.
|
251
|
+
#
|
252
|
+
# All fields including the top-level "root" property (which has an empty
|
253
|
+
# string for a name) will be passed to the block in order of definition,
|
254
|
+
# recursing into nested objects, arrays and so-on as each is encountered.
|
255
|
+
#
|
256
|
+
def self.walk( &block )
|
257
|
+
@schema.walk( &block )
|
258
|
+
end
|
259
|
+
|
260
|
+
# Does this presenter use internationalisation? Returns +true+ if so,
|
261
|
+
# else +false+.
|
262
|
+
#
|
263
|
+
def self.is_internationalised?
|
264
|
+
@schema.is_internationalised?
|
265
|
+
end
|
266
|
+
|
267
|
+
# Return the schema graph. See also #get_schema_definition.
|
268
|
+
#
|
269
|
+
def self.get_schema
|
270
|
+
@schema
|
271
|
+
end
|
272
|
+
|
273
|
+
# Read back the block that defined the schema graph. See also
|
274
|
+
# #get_schema.
|
275
|
+
#
|
276
|
+
def self.get_schema_definition
|
277
|
+
@schema_definition
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|