pg_audit_log 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/generators/pg_audit_log/install_generator.rb +7 -0
- data/lib/generators/pg_audit_log/rspec_generator.rb +0 -1
- data/lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log.rake +15 -55
- data/lib/generators/pg_audit_log/templates/migration.rb +15 -0
- data/lib/pg_audit_log.rb +4 -0
- data/lib/pg_audit_log/active_record.rb +15 -0
- data/lib/pg_audit_log/entry.rb +36 -2
- data/lib/{generators/pg_audit_log/templates/lib/tasks/pg_audit_log/create_audit_changes.sql → pg_audit_log/function.rb} +18 -4
- data/lib/pg_audit_log/triggers.rb +36 -0
- data/lib/pg_audit_log/version.rb +1 -1
- data/spec/spec_helper.rb +3 -14
- metadata +6 -5
- data/lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log/create_audit_log_table.sql +0 -18
- data/lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log/uninstall_audit_changes.sql +0 -1
@@ -1,11 +1,18 @@
|
|
1
|
+
require "rails/generators/active_record"
|
2
|
+
|
1
3
|
module PgAuditLog
|
2
4
|
module Generators
|
3
5
|
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
extend ActiveRecord::Generators::Migration
|
8
|
+
|
4
9
|
source_root File.expand_path('../templates', __FILE__)
|
5
10
|
|
6
11
|
def install
|
7
12
|
directory "lib/tasks"
|
13
|
+
migration_template "migration.rb", "db/migrate/install_pg_audit_log"
|
8
14
|
end
|
15
|
+
|
9
16
|
end
|
10
17
|
end
|
11
18
|
end
|
@@ -1,76 +1,36 @@
|
|
1
1
|
namespace :pg_audit_log do
|
2
|
-
IGNORED_TABLES = ["plugin_schema_migrations", "sessions", "schema_migrations"]
|
3
|
-
|
4
2
|
desc "Install audit_log triggers on all tables"
|
5
3
|
task :install => :environment do
|
6
|
-
unless
|
4
|
+
unless PgAuditLog::Entry.installed?
|
7
5
|
puts "Creating #{PgAuditLog::Entry.table_name} table..."
|
8
|
-
|
9
|
-
connection.execute_without_auditing(sql)
|
6
|
+
PgAuditLog::Entry.install
|
10
7
|
end
|
8
|
+
|
11
9
|
puts "Installing audit_changes() function..."
|
12
|
-
|
13
|
-
connection.execute_without_auditing(sql)
|
10
|
+
PgAuditLog::Function.install
|
14
11
|
|
15
12
|
puts "Installing all audit log triggers... "
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
AFTER INSERT OR UPDATE OR DELETE
|
20
|
-
ON #{table}
|
21
|
-
FOR EACH ROW
|
22
|
-
EXECUTE PROCEDURE audit_changes()
|
23
|
-
SQL
|
24
|
-
end
|
25
|
-
puts "Exporting development_structure.sql..."
|
26
|
-
Rake::Task["db:structure:dump"].reenable
|
27
|
-
Rake::Task["db:structure:dump"].invoke
|
13
|
+
PgAuditLog::Triggers.install
|
14
|
+
|
15
|
+
export_development_structure
|
28
16
|
end
|
29
17
|
|
30
18
|
desc "Uninstall audit log triggers on all tables"
|
31
19
|
task :uninstall => :environment do
|
32
20
|
puts "Dropping all audit_log triggers... "
|
33
|
-
|
34
|
-
|
35
|
-
end
|
21
|
+
PgAuditLog::Triggers.uninstall
|
22
|
+
|
36
23
|
puts "Uninstalling audit_changes() function..."
|
37
|
-
|
38
|
-
connection.execute_without_auditing(sql)
|
24
|
+
PgAuditLog::Function.uninstall
|
39
25
|
|
40
|
-
|
41
|
-
Rake::Task["db:structure:dump"].reenable
|
42
|
-
Rake::Task["db:structure:dump"].invoke
|
26
|
+
export_development_structure
|
43
27
|
end
|
44
28
|
|
45
29
|
private
|
46
30
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
def all_tables
|
52
|
-
connection.tables
|
53
|
-
end
|
54
|
-
|
55
|
-
def audit_log_tables
|
56
|
-
all_tables - (IGNORED_TABLES + [PgAuditLog::Entry.table_name])
|
57
|
-
end
|
58
|
-
|
59
|
-
def sql_path
|
60
|
-
Rails.root.join("lib/tasks/pg_audit_log")
|
61
|
-
end
|
62
|
-
|
63
|
-
def run_on(tables, &block)
|
64
|
-
tables.sort.each do |table|
|
65
|
-
puts "* #{table}"
|
66
|
-
sql = yield(table)
|
67
|
-
begin
|
68
|
-
connection.execute_without_auditing(sql)
|
69
|
-
rescue => e
|
70
|
-
puts e.to_s
|
71
|
-
connection.reconnect!
|
72
|
-
end
|
73
|
-
end
|
31
|
+
def export_development_structure
|
32
|
+
puts "Exporting development_structure.sql..."
|
33
|
+
Rake::Task["db:structure:dump"].reenable
|
34
|
+
Rake::Task["db:structure:dump"].invoke
|
74
35
|
end
|
75
|
-
|
76
36
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class InstallPgAuditLog < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
PgAuditLog::Entry.install
|
5
|
+
PgAuditLog::Function.install
|
6
|
+
PgAuditLog::Triggers.install
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.down
|
10
|
+
PgAuditLog::Triggers.uninstall
|
11
|
+
PgAuditLog::Function.uninstall
|
12
|
+
PgAuditLog::Entry.uninstall
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
data/lib/pg_audit_log.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
module PgAuditLog
|
2
|
+
IGNORED_TABLES = ["plugin_schema_migrations", "sessions", "schema_migrations"]
|
2
3
|
end
|
3
4
|
|
4
5
|
require "active_record"
|
5
6
|
require "pg_audit_log/version"
|
6
7
|
require "pg_audit_log/extensions/postgresql_adapter.rb"
|
8
|
+
require "pg_audit_log/active_record"
|
7
9
|
require "pg_audit_log/entry"
|
10
|
+
require "pg_audit_log/function"
|
11
|
+
require "pg_audit_log/triggers"
|
8
12
|
|
data/lib/pg_audit_log/entry.rb
CHANGED
@@ -1,16 +1,50 @@
|
|
1
1
|
class PgAuditLog::Entry < ActiveRecord::Base
|
2
|
+
TABLE_NAME = "audit_log"
|
3
|
+
set_table_name TABLE_NAME
|
4
|
+
|
2
5
|
class CannotDeleteError < StandardError
|
3
6
|
def message
|
4
7
|
"Audit Logs cannot be deleted!"
|
5
8
|
end
|
6
9
|
end
|
7
|
-
set_table_name :audit_log
|
8
10
|
|
9
11
|
before_destroy do
|
10
12
|
raise CannotDeleteError
|
11
13
|
end
|
12
14
|
|
13
15
|
class << self
|
16
|
+
def installed?
|
17
|
+
connection.tables.include?(self.table_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def install
|
21
|
+
sql = <<-SQL
|
22
|
+
CREATE SEQUENCE #{self.table_name}_id_seq
|
23
|
+
START WITH 1
|
24
|
+
INCREMENT BY 1;
|
25
|
+
|
26
|
+
CREATE TABLE #{self.table_name} (
|
27
|
+
id integer PRIMARY KEY DEFAULT nextval('#{self.table_name}_id_seq'),
|
28
|
+
user_id integer,
|
29
|
+
user_unique_name character varying(255),
|
30
|
+
operation character varying(255),
|
31
|
+
table_name character varying(255),
|
32
|
+
field_name character varying(255),
|
33
|
+
field_value_new text,
|
34
|
+
field_value_old text,
|
35
|
+
occurred_at timestamp without time zone,
|
36
|
+
primary_key character varying(255)
|
37
|
+
);
|
38
|
+
|
39
|
+
ALTER SEQUENCE #{self.table_name}_id_seq OWNED BY #{self.table_name}.id;
|
40
|
+
SQL
|
41
|
+
connection.execute_without_auditing(sql)
|
42
|
+
end
|
43
|
+
|
44
|
+
def uninstall
|
45
|
+
connection.execute("DROP TABLE IF EXISTS #{self.table_name}")
|
46
|
+
end
|
47
|
+
|
14
48
|
def delete(id)
|
15
49
|
raise CannotDeleteError
|
16
50
|
end
|
@@ -20,4 +54,4 @@ class PgAuditLog::Entry < ActiveRecord::Base
|
|
20
54
|
end
|
21
55
|
end
|
22
56
|
|
23
|
-
end
|
57
|
+
end
|
@@ -1,7 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module PgAuditLog
|
2
|
+
class Function < ActiveRecord
|
3
|
+
class << self
|
4
|
+
def install
|
5
|
+
execute <<-SQL
|
6
|
+
CREATE OR REPLACE PROCEDURAL LANGUAGE plpgsql;
|
7
|
+
CREATE OR REPLACE FUNCTION audit_changes() RETURNS trigger
|
8
|
+
LANGUAGE plpgsql
|
9
|
+
AS $_$
|
5
10
|
DECLARE
|
6
11
|
col information_schema.columns %ROWTYPE;
|
7
12
|
new_value text;
|
@@ -70,3 +75,12 @@ CREATE OR REPLACE FUNCTION audit_changes() RETURNS trigger
|
|
70
75
|
RETURN NULL;
|
71
76
|
END
|
72
77
|
$_$;
|
78
|
+
SQL
|
79
|
+
end
|
80
|
+
|
81
|
+
def uninstall
|
82
|
+
execute "DROP FUNCTION audit_changes()"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PgAuditLog
|
2
|
+
class Triggers < ActiveRecord
|
3
|
+
class << self
|
4
|
+
def tables
|
5
|
+
connection.tables - (PgAuditLog::IGNORED_TABLES + [PgAuditLog::Entry.table_name])
|
6
|
+
end
|
7
|
+
|
8
|
+
def install
|
9
|
+
tables.each do |table|
|
10
|
+
create_for_table(table)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def uninstall
|
15
|
+
tables.each do |table|
|
16
|
+
drop_for_table(table)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_for_table(table_name)
|
21
|
+
execute <<-SQL
|
22
|
+
CREATE TRIGGER audit_#{table_name}
|
23
|
+
AFTER INSERT OR UPDATE OR DELETE
|
24
|
+
ON #{table_name}
|
25
|
+
FOR EACH ROW
|
26
|
+
EXECUTE PROCEDURE audit_changes()
|
27
|
+
SQL
|
28
|
+
end
|
29
|
+
|
30
|
+
def drop_for_table(table_name)
|
31
|
+
execute "DROP TRIGGER audit_#{table_name} ON #{table_name};"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/pg_audit_log/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -18,20 +18,9 @@ rescue PGError => e
|
|
18
18
|
raise e
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
["create_audit_changes.sql", "create_audit_log_table.sql"].each do |sql_file|
|
26
|
-
begin
|
27
|
-
connection.execute File.read(File.join(sql_path, sql_file))
|
28
|
-
rescue => e
|
29
|
-
puts "-" * 80
|
30
|
-
puts "Unable to install #{sql_file}"
|
31
|
-
puts "-" * 80
|
32
|
-
raise e
|
33
|
-
end
|
34
|
-
end
|
21
|
+
PgAuditLog::Entry.uninstall
|
22
|
+
PgAuditLog::Entry.install
|
23
|
+
PgAuditLog::Function.install
|
35
24
|
|
36
25
|
RSpec.configure do |config|
|
37
26
|
config.mock_with :rspec
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: pg_audit_log
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Case Commons, LLC
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-03-
|
13
|
+
date: 2011-03-29 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -66,14 +66,15 @@ files:
|
|
66
66
|
- lib/generators/pg_audit_log/install_generator.rb
|
67
67
|
- lib/generators/pg_audit_log/rspec_generator.rb
|
68
68
|
- lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log.rake
|
69
|
-
- lib/generators/pg_audit_log/templates/
|
70
|
-
- lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log/create_audit_log_table.sql
|
71
|
-
- lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log/uninstall_audit_changes.sql
|
69
|
+
- lib/generators/pg_audit_log/templates/migration.rb
|
72
70
|
- lib/generators/pg_audit_log/templates/spec/models/pg_audit_log_spec.rb
|
73
71
|
- lib/generators/pg_audit_log/templates/spec/models/pg_audit_log_spec_helper.rb
|
74
72
|
- lib/pg_audit_log.rb
|
73
|
+
- lib/pg_audit_log/active_record.rb
|
75
74
|
- lib/pg_audit_log/entry.rb
|
76
75
|
- lib/pg_audit_log/extensions/postgresql_adapter.rb
|
76
|
+
- lib/pg_audit_log/function.rb
|
77
|
+
- lib/pg_audit_log/triggers.rb
|
77
78
|
- lib/pg_audit_log/version.rb
|
78
79
|
- pg_audit_log.gemspec
|
79
80
|
- spec/configuration_spec.rb
|
data/lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log/create_audit_log_table.sql
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
CREATE SEQUENCE audit_log_id_seq
|
2
|
-
START WITH 1
|
3
|
-
INCREMENT BY 1;
|
4
|
-
|
5
|
-
CREATE TABLE audit_log (
|
6
|
-
id integer PRIMARY KEY DEFAULT nextval('audit_log_id_seq'),
|
7
|
-
user_id integer,
|
8
|
-
user_unique_name character varying(255),
|
9
|
-
operation character varying(255),
|
10
|
-
table_name character varying(255),
|
11
|
-
field_name character varying(255),
|
12
|
-
field_value_new text,
|
13
|
-
field_value_old text,
|
14
|
-
occurred_at timestamp without time zone,
|
15
|
-
primary_key character varying(255)
|
16
|
-
);
|
17
|
-
|
18
|
-
ALTER SEQUENCE audit_log_id_seq OWNED BY audit_log.id;
|
data/lib/generators/pg_audit_log/templates/lib/tasks/pg_audit_log/uninstall_audit_changes.sql
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
DROP FUNCTION audit_changes();
|