active_spy 1.4.4 → 2.0.0.pre1
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 +4 -4
- data/Gemfile +7 -8
- data/Gemfile.lock +57 -108
- data/Rakefile +19 -9
- data/active_spy.gemspec +29 -38
- data/lib/active_spy.rb +16 -64
- data/lib/active_spy/agent.rb +77 -0
- data/lib/active_spy/handler.rb +124 -0
- data/lib/active_spy/station.rb +56 -0
- data/lib/active_spy/version.rb +10 -0
- metadata +46 -55
- data/VERSION +0 -1
- data/app/controllers/active_spy/notifications_controller.rb +0 -71
- data/lib/active_spy/base.rb +0 -9
- data/lib/active_spy/configuration.rb +0 -106
- data/lib/active_spy/rails/base.rb +0 -140
- data/lib/active_spy/rails/engine.rb +0 -7
- data/lib/active_spy/rails/hook_list.rb +0 -141
- data/lib/active_spy/rails/listener.rb +0 -117
- data/lib/active_spy/rails/railtie.rb +0 -13
- data/lib/active_spy/rails/spy.rb +0 -70
- data/lib/active_spy/rails/validation.rb +0 -87
- data/lib/active_spy/spy/spy.rb +0 -42
- data/lib/active_spy/spy/spy_list.rb +0 -91
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
1.4.4
|
@@ -1,71 +0,0 @@
|
|
1
|
-
class UnsupportedORM < RuntimeError
|
2
|
-
end
|
3
|
-
|
4
|
-
module ActiveSpy
|
5
|
-
# Controller to handle notifications request coming from an event-runner
|
6
|
-
# instance.
|
7
|
-
#
|
8
|
-
class NotificationsController < ActionController::Base
|
9
|
-
def handle
|
10
|
-
request.format = 'application/json'
|
11
|
-
hooks = ActiveSpy::Rails::HookList.hooks
|
12
|
-
result = nil
|
13
|
-
hooks.each do |hook|
|
14
|
-
if hook['post_class'].downcase == params['class']
|
15
|
-
handle_result(hook, params) and return
|
16
|
-
end
|
17
|
-
end
|
18
|
-
render nothing: true, status: :not_found
|
19
|
-
end
|
20
|
-
|
21
|
-
def handle_result(hook, params)
|
22
|
-
::Rails.logger.warn("[EVENT][#{hook['post_class']}] Event with result: #{params}")
|
23
|
-
result = get_result(hook, params)
|
24
|
-
::Rails.logger.warn("[EVENT][#{hook['post_class']}] Listener result: #{result}")
|
25
|
-
if result.is_a? Array
|
26
|
-
handle_array_result(hook, result, params)
|
27
|
-
elsif is_a_model?(result)
|
28
|
-
handle_model_result(hook, result, params)
|
29
|
-
else
|
30
|
-
render nothing: true
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def is_a_model?(something)
|
35
|
-
if defined?(ActiveRecord)
|
36
|
-
something.is_a? ActiveRecord::Base
|
37
|
-
elsif defined?(Mongoid)
|
38
|
-
something.class.included_modules.include? Mongoid::Document
|
39
|
-
else
|
40
|
-
raise UnsupportedORM
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def get_result(hook, params)
|
45
|
-
listener = "#{hook['post_class']}Listener".constantize
|
46
|
-
result = listener.new.handle(params['event'])
|
47
|
-
end
|
48
|
-
|
49
|
-
def handle_model_result(hook, result, params)
|
50
|
-
if result.errors.present?
|
51
|
-
::Rails.logger.warn("[EVENT][#{hook['post_class']}] Result errors: #{result.errors.full_messages}")
|
52
|
-
render json: result.errors, status: :unprocessable_entity
|
53
|
-
else
|
54
|
-
render nothing: true
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def handle_array_result(hook, result, params)
|
59
|
-
model_with_errors = result.select { |m| m.errors.present? }
|
60
|
-
if model_with_errors.any?
|
61
|
-
::Rails.logger.warn("[EVENT][#{hook['post_class']}] Error receiving event #{params}")
|
62
|
-
model_with_errors.each do |model|
|
63
|
-
::Rails.logger.warn("[EVENT][#{hook['post_class']}] #{model} errors: #{model.errors.full_messages}")
|
64
|
-
end
|
65
|
-
render nothing: true, status: :internal_server_error
|
66
|
-
else
|
67
|
-
render nothing: true
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/lib/active_spy/base.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
module ActiveSpy
|
2
|
-
# Defines a class to hold the configuration used to send events.
|
3
|
-
#
|
4
|
-
class Configuration
|
5
|
-
class << self
|
6
|
-
# Set the application host
|
7
|
-
#
|
8
|
-
# @param [String] host to set
|
9
|
-
#
|
10
|
-
# @return [String] the host set
|
11
|
-
def host(host = nil)
|
12
|
-
@host = host unless host.nil?
|
13
|
-
@host
|
14
|
-
end
|
15
|
-
|
16
|
-
# Set the application port
|
17
|
-
#
|
18
|
-
# @param [String] port to set
|
19
|
-
#
|
20
|
-
# @return [String] the port set
|
21
|
-
def port(port = nil)
|
22
|
-
@port = port unless port.nil?
|
23
|
-
@port
|
24
|
-
end
|
25
|
-
|
26
|
-
# Set the application name
|
27
|
-
#
|
28
|
-
# @param [String] name to set
|
29
|
-
#
|
30
|
-
# @return [String] the name set
|
31
|
-
def name(name = nil)
|
32
|
-
@name = name unless name.nil?
|
33
|
-
@name
|
34
|
-
end
|
35
|
-
|
36
|
-
# Set the default event-runner host
|
37
|
-
#
|
38
|
-
# @param [String] host to set
|
39
|
-
#
|
40
|
-
# @return [String] the host set
|
41
|
-
def event_host(host = nil)
|
42
|
-
@event_host = host unless host.nil?
|
43
|
-
@event_host
|
44
|
-
end
|
45
|
-
|
46
|
-
# Set the default event-tunner verify_ssl mode
|
47
|
-
#
|
48
|
-
# @param [String] host to set
|
49
|
-
#
|
50
|
-
# @return [String] the host set
|
51
|
-
def event_verify_ssl(event_verify_ssl = nil)
|
52
|
-
@event_verify_ssl = event_verify_ssl unless event_verify_ssl.nil?
|
53
|
-
@event_verify_ssl
|
54
|
-
end
|
55
|
-
|
56
|
-
# Set if the gem is in development mode or not.
|
57
|
-
#
|
58
|
-
# @param [Boolean] development moded state to set
|
59
|
-
#
|
60
|
-
# @return [Boolean] development moded state to set
|
61
|
-
def development_mode(mode = nil, options = nil)
|
62
|
-
unless mode.nil?
|
63
|
-
@development_mode = mode
|
64
|
-
@skip_validations = options[:skip_validations] if options.present?
|
65
|
-
end
|
66
|
-
@development_mode
|
67
|
-
end
|
68
|
-
|
69
|
-
# Simple reader for +skip_validations+ attribute.
|
70
|
-
#
|
71
|
-
def skip_validations
|
72
|
-
@skip_validations
|
73
|
-
end
|
74
|
-
|
75
|
-
# Imperative method to set development mode.
|
76
|
-
#
|
77
|
-
def development_mode!
|
78
|
-
@development_mode = true
|
79
|
-
end
|
80
|
-
|
81
|
-
# Set the default event-runner port
|
82
|
-
#
|
83
|
-
# @param [String] port to set
|
84
|
-
#
|
85
|
-
# @return [String] the port set
|
86
|
-
def event_port(port = nil)
|
87
|
-
@event_port = port unless port.nil?
|
88
|
-
@event_port
|
89
|
-
end
|
90
|
-
|
91
|
-
# See how are the settings
|
92
|
-
#
|
93
|
-
# @return [Hash] actual settings
|
94
|
-
def settings
|
95
|
-
{ name: @name, hostname: @host, port: @port }
|
96
|
-
end
|
97
|
-
|
98
|
-
# See how are the event settings
|
99
|
-
#
|
100
|
-
# @return [Hash] actual event settings
|
101
|
-
def event_settings
|
102
|
-
{ host: @event_host, port: @event_port, verify_ssl: @event_verify_ssl }
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,140 +0,0 @@
|
|
1
|
-
require 'rest-client'
|
2
|
-
require 'singleton'
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
module ActiveSpy
|
6
|
-
# Module to hold Rails specific classes and helpers.
|
7
|
-
#
|
8
|
-
module Rails
|
9
|
-
# Default template for callbacks handlers.
|
10
|
-
#
|
11
|
-
class Base
|
12
|
-
def initialize(object)
|
13
|
-
@object = object
|
14
|
-
inject_is_new_method(@object)
|
15
|
-
@object.is_new = true if @object.new_record?
|
16
|
-
end
|
17
|
-
|
18
|
-
# Overriding to avoid sending the object to server 2 times (in both
|
19
|
-
# before and after callabcks).
|
20
|
-
#
|
21
|
-
def respond_to?(method)
|
22
|
-
method.include?('after_')
|
23
|
-
end
|
24
|
-
|
25
|
-
# Inject an attribute in the +object+, called +is_new?+ and a setter
|
26
|
-
# for it.
|
27
|
-
#
|
28
|
-
def inject_is_new_method(object)
|
29
|
-
object.instance_eval do
|
30
|
-
def is_new=(value)
|
31
|
-
@is_new = value
|
32
|
-
end
|
33
|
-
|
34
|
-
def is_new?
|
35
|
-
@is_new
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Handles the generic +save+. Determines which rail action was done,
|
41
|
-
# +create+ or +update+ and call the right callback.
|
42
|
-
#
|
43
|
-
def after_save
|
44
|
-
action = get_action('save')
|
45
|
-
send("after_#{action}")
|
46
|
-
end
|
47
|
-
|
48
|
-
# Handles a +create+ callback, prepare and send the request to the event-runner.
|
49
|
-
#
|
50
|
-
def after_create
|
51
|
-
request_params = get_request_params('create')
|
52
|
-
prepare_request(request_params)
|
53
|
-
send_event_request unless ActiveSpy::Configuration.development_mode
|
54
|
-
end
|
55
|
-
|
56
|
-
# Handles an +update+ callback, prepare and send the request to the event-runner.
|
57
|
-
#
|
58
|
-
def after_update
|
59
|
-
request_params = get_request_params('update')
|
60
|
-
prepare_request(request_params)
|
61
|
-
send_event_request unless ActiveSpy::Configuration.development_mode
|
62
|
-
end
|
63
|
-
|
64
|
-
# Handles an +destroy+ callback, prepare and send the request to the event-runner.
|
65
|
-
#
|
66
|
-
def after_destroy
|
67
|
-
request_params = get_request_params('destroy')
|
68
|
-
prepare_request(request_params)
|
69
|
-
send_event_request unless ActiveSpy::Configuration.development_mode
|
70
|
-
end
|
71
|
-
|
72
|
-
# Prepare a request with +request_params+, validates the request and
|
73
|
-
# remove the injected +is_mew_method+, because it's not needed anymore.
|
74
|
-
#
|
75
|
-
def prepare_request(request_params)
|
76
|
-
@event_json = { event: request_params }.to_json
|
77
|
-
ActiveSpy::Rails::Validation::Event.new(@event_json).validate! unless ActiveSpy::Configuration.skip_validations
|
78
|
-
remove_is_new_method(@object)
|
79
|
-
end
|
80
|
-
|
81
|
-
# Sends the event request to the configured event-runner instance.
|
82
|
-
#
|
83
|
-
def send_event_request
|
84
|
-
response = nil
|
85
|
-
host = ActiveSpy::Configuration.event_host
|
86
|
-
port = ActiveSpy::Configuration.event_port
|
87
|
-
verify_ssl = ActiveSpy::Configuration.event_verify_ssl
|
88
|
-
url = "#{host}:#{port}/events"
|
89
|
-
|
90
|
-
params = { headers: { content_type: :json }, method: :post, url: url, payload: @event_json }
|
91
|
-
params[:verify_ssl] = verify_ssl if verify_ssl
|
92
|
-
|
93
|
-
begin
|
94
|
-
response = RestClient::Request.execute(params)
|
95
|
-
rescue => e
|
96
|
-
::Rails.logger.info(e.response)
|
97
|
-
end
|
98
|
-
if response && defined?(Rails) && !ActiveSpy::Configuration.development_mode
|
99
|
-
::Rails.logger.info('[SPY] Event sent to event-runner.')
|
100
|
-
::Rails.logger.info("[SPY] Event-runner response code: #{response.code}")
|
101
|
-
::Rails.logger.info("[SPY] Event-runner response: #{response.body}")
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# Get the event request params for a given +method+.
|
106
|
-
#
|
107
|
-
def get_request_params(action)
|
108
|
-
# real_method = method.to_s.split('_').last
|
109
|
-
# action = get_action(real_method)
|
110
|
-
{
|
111
|
-
type: @object.class.name,
|
112
|
-
actor: @object.instance_variable_get('@actor'),
|
113
|
-
realm: @object.instance_variable_get('@realm'),
|
114
|
-
payload: @object.payload_for(action),
|
115
|
-
action: action
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
# Remove a previously added +is_new+ attribute from a given object.
|
120
|
-
#
|
121
|
-
def remove_is_new_method(object)
|
122
|
-
object.instance_eval do
|
123
|
-
undef :is_new=
|
124
|
-
undef :is_new?
|
125
|
-
instance_variable_set(:@is_new, nil)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns the correct action for the method called in the model.
|
130
|
-
#
|
131
|
-
def get_action(real_method)
|
132
|
-
if real_method == 'save'
|
133
|
-
return 'create' if @object.is_new?
|
134
|
-
return 'update'
|
135
|
-
end
|
136
|
-
'destroy'
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
@@ -1,141 +0,0 @@
|
|
1
|
-
module ActiveSpy
|
2
|
-
module Rails
|
3
|
-
# Class used to hold all the events hook's paths and later sync
|
4
|
-
# them with an event runner instance.
|
5
|
-
#
|
6
|
-
class HookList
|
7
|
-
include Singleton
|
8
|
-
|
9
|
-
# Simple attribute reader for hooks
|
10
|
-
#
|
11
|
-
attr_reader :hooks
|
12
|
-
|
13
|
-
# Initialize an empty hook list
|
14
|
-
#
|
15
|
-
def initialize
|
16
|
-
host = ActiveSpy::Configuration.event_host
|
17
|
-
port = ActiveSpy::Configuration.event_port
|
18
|
-
name = ActiveSpy::Configuration.name.downcase.gsub(' ', '-').strip
|
19
|
-
|
20
|
-
@verify_ssl = ActiveSpy::Configuration.event_verify_ssl
|
21
|
-
@base_service_url = "#{host}:#{port}/services/#{name}"
|
22
|
-
@hooks = []
|
23
|
-
end
|
24
|
-
|
25
|
-
# Proxy all methods called in the {ActiveSpy::Hook} to
|
26
|
-
# {ActiveSpy::Hook} instance. Just a syntax sugar.
|
27
|
-
#
|
28
|
-
def self.method_missing(method, *args, &block)
|
29
|
-
instance.send(method, *args, &block)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Clear the hook list.
|
33
|
-
#
|
34
|
-
def clear
|
35
|
-
@hooks = []
|
36
|
-
end
|
37
|
-
|
38
|
-
# forward {<<} method to the hook list.
|
39
|
-
#
|
40
|
-
def <<(other)
|
41
|
-
@hooks << other
|
42
|
-
end
|
43
|
-
|
44
|
-
# Register in event runner all the hooks defined in the list. If some of
|
45
|
-
# them already exists, they will be excluded and readded.
|
46
|
-
#
|
47
|
-
def register
|
48
|
-
@hooks = @hooks.map(&:to_hook).flatten
|
49
|
-
old_hooks = get_old_hooks
|
50
|
-
hooks_to_delete = get_hooks_to_delete(old_hooks)
|
51
|
-
hooks_to_add = get_hooks_to_add(old_hooks)
|
52
|
-
delete_hooks(hooks_to_delete) if hooks_to_delete.any?
|
53
|
-
add_hooks(hooks_to_add) unless hooks_to_add.empty?
|
54
|
-
end
|
55
|
-
|
56
|
-
# Get the old hooks list for this service from the event-runner
|
57
|
-
#
|
58
|
-
def get_old_hooks
|
59
|
-
request = if @verify_ssl
|
60
|
-
RestClient::Request.execute(method: :get, url: @base_service_url, verify_ssl: @verify_ssl)
|
61
|
-
else
|
62
|
-
RestClient.get(@base_service_url)
|
63
|
-
end
|
64
|
-
|
65
|
-
JSON.load(request)['hooks']
|
66
|
-
end
|
67
|
-
|
68
|
-
# Select from old hooks those that should be deleted from event runner.
|
69
|
-
#
|
70
|
-
def get_hooks_to_delete(old_hooks)
|
71
|
-
hooks_to_delete = []
|
72
|
-
old_hooks.each do |old_hook|
|
73
|
-
found = false
|
74
|
-
@hooks.each do |hook|
|
75
|
-
if hook['class'] == old_hook['class'] && old_hook['active']
|
76
|
-
found = true
|
77
|
-
break
|
78
|
-
end
|
79
|
-
end
|
80
|
-
next if found
|
81
|
-
hooks_to_delete << old_hook
|
82
|
-
end
|
83
|
-
hooks_to_delete
|
84
|
-
end
|
85
|
-
|
86
|
-
# Select from the hooks defined in the app those that should be created
|
87
|
-
# in the event runner.
|
88
|
-
#
|
89
|
-
def get_hooks_to_add(old_hooks)
|
90
|
-
hooks_to_add = []
|
91
|
-
@hooks.each do |hook|
|
92
|
-
found = false
|
93
|
-
old_hooks.each do |old_hook|
|
94
|
-
if hook['class'] == old_hook['class'] && old_hook['active']
|
95
|
-
found = true
|
96
|
-
break
|
97
|
-
end
|
98
|
-
end
|
99
|
-
next if found
|
100
|
-
hooks_to_add << hook
|
101
|
-
end
|
102
|
-
hooks_to_add
|
103
|
-
end
|
104
|
-
|
105
|
-
# Properly delete the +hooks_to_delete+ in the event runner.
|
106
|
-
#
|
107
|
-
def delete_hooks(hooks_to_delete)
|
108
|
-
hooks_to_delete.each do |hook|
|
109
|
-
url = "#{@base_service_url}/hooks/#{hook['id']}"
|
110
|
-
if @verify_ssl
|
111
|
-
RestClient::Request.execute(method: :delete, url: url, verify_ssl: @verify_ssl)
|
112
|
-
else
|
113
|
-
RestClient.delete url
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# # Properly creates the +hooks_to_add+ in the event runner.
|
119
|
-
#
|
120
|
-
def add_hooks(hooks_to_add)
|
121
|
-
url = "#{@base_service_url}/hooks"
|
122
|
-
|
123
|
-
hooks_to_add.each do |hook|
|
124
|
-
hook = {
|
125
|
-
'hook' => {
|
126
|
-
'class' => hook['class'],
|
127
|
-
'post_path' => ActiveSpy::Engine.routes.url_helpers.notifications_path(hook['post_class'].downcase),
|
128
|
-
}
|
129
|
-
}
|
130
|
-
|
131
|
-
if @verify_ssl
|
132
|
-
RestClient::Request.execute(method: :post, url: url, payload: hook.to_json,
|
133
|
-
headers: { content_type: :json }, verify_ssl: @verify_ssl)
|
134
|
-
else
|
135
|
-
RestClient.post url, hook.to_json, content_type: :json
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|