pg_audit_log 0.4.0 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .vimlog
1
2
  *.gem
2
3
  *~
3
4
  .DS_Store
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.2@pg_audit_log --create
1
+ rvm 1.9.3-p0@pg_audit_log --create
@@ -9,7 +9,9 @@ Comes with specs for your project and a rake task to generate the reverse SQL to
9
9
 
10
10
  All SQL INSERTs, UPDATEs, and DELETEs will be captured. Record columns that do not change do not generate an audit log entry.
11
11
 
12
- Compatible with Rails 3.0.x and 3.1.x
12
+ Compatible with Rails 3.0.x, 3.1.x and 3.2.x
13
+
14
+ On a 2.93GHz i7 with postgresql 9.1 the audit log has an overhead of about 0.0035 seconds to each INSERT, UPDATE or DELETE
13
15
 
14
16
  == INSTALL
15
17
 
@@ -1,6 +1,10 @@
1
1
  class PgAuditLog::Entry < ActiveRecord::Base
2
2
  TABLE_NAME = "audit_log"
3
- set_table_name TABLE_NAME
3
+ if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR >= 2
4
+ self.table_name = TABLE_NAME
5
+ else
6
+ set_table_name TABLE_NAME
7
+ end
4
8
 
5
9
  class CannotDeleteError < StandardError
6
10
  def message
@@ -30,7 +30,11 @@ class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
30
30
  if PgAuditLog::Triggers.tables_with_triggers.include?(table_name)
31
31
  PgAuditLog::Triggers.drop_for_table(table_name)
32
32
  end
33
- drop_table_without_auditing(table_name, options)
33
+ if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR >= 2
34
+ drop_table_without_auditing(table_name)
35
+ else
36
+ drop_table_without_auditing(table_name, options)
37
+ end
34
38
  end
35
39
  alias_method_chain :drop_table, :auditing
36
40
 
@@ -61,40 +61,39 @@ module PgAuditLog
61
61
  unique_name varchar;
62
62
  column_name varchar;
63
63
  BEGIN
64
+ primary_key_column := NULL;
65
+ EXECUTE 'SELECT pg_attribute.attname
66
+ FROM pg_index, pg_class, pg_attribute
67
+ WHERE pg_class.oid = $1::regclass
68
+ AND indrelid = pg_class.oid
69
+ AND pg_attribute.attrelid = pg_class.oid
70
+ AND pg_attribute.attnum = any(pg_index.indkey)
71
+ AND indisprimary'
72
+ INTO primary_key_column USING TG_RELNAME;
73
+ user_identifier := pg_temp.pg_audit_log_user_identifier();
74
+ unique_name := pg_temp.pg_audit_log_user_unique_name();
75
+ primary_key_value := NULL;
76
+
64
77
  FOR col IN SELECT * FROM information_schema.columns WHERE table_name = TG_RELNAME LOOP
65
78
  new_value := NULL;
66
79
  old_value := NULL;
67
- primary_key_column := NULL;
68
- primary_key_value := NULL;
69
- user_identifier := pg_temp.pg_audit_log_user_identifier();
70
- unique_name := pg_temp.pg_audit_log_user_unique_name();
71
80
  column_name := col.column_name;
72
-
73
- EXECUTE 'SELECT pg_attribute.attname
74
- FROM pg_index, pg_class, pg_attribute
75
- WHERE pg_class.oid = $1::regclass
76
- AND indrelid = pg_class.oid
77
- AND pg_attribute.attrelid = pg_class.oid
78
- AND pg_attribute.attnum = any(pg_index.indkey)
79
- AND indisprimary'
80
- INTO primary_key_column USING TG_RELNAME;
81
-
82
- IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
83
- EXECUTE 'SELECT CAST($1 . '|| column_name ||' AS TEXT)' INTO new_value USING NEW;
84
- IF primary_key_column IS NOT NULL THEN
85
- EXECUTE 'SELECT CAST($1 . '|| primary_key_column ||' AS VARCHAR)' INTO primary_key_value USING NEW;
86
- END IF;
87
- END IF;
88
- IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
89
- EXECUTE 'SELECT CAST($1 . '|| column_name ||' AS TEXT)' INTO old_value USING OLD;
90
- IF primary_key_column IS NOT NULL THEN
91
- EXECUTE 'SELECT CAST($1 . '|| primary_key_column ||' AS VARCHAR)' INTO primary_key_value USING OLD;
92
- END IF;
93
- END IF;
94
-
95
81
  IF TG_RELNAME = '#{users_table_name}' AND column_name = '#{users_access_column}' THEN
96
82
  NULL;
97
83
  ELSE
84
+ IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
85
+ EXECUTE 'SELECT CAST($1 . '|| column_name ||' AS TEXT)' INTO new_value USING NEW;
86
+ IF primary_key_value IS NULL AND primary_key_column IS NOT NULL THEN
87
+ EXECUTE 'SELECT CAST($1 . '|| primary_key_column ||' AS VARCHAR)' INTO primary_key_value USING NEW;
88
+ END IF;
89
+ END IF;
90
+ IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
91
+ EXECUTE 'SELECT CAST($1 . '|| column_name ||' AS TEXT)' INTO old_value USING OLD;
92
+ IF primary_key_value IS NULL AND primary_key_column IS NOT NULL THEN
93
+ EXECUTE 'SELECT CAST($1 . '|| primary_key_column ||' AS VARCHAR)' INTO primary_key_value USING OLD;
94
+ END IF;
95
+ END IF;
96
+
98
97
  IF TG_OP != 'UPDATE' OR new_value != old_value OR (TG_OP = 'UPDATE' AND ( (new_value IS NULL AND old_value IS NOT NULL) OR (new_value IS NOT NULL AND old_value IS NULL))) THEN
99
98
  INSERT INTO audit_log("operation",
100
99
  "table_name",
@@ -11,7 +11,11 @@ module PgAuditLog
11
11
 
12
12
  class << self
13
13
  def tables
14
- connection.tables - (PgAuditLog::IGNORED_TABLES + [PgAuditLog::Entry.table_name])
14
+ skip_tables = (PgAuditLog::IGNORED_TABLES + [PgAuditLog::Entry.table_name])
15
+ connection.tables.reject do |table|
16
+ skip_tables.include?(table) ||
17
+ skip_tables.any? { |skip_table| skip_table =~ table if skip_table.is_a? Regexp }
18
+ end
15
19
  end
16
20
 
17
21
  def tables_with_triggers
@@ -28,6 +32,10 @@ module PgAuditLog
28
32
  tables - tables_with_triggers
29
33
  end
30
34
 
35
+ def all_tables_without_triggers
36
+ connection.tables - tables_with_triggers
37
+ end
38
+
31
39
  def install
32
40
  tables.each do |table|
33
41
  create_for_table(table) unless tables_with_triggers.include?(table)
@@ -1,3 +1,3 @@
1
1
  module PgAuditLog
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.add_dependency("rails", ">= 3.0.0")
21
21
  s.add_dependency("pg", ">= 0.9.0")
22
- s.add_development_dependency('rspec-rails')
22
+ s.add_development_dependency('rspec-rails', "= 2.7")
23
23
  s.add_development_dependency('with_model', '>= 0.1.3')
24
24
  s.add_development_dependency('autotest')
25
25
  end
@@ -222,6 +222,19 @@ describe PgAuditLog do
222
222
  its(:primary_key) { should be_nil }
223
223
  end
224
224
  end
225
+
226
+ describe "performance" do
227
+ xit "should perform well" do
228
+ require "benchmark"
229
+ results = Benchmark.measure do
230
+ 1000.times do
231
+ AuditedModel.create!(attributes)
232
+ end
233
+ end
234
+ puts results.real
235
+ puts results.real / 1000.0
236
+ end
237
+ end
225
238
  end
226
239
 
227
240
  describe "during migrations" do
@@ -17,6 +17,23 @@ describe PgAuditLog::Triggers do
17
17
  PgAuditLog::Triggers.drop_for_table(TableWithoutTriggers.table_name) rescue nil
18
18
  end
19
19
 
20
+ describe ".tables" do
21
+ subject { PgAuditLog::Triggers.tables }
22
+
23
+ with_model :table_to_ignore do
24
+ table {}
25
+ end
26
+
27
+ before do
28
+ PgAuditLog::IGNORED_TABLES << /ignore/
29
+ end
30
+
31
+ it { should include(TableWithTriggers.table_name) }
32
+ it { should include(TableWithoutTriggers.table_name) }
33
+ it { should_not include(PgAuditLog::Entry.table_name) }
34
+ it { should_not include(TableToIgnore.table_name) }
35
+ end
36
+
20
37
  describe ".tables_with_triggers" do
21
38
  it "should return an array of all tables that do have an audit trigger installed" do
22
39
  PgAuditLog::Triggers.tables_with_triggers.should include(TableWithTriggers.table_name)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_audit_log
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-03 00:00:00.000000000Z
12
+ date: 2012-02-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &2152506680 !ruby/object:Gem::Requirement
16
+ requirement: &70094371058580 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2152506680
24
+ version_requirements: *70094371058580
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: pg
27
- requirement: &2152505720 !ruby/object:Gem::Requirement
27
+ requirement: &70094371056820 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,21 +32,21 @@ dependencies:
32
32
  version: 0.9.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2152505720
35
+ version_requirements: *70094371056820
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec-rails
38
- requirement: &2152505120 !ruby/object:Gem::Requirement
38
+ requirement: &70094371056040 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ! '>='
41
+ - - =
42
42
  - !ruby/object:Gem::Version
43
- version: '0'
43
+ version: '2.7'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2152505120
46
+ version_requirements: *70094371056040
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: with_model
49
- requirement: &2152503960 !ruby/object:Gem::Requirement
49
+ requirement: &70094371055100 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.1.3
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2152503960
57
+ version_requirements: *70094371055100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: autotest
60
- requirement: &2152503100 !ruby/object:Gem::Requirement
60
+ requirement: &70094371054000 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2152503100
68
+ version_requirements: *70094371054000
69
69
  description: A completely transparent audit logging component for your application
70
70
  using a stored procedure and triggers. Comes with specs for your project and a rake
71
71
  task to generate the reverse SQL to undo changes logged
@@ -120,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
120
  version: '0'
121
121
  segments:
122
122
  - 0
123
- hash: -732310515117041189
123
+ hash: -4309702284919187778
124
124
  required_rubygems_version: !ruby/object:Gem::Requirement
125
125
  none: false
126
126
  requirements:
@@ -129,10 +129,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
129
  version: '0'
130
130
  segments:
131
131
  - 0
132
- hash: -732310515117041189
132
+ hash: -4309702284919187778
133
133
  requirements: []
134
134
  rubyforge_project:
135
- rubygems_version: 1.8.10
135
+ rubygems_version: 1.8.6
136
136
  signing_key:
137
137
  specification_version: 3
138
138
  summary: postgresql only database-level audit logging of all databases changes