active_spy 1.4.4 → 2.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|