effective_logging 1.9.0 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/app/controllers/effective/logs_controller.rb +0 -1
- data/app/helpers/effective_logging_helper.rb +2 -1
- data/app/models/effective/datatables/logs.rb +10 -11
- data/app/models/effective/log.rb +14 -11
- data/app/models/effective_logger.rb +5 -0
- data/config/effective_logging.rb +7 -5
- data/db/migrate/01_create_effective_logging.rb.erb +3 -0
- data/lib/effective_logging/active_record_logger.rb +7 -7
- data/lib/effective_logging/email_logger.rb +3 -3
- data/lib/effective_logging/engine.rb +3 -3
- data/lib/effective_logging/log_page_views.rb +8 -8
- data/lib/effective_logging/user_logger.rb +19 -17
- data/lib/effective_logging/version.rb +1 -1
- data/lib/effective_logging.rb +9 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e724ec2b890ab6af1c5f9a6e5fa573231cf64b8
|
4
|
+
data.tar.gz: dad4e05c79b2eeca0be0434e5aa4987dbb7e6ec0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0227e4b2c520bafc19e5a27a71b7f51964d30302f48a99f1902d51dd87dd6d97d172468fc8938c568c28e00f5a563108e2a42d71a83c03f13e11e7124cba3fc
|
7
|
+
data.tar.gz: e0ba574c10badde2f13e6533ca8d2838c2d2da107abf2d7e05b4da69dce67dea11bf38003ab2d130828bf67b2a588c3d48d787720dc997d7701d2275d53a6d9f
|
data/README.md
CHANGED
@@ -102,7 +102,7 @@ Any email sent by the application will be automatically logged.
|
|
102
102
|
|
103
103
|
This behaviour can be disabled in the config/initializers/effective_logging.rb initializer.
|
104
104
|
|
105
|
-
If the TO email address match a User, the :
|
105
|
+
If the TO email address match a User, the :associated will be set to this user.
|
106
106
|
|
107
107
|
You can specify additional fields to be logged via your mailer:
|
108
108
|
|
@@ -111,7 +111,7 @@ def notify_admin_of_new_post(post)
|
|
111
111
|
mail(
|
112
112
|
to: 'admin@example.com',
|
113
113
|
subject: 'A new post was created',
|
114
|
-
log: { :
|
114
|
+
log: { :post => post, :title => post.title }
|
115
115
|
)
|
116
116
|
end
|
117
117
|
```
|
@@ -229,7 +229,7 @@ And on each create / destroy / update, a full dump of all current attributes is
|
|
229
229
|
|
230
230
|
There is some initial support for passing `only`, `except`, and `additionally` to the mixin to customize what attributes are saved.
|
231
231
|
|
232
|
-
Define your model with `log_changes additionally: [:method1, :method2]` to also log the value of
|
232
|
+
Define your model with `log_changes additionally: [:method1, :method2]` to also _always_ log the value of that method. Even if it's unchanged.
|
233
233
|
|
234
234
|
Apply your own formatting to the logged title of each attribute by creating an instance method on the resource:
|
235
235
|
|
@@ -328,7 +328,7 @@ render_datatable(@datatable)
|
|
328
328
|
|
329
329
|
We can also use a similar method to create a datatable of logs for just one user.
|
330
330
|
|
331
|
-
When initialized with :user_id, the 'User' column is hidden and the Logs are scoped to the User.
|
331
|
+
When initialized with :user_id, the 'User' column is hidden and the Logs are scoped to any logs where this user is the User or Associated column.
|
332
332
|
|
333
333
|
In your controller:
|
334
334
|
|
@@ -8,12 +8,13 @@ module EffectiveLoggingHelper
|
|
8
8
|
when 'info' ; 'info'
|
9
9
|
when 'warning' ; 'warning'
|
10
10
|
when 'error' ; 'danger'
|
11
|
+
when 'change' ; 'info'
|
11
12
|
else 'primary'
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
15
16
|
def render_log(log)
|
16
|
-
render(partial: 'effective/logs/log', locals: {:
|
17
|
+
render(partial: 'effective/logs/log', locals: {log: log})
|
17
18
|
end
|
18
19
|
|
19
20
|
def parents_of_log(log)
|
@@ -15,17 +15,19 @@ if defined?(EffectiveDatatables)
|
|
15
15
|
end
|
16
16
|
|
17
17
|
unless attributes[:status] == false
|
18
|
-
table_column :status, filter: { type: :select, values:
|
18
|
+
table_column :status, filter: { type: :select, values: EffectiveLogging.statuses }
|
19
19
|
end
|
20
20
|
|
21
|
+
table_column :associated_type, visible: false
|
22
|
+
table_column :associated_id, visible: false, label: 'Associated Id'
|
23
|
+
table_column :associated_to_s, label: 'Associated'
|
24
|
+
|
21
25
|
table_column :message do |log|
|
22
26
|
log.message.starts_with?("\t") ? log.message.gsub("\t", " ") : log.message
|
23
27
|
end
|
24
28
|
|
25
29
|
table_column :logs_count, visible: false
|
26
30
|
|
27
|
-
table_column :associated, filter: false, sortable: false, visible: false
|
28
|
-
|
29
31
|
table_column :details, visible: false, sortable: false do |log|
|
30
32
|
tableize_hash(log.details.except(:email), th: true, sub_th: false, width: '100%')
|
31
33
|
end
|
@@ -42,22 +44,19 @@ if defined?(EffectiveDatatables)
|
|
42
44
|
def collection
|
43
45
|
collection = Effective::Log.unscoped.where(parent_id: attributes[:log_id]).includes(:user, :associated)
|
44
46
|
|
45
|
-
if attributes[:
|
46
|
-
collection = collection.where(
|
47
|
+
if attributes[:log_changes]
|
48
|
+
collection = collection.where(status: EffectiveLogging.log_changes_status)
|
47
49
|
end
|
48
50
|
|
49
|
-
if attributes[:user].present?
|
50
|
-
|
51
|
+
if (attributes[:user] || attributes[:user_id]).present?
|
52
|
+
user_id = attributes[:user_id] || (attributes[:user].kind_of?(User) ? attributes[:user].id : attributes[:user].to_i)
|
53
|
+
collection = collection.where('user_id = ? OR (associated_id = ? AND associated_type = ?)', user_id, user_id, 'User')
|
51
54
|
end
|
52
55
|
|
53
56
|
if attributes[:associated_id] && attributes[:associated_type]
|
54
57
|
collection = collection.where(associated_id: attributes[:associated_id], associated_type: attributes[:associated_type])
|
55
58
|
end
|
56
59
|
|
57
|
-
if attributes[:log_changes]
|
58
|
-
collection = collection.where(status: EffectiveLogging.log_changes_status)
|
59
|
-
end
|
60
|
-
|
61
60
|
if attributes[:associated]
|
62
61
|
collection = collection.where(associated: attributes[:associated])
|
63
62
|
end
|
data/app/models/effective/log.rb
CHANGED
@@ -13,21 +13,24 @@ module Effective
|
|
13
13
|
|
14
14
|
# The user this log item is referring to
|
15
15
|
# An associated object, if we wanna add anything extra
|
16
|
-
belongs_to :user
|
17
|
-
belongs_to :associated, polymorphic: true
|
16
|
+
belongs_to :user, optional: true
|
17
|
+
belongs_to :associated, polymorphic: true, optional: true
|
18
18
|
|
19
19
|
serialize :details, Hash
|
20
20
|
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
21
|
+
# Attributes
|
22
|
+
# logs_count :integer # Rails Counter Cache
|
23
|
+
|
24
|
+
# associated_type :string
|
25
|
+
# associated_id :integer
|
26
|
+
# associated_to_s :string
|
27
|
+
# message :string
|
28
|
+
# details :text
|
29
|
+
# status :string
|
30
|
+
# timestamps
|
28
31
|
|
29
32
|
validates :message, presence: true
|
30
|
-
validates :status, presence: true, inclusion: { in:
|
33
|
+
validates :status, presence: true, inclusion: { in: EffectiveLogging.statuses }
|
31
34
|
|
32
35
|
default_scope -> { order(updated_at: :desc) }
|
33
36
|
|
@@ -39,7 +42,7 @@ module Effective
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def log(message, status = EffectiveLogging.statuses.first, options = {})
|
42
|
-
EffectiveLogger.log(message, status, (options || {}).merge(
|
45
|
+
EffectiveLogger.log(message, status, (options || {}).merge(parent: self))
|
43
46
|
end
|
44
47
|
|
45
48
|
def details
|
@@ -22,6 +22,11 @@ class EffectiveLogger
|
|
22
22
|
log.user = options.delete(:user)
|
23
23
|
log.parent = options.delete(:parent)
|
24
24
|
log.associated = options.delete(:associated)
|
25
|
+
log.associated_to_s = options.delete(:associated_to_s)
|
26
|
+
|
27
|
+
if log.associated.present?
|
28
|
+
log.associated_to_s ||= (log.associated.to_s rescue nil)
|
29
|
+
end
|
25
30
|
|
26
31
|
log.details = options.delete_if { |k, v| v.blank? } if options.kind_of?(Hash)
|
27
32
|
|
data/config/effective_logging.rb
CHANGED
@@ -42,10 +42,12 @@ EffectiveLogging.setup do |config|
|
|
42
42
|
#### Automatic Logging Functionality ####
|
43
43
|
#########################################
|
44
44
|
|
45
|
-
# Log all emails
|
46
|
-
config.
|
45
|
+
# Log all sent emails
|
46
|
+
config.email_enabled = true
|
47
47
|
|
48
|
-
# Log all
|
49
|
-
config.
|
50
|
-
|
48
|
+
# Log all sign ins (successful only)
|
49
|
+
config.sign_in_enabled = true
|
50
|
+
|
51
|
+
# Log all sign outs
|
52
|
+
config.sign_out_enabled = false
|
51
53
|
end
|
@@ -2,10 +2,12 @@ class CreateEffectiveLogging < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
3
3
|
create_table <%= @logs_table_name %> do |t|
|
4
4
|
t.integer :parent_id
|
5
|
+
|
5
6
|
t.integer :user_id
|
6
7
|
|
7
8
|
t.string :associated_type
|
8
9
|
t.integer :associated_id
|
10
|
+
t.string :associated_to_s
|
9
11
|
|
10
12
|
t.integer :logs_count
|
11
13
|
|
@@ -21,6 +23,7 @@ class CreateEffectiveLogging < ActiveRecord::Migration
|
|
21
23
|
add_index <%= @logs_table_name %>, :parent_id
|
22
24
|
add_index <%= @logs_table_name %>, [:associated_type, :associated_id]
|
23
25
|
add_index <%= @logs_table_name %>, :associated_id
|
26
|
+
add_index <%= @logs_table_name %>, :associated_to_s
|
24
27
|
end
|
25
28
|
|
26
29
|
def self.down
|
@@ -53,11 +53,7 @@ module EffectiveLogging
|
|
53
53
|
resource.log_changes_formatted_attribute(attribute)
|
54
54
|
end || attribute.titleize
|
55
55
|
|
56
|
-
|
57
|
-
log("#{attribute} changed from #{before.presence || BLANK} to #{after.presence || BLANK}", details: { attribute: attribute, before: before, after: after })
|
58
|
-
else
|
59
|
-
log("#{attribute} set to #{before || BLANK}", details: { attribute: attribute, value: before })
|
60
|
-
end
|
56
|
+
log("#{attribute}: #{before.presence || BLANK} to #{after.presence || BLANK}", details: { attribute: attribute, before: before, after: after })
|
61
57
|
end
|
62
58
|
|
63
59
|
# Log changes on all accepts_as_nested_parameters has_many associations
|
@@ -75,7 +71,7 @@ module EffectiveLogging
|
|
75
71
|
|
76
72
|
# Collect to_s representations of all belongs_to associations
|
77
73
|
(resource.class.try(:reflect_on_all_associations, :belongs_to) || []).each do |association|
|
78
|
-
attributes[association.name] = resource.send(association.name).to_s.presence
|
74
|
+
attributes[association.name] = resource.send(association.name).to_s.presence
|
79
75
|
end
|
80
76
|
|
81
77
|
# Collect to_s representations for all has_one associations
|
@@ -90,6 +86,8 @@ module EffectiveLogging
|
|
90
86
|
Array(resource.send(association.name)).each_with_index do |child, index|
|
91
87
|
attributes[association.name][index+1] = ActiveRecordLogger.new(child, options.merge(logger: logger)).attributes
|
92
88
|
end
|
89
|
+
|
90
|
+
attributes[association.name].presence
|
93
91
|
end
|
94
92
|
|
95
93
|
attributes
|
@@ -101,7 +99,7 @@ module EffectiveLogging
|
|
101
99
|
# Log to_s changes on all belongs_to associations
|
102
100
|
(resource.class.try(:reflect_on_all_associations, :belongs_to) || []).each do |association|
|
103
101
|
if (change = changes.delete(association.foreign_key)).present?
|
104
|
-
changes[association.name] = [association.klass.find_by_id(change.first), resource.send(association.name)]
|
102
|
+
changes[association.name] = [(association.klass.find_by_id(change.first) if changes.first), resource.send(association.name)]
|
105
103
|
end
|
106
104
|
end
|
107
105
|
|
@@ -115,6 +113,8 @@ module EffectiveLogging
|
|
115
113
|
user: EffectiveLogging.current_user,
|
116
114
|
status: EffectiveLogging.log_changes_status,
|
117
115
|
message: "#{"\t" * depth}#{options[:prefix]}#{message}",
|
116
|
+
associated: resource,
|
117
|
+
associated_to_s: (resource.to_s rescue nil),
|
118
118
|
details: details
|
119
119
|
).tap { |log| log.save }
|
120
120
|
end
|
@@ -7,7 +7,7 @@ module EffectiveLogging
|
|
7
7
|
logged_fields = { from: message.from.join(','), to: message.to, subject: message.subject }
|
8
8
|
|
9
9
|
# Add a log header to your mailer to pass some objects or additional things to EffectiveLogger
|
10
|
-
# mail(to: 'admin@example.com', subject: @post.title, log: {
|
10
|
+
# mail(to: 'admin@example.com', subject: @post.title, log: { post: @post })
|
11
11
|
if message.header['log'].present?
|
12
12
|
# This is a bit sketchy, but gives access to the object in Rails 4.2 anyway
|
13
13
|
logged_fields.merge!(message.header['log'].instance_variable_get(:@value) || {})
|
@@ -22,9 +22,9 @@ module EffectiveLogging
|
|
22
22
|
|
23
23
|
(message.to || []).each do |to|
|
24
24
|
logged_fields[:to] = to
|
25
|
-
logged_fields[:
|
25
|
+
logged_fields[:associated] ||= (User.where(email: to).first rescue nil)
|
26
26
|
|
27
|
-
::EffectiveLogger.
|
27
|
+
::EffectiveLogger.email("#{message.subject} - #{message.to.join(', ')}", logged_fields)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -19,7 +19,7 @@ module EffectiveLogging
|
|
19
19
|
|
20
20
|
# Automatically Log Emails
|
21
21
|
initializer 'effective_logging.emails' do |app|
|
22
|
-
if EffectiveLogging.
|
22
|
+
if EffectiveLogging.email_enabled == true
|
23
23
|
require 'effective_logging/email_logger'
|
24
24
|
ActionMailer::Base.register_interceptor(EffectiveLogging::EmailLogger)
|
25
25
|
end
|
@@ -51,12 +51,12 @@ module EffectiveLogging
|
|
51
51
|
|
52
52
|
# This has to be run after initialization or User hasn't been loaded yet
|
53
53
|
config.after_initialize do
|
54
|
-
if EffectiveLogging.
|
54
|
+
if EffectiveLogging.sign_in_enabled || EffectiveLogging.sign_out_enabled
|
55
55
|
ActiveSupport.on_load :active_record do
|
56
56
|
if defined?(Devise)
|
57
57
|
EffectiveLogging::UserLogger.create_warden_hooks()
|
58
58
|
else
|
59
|
-
raise ArgumentError.new("EffectiveLogging.
|
59
|
+
raise ArgumentError.new("EffectiveLogging.sign_in_enabled only works with Devise")
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -48,15 +48,15 @@ module EffectiveLogging
|
|
48
48
|
user = (current_user rescue nil)
|
49
49
|
|
50
50
|
if self.class.log_page_views_opts[:details] == false
|
51
|
-
::EffectiveLogger.
|
51
|
+
::EffectiveLogger.view("#{request.request_method} #{request.path}", user: user)
|
52
52
|
else
|
53
|
-
::EffectiveLogger.
|
54
|
-
"
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
59
|
-
:
|
53
|
+
::EffectiveLogger.view(
|
54
|
+
"#{request.request_method} #{request.path}",
|
55
|
+
user: user,
|
56
|
+
params: request.filtered_parameters.reject { |k, v| (k == 'controller' || k == 'action') },
|
57
|
+
format: (request.format.to_s == 'text/html' ? nil : request.format.to_s),
|
58
|
+
referrer: request.referrer,
|
59
|
+
user_agent: request.user_agent
|
60
60
|
)
|
61
61
|
end
|
62
62
|
end
|
@@ -2,32 +2,34 @@ module EffectiveLogging
|
|
2
2
|
class UserLogger
|
3
3
|
def self.create_warden_hooks
|
4
4
|
Warden::Manager.after_authentication do |user, warden, opts|
|
5
|
-
if EffectiveLogging.
|
6
|
-
::EffectiveLogger.
|
7
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
5
|
+
if EffectiveLogging.sign_in_enabled && !EffectiveLogging.supressed?
|
6
|
+
::EffectiveLogger.sign_in('Sign in',
|
7
|
+
user: user,
|
8
|
+
associated: user,
|
9
|
+
ip: warden.request.ip.presence,
|
10
|
+
referrer: warden.request.referrer,
|
11
|
+
user_agent: warden.request.user_agent
|
11
12
|
)
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
15
16
|
Warden::Manager.after_set_user do |user, warden, opts|
|
16
|
-
if EffectiveLogging.
|
17
|
+
if EffectiveLogging.sign_in_enabled && !EffectiveLogging.supressed?
|
17
18
|
if (opts[:event] == :set_user rescue false) # User has just reset their password and signed in
|
18
|
-
::EffectiveLogger.
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
19
|
+
::EffectiveLogger.sign_in('Sign in',
|
20
|
+
user: user,
|
21
|
+
associated: user,
|
22
|
+
ip: warden.request.ip.presence,
|
23
|
+
referrer: warden.request.referrer,
|
24
|
+
user_agent: warden.request.user_agent,
|
25
|
+
notes: 'after password reset'
|
24
26
|
)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
31
|
Warden::Manager.before_logout do |user, warden, opts|
|
30
|
-
if EffectiveLogging.
|
32
|
+
if EffectiveLogging.sign_out_enabled && !EffectiveLogging.supressed?
|
31
33
|
if user.respond_to?(:timedout?) && user.respond_to?(:timeout_in)
|
32
34
|
scope = opts[:scope]
|
33
35
|
last_request_at = (warden.request.session["warden.#{scope}.#{scope}.session"]['last_request_at'] rescue Time.zone.now)
|
@@ -40,12 +42,12 @@ module EffectiveLogging
|
|
40
42
|
end
|
41
43
|
|
42
44
|
if user.timedout?(last_request_at) && !warden.request.env['devise.skip_timeout']
|
43
|
-
::EffectiveLogger.
|
45
|
+
::EffectiveLogger.sign_out('Sign out', user: user, associated: user, timedout: true)
|
44
46
|
else
|
45
|
-
::EffectiveLogger.
|
47
|
+
::EffectiveLogger.sign_out('Sign out', user: user, associated: user)
|
46
48
|
end
|
47
49
|
else # User does not respond to timedout
|
48
|
-
::EffectiveLogger.
|
50
|
+
::EffectiveLogger.sign_out('Sign out', user: user, associated: user)
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
data/lib/effective_logging.rb
CHANGED
@@ -12,9 +12,9 @@ module EffectiveLogging
|
|
12
12
|
mattr_accessor :layout
|
13
13
|
mattr_accessor :additional_statuses
|
14
14
|
|
15
|
-
mattr_accessor :
|
16
|
-
mattr_accessor :
|
17
|
-
mattr_accessor :
|
15
|
+
mattr_accessor :email_enabled
|
16
|
+
mattr_accessor :sign_in_enabled
|
17
|
+
mattr_accessor :sign_out_enabled
|
18
18
|
|
19
19
|
def self.setup
|
20
20
|
yield self
|
@@ -36,11 +36,15 @@ module EffectiveLogging
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def self.statuses
|
39
|
-
@statuses ||= (
|
39
|
+
@statuses ||= (
|
40
|
+
Array(@@additional_statuses).map do |status|
|
41
|
+
status.to_s.downcase
|
42
|
+
end | ['info', 'success', 'error', log_changes_status, ('email' if email_enabled), ('sign_in' if sign_in_enabled), ('sign_out' if sign_out_enabled), 'view'].compact
|
43
|
+
)
|
40
44
|
end
|
41
45
|
|
42
46
|
def self.log_changes_status
|
43
|
-
'
|
47
|
+
'change'.freeze
|
44
48
|
end
|
45
49
|
|
46
50
|
# This is set by the "set_effective_logging_current_user" before_filter.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_logging
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|