oh_my_log 1.0.1
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/.codeclimate.yml +65 -0
- data/.document +4 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +73 -0
- data/.ruby-version +1 -0
- data/.travis.yml +31 -0
- data/Appraisals +25 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +180 -0
- data/Rakefile +20 -0
- data/blue_print/oh_my_log_initializer.rb +8 -0
- data/gemfiles/rails_4.2_stable.gemfile +8 -0
- data/gemfiles/rails_4.2_stable.gemfile.lock +181 -0
- data/gemfiles/rails_5.0_stable.gemfile +8 -0
- data/gemfiles/rails_5.0_stable.gemfile.lock +188 -0
- data/gemfiles/rails_5.1_stable.gemfile +8 -0
- data/gemfiles/rails_5.1_stable.gemfile.lock +188 -0
- data/gemfiles/rails_5.2_stable.gemfile +8 -0
- data/gemfiles/rails_5.2_stable.gemfile.lock +196 -0
- data/lib/oh_my_log/active_record_observer.rb +11 -0
- data/lib/oh_my_log/configuration.rb +37 -0
- data/lib/oh_my_log/effect.rb +18 -0
- data/lib/oh_my_log/log.rb +140 -0
- data/lib/oh_my_log/mongoid_observer.rb +11 -0
- data/lib/oh_my_log/observer_factory.rb +90 -0
- data/lib/oh_my_log/request.rb +22 -0
- data/lib/oh_my_log/result.rb +48 -0
- data/lib/oh_my_log/selector.rb +44 -0
- data/lib/oh_my_log/version.rb +5 -0
- data/lib/oh_my_log.rb +47 -0
- data/lib/railtie.rb +48 -0
- data/lib/tasks/oh_my_log.rake +32 -0
- data/oh_my_log.gemspec +36 -0
- data/spec/controllers/foos_controller_spec.rb +116 -0
- data/spec/dummy/Rakefile +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/foos_controller.rb +23 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/models/doo.rb +2 -0
- data/spec/dummy/app/models/foo.rb +2 -0
- data/spec/dummy/app/views/foos/create.html.erb +0 -0
- data/spec/dummy/app/views/foos/index.html.erb +0 -0
- data/spec/dummy/app/views/foos/show.html.erb +0 -0
- data/spec/dummy/app/views/foos/two_in_one.html.erb +0 -0
- data/spec/dummy/app/views/foos/update.html.erb +0 -0
- data/spec/dummy/config/application.rb +20 -0
- data/spec/dummy/config/boot.rb +6 -0
- data/spec/dummy/config/database.yml +7 -0
- data/spec/dummy/config/environment.rb +2 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/migration_class.rb +8 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/config/secrets.yml +2 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20120508165529_create_tables.rb +21 -0
- data/spec/rails_helper.rb +1 -0
- data/spec/spec_helper.rb +32 -0
- metadata +262 -0
@@ -0,0 +1,140 @@
|
|
1
|
+
require "active_support/all"
|
2
|
+
require_relative '../oh_my_log'
|
3
|
+
|
4
|
+
module OhMyLog
|
5
|
+
module Log
|
6
|
+
#all the models effected by this
|
7
|
+
mattr_accessor :targets
|
8
|
+
#config for this log
|
9
|
+
mattr_accessor :configuration
|
10
|
+
#contains all the request done in a session
|
11
|
+
mattr_accessor :history
|
12
|
+
#last action done by the user
|
13
|
+
mattr_accessor :last_recorded
|
14
|
+
|
15
|
+
def self.configuration_rule
|
16
|
+
configuration.models.keys[0]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configuration_models
|
20
|
+
Log.configuration.models.values
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.configure
|
24
|
+
self.configuration ||= Configuration.new
|
25
|
+
self.targets = []
|
26
|
+
self.history = []
|
27
|
+
yield(configuration)
|
28
|
+
self.configuration.add_selector(Selector.universal_for) if self.configuration.selectors.empty?
|
29
|
+
self.configuration.process_path
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.clear
|
33
|
+
self.history = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.reset
|
37
|
+
self.clear
|
38
|
+
self.flush
|
39
|
+
self.configuration = nil
|
40
|
+
self.last_recorded = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.add_target(target)
|
44
|
+
#do not add duplicates
|
45
|
+
self.targets << target unless self.targets.include? target
|
46
|
+
end
|
47
|
+
|
48
|
+
#Is the action/controller passed in params allowed by the selectors
|
49
|
+
# TODO: add method as well in the selector
|
50
|
+
#
|
51
|
+
|
52
|
+
def self.permitted_range?(selector, status)
|
53
|
+
in_range = true
|
54
|
+
case selector.status_codes.keys[0]
|
55
|
+
when "ONLY"
|
56
|
+
in_range = false
|
57
|
+
selector.status_codes.values[0].each do |range|
|
58
|
+
range = (range.to_i..range.to_i) if range.class != Range
|
59
|
+
in_range = (range === status.to_i) unless in_range
|
60
|
+
end
|
61
|
+
when "EXCEPT"
|
62
|
+
selector.status_codes.values[0].each do |range|
|
63
|
+
in_range = false if (range === status.to_i)
|
64
|
+
end
|
65
|
+
when "ALL"
|
66
|
+
in_range = true
|
67
|
+
else
|
68
|
+
raise "UNDEFINED RULE: please us any of [ONLY/EXCEPT/ALL]"
|
69
|
+
end
|
70
|
+
return in_range
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.permitted_controller?(selector, ctrl_name)
|
74
|
+
case selector.controllers.keys[0]
|
75
|
+
when "ALL"
|
76
|
+
permitted_controller = true
|
77
|
+
when "ONLY"
|
78
|
+
permitted_controller = selector.controllers.values[0].include?(ctrl_name.classify)
|
79
|
+
when "EXCEPT"
|
80
|
+
permitted_controller = !selector.controllers.values[0].include?(ctrl_name.classify)
|
81
|
+
else
|
82
|
+
raise "UNDEFINED RULE: please us any of [ONLY/EXCEPT/ALL]"
|
83
|
+
end
|
84
|
+
return permitted_controller
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.permitted_ip?(selector, ip)
|
88
|
+
case selector.ips.keys[0]
|
89
|
+
when "EXCEPT"
|
90
|
+
permitted_ip = selector.ips.values[0].include?(ip)
|
91
|
+
when "ONLY"
|
92
|
+
permitted_ip = !selector.ips.values[0].empty? && !selector.ips.values[0].include?(ip)
|
93
|
+
when "ALL"
|
94
|
+
permitted_ip = true
|
95
|
+
else
|
96
|
+
raise "UNDEFINED RULE: please us any of [ONLY/EXCEPT/ALL]"
|
97
|
+
end
|
98
|
+
return permitted_ip
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.permitted_action?(selector, ctrl_action)
|
102
|
+
permitted_action = true
|
103
|
+
case selector.actions.keys[0]
|
104
|
+
when "EXCEPT"
|
105
|
+
selector.actions.values[0].each {|action| permitted_action = false if action.downcase.to_sym == ctrl_action}
|
106
|
+
when "ONLY"
|
107
|
+
selector.actions.values[0].each {|action| permitted_action = true if action.downcase.to_sym == ctrl_action}
|
108
|
+
when "ALL"
|
109
|
+
permitted_action = true
|
110
|
+
else
|
111
|
+
raise "UNDEFINED RULE: please us any of [ONLY/EXCEPT/ALL]"
|
112
|
+
end
|
113
|
+
return permitted_action
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.loggable?(params, status, method)
|
117
|
+
ctrl_name = params["controller"]
|
118
|
+
ctrl_action = params["action"].to_sym
|
119
|
+
final_response = false
|
120
|
+
self.configuration.selectors.each do |selector|
|
121
|
+
final_response = permitted_range?(selector, status)
|
122
|
+
return false unless final_response
|
123
|
+
|
124
|
+
final_response = final_response && permitted_controller?(selector, ctrl_name)
|
125
|
+
return false unless final_response
|
126
|
+
|
127
|
+
final_response = final_response && permitted_ip?(selector, Thread.current[:remote_ip])
|
128
|
+
return false unless final_response
|
129
|
+
|
130
|
+
return false unless permitted_action?(selector, ctrl_action)
|
131
|
+
end
|
132
|
+
final_response
|
133
|
+
end
|
134
|
+
|
135
|
+
#once we processed an action we can get rid of all the cached data(targets) stored in the Log
|
136
|
+
def self.flush
|
137
|
+
self.targets = []
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module OhMyLog
|
2
|
+
class MongoidObserver < ::Mongoid::Observer
|
3
|
+
|
4
|
+
#this is the callback that happens every time after we made changes to the model
|
5
|
+
def after_save(model)
|
6
|
+
#we only add this model in the target list if this model got SUCCESSFULLY changed
|
7
|
+
must_be_logged = model.methods.include?(:saved_changes) ? model.saved_changes.empty? : model.changes.empty?
|
8
|
+
Log::add_target(model) unless must_be_logged
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module OhMyLog
|
2
|
+
module ObserverFactory
|
3
|
+
|
4
|
+
#this will initialize the observes logic
|
5
|
+
def self.activate_observers
|
6
|
+
#should raise an error if there are no observers -> "Build the observer list using the task"
|
7
|
+
Rails.application.eager_load!
|
8
|
+
|
9
|
+
build_activerecord_obs if defined?(ActiveRecord)
|
10
|
+
build_mongoid_obs if defined?(Mongoid)
|
11
|
+
end
|
12
|
+
|
13
|
+
#this will be runned by the task to build the collection of observed models FILE
|
14
|
+
require 'fileutils'
|
15
|
+
|
16
|
+
def self.generate_collection
|
17
|
+
Rails.application.eager_load!
|
18
|
+
|
19
|
+
#rebuild folder if it's already there
|
20
|
+
FileUtils.rm_rf(Rails.root + "app/models/observers/oh_my_log") if File.directory?(Rails.root + "app/models/observers/oh_my_log")
|
21
|
+
FileUtils.mkdir_p(Rails.root + "app/models/observers/oh_my_log")
|
22
|
+
generate_collection_for(ActiveRecord) if defined?(ActiveRecord)
|
23
|
+
generate_collection_for(Mongoid) if defined?(Mongoid)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.remove_collection
|
27
|
+
FileUtils.rm_rf(Rails.root + "app/models/observers/oh_my_log") if File.directory?(Rails.root + "app/models/observers/oh_my_log")
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def self.build_activerecord_obs
|
33
|
+
supported_models = supported_models_for(ActiveRecord)
|
34
|
+
supported_models.each {|class_name| ActiveRecord::Base.add_observer class_name.instance}
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.build_mongoid_obs
|
38
|
+
supported_models = supported_models_for(Mongoid)
|
39
|
+
supported_models.each {|class_name| ::Mongoid::Document.add_observer class_name.instance}
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.generate_collection_for(klass)
|
43
|
+
models = available_models_for(klass)
|
44
|
+
models.each do |model|
|
45
|
+
model_file = File.join("#{Rails.root}/app", "models", "observers", "oh_my_log", model.underscore + "_observer.rb")
|
46
|
+
p "Generated #{model_file}"
|
47
|
+
File.open(model_file, "w+") do |f|
|
48
|
+
f << "class #{model + "Observer"} < OhMyLog::#{klass}Observer\nend"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.supported_models_for(klass)
|
54
|
+
supported_models = []
|
55
|
+
models = available_models_for(klass)
|
56
|
+
models.each do |model|
|
57
|
+
if File.file?(Rails.root + "app/models/observers/oh_my_log/#{model.underscore}_observer.rb")
|
58
|
+
supported_models << ('::' + model + "Observer").constantize
|
59
|
+
else
|
60
|
+
p "You didn't create an observer for #{model.constantize}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
return supported_models
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def self.available_models_for(klass)
|
69
|
+
config_rule = Log.configuration_rule
|
70
|
+
config_models = Log.configuration_models
|
71
|
+
models = []
|
72
|
+
if klass == ActiveRecord
|
73
|
+
models = ActiveRecord::Base.subclasses.collect {|type| type.name}
|
74
|
+
models = models + ApplicationRecord.subclasses.collect {|type| type.name} if defined?(ApplicationRecord)
|
75
|
+
elsif klass == Mongoid
|
76
|
+
models = Mongoid.models.collect {|type| type.name}
|
77
|
+
end
|
78
|
+
#reject modules
|
79
|
+
models = models.reject {|model| model.include?("::") || model.include?("HABTM") || model.include?("Mongoid")}
|
80
|
+
case config_rule
|
81
|
+
when "ONLY"
|
82
|
+
return models.select {|model| config_models.include?(model)}
|
83
|
+
when "ALL"
|
84
|
+
return models
|
85
|
+
when "EXCEPT"
|
86
|
+
return models.reject {|model| config_models.include?(model)}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module OhMyLog
|
2
|
+
module Log
|
3
|
+
#the request is what the user is trying to do
|
4
|
+
class Request
|
5
|
+
attr_reader :sender, :date, :params, :method, :status
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
@sender = args[:sender]
|
9
|
+
@date = args[:date]
|
10
|
+
@params = args[:params]
|
11
|
+
@method = args[:method]
|
12
|
+
@status = args[:status]
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
user_info = @sender.try(:email)
|
17
|
+
sender = !user_info.blank? ? user_info : Thread.current["remote_ip"]
|
18
|
+
"#{@date}, #{sender}, #{@method}, #{@params}, #{@status}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Result contains the request and all the effects that a specific request caused all over the models
|
2
|
+
module OhMyLog
|
3
|
+
module Log
|
4
|
+
class Result
|
5
|
+
attr_reader :effects
|
6
|
+
attr_reader :request
|
7
|
+
|
8
|
+
def initialize(request)
|
9
|
+
@request = request
|
10
|
+
@effects = calculate_effects
|
11
|
+
end
|
12
|
+
|
13
|
+
# call this to record the current action done by the user
|
14
|
+
def record!
|
15
|
+
if OhMyLog::Log.configuration.print_log
|
16
|
+
p "REQUEST"
|
17
|
+
p @request.to_s
|
18
|
+
p "RESPONSE" unless @effects.empty?
|
19
|
+
@effects.each {|effect| p effect.to_s}
|
20
|
+
end
|
21
|
+
|
22
|
+
print_into_log
|
23
|
+
|
24
|
+
#we can record everything that happend (OPTIONALL)
|
25
|
+
if OhMyLog::Log.configuration.record_history
|
26
|
+
OhMyLog::Log.history << self
|
27
|
+
end
|
28
|
+
#We always save the last operation recorded
|
29
|
+
OhMyLog::Log.last_recorded = self
|
30
|
+
#save this string on file or upload it somewhere
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def print_into_log
|
36
|
+
OhMyLog::Log.configuration.log_instance.info('REQUEST')
|
37
|
+
OhMyLog::Log.configuration.log_instance.info(@request.to_s)
|
38
|
+
OhMyLog::Log.configuration.log_instance.info('RESPONSE') unless @effects.empty?
|
39
|
+
@effects.each {|effect| OhMyLog::Log.configuration.log_instance.info(effect.to_s)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def calculate_effects
|
43
|
+
return OhMyLog::Log::targets.map {|target| Effect.new(target)}
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module OhMyLog
|
2
|
+
module Log
|
3
|
+
#Selector is a set of rule that Log.loggable? will have to respect
|
4
|
+
class Selector
|
5
|
+
attr_reader :controllers, :actions, :status_codes, :ips
|
6
|
+
METHODS = ["GET", "HEAD", "POST", "PATCH", "PUT", "DELETE"].freeze
|
7
|
+
ACTIONS = ["ONLY", "EXCEPT", "ALL"].freeze
|
8
|
+
# add methods in the same style as anythingelse
|
9
|
+
# and it will affect the parameter method in the loggable function in LOG.rb
|
10
|
+
##EXCEPT O ONLY
|
11
|
+
def initialize(controllers: default_hash_setting, actions: default_hash_setting, ips: default_hash_setting, status_codes: default_hash_setting)
|
12
|
+
@controllers = controllers
|
13
|
+
@actions = actions
|
14
|
+
@ips = ips
|
15
|
+
@status_codes = status_codes
|
16
|
+
build_attr_setters
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def default_hash_setting
|
22
|
+
return {"ALL" => []}
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.default_hash_setting
|
26
|
+
return {"ALL" => []}
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_attr_setters
|
30
|
+
self.instance_variables.each do |attribute|
|
31
|
+
attribute = attribute.to_s.gsub("@", "")
|
32
|
+
self.define_singleton_method(:"set_#{attribute}") do |value|
|
33
|
+
raise "Unpermitted rule: use #{ACTIONS}" if attribute == "rule" && !ACTIONS.include?(value)
|
34
|
+
instance_variable_set("@#{attribute}", value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.universal_for(actions: default_hash_setting, controllers: default_hash_setting)
|
40
|
+
return Selector.new(controllers: controllers, actions: actions)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/oh_my_log.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rails/observers/activerecord/base'
|
2
|
+
#force LOAD the gem "rails-observers"
|
3
|
+
module ActiveRecord
|
4
|
+
autoload :Observer, 'rails/observers/activerecord/observer'
|
5
|
+
end
|
6
|
+
|
7
|
+
#load the gem's lib folder
|
8
|
+
Dir[File.dirname(__FILE__) + '/oh_my_log/*.rb'].each do |file|
|
9
|
+
name = File.basename(file, File.extname(file))
|
10
|
+
#we are gonna skip this file FOR NOW since it depends of gem loaded after the rails initializer
|
11
|
+
next if name == "mongoid_observer"
|
12
|
+
require_relative "oh_my_log/" + name
|
13
|
+
end
|
14
|
+
|
15
|
+
module OhMyLog
|
16
|
+
#call this after you configured the Log Module
|
17
|
+
def self.start
|
18
|
+
Railtie.start_oh_my_log
|
19
|
+
|
20
|
+
#the main loop to get callbacks from controllers
|
21
|
+
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
|
22
|
+
data = args[-1]
|
23
|
+
if Log::loggable?(data[:params], data[:status], data[:method])
|
24
|
+
request = Log::Request.new(sender: Thread.current[:user], date: Time.now.utc, params: data[:params], method: data[:method], status: data[:status])
|
25
|
+
result = Log::Result.new(request)
|
26
|
+
result.record!
|
27
|
+
end
|
28
|
+
Log::flush
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.generate_initializer
|
33
|
+
FileUtils.cp_r(File.expand_path(__dir__ + '/../blue_print/oh_my_log_initializer.rb'), Rails.root + "config/initializers")
|
34
|
+
p "Successfully created initializer!"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.destroy_initializer
|
38
|
+
path = Rails.root + "config/initializers/oh_my_log_initializer.rb"
|
39
|
+
File.delete(path) if File.exist?(path)
|
40
|
+
p "Successfully destroyed the initializer!"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
#load the script to inject code to rails source and create rake task
|
46
|
+
require_relative "railtie"
|
47
|
+
|
data/lib/railtie.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#let's inject some code into rails before and after the initialization
|
2
|
+
class Railtie < ::Rails::Railtie
|
3
|
+
#auto load our observers folder before rails freeze this variable
|
4
|
+
initializer 'activeservice.autoload', :before => :set_autoload_paths do |app|
|
5
|
+
if File.directory?(Rails.root + "app/models/observers/oh_my_log")
|
6
|
+
app.config.autoload_paths << "app/models/observers/oh_my_log"
|
7
|
+
else
|
8
|
+
p "Could not find the observers folder, did you use the task to generate them?"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
#now let's start our gem(only if there is an initializer) after the rails initialize process
|
13
|
+
config.after_initialize do
|
14
|
+
load Rails.root + "app/controllers/application_controller.rb"
|
15
|
+
class ::ApplicationController
|
16
|
+
before_action :get__session__info
|
17
|
+
|
18
|
+
def get__session__info
|
19
|
+
user = nil
|
20
|
+
if defined?(current_user)
|
21
|
+
user = current_user
|
22
|
+
elsif defined?(current_admin_user)
|
23
|
+
user = current_admin_user
|
24
|
+
end
|
25
|
+
Thread.current[:user] = user
|
26
|
+
Thread.current[:remote_ip] = request.remote_ip
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.start_oh_my_log
|
32
|
+
if defined?(Mongoid)
|
33
|
+
require 'mongoid-observers'
|
34
|
+
require_relative "oh_my_log/mongoid_observer"
|
35
|
+
end
|
36
|
+
begin
|
37
|
+
require Rails.root + "config/initializers/oh_my_log_initializer.rb"
|
38
|
+
::OhMyLog::ObserverFactory.activate_observers
|
39
|
+
rescue
|
40
|
+
return "could not start the gem, did you run oh_my_log:install ?"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#time to add some tasks
|
45
|
+
rake_tasks do
|
46
|
+
load 'tasks/oh_my_log.rake'
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :oh_my_log do
|
4
|
+
desc 'Generate the observers for each ActiveRecord model'
|
5
|
+
# in futuro fare che puoi passare parametri e in base a quello limita gli observer da generare
|
6
|
+
task generate_observers: :environment do
|
7
|
+
raise "Cannot create observers without an initializer, did you created it with 'oh_my_log:generate_initializer'" unless File.file?(Rails.root + 'config/initializers/oh_my_log_initializer.rb')
|
8
|
+
OhMyLog::ObserverFactory.generate_collection
|
9
|
+
end
|
10
|
+
desc 'Generate a template initializer for OhMyLog'
|
11
|
+
# in futuro puoi passare direttamente qui alcune impostazioni dell' initialize
|
12
|
+
task generate_initializer: :environment do
|
13
|
+
raise 'The initializer has been already generated!' if File.file?(Rails.root + 'config/initializers/oh_my_log_initializer')
|
14
|
+
OhMyLog.generate_initializer
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Install the gem by building initializer and observers'
|
18
|
+
task install: :environment do
|
19
|
+
OhMyLog.generate_initializer
|
20
|
+
p "generated initializer"
|
21
|
+
sleep(1)
|
22
|
+
require Rails.root + "config/initializers/oh_my_log_initializer.rb"
|
23
|
+
OhMyLog::ObserverFactory.generate_collection
|
24
|
+
p "generated collections"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Clean observers and initializer'
|
28
|
+
task clean: :environment do
|
29
|
+
OhMyLog.destroy_initializer
|
30
|
+
OhMyLog::ObserverFactory.remove_collection
|
31
|
+
end
|
32
|
+
end
|
data/oh_my_log.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'rubygems'
|
4
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
5
|
+
require 'oh_my_log/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = %q{oh_my_log}
|
9
|
+
s.authors = ["Fabrizio Spadaro"]
|
10
|
+
s.email = ["work.fabriziospadaro@gmail.com"]
|
11
|
+
s.license = "MIT"
|
12
|
+
s.version = OhMyLog::VERSION
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.date = %q{2018-11-26}
|
15
|
+
s.homepage = 'https://github.com/fabriziospadaro/oh_my_log'
|
16
|
+
s.summary = %q{A powerful auditing logging system}
|
17
|
+
s.files = `git ls-files`.split($\)
|
18
|
+
s.required_ruby_version = '>= 2.3.0' #, '<= 2.5.0'
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
if RUBY_VERSION >= '2.4'
|
22
|
+
s.add_runtime_dependency 'rails', '>= 4.2.0', '< 7.0'
|
23
|
+
else
|
24
|
+
s.add_runtime_dependency 'railties', '>= 4.2.0', '< 6.0'
|
25
|
+
end
|
26
|
+
s.add_runtime_dependency 'json'
|
27
|
+
s.add_runtime_dependency("rails-observers", "~> 0.1.5")
|
28
|
+
s.add_development_dependency 'coveralls'
|
29
|
+
s.add_development_dependency 'rubocop', '~> 0.59.2'
|
30
|
+
s.add_development_dependency 'bundler'
|
31
|
+
s.add_development_dependency 'appraisal'
|
32
|
+
s.add_development_dependency 'sqlite3', '1.3.10'
|
33
|
+
s.add_development_dependency 'rspec-core'
|
34
|
+
s.add_development_dependency 'wwtd'
|
35
|
+
s.add_development_dependency 'rspec-rails'
|
36
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe FoosController, type: :controller do
|
4
|
+
let(:oml) {OhMyLog::Log}
|
5
|
+
|
6
|
+
context "#When using a custom configuration for the Logger" do
|
7
|
+
before(:all) do
|
8
|
+
Rake::Task['oh_my_log:install'].invoke
|
9
|
+
Foo.destroy_all
|
10
|
+
Doo.destroy_all
|
11
|
+
OhMyLog.start
|
12
|
+
end
|
13
|
+
#reset the configuration to the default state
|
14
|
+
before(:each) do
|
15
|
+
oml.reset
|
16
|
+
oml.configure do |config|
|
17
|
+
config.print_log = true
|
18
|
+
selector = oml::Selector.universal_for(actions: {"EXCEPT" => ["index"]})
|
19
|
+
config.add_selector(selector)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:all) do
|
24
|
+
Rake::Task['oh_my_log:clean'].invoke
|
25
|
+
end
|
26
|
+
|
27
|
+
it "Should not log anything when the response is 200 and we put 200 in the status_codes blacklist" do
|
28
|
+
oml.configuration.selectors[-1].set_status_codes("EXCEPT" => [(200..204)])
|
29
|
+
put :create, params: {name: 'foo name'}
|
30
|
+
expect(oml.last_recorded).to eq(nil)
|
31
|
+
end
|
32
|
+
it "Should log when the response is 200 and we put 200 in the white_list" do
|
33
|
+
oml.configuration.selectors[-1].set_status_codes("ONLY" => [(200..204)])
|
34
|
+
put :create, params: {name: 'foo name'}
|
35
|
+
expect(oml.last_recorded).not_to eq(nil)
|
36
|
+
end
|
37
|
+
it "Should not log when we removing the FooController from the permitted controller list" do
|
38
|
+
oml.configuration.selectors[-1].set_controllers({"ONLY" => ["Doo"]})
|
39
|
+
put :create, params: {name: 'foo name'}
|
40
|
+
expect(oml.last_recorded).to eq(nil)
|
41
|
+
end
|
42
|
+
it "Should log when including FooController in the permitted controller list" do
|
43
|
+
oml.configuration.selectors[-1].set_controllers({"ONLY" => ["Foo"]})
|
44
|
+
put :create, params: {name: 'foo name'}
|
45
|
+
expect(oml.last_recorded).not_to eq(nil)
|
46
|
+
end
|
47
|
+
it "Should not log when using the create method and using a configuration to only log the index action" do
|
48
|
+
oml.configuration.selectors[-1].set_actions("EXCEPT" => ["create"])
|
49
|
+
put :create, params: {name: 'foo name'}
|
50
|
+
expect(oml.last_recorded).to eq(nil)
|
51
|
+
end
|
52
|
+
it "Should log when rooting to index and using a configuration to only log the index action" do
|
53
|
+
oml.configuration.selectors[-1].set_actions("ONLY" => ["index"])
|
54
|
+
get :index
|
55
|
+
expect(oml.last_recorded).not_to eq(nil)
|
56
|
+
end
|
57
|
+
##non va perchè non si riesce a fare il monkeypatch di application controller dato ceh abbiamo il rails dei poveri
|
58
|
+
it "Should not log when black listing the local ip" do
|
59
|
+
oml.configuration.selectors[-1].set_ips("EXCEPT" => ["192.168.0.1"])
|
60
|
+
put :create, params: {name: 'foo name'}
|
61
|
+
expect(oml.last_recorded).to eq(nil)
|
62
|
+
end
|
63
|
+
it "Should be able to correctly use multiple selector" do
|
64
|
+
selector = OhMyLog::Log::Selector.new
|
65
|
+
selector.set_controllers({"EXCEPT" => ["Foo"]})
|
66
|
+
oml.configuration.add_selector(selector)
|
67
|
+
put :create, params: {name: 'foo name'}
|
68
|
+
expect(oml.last_recorded).to eq(nil)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "When testing the event logger for a generic Model" do
|
73
|
+
before(:all) do
|
74
|
+
Foo.destroy_all
|
75
|
+
Doo.destroy_all
|
76
|
+
@dummy = Foo.create(name: "Dummy model", value: 2)
|
77
|
+
end
|
78
|
+
before(:each) do
|
79
|
+
oml.reset
|
80
|
+
oml.configure do |config|
|
81
|
+
config.print_log = true
|
82
|
+
selector = oml::Selector.universal_for(actions: {"EXCEPT" => ["index"]})
|
83
|
+
config.add_selector(selector)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
it "Should create a log in the path specified in teh configuration" do
|
87
|
+
expect(File.file?(Rails.root + "log/oh_my_log.log")).to eq(true)
|
88
|
+
end
|
89
|
+
it "Should write a log when creating a Model" do
|
90
|
+
put :create, params: {name: 'foo name'}
|
91
|
+
expect(oml.last_recorded).not_to eq(nil)
|
92
|
+
end
|
93
|
+
it "Should write a log when changing an Model" do
|
94
|
+
if Rails::VERSION::MAJOR >= 5
|
95
|
+
put :update, params: {name: "dummy name", value: 99, id: @dummy.id}
|
96
|
+
else
|
97
|
+
put :update, {name: "dummy name", value: 99, id: @dummy.id}
|
98
|
+
end
|
99
|
+
expect(oml.last_recorded).not_to eq(nil)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "The log created should have a receiver if the action made any changes to the model" do
|
103
|
+
if Rails::VERSION::MAJOR >= 5
|
104
|
+
put :update, params: {name: "not dummy name", value: 99, id: @dummy.id}
|
105
|
+
else
|
106
|
+
put :update, {name: "not dummy name", value: 99, id: @dummy.id}
|
107
|
+
end
|
108
|
+
expect(oml.last_recorded.effects[0].receiver).not_to eq(nil)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "The action indicated by the log should math the action did by the controller " do
|
112
|
+
put :create, params: {name: "nameless dummy"}
|
113
|
+
expect(oml.last_recorded.request.params["action"]).to eq("create")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
class FoosController < ActionController::Base
|
2
|
+
protect_from_forgery
|
3
|
+
def index
|
4
|
+
end
|
5
|
+
|
6
|
+
def create
|
7
|
+
Foo.create(name: params["name"],value: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
def update
|
11
|
+
Foo.find(params["id"]).update(name: params["name"],value: params["value"])
|
12
|
+
redirect_to edit_foo_url
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit
|
16
|
+
end
|
17
|
+
|
18
|
+
def two_in_one
|
19
|
+
Doo.create(name: "doo dummy", value: 2)
|
20
|
+
Foo.first.update(name: "Dummy nameee",value: 4)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|