pg_audit_log 0.5.0 → 0.5.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.
- data/lib/pg_audit_log/active_record.rb +1 -1
- data/lib/pg_audit_log/entry.rb +1 -1
- data/lib/pg_audit_log/extensions/{shared/postgresql_adapter.rb → postgresql_adapter.rb} +41 -27
- data/lib/pg_audit_log/function.rb +2 -20
- data/lib/pg_audit_log/version.rb +1 -1
- data/lib/pg_audit_log.rb +3 -11
- data/spec/pg_audit_log_spec.rb +12 -1
- metadata +16 -20
- data/lib/pg_audit_log/extensions/3.0/postgresql_adapter.rb +0 -26
- data/lib/pg_audit_log/extensions/3.1/postgresql_adapter.rb +0 -35
- data/spec/connection_adapter_spec.rb +0 -13
data/lib/pg_audit_log/entry.rb
CHANGED
|
@@ -2,30 +2,6 @@ require "active_record/connection_adapters/postgresql_adapter"
|
|
|
2
2
|
|
|
3
3
|
# Did not want to reopen the class but sending an include seemingly is not working.
|
|
4
4
|
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
|
5
|
-
def begin_db_transaction
|
|
6
|
-
execute_without_auditing "BEGIN"
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def commit_db_transaction
|
|
10
|
-
execute_without_auditing "COMMIT"
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def rollback_db_transaction
|
|
14
|
-
execute_without_auditing "ROLLBACK"
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def create_savepoint
|
|
18
|
-
execute_without_auditing("SAVEPOINT #{current_savepoint_name}")
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def rollback_to_savepoint
|
|
22
|
-
execute_without_auditing("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def release_savepoint
|
|
26
|
-
execute_without_auditing("RELEASE SAVEPOINT #{current_savepoint_name}")
|
|
27
|
-
end
|
|
28
|
-
|
|
29
5
|
def drop_table_with_auditing(table_name, options = {})
|
|
30
6
|
if PgAuditLog::Triggers.tables_with_triggers.include?(table_name)
|
|
31
7
|
PgAuditLog::Triggers.drop_for_table(table_name)
|
|
@@ -49,17 +25,55 @@ class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
|
|
49
25
|
alias_method_chain :create_table, :auditing
|
|
50
26
|
|
|
51
27
|
def rename_table_with_auditing(table_name, new_name)
|
|
52
|
-
rename_table_without_auditing(table_name, new_name)
|
|
53
28
|
if PgAuditLog::Triggers.tables_with_triggers.include?(table_name)
|
|
54
29
|
PgAuditLog::Triggers.drop_for_table(table_name)
|
|
55
30
|
end
|
|
56
|
-
|
|
57
|
-
|
|
31
|
+
rename_table_without_auditing(table_name, new_name)
|
|
32
|
+
unless PgAuditLog::IGNORED_TABLES.include?(table_name) || PgAuditLog::Triggers.tables_with_triggers.include?(new_name)
|
|
58
33
|
PgAuditLog::Triggers.create_for_table(new_name)
|
|
59
34
|
end
|
|
60
35
|
end
|
|
61
36
|
alias_method_chain :rename_table, :auditing
|
|
62
37
|
|
|
38
|
+
def set_audit_user_id_and_name
|
|
39
|
+
user_id, unique_name = user_id_and_name
|
|
40
|
+
return true if (@last_user_id && @last_user_id == user_id) && (@last_unique_name && @last_unique_name == unique_name)
|
|
41
|
+
|
|
42
|
+
execute_without_pg_audit_log PgAuditLog::Function::user_identifier_temporary_function(user_id)
|
|
43
|
+
execute_without_pg_audit_log PgAuditLog::Function::user_unique_name_temporary_function(unique_name)
|
|
44
|
+
@last_user_id = user_id
|
|
45
|
+
@last_unique_name = unique_name
|
|
46
|
+
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def blank_audit_user_id_and_name
|
|
51
|
+
@last_user_id = @last_unique_name = nil
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def reconnect_with_pg_audit_log!
|
|
56
|
+
reconnect_without_pg_audit_log!
|
|
57
|
+
@last_user_id = @last_unique_name = nil
|
|
58
|
+
end
|
|
59
|
+
alias_method_chain :reconnect!, :pg_audit_log
|
|
60
|
+
|
|
61
|
+
def execute_with_pg_audit_log(sql, name = nil)
|
|
62
|
+
conn = execute_without_pg_audit_log(sql, name = nil)
|
|
63
|
+
set_audit_user_id_and_name
|
|
64
|
+
conn
|
|
65
|
+
end
|
|
66
|
+
alias_method_chain :execute, :pg_audit_log
|
|
67
|
+
|
|
68
|
+
if ::ActiveRecord::VERSION::MAJOR >= 3 && ::ActiveRecord::VERSION::MINOR >= 1
|
|
69
|
+
def exec_query_with_pg_audit_log(sql, name = 'SQL', binds = [])
|
|
70
|
+
conn = exec_query_without_pg_audit_log(sql, name, binds)
|
|
71
|
+
set_audit_user_id_and_name
|
|
72
|
+
conn
|
|
73
|
+
end
|
|
74
|
+
alias_method_chain :exec_query, :pg_audit_log
|
|
75
|
+
end
|
|
76
|
+
|
|
63
77
|
private
|
|
64
78
|
|
|
65
79
|
def user_id_and_name
|
|
@@ -22,29 +22,11 @@ module PgAuditLog
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def user_identifier_temporary_function(user_id)
|
|
25
|
-
|
|
26
|
-
CREATE OR REPLACE FUNCTION pg_temp.pg_audit_log_user_identifier() RETURNS integer
|
|
27
|
-
LANGUAGE plpgsql
|
|
28
|
-
AS $_$
|
|
29
|
-
BEGIN
|
|
30
|
-
RETURN #{user_id};
|
|
31
|
-
END
|
|
32
|
-
$_$;
|
|
33
|
-
SQL
|
|
34
|
-
sql.split("\n").join(" ")
|
|
25
|
+
"CREATE OR REPLACE FUNCTION pg_temp.pg_audit_log_user_identifier() RETURNS integer AS 'SELECT #{user_id}' LANGUAGE SQL STABLE;"
|
|
35
26
|
end
|
|
36
27
|
|
|
37
28
|
def user_unique_name_temporary_function(username)
|
|
38
|
-
|
|
39
|
-
CREATE OR REPLACE FUNCTION pg_temp.pg_audit_log_user_unique_name() RETURNS varchar
|
|
40
|
-
LANGUAGE plpgsql
|
|
41
|
-
AS $_$
|
|
42
|
-
BEGIN
|
|
43
|
-
RETURN '#{username}';
|
|
44
|
-
END
|
|
45
|
-
$_$;
|
|
46
|
-
SQL
|
|
47
|
-
sql.split("\n").join(" ")
|
|
29
|
+
"CREATE OR REPLACE FUNCTION pg_temp.pg_audit_log_user_unique_name() RETURNS varchar AS $_$ SELECT '#{username}'::varchar $_$ LANGUAGE SQL STABLE;"
|
|
48
30
|
end
|
|
49
31
|
|
|
50
32
|
def install
|
data/lib/pg_audit_log/version.rb
CHANGED
data/lib/pg_audit_log.rb
CHANGED
|
@@ -5,17 +5,9 @@ end
|
|
|
5
5
|
require "active_record"
|
|
6
6
|
require "pg_audit_log/version"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if ::ActiveRecord::VERSION::MINOR == 0
|
|
12
|
-
require "pg_audit_log/extensions/3.0/postgresql_adapter.rb"
|
|
13
|
-
else
|
|
14
|
-
require "pg_audit_log/extensions/3.1/postgresql_adapter.rb"
|
|
15
|
-
end
|
|
16
|
-
else
|
|
17
|
-
raise "ActiveRecord #{::ActiveRecord::VERSION::MAJOR}.x unsupported!"
|
|
18
|
-
end
|
|
8
|
+
raise "ActiveRecord #{::ActiveRecord::VERSION::MAJOR}.x unsupported!" unless ::ActiveRecord::VERSION::MAJOR == 3
|
|
9
|
+
|
|
10
|
+
require "pg_audit_log/extensions/postgresql_adapter.rb"
|
|
19
11
|
require "pg_audit_log/active_record"
|
|
20
12
|
require "pg_audit_log/entry"
|
|
21
13
|
require "pg_audit_log/function"
|
data/spec/pg_audit_log_spec.rb
CHANGED
|
@@ -265,12 +265,23 @@ describe PgAuditLog do
|
|
|
265
265
|
end
|
|
266
266
|
|
|
267
267
|
describe "when renaming the table" do
|
|
268
|
+
def trigger_names
|
|
269
|
+
connection.select_values <<-SQL
|
|
270
|
+
SELECT triggers.tgname as trigger_name
|
|
271
|
+
FROM pg_trigger triggers
|
|
272
|
+
WHERE triggers.tgname LIKE '#{PgAuditLog::Triggers.trigger_prefix}%'
|
|
273
|
+
SQL
|
|
274
|
+
end
|
|
275
|
+
|
|
268
276
|
it "should automatically drop and create the trigger" do
|
|
269
277
|
new_table_name = "new_table_#{Time.now.to_i}"
|
|
270
278
|
connection.create_table("test_table")
|
|
271
279
|
connection.rename_table("test_table", new_table_name)
|
|
272
|
-
|
|
280
|
+
|
|
281
|
+
trigger_names.should_not include("audit_test_table")
|
|
282
|
+
trigger_names.should include("audit_#{new_table_name}")
|
|
273
283
|
PgAuditLog::Triggers.tables_with_triggers.should include(new_table_name)
|
|
284
|
+
|
|
274
285
|
connection.drop_table(new_table_name) rescue nil
|
|
275
286
|
end
|
|
276
287
|
end
|
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.5.
|
|
4
|
+
version: 0.5.1
|
|
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: 2012-02
|
|
12
|
+
date: 2012-04-02 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rails
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70263689333140 !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: *
|
|
24
|
+
version_requirements: *70263689333140
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: pg
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70263689332640 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ! '>='
|
|
@@ -32,10 +32,10 @@ dependencies:
|
|
|
32
32
|
version: 0.9.0
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *70263689332640
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: rspec-rails
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &70263689332180 !ruby/object:Gem::Requirement
|
|
39
39
|
none: false
|
|
40
40
|
requirements:
|
|
41
41
|
- - =
|
|
@@ -43,10 +43,10 @@ dependencies:
|
|
|
43
43
|
version: '2.7'
|
|
44
44
|
type: :development
|
|
45
45
|
prerelease: false
|
|
46
|
-
version_requirements: *
|
|
46
|
+
version_requirements: *70263689332180
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: with_model
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &70263689331720 !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: *
|
|
57
|
+
version_requirements: *70263689331720
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: autotest
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &70263689331340 !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: *
|
|
68
|
+
version_requirements: *70263689331340
|
|
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
|
|
@@ -92,15 +92,12 @@ files:
|
|
|
92
92
|
- lib/pg_audit_log.rb
|
|
93
93
|
- lib/pg_audit_log/active_record.rb
|
|
94
94
|
- lib/pg_audit_log/entry.rb
|
|
95
|
-
- lib/pg_audit_log/extensions/
|
|
96
|
-
- lib/pg_audit_log/extensions/3.1/postgresql_adapter.rb
|
|
97
|
-
- lib/pg_audit_log/extensions/shared/postgresql_adapter.rb
|
|
95
|
+
- lib/pg_audit_log/extensions/postgresql_adapter.rb
|
|
98
96
|
- lib/pg_audit_log/function.rb
|
|
99
97
|
- lib/pg_audit_log/triggers.rb
|
|
100
98
|
- lib/pg_audit_log/version.rb
|
|
101
99
|
- pg_audit_log.gemspec
|
|
102
100
|
- spec/configuration_spec.rb
|
|
103
|
-
- spec/connection_adapter_spec.rb
|
|
104
101
|
- spec/function_spec.rb
|
|
105
102
|
- spec/model_spec.rb
|
|
106
103
|
- spec/pg_audit_log_spec.rb
|
|
@@ -120,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
120
117
|
version: '0'
|
|
121
118
|
segments:
|
|
122
119
|
- 0
|
|
123
|
-
hash:
|
|
120
|
+
hash: -372258529913880576
|
|
124
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
122
|
none: false
|
|
126
123
|
requirements:
|
|
@@ -129,16 +126,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
129
126
|
version: '0'
|
|
130
127
|
segments:
|
|
131
128
|
- 0
|
|
132
|
-
hash:
|
|
129
|
+
hash: -372258529913880576
|
|
133
130
|
requirements: []
|
|
134
131
|
rubyforge_project:
|
|
135
|
-
rubygems_version: 1.8.
|
|
132
|
+
rubygems_version: 1.8.17
|
|
136
133
|
signing_key:
|
|
137
134
|
specification_version: 3
|
|
138
135
|
summary: postgresql only database-level audit logging of all databases changes
|
|
139
136
|
test_files:
|
|
140
137
|
- spec/configuration_spec.rb
|
|
141
|
-
- spec/connection_adapter_spec.rb
|
|
142
138
|
- spec/function_spec.rb
|
|
143
139
|
- spec/model_spec.rb
|
|
144
140
|
- spec/pg_audit_log_spec.rb
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
require "active_record/connection_adapters/postgresql_adapter"
|
|
2
|
-
|
|
3
|
-
# Did not want to reopen the class but sending an include seemingly is not working.
|
|
4
|
-
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
|
5
|
-
def execute_with_auditing(sql, name = nil)
|
|
6
|
-
user_id, unique_name = user_id_and_name
|
|
7
|
-
log_user_id = PgAuditLog::Function.user_identifier_temporary_function(user_id)
|
|
8
|
-
log_user_unique_name = PgAuditLog::Function.user_unique_name_temporary_function(unique_name)
|
|
9
|
-
|
|
10
|
-
logged_sql = ENV["LOG_AUDIT_SQL"] ? [log_user_id, log_user_unique_name, sql].values.join('; ') : sql
|
|
11
|
-
log(logged_sql, name) do
|
|
12
|
-
if @async
|
|
13
|
-
@connection.async_exec(log_user_id)
|
|
14
|
-
@connection.async_exec(log_user_unique_name)
|
|
15
|
-
@connection.async_exec(sql)
|
|
16
|
-
else
|
|
17
|
-
@connection.exec(log_user_id)
|
|
18
|
-
@connection.exec(log_user_unique_name)
|
|
19
|
-
@connection.exec(sql)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
alias_method_chain :execute, :auditing
|
|
25
|
-
end
|
|
26
|
-
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
require "active_record/connection_adapters/postgresql_adapter"
|
|
2
|
-
|
|
3
|
-
# Did not want to reopen the class but sending an include seemingly is not working.
|
|
4
|
-
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
|
5
|
-
def generate_auditing_sql(sql)
|
|
6
|
-
user_id, unique_name = user_id_and_name
|
|
7
|
-
log_user_id = PgAuditLog::Function.user_identifier_temporary_function(user_id)
|
|
8
|
-
log_user_unique_name = PgAuditLog::Function.user_unique_name_temporary_function(unique_name)
|
|
9
|
-
{ :user_id => log_user_id, :unique_name => log_user_unique_name, :sql => sql }
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def exec_query_with_auditing(sql, name = 'SQL', binds = [])
|
|
13
|
-
audited_sql = generate_auditing_sql(sql)
|
|
14
|
-
logged_sql = ENV["LOG_AUDIT_SQL"] ? audited_sql.values.join('; ') : sql
|
|
15
|
-
log(logged_sql, name, binds) do
|
|
16
|
-
exec_no_cache(audited_sql[:user_id], binds)
|
|
17
|
-
exec_no_cache(audited_sql[:unique_name], binds)
|
|
18
|
-
result = binds.empty? ? exec_no_cache(sql, binds) :
|
|
19
|
-
exec_cache(sql, binds)
|
|
20
|
-
|
|
21
|
-
ret = ActiveRecord::Result.new(result.fields, result_as_array(result))
|
|
22
|
-
result.clear
|
|
23
|
-
return ret
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
alias_method_chain :exec_query, :auditing
|
|
27
|
-
|
|
28
|
-
def execute_with_auditing(sql, name = nil)
|
|
29
|
-
log(generate_auditing_sql(sql), name) do
|
|
30
|
-
@connection.async_exec(sql)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
alias_method_chain :execute, :auditing
|
|
34
|
-
end
|
|
35
|
-
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
-
|
|
3
|
-
describe "the connection adapter" do
|
|
4
|
-
subject { ActiveRecord::Base.connection }
|
|
5
|
-
|
|
6
|
-
it { should respond_to(:execute_without_auditing) }
|
|
7
|
-
|
|
8
|
-
it "should work for both execute and execute_without_auditing" do
|
|
9
|
-
subject.execute("SELECT 1 = 1")
|
|
10
|
-
subject.execute_without_auditing("SELECT 1 = 1")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
end
|