ixtlan-audit 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ixtlan-audit.rb +20 -0
- data/lib/ixtlan/audit/audit_resource.rb~ +55 -0
- data/lib/ixtlan/audit/audit_serializer.rb~ +14 -0
- data/lib/ixtlan/audit/cuba.rb +37 -0
- data/lib/ixtlan/audit/cuba.rb~ +14 -0
- data/lib/ixtlan/audit/cuba_plugin.rb +46 -0
- data/lib/ixtlan/audit/cuba_plugin.rb~ +34 -0
- data/lib/ixtlan/audit/cuba_setup.rb~ +34 -0
- data/lib/ixtlan/audit/manager.rb +77 -39
- data/lib/ixtlan/audit/rack.rb +38 -0
- data/lib/ixtlan/audit/{audit_rack.rb → rack.rb~} +0 -0
- data/lib/ixtlan/audit/railtie.rb +23 -3
- data/lib/ixtlan/audit/resource.rb +40 -0
- data/lib/ixtlan/audit/serializer.rb +33 -0
- data/lib/ixtlan/audit/user_logger.rb +30 -9
- data/spec/audit_manager_spec.rb +8 -13
- metadata +122 -115
- data/README.textile +0 -4
data/lib/ixtlan-audit.rb
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
1
21
|
if defined?(Rails)
|
2
22
|
require 'ixtlan/audit/railtie'
|
3
23
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-migrations'
|
3
|
+
require 'slf4r/ruby_logger'
|
4
|
+
require 'ixtlan/audit/manager'
|
5
|
+
|
6
|
+
class Audit
|
7
|
+
include DataMapper::Resource
|
8
|
+
|
9
|
+
property :id, Serial
|
10
|
+
|
11
|
+
property :login, String
|
12
|
+
property :message, String
|
13
|
+
|
14
|
+
property :created_at, DateTime
|
15
|
+
|
16
|
+
before :save do
|
17
|
+
self.created_at = DateTime.now
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Fixnum
|
22
|
+
def days
|
23
|
+
self
|
24
|
+
end
|
25
|
+
def ago
|
26
|
+
DateTime.now - 86000 * self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
30
|
+
DataMapper.finalize
|
31
|
+
DataMapper.repository.auto_migrate!
|
32
|
+
|
33
|
+
describe Ixtlan::Audit::Manager do
|
34
|
+
|
35
|
+
it 'should collect log events and the save them all in one go' do
|
36
|
+
size = Audit.all.size
|
37
|
+
subject.push("msg1", "login1")
|
38
|
+
subject.push("msg2", "login2")
|
39
|
+
subject.push("msg3", "login3")
|
40
|
+
subject.save_all
|
41
|
+
|
42
|
+
Audit.all.size.should == size + 3
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should clean up audit logs" do
|
46
|
+
Audit.create(:message => "msg", :login => "login")
|
47
|
+
Audit.all.size.should > 0
|
48
|
+
subject.keep_logs = 0
|
49
|
+
Audit.all.size.should == 0
|
50
|
+
subject.push("msg", "login")
|
51
|
+
subject.push("msg", "login")
|
52
|
+
subject.save_all
|
53
|
+
Audit.all.size.should == 2
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
21
|
+
require 'cuba_api'
|
22
|
+
require 'ixtlan/audit/resource'
|
23
|
+
require 'ixtlan/audit/serializer'
|
24
|
+
module Ixtlan
|
25
|
+
module Audit
|
26
|
+
class Cuba < ::CubaAPI
|
27
|
+
define do
|
28
|
+
on get, :numder do |number|
|
29
|
+
write Ixtlan::Audit::Audit.get!( number.to_i )
|
30
|
+
end
|
31
|
+
on get do
|
32
|
+
write Ixtlan::Audit::Audit.all.reverse
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
21
|
+
require 'ixtlan/audit/manager'
|
22
|
+
require 'ixtlan/audit/rack'
|
23
|
+
module Ixtlan
|
24
|
+
module Audit
|
25
|
+
module CubaPlugin
|
26
|
+
def audit( obj, args )
|
27
|
+
if args[ :audit ] != false
|
28
|
+
username = current_user_name if respond_to?( :current_user_name )
|
29
|
+
audit_manager.push( username, env['SCRIPT_NAME'], obj )
|
30
|
+
end
|
31
|
+
obj
|
32
|
+
end
|
33
|
+
|
34
|
+
def audit_manager
|
35
|
+
@audit_manager ||= self.class[ :audit_manager ] || Manager.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.included( base )
|
39
|
+
base.prepend_aspect :audit
|
40
|
+
manager = Manager.new
|
41
|
+
base[ :audit_manager ] = manager
|
42
|
+
base.use( Rack, manager)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'ixtlan/audit/manager'
|
2
|
+
require 'ixtlan/audit/rack'
|
3
|
+
module Ixtlan
|
4
|
+
module Audit
|
5
|
+
module CubaSetup
|
6
|
+
|
7
|
+
module Audit
|
8
|
+
def audit( obj, args )
|
9
|
+
if args[ :audit ] != false
|
10
|
+
username = current_user_name if respond_to?( :current_user_name )
|
11
|
+
audit_manager.push( username, env['SCRIPT_NAME'], obj )
|
12
|
+
end
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
|
16
|
+
def audit_manager
|
17
|
+
@audit_manager ||= self.class.settings[ :audit_manager ] || Manager.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.included( base )
|
21
|
+
base.add_aspect :audit
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.setup( cuba, model = nil )
|
26
|
+
#cuba.plugin Audit
|
27
|
+
manager = Manager.new( model )
|
28
|
+
cuba.settings[ :audit_manager ] = manager
|
29
|
+
cuba.use( Rack, manager)
|
30
|
+
manager
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'ixtlan/audit/manager'
|
2
|
+
require 'ixtlan/audit/rack'
|
3
|
+
module Ixtlan
|
4
|
+
module Audit
|
5
|
+
module CubaSetup
|
6
|
+
|
7
|
+
module Audit
|
8
|
+
def audit( obj, args )
|
9
|
+
if args[ :audit ] != false
|
10
|
+
username = current_user_name if respond_to?( :current_user_name )
|
11
|
+
audit_manager.push( username, env['SCRIPT_NAME'], obj )
|
12
|
+
end
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
|
16
|
+
def audit_manager
|
17
|
+
@audit_manager ||= self.class.settings[ :audit_manager ] || Manager.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.included( base )
|
21
|
+
base.add_aspect :audit
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.setup( cuba, model = nil )
|
26
|
+
#cuba.plugin Audit
|
27
|
+
manager = Manager.new( model )
|
28
|
+
cuba.settings[ :audit_manager ] = manager
|
29
|
+
cuba.use( Rack, manager)
|
30
|
+
manager
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/ixtlan/audit/manager.rb
CHANGED
@@ -1,44 +1,86 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
3
21
|
module Ixtlan
|
4
22
|
module Audit
|
5
23
|
class Manager
|
6
24
|
|
7
25
|
private
|
8
26
|
|
9
|
-
|
27
|
+
if defined? ::Slf4r
|
28
|
+
include ::Slf4r::Logger
|
29
|
+
else
|
30
|
+
require 'logger'
|
31
|
+
def logger
|
32
|
+
@logger ||= Logger.new( STDOUT )
|
33
|
+
end
|
34
|
+
end
|
10
35
|
|
11
36
|
def list
|
12
37
|
Thread.current[:audit] ||= []
|
13
38
|
end
|
14
39
|
|
15
|
-
def model
|
16
|
-
@model ||= (::Audit rescue nil)
|
17
|
-
end
|
18
|
-
|
19
40
|
public
|
20
41
|
|
21
|
-
|
22
|
-
|
42
|
+
attr_accessor :model, :block, :keep_logs
|
43
|
+
|
44
|
+
def initialize( model = nil, &block )
|
45
|
+
@model = model
|
23
46
|
@keep_logs = 90
|
47
|
+
block.call( self ) if block
|
48
|
+
@block = block
|
24
49
|
end
|
25
|
-
|
26
|
-
def
|
27
|
-
@
|
28
|
-
end
|
29
|
-
|
30
|
-
def model=(m)
|
31
|
-
@model = m if m
|
50
|
+
|
51
|
+
def model
|
52
|
+
@model ||= (Ixtlan::Audit::Audit rescue nil)
|
32
53
|
end
|
33
54
|
|
34
|
-
def keep_logs=(
|
55
|
+
def keep_logs=( keep )
|
35
56
|
old = @keep_logs
|
36
|
-
@keep_logs =
|
57
|
+
@keep_logs = keep
|
37
58
|
daily_cleanup if old != @keep_logs
|
38
59
|
end
|
60
|
+
|
61
|
+
def keep_logs
|
62
|
+
if block
|
63
|
+
keep_logs = block.call
|
64
|
+
end
|
65
|
+
@keep_logs
|
66
|
+
end
|
39
67
|
|
40
|
-
def push(
|
41
|
-
|
68
|
+
def push( username, path, obj )
|
69
|
+
if model
|
70
|
+
message =
|
71
|
+
if !obj.is_a?( String ) && obj.respond_to?( :collect )
|
72
|
+
if o = obj.first
|
73
|
+
"#{o.class}[ #{obj.size} ]"
|
74
|
+
else
|
75
|
+
"[ 0 ] - <EMPTY ARRAY>"
|
76
|
+
end
|
77
|
+
else
|
78
|
+
obj.to_s
|
79
|
+
end
|
80
|
+
list << model.new( :path => path,
|
81
|
+
:message => message,
|
82
|
+
:login => username || '???' )
|
83
|
+
end
|
42
84
|
list.last
|
43
85
|
end
|
44
86
|
|
@@ -56,35 +98,31 @@ module Ixtlan
|
|
56
98
|
list.clear
|
57
99
|
end
|
58
100
|
|
59
|
-
def username_method
|
60
|
-
@username_method
|
61
|
-
end
|
62
|
-
|
63
101
|
def daily_cleanup
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
102
|
+
return unless model
|
103
|
+
now = DateTime.now
|
104
|
+
if(@last_cleanup.nil? || @last_cleanup < (now - 1))
|
105
|
+
@last_cleanup = now
|
106
|
+
begin
|
107
|
+
delete_all( now - keep_logs )
|
108
|
+
logger.info "cleaned audit logs"
|
109
|
+
rescue Exception => e
|
110
|
+
logger.warn "error cleaning up audit logs: #{e.message}"
|
73
111
|
end
|
74
112
|
end
|
75
113
|
end
|
76
|
-
|
114
|
+
|
77
115
|
private
|
78
116
|
|
79
117
|
if defined? ::DataMapper
|
80
|
-
def delete_all
|
81
|
-
model.all(:created_at.lte =>
|
118
|
+
def delete_all( expired )
|
119
|
+
model.all( :created_at.lte => expired ).destroy!
|
82
120
|
end
|
83
121
|
else # ActiveRecord
|
84
|
-
def delete_all
|
85
|
-
model.all(:conditions => ["created_at <= ?",
|
122
|
+
def delete_all( expired )
|
123
|
+
model.all( :conditions => ["created_at <= ?", expired] ).each(&:delete)
|
86
124
|
end
|
87
125
|
end
|
88
126
|
end
|
89
127
|
end
|
90
|
-
end
|
128
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
21
|
+
module Ixtlan
|
22
|
+
module Audit
|
23
|
+
class Rack
|
24
|
+
|
25
|
+
def initialize(app, audit_manager)
|
26
|
+
@app = app
|
27
|
+
@audit_manager = audit_manager
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
result = @app.call(env)
|
32
|
+
@audit_manager.save_all
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
File without changes
|
data/lib/ixtlan/audit/railtie.rb
CHANGED
@@ -1,5 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
1
21
|
require 'ixtlan/audit/manager'
|
2
|
-
require 'ixtlan/audit/
|
22
|
+
require 'ixtlan/audit/rack'
|
3
23
|
require 'ixtlan/audit/user_logger'
|
4
24
|
|
5
25
|
|
@@ -11,7 +31,7 @@ module Ixtlan
|
|
11
31
|
app.config.audit_manager = Manager.new
|
12
32
|
::ActionController::Base.send(:include, Module)
|
13
33
|
::ActionController::Base.send(:after_filter, :audit)
|
14
|
-
app.config.middleware.use(
|
34
|
+
app.config.middleware.use(Rack, app.config.audit_manager)
|
15
35
|
end
|
16
36
|
end
|
17
37
|
|
@@ -23,4 +43,4 @@ module Ixtlan
|
|
23
43
|
end
|
24
44
|
end
|
25
45
|
end
|
26
|
-
end
|
46
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
21
|
+
require 'dm-core'
|
22
|
+
module Ixtlan
|
23
|
+
module Audit
|
24
|
+
class Audit
|
25
|
+
include DataMapper::Resource
|
26
|
+
|
27
|
+
property :id, Serial
|
28
|
+
|
29
|
+
property :login, String
|
30
|
+
property :path, String
|
31
|
+
property :message, String
|
32
|
+
|
33
|
+
property :created_at, DateTime
|
34
|
+
|
35
|
+
before :save do
|
36
|
+
self.created_at = DateTime.now
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
21
|
+
require 'ixtlan/babel/serializer'
|
22
|
+
module Ixtlan
|
23
|
+
module Audit
|
24
|
+
class AuditSerializer < Ixtlan::Babel::Serializer
|
25
|
+
|
26
|
+
root 'audit'
|
27
|
+
|
28
|
+
add_context( :single )
|
29
|
+
|
30
|
+
add_context( :collection, :except => [:created_at] )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,3 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2012 Christian Meier
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
1
21
|
require 'slf4r/logger'
|
2
22
|
|
3
23
|
module Ixtlan
|
@@ -14,7 +34,7 @@ module Ixtlan
|
|
14
34
|
|
15
35
|
def login_from(controller)
|
16
36
|
user = controller.respond_to?(:current_user) ? controller.send(:current_user) : nil
|
17
|
-
user.nil? ? nil: user.
|
37
|
+
user.nil? ? nil: (user.respond_to?(:login) ? user.login : user.username)
|
18
38
|
end
|
19
39
|
|
20
40
|
public
|
@@ -25,15 +45,14 @@ module Ixtlan
|
|
25
45
|
|
26
46
|
def log_action(controller, message = nil)
|
27
47
|
log_user(login_from(controller)) do
|
28
|
-
as_xml = controller.response.content_type == 'application/xml' ? " - xml" : ""
|
29
48
|
if controller.params[:controller]
|
30
49
|
clname = controller.params[:controller]
|
31
50
|
cname = clname.sub(/^.*\//, '')
|
32
51
|
audits = controller.instance_variable_get("@#{cname}")
|
33
|
-
if(audits)
|
34
|
-
"#{clname}##{controller.params[:action]} #{cname.classify}[#{audits.size}]#{
|
52
|
+
if(audits && audits.respond_to?(:collect))
|
53
|
+
"#{clname}##{controller.params[:action]} #{cname.classify}[#{audits.size}]#{message}"
|
35
54
|
else
|
36
|
-
audit = controller.instance_variable_get("@#{cname.singularize}")
|
55
|
+
audit = audits || controller.instance_variable_get("@#{cname.singularize}")
|
37
56
|
if(audit)
|
38
57
|
errors = if(audit.respond_to?(:errors) && !audit.errors.empty?)
|
39
58
|
" - errors: " + audit.errors.full_messages.join(", ")
|
@@ -42,12 +61,14 @@ module Ixtlan
|
|
42
61
|
audit.to_log
|
43
62
|
elsif audit.is_a? String
|
44
63
|
audit
|
64
|
+
elsif audit.respond_to?(:model)
|
65
|
+
"#{audit.model}(#{audit.id})"
|
45
66
|
else
|
46
67
|
"#{audit.class.name}(#{audit.id})"
|
47
68
|
end
|
48
|
-
"#{clname}##{controller.params[:action]} #{audit_log}#{
|
69
|
+
"#{clname}##{controller.params[:action]} #{audit_log}#{message}#{errors}"
|
49
70
|
else
|
50
|
-
"#{clname}##{controller.params[:action]}#{
|
71
|
+
"#{clname}##{controller.params[:action]}#{message}"
|
51
72
|
end
|
52
73
|
end
|
53
74
|
else
|
@@ -59,9 +80,9 @@ module Ixtlan
|
|
59
80
|
def log_user(user, message = nil, &block)
|
60
81
|
user ||= "???"
|
61
82
|
msg = "#{message}#{block.call if block}"
|
62
|
-
@manager.push( msg,
|
83
|
+
@manager.push( user, msg.sub(/\ .*$/, ''), msg )
|
63
84
|
logger.debug {"[#{user}] #{msg}" }
|
64
85
|
end
|
65
86
|
end
|
66
87
|
end
|
67
|
-
end
|
88
|
+
end
|
data/spec/audit_manager_spec.rb
CHANGED
@@ -9,6 +9,7 @@ class Audit
|
|
9
9
|
property :id, Serial
|
10
10
|
|
11
11
|
property :login, String
|
12
|
+
property :path, String
|
12
13
|
property :message, String
|
13
14
|
|
14
15
|
property :created_at, DateTime
|
@@ -18,25 +19,19 @@ class Audit
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
class Fixnum
|
22
|
-
def days
|
23
|
-
self
|
24
|
-
end
|
25
|
-
def ago
|
26
|
-
DateTime.now - 86000 * self
|
27
|
-
end
|
28
|
-
end
|
29
22
|
DataMapper.setup(:default, "sqlite3::memory:")
|
30
23
|
DataMapper.finalize
|
31
24
|
DataMapper.repository.auto_migrate!
|
32
25
|
|
33
26
|
describe Ixtlan::Audit::Manager do
|
34
27
|
|
28
|
+
before { subject.model = Audit }
|
29
|
+
|
35
30
|
it 'should collect log events and the save them all in one go' do
|
36
31
|
size = Audit.all.size
|
37
|
-
subject.push("
|
38
|
-
subject.push("
|
39
|
-
subject.push("
|
32
|
+
subject.push( "login1", "path1", "msg1" )
|
33
|
+
subject.push( "login2", "path2", "msg2" )
|
34
|
+
subject.push( "login3", "path3", "msg3" )
|
40
35
|
subject.save_all
|
41
36
|
|
42
37
|
Audit.all.size.should == size + 3
|
@@ -47,8 +42,8 @@ describe Ixtlan::Audit::Manager do
|
|
47
42
|
Audit.all.size.should > 0
|
48
43
|
subject.keep_logs = 0
|
49
44
|
Audit.all.size.should == 0
|
50
|
-
subject.push("
|
51
|
-
subject.push("
|
45
|
+
subject.push( "login1", "path1", "msg1" )
|
46
|
+
subject.push( "login2", "path2", "msg2" )
|
52
47
|
subject.save_all
|
53
48
|
Audit.all.size.should == 2
|
54
49
|
end
|
metadata
CHANGED
@@ -1,133 +1,140 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ixtlan-audit
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.1
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
|
7
|
+
authors:
|
8
|
+
- Christian Meier
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
12
|
+
date: 2012-12-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: slf4r
|
16
|
+
requirement: &16127020 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.4.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *16127020
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &16126340 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - =
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.6.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *16126340
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &16125600 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - =
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.8.7
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *16125600
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: dm-core
|
49
|
+
requirement: &16124940 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - =
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *16124940
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: dm-migrations
|
60
|
+
requirement: &16124460 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - =
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.2.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *16124460
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dm-sqlite-adapter
|
71
|
+
requirement: &16123860 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - =
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.2.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *16123860
|
80
|
+
description: audit the controller actions for the current user. log that data into
|
81
|
+
the database and allow to expire this log files (privacy protection) and be able
|
82
|
+
to browse it from the UI
|
83
|
+
email:
|
84
|
+
- m.kristian@web.de
|
84
85
|
executables: []
|
85
|
-
|
86
86
|
extensions: []
|
87
|
-
|
88
87
|
extra_rdoc_files: []
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
88
|
+
files:
|
89
|
+
- MIT-LICENSE
|
90
|
+
- lib/ixtlan-audit.rb~
|
91
|
+
- lib/ixtlan-audit.rb
|
92
|
+
- lib/ixtlan/audit/cuba.rb~
|
93
|
+
- lib/ixtlan/audit/cuba_plugin.rb
|
94
|
+
- lib/ixtlan/audit/cuba.rb
|
95
|
+
- lib/ixtlan/audit/resource.rb
|
96
|
+
- lib/ixtlan/audit/cuba_setup.rb~
|
97
|
+
- lib/ixtlan/audit/logging_configurator.rb~
|
98
|
+
- lib/ixtlan/audit/user_logger.rb
|
99
|
+
- lib/ixtlan/audit/audit_resource.rb~
|
100
|
+
- lib/ixtlan/audit/manager.rb
|
101
|
+
- lib/ixtlan/audit/audit_serializer.rb~
|
102
|
+
- lib/ixtlan/audit/manager.rb~
|
103
|
+
- lib/ixtlan/audit/railtie.rb
|
104
|
+
- lib/ixtlan/audit/user_logger.rb~
|
105
|
+
- lib/ixtlan/audit/rack.rb~
|
106
|
+
- lib/ixtlan/audit/rack.rb
|
107
|
+
- lib/ixtlan/audit/cuba_plugin.rb~
|
108
|
+
- lib/ixtlan/audit/serializer.rb
|
109
|
+
- spec/audit_manager_spec.rb
|
110
|
+
- spec/audit_manager_spec.rb~
|
104
111
|
homepage: http://github.com/mkristian/ixtlan-audit
|
105
|
-
licenses:
|
106
|
-
|
112
|
+
licenses:
|
113
|
+
- MIT
|
107
114
|
post_install_message:
|
108
|
-
rdoc_options:
|
109
|
-
|
110
|
-
|
111
|
-
require_paths:
|
112
|
-
|
113
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
rdoc_options:
|
116
|
+
- --main
|
117
|
+
- README.textile
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
121
|
none: false
|
115
|
-
requirements:
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
127
|
none: false
|
121
|
-
requirements:
|
122
|
-
|
123
|
-
|
124
|
-
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
125
132
|
requirements: []
|
126
|
-
|
127
133
|
rubyforge_project:
|
128
|
-
rubygems_version: 1.8.
|
134
|
+
rubygems_version: 1.8.11
|
129
135
|
signing_key:
|
130
136
|
specification_version: 3
|
131
137
|
summary: audit the controller actions for the current user
|
132
|
-
test_files:
|
133
|
-
|
138
|
+
test_files:
|
139
|
+
- spec/audit_manager_spec.rb
|
140
|
+
has_rdoc:
|
data/README.textile
DELETED
@@ -1,4 +0,0 @@
|
|
1
|
-
h1. Rails Audit Log
|
2
|
-
|
3
|
-
p. once you have a logged in user in your system, the usual request log can be improved by added the login name of the user to log output. but since you associate data with a "real" person privacy comes into play. the best privacy protection is not to store data, but in our case the compromise is to just define how long the data shall be stored (define an expiration date for the data).
|
4
|
-
|