saseo 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.saseo.standalone_migrations +6 -0
- data/.saseo_source.standalone_migrations +6 -0
- data/.travis.yml +38 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +38 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/db/saseo/migrate/20151028181502_initial_schema.rb +18 -0
- data/db/saseo/schema.rb +32 -0
- data/db/saseo_source/migrate/20151028181502_initial_schema.rb +16 -0
- data/db/saseo_source/schema.rb +30 -0
- data/exe/saseo_consumer +6 -0
- data/exe/saseo_publisher +6 -0
- data/lib/generators/saseo/install_generator.rb +35 -0
- data/lib/generators/saseo/templates/add_saseo_trigger.rb.erb +14 -0
- data/lib/generators/saseo/templates/add_saseo_trigger_function.rb +105 -0
- data/lib/generators/saseo/trigger_generator.rb +42 -0
- data/lib/saseo/config/defaults.rb +41 -0
- data/lib/saseo/config/saseo_database.yml +14 -0
- data/lib/saseo/config/saseo_source_database.yml +14 -0
- data/lib/saseo/config.rb +52 -0
- data/lib/saseo/extensions/active_record/detector.rb +17 -0
- data/lib/saseo/extensions/active_record/patcher.rb +32 -0
- data/lib/saseo/extensions/active_record/v_3/connection_adapters/postgresql_adapter.rb +26 -0
- data/lib/saseo/extensions/active_record/v_3.rb +11 -0
- data/lib/saseo/extensions/active_record/v_4/connection_adapters/postgresql/database_statements.rb +29 -0
- data/lib/saseo/extensions/active_record/v_4.rb +11 -0
- data/lib/saseo/extensions/active_record.rb +9 -0
- data/lib/saseo/extensions.rb +7 -0
- data/lib/saseo/models/base.rb +51 -0
- data/lib/saseo/models/source/base.rb +22 -0
- data/lib/saseo/models/source/version.rb +20 -0
- data/lib/saseo/models/version.rb +19 -0
- data/lib/saseo/persistence/consumer.rb +25 -0
- data/lib/saseo/persistence/persistor.rb +37 -0
- data/lib/saseo/persistence.rb +8 -0
- data/lib/saseo/publishing/data_change_message.rb +43 -0
- data/lib/saseo/publishing/publisher.rb +95 -0
- data/lib/saseo/publishing.rb +8 -0
- data/lib/saseo/version.rb +3 -0
- data/lib/saseo/whodunnit.rb +41 -0
- data/lib/saseo.rb +10 -0
- data/saseo.example.yml +12 -0
- data/saseo.gemspec +34 -0
- data/tasks/bump.rake +30 -0
- metadata +264 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 13c887bdc257323e0273ef0b9dc529e01ba99bcc
|
4
|
+
data.tar.gz: 21131a2fd553dab157facf48ba0e4e7cacb321aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0eb41500a2fc709e0aab838e6f724d3922359e91c821f68735ab644d05451f7853ee14937ba328536bf4d5192569a4597cf3cee5d6087321da78774451489605
|
7
|
+
data.tar.gz: 352a0efffeeca3687497461015391efb93e4c1aaba33d781dd68970bdc35182603c2c234b1a0b998fdb8ecf2fbe10f55e8f99524e429b44a4c558229298929dd
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
saseo
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
data/.travis.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
sudo: false
|
2
|
+
language: ruby
|
3
|
+
before_install: gem install bundler -v 1.10.6
|
4
|
+
rvm:
|
5
|
+
- 2.1.5
|
6
|
+
- 2.2.0
|
7
|
+
- 2.2.1
|
8
|
+
- 2.2.2
|
9
|
+
- 2.2.3
|
10
|
+
- rbx-2
|
11
|
+
- jruby-19mode
|
12
|
+
- ruby-head
|
13
|
+
- jruby-head
|
14
|
+
script:
|
15
|
+
- bundle exec rake DATABASE=saseo_source DB=test db:create db:migrate && bundle exec rake DATABASE=saseo DB=test db:create db:migrate && DATABASE=saseo bundle exec rspec
|
16
|
+
addons:
|
17
|
+
postgresql: "9.4"
|
18
|
+
code_climate:
|
19
|
+
repo_token:
|
20
|
+
secure: UdY6NcwRikTo7j9Aj4MViFG9EHB3BUsbHVYsC76hK31CCMkx0ZGik0pEUggZCTSomwJktYQuPupcW63mp3Udyelj/1GILv8FRWnAvtCrbSW255vOBhR7HR9axh3lh9AXiShm5sfMe50JUBeCoTyC3R7G5LkDp1WtPPcvko28JYA429+01BmLayrymt37TYuuFWxhzEjO9fhjezL5ibyOHNzjCOQLBNcEWRwLO1qeIXn82fxabi4fC0ciQqwRQS8yyR2m+s/UUrCePk2Dm0FDvPDL4HSnHGLPzuWvLcvU3wI0g1zpZvBhaBGnYEIvsIfekLzMN86Ke6BbByCorno4Qgu/v08XVbJxIr//efdAeZaZhR6LPee9tM+trBI2nWAovqzFdiD7+09yDgnCYvA5JO3ls9K9YOrNl1Dt1IX/E1Wk5SQtuz+2tmc/NlkEpYAPK6qtW/oGQmw7MS9+s4/BfsB8faVb4CKoJ8sIkpmur+jNJovBDcwya3cD7U5uioV47pdLgO3X1bdFt6s8PovJnIiNVTZsCiCeiIvFXrDrrCsS19S2GVF7m7MRvfNlO1Jp82SthakQmpCsYjxfk0M7zraPvyOoYVc75vd5nUWph+xWYj/jrr8IxOFJmMU2SFTm1EMONeQP1tqkRNwTxqPFnUl1WAI3OZdeCWrpsUwTMC4=
|
21
|
+
notifications:
|
22
|
+
email:
|
23
|
+
on_success: change
|
24
|
+
on_failure: change
|
25
|
+
hipchat:
|
26
|
+
on_success: change
|
27
|
+
on_failure: change
|
28
|
+
template:
|
29
|
+
- "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}
|
30
|
+
| Details: %{build_url} | Changes: %{compare_url}"
|
31
|
+
rooms:
|
32
|
+
secure: HE3Kx3MzyJFg+uj4EUmQLa1cs5QOLju66W3ao0zFSdfDx1XDrRXNu5sGi9cwKRxxZ2uksD4g7A9cCnnjqgfemB8ktrbyeM6AxI2LqPreUx/zep8+wnTKd3wRcsr8J7zFAZ45Rfa1qnSangUMD/ZuHaaXfI8Nvxcdc+lCiFD2vSiweo5Qt1eURY7gr1+WGw/QeTyuRAAUoSuiJJp8GP7jOxZMbdYWJXcSp7HIIjHOUIw8oaRKBaYpXYxRjdCyFfW3a+B4QnDiizIvoLxdcSyqI5qXvBxGg/5YzSkQkpDUSvNqv8nWYXfE0YgyzL2UItOWnZj77CiL2GHOEyg64bvUk1mGp9ABRxF5f56/vqG5ZzOz2Mnyduvsp4VMhe/LiMmulqdCJSFHA8/Uz9QccL30MpDnPZM13aZ9XRKj76ARDdgIhoLorxaX857xcCrlxgD4+29nx9FS1dWWBzo7r9qUsetdbeGGyp9qbcBa30wo0kxpdNQid5r05t8LnYZRbRwu51vx0oPRRxnpMMpBanBJvrrGJXPNO4LQ1wX4gLsPDuqB3UtlncgjKQvP4ES+N/+3z2pbV429tAqj3TsZ8rpiqJCBvKwTzLeOMluhW6sJBoua5eFDMHKzgQRgreW/joLLoCIsC2N3LVoF0pKktN9L7khSui2hI8r1yzO8lnJugMs=
|
33
|
+
matrix:
|
34
|
+
allow_failures:
|
35
|
+
- rvm: 2.0.0
|
36
|
+
- rvm: jruby-19mode
|
37
|
+
- rvm: jruby-head
|
38
|
+
- rvm: ruby-head
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Avant Credit Corporation
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Saseo - 사서
|
2
|
+
RabbitMQ based PaperTrail replacement
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/avantcredit/saseo.png?branch=master)](https://travis-ci.org/avantcredit/saseo)
|
5
|
+
[![Dependency Status](https://gemnasium.com/avantcredit/saseo.svg)](https://gemnasium.com/avantcredit/saseo)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/avantcredit/saseo/badges/gpa.svg)](https://codeclimate.com/github/avantcredit/saseo)
|
7
|
+
[![Test Coverage](https://codeclimate.com/github/avantcredit/saseo/badges/coverage.svg)](https://codeclimate.com/github/avantcredit/saseo)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'saseo'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install saseo
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
TODO: Write usage instructions here
|
28
|
+
|
29
|
+
## Development
|
30
|
+
|
31
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
32
|
+
|
33
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/saseo.
|
38
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'standalone_migrations'
|
4
|
+
|
5
|
+
StandaloneMigrations::Tasks.load_tasks
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
task :default => :spec
|
10
|
+
|
11
|
+
Dir["tasks/**/*.rake"].each { |ext| load ext }
|
12
|
+
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "saseo"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class InitialSchema < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
|
4
|
+
enable_extension 'uuid-ossp'
|
5
|
+
|
6
|
+
create_table 'saseo_versions', id: :uuid, force: true do |t|
|
7
|
+
t.integer 'transaction_id', null: false, limit: 8 # bigint
|
8
|
+
t.integer 'item_id', null: false
|
9
|
+
t.uuid 'item_uuid'
|
10
|
+
t.string 'table_name', null: false
|
11
|
+
t.string 'action', null: false
|
12
|
+
t.datetime 'action_timestamp', null: false
|
13
|
+
t.string 'whodunnit', null: false
|
14
|
+
t.jsonb 'old_data'
|
15
|
+
t.jsonb 'new_data'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/db/saseo/schema.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(version: 20151028181502) do
|
15
|
+
|
16
|
+
# These are extensions that must be enabled in order to support this database
|
17
|
+
enable_extension "plpgsql"
|
18
|
+
enable_extension "uuid-ossp"
|
19
|
+
|
20
|
+
create_table "saseo_versions", id: :uuid, default: "uuid_generate_v4()", force: :cascade do |t|
|
21
|
+
t.integer "transaction_id", limit: 8, null: false
|
22
|
+
t.integer "item_id", null: false
|
23
|
+
t.uuid "item_uuid"
|
24
|
+
t.string "table_name", null: false
|
25
|
+
t.string "action", null: false
|
26
|
+
t.datetime "action_timestamp", null: false
|
27
|
+
t.string "whodunnit", null: false
|
28
|
+
t.jsonb "old_data"
|
29
|
+
t.jsonb "new_data"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class InitialSchema < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
|
4
|
+
enable_extension 'uuid-ossp'
|
5
|
+
|
6
|
+
create_table 'saseo_source_versions', id: :uuid, force: true do |t|
|
7
|
+
t.integer 'transaction_id', null: false, limit: 8 # bigint
|
8
|
+
t.string 'table_name', null: false
|
9
|
+
t.string 'action', null: false
|
10
|
+
t.datetime 'action_timestamp', null: false
|
11
|
+
t.string 'whodunnit', null: false
|
12
|
+
t.jsonb 'old_data'
|
13
|
+
t.jsonb 'new_data'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(version: 20151028181502) do
|
15
|
+
|
16
|
+
# These are extensions that must be enabled in order to support this database
|
17
|
+
enable_extension "plpgsql"
|
18
|
+
enable_extension "uuid-ossp"
|
19
|
+
|
20
|
+
create_table "saseo_source_versions", id: :uuid, default: "uuid_generate_v4()", force: :cascade do |t|
|
21
|
+
t.integer "transaction_id", limit: 8, null: false
|
22
|
+
t.string "table_name", null: false
|
23
|
+
t.string "action", null: false
|
24
|
+
t.datetime "action_timestamp", null: false
|
25
|
+
t.string "whodunnit", null: false
|
26
|
+
t.jsonb "old_data"
|
27
|
+
t.jsonb "new_data"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/exe/saseo_consumer
ADDED
data/exe/saseo_publisher
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module Saseo
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
include ::Rails::Generators::Migration
|
7
|
+
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
argument :table_names, type: :array, default: [], banner: 'tables to add triggers to'
|
10
|
+
|
11
|
+
|
12
|
+
desc 'Generates (but does not run) a migration to add the trigger function.'
|
13
|
+
|
14
|
+
def create_migration_file
|
15
|
+
add_saseo_migration('add_saseo_trigger_function')
|
16
|
+
Rails::Generators.invoke('saseo:trigger', table_names) unless table_names.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.next_migration_number(dirname)
|
20
|
+
::ActiveRecord::Generators::Base.next_migration_number(dirname)
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
def add_saseo_migration(template)
|
25
|
+
migration_dir = File.expand_path('db/migrate')
|
26
|
+
|
27
|
+
unless self.class.migration_exists?(migration_dir, template)
|
28
|
+
migration_template "#{template}.rb", "db/migrate/#{template}.rb"
|
29
|
+
else
|
30
|
+
warn("ALERT: Migration already exists named '#{template}'." +
|
31
|
+
" Please check your migrations directory before re-running")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class AddSaseoTriggerTo<%= @table_name.camelcase %> < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
# originally copied from:
|
4
|
+
# https://wiki.postgresql.org/wiki/Audit_trigger
|
5
|
+
trigger_definition = <<SQL
|
6
|
+
CREATE TRIGGER <%= @table_name %>_saseo_trigger AFTER INSERT OR UPDATE OR DELETE ON <%= @table_name %> FOR EACH ROW EXECUTE PROCEDURE saseo_audit_func();
|
7
|
+
SQL
|
8
|
+
execute(trigger_definition)
|
9
|
+
end
|
10
|
+
|
11
|
+
def down
|
12
|
+
execute('DROP TRIGGER <%= @table_name %>_saseo_trigger ON <%= @table_name %> CASCADE;')
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
class AddSaseoTriggerFunction < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
|
4
|
+
uuid_extension_sql = 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'
|
5
|
+
|
6
|
+
audit_table_sql = <<SQL
|
7
|
+
CREATE TABLE saseo_source_versions (
|
8
|
+
id uuid PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
9
|
+
transaction_id bigint NOT NULL,
|
10
|
+
table_name text NOT NULL,
|
11
|
+
action_timestamp timestamp WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
12
|
+
action text NOT NULL CHECK (action IN ('INSERT','DELETE','UPDATE')),
|
13
|
+
whodunnit text NOT NULL,
|
14
|
+
old_data jsonb,
|
15
|
+
new_data jsonb
|
16
|
+
)
|
17
|
+
SQL
|
18
|
+
|
19
|
+
|
20
|
+
# originally copied from:
|
21
|
+
# https://wiki.postgresql.org/wiki/Audit_trigger
|
22
|
+
#
|
23
|
+
# modified to use NOTIFY
|
24
|
+
#
|
25
|
+
# a trigger must be added to every table
|
26
|
+
# CREATE TRIGGER identities_saseo_trigger AFTER INSERT OR UPDATE OR DELETE ON identities FOR EACH ROW EXECUTE PROCEDURE saseo_audit_func();
|
27
|
+
whodunnit_sql = <<SQL
|
28
|
+
CREATE OR REPLACE FUNCTION saseo_whodunnit() RETURNS TEXT AS $body$
|
29
|
+
BEGIN
|
30
|
+
return current_setting('saseo.whodunnit');
|
31
|
+
EXCEPTION WHEN undefined_object THEN
|
32
|
+
return current_user;
|
33
|
+
END;
|
34
|
+
$body$
|
35
|
+
LANGUAGE plpgsql
|
36
|
+
SQL
|
37
|
+
audit_sql = <<SQL
|
38
|
+
CREATE OR REPLACE FUNCTION saseo_audit_func() RETURNS TRIGGER AS $body$
|
39
|
+
DECLARE
|
40
|
+
v_old_data json;
|
41
|
+
v_new_data json;
|
42
|
+
v_whodunnit text;
|
43
|
+
v_channel text;
|
44
|
+
v_audit_uuid uuid;
|
45
|
+
BEGIN
|
46
|
+
v_whodunnit := saseo_whodunnit();
|
47
|
+
v_audit_uuid := uuid_generate_v4();
|
48
|
+
|
49
|
+
v_channel := upper('SASEO' || '_' || TG_TABLE_NAME::TEXT || '_' || TG_OP || '_AUDIT');
|
50
|
+
|
51
|
+
IF (TG_OP = 'UPDATE') THEN
|
52
|
+
v_old_data := row_to_json(OLD);
|
53
|
+
v_new_data := row_to_json(NEW);
|
54
|
+
|
55
|
+
INSERT INTO saseo_source_versions VALUES(v_audit_uuid, txid_current(), TG_TABLE_NAME, DEFAULT, TG_OP, v_whodunnit, v_old_data::JSONB, v_new_data::JSONB);
|
56
|
+
PERFORM pg_notify(v_channel, v_audit_uuid::TEXT);
|
57
|
+
|
58
|
+
RETURN NEW;
|
59
|
+
ELSIF (TG_OP = 'DELETE') THEN
|
60
|
+
v_old_data := row_to_json(OLD);
|
61
|
+
|
62
|
+
INSERT INTO saseo_source_versions VALUES(v_audit_uuid, txid_current(), TG_TABLE_NAME, DEFAULT, TG_OP, v_whodunnit, v_old_data::JSONB, NULL);
|
63
|
+
PERFORM pg_notify(v_channel, v_audit_uuid::TEXT);
|
64
|
+
|
65
|
+
RETURN OLD;
|
66
|
+
ELSIF (TG_OP = 'INSERT') THEN
|
67
|
+
v_new_data := row_to_json(NEW);
|
68
|
+
|
69
|
+
INSERT INTO saseo_source_versions VALUES(v_audit_uuid, txid_current(), TG_TABLE_NAME, DEFAULT, TG_OP, v_whodunnit, NULL, v_new_data::JSONB);
|
70
|
+
PERFORM pg_notify(v_channel, v_audit_uuid::TEXT);
|
71
|
+
|
72
|
+
RETURN NEW;
|
73
|
+
ELSE
|
74
|
+
RAISE WARNING '[SASEO_AUDIT_FUNC] - Other action occurred: %, at %',TG_OP,now();
|
75
|
+
RETURN NULL;
|
76
|
+
END IF;
|
77
|
+
|
78
|
+
EXCEPTION
|
79
|
+
WHEN data_exception THEN
|
80
|
+
RAISE WARNING '[SASEO_AUDIT_FUNC] - UDF ERROR [DATA EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
|
81
|
+
RETURN NULL;
|
82
|
+
WHEN unique_violation THEN
|
83
|
+
RAISE WARNING '[SASEO_AUDIT_FUNC] - UDF ERROR [UNIQUE] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
|
84
|
+
RETURN NULL;
|
85
|
+
WHEN OTHERS THEN
|
86
|
+
RAISE WARNING '[SASEO_AUDIT_FUNC] - UDF ERROR [OTHER] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
|
87
|
+
RETURN NULL;
|
88
|
+
END;
|
89
|
+
$body$
|
90
|
+
LANGUAGE plpgsql
|
91
|
+
SQL
|
92
|
+
execute(uuid_extension_sql)
|
93
|
+
execute(audit_table_sql)
|
94
|
+
execute(whodunnit_sql)
|
95
|
+
execute(audit_sql)
|
96
|
+
end
|
97
|
+
|
98
|
+
def down
|
99
|
+
execute('DROP FUNCTION IF EXISTS saseo_audit_func() CASCADE')
|
100
|
+
execute('DROP FUNCTION IF EXISTS saseo_whodunnit() CASCADE')
|
101
|
+
execute('DROP TABLE IF EXISTS saseo_source_versions CASCADE')
|
102
|
+
execute('DROP EXTENSION IF EXISTS "uuid-ossp" CASCADE')
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
require 'saseo/models/source/base'
|
4
|
+
require 'saseo/config'
|
5
|
+
|
6
|
+
module Saseo
|
7
|
+
class TriggerGenerator < ::Rails::Generators::Base
|
8
|
+
include ::Rails::Generators::Migration
|
9
|
+
|
10
|
+
source_root File.expand_path('../templates', __FILE__)
|
11
|
+
argument :table_names, type: :array, banner: 'tables to add triggers to'
|
12
|
+
|
13
|
+
desc 'Generates (but does not run) a migration to add the trigger.'
|
14
|
+
|
15
|
+
def create_migration_file
|
16
|
+
tables = table_names.dup
|
17
|
+
tables = Saseo::Models::Source::Base.connection.tables if tables.include? 'all'
|
18
|
+
tables -= [Saseo.config.source_table_name, Saseo.config.table_name]
|
19
|
+
|
20
|
+
tables.each do |table_name|
|
21
|
+
@table_name = table_name
|
22
|
+
add_saseo_migration("add_saseo_trigger")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.next_migration_number(dirname)
|
27
|
+
::ActiveRecord::Generators::Base.next_migration_number(dirname)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
def add_saseo_migration(template)
|
32
|
+
migration_dir = File.expand_path('db/migrate')
|
33
|
+
|
34
|
+
unless self.class.migration_exists?(migration_dir, template)
|
35
|
+
migration_template "#{template}.rb.erb", "db/migrate/#{template}_to_#{@table_name}.rb"
|
36
|
+
else
|
37
|
+
warn("ALERT: Migration already exists named '#{template}'." +
|
38
|
+
" Please check your migrations directory before re-running")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Saseo
|
2
|
+
class Config
|
3
|
+
module Defaults
|
4
|
+
|
5
|
+
CHANNELS = :all
|
6
|
+
SOURCE_DATABASE_URL = nil
|
7
|
+
SOURCE_DATABASE_CONFIG_PATH = 'config/database.yml'
|
8
|
+
DATABASE_URL = nil
|
9
|
+
DATABASE_CONFIG_PATH = 'saseo/config/saseo_database.yml'
|
10
|
+
TABLE_NAME = 'saseo_versions'
|
11
|
+
SOURCE_TABLE_NAME = 'saseo_source_versions'
|
12
|
+
CONSUMER_PHILOTIC_SUBSCRIPTION = 'saseo_audit'
|
13
|
+
|
14
|
+
def defaults
|
15
|
+
@defaults ||= Hash[Saseo::Config::Defaults.constants.map do |c|
|
16
|
+
key = c.downcase.to_sym
|
17
|
+
|
18
|
+
env_key = "#{ENV_PREFIX}_#{key}".upcase
|
19
|
+
|
20
|
+
[key, ENV[env_key] || Saseo::Config::Defaults.const_get(c)]
|
21
|
+
end
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.included(base)
|
26
|
+
Saseo::Config::Defaults.constants.each do |c|
|
27
|
+
attr_symbol = c.downcase.to_sym
|
28
|
+
base.send(:attr_writer, attr_symbol)
|
29
|
+
base.class_eval %Q{
|
30
|
+
def #{attr_symbol}
|
31
|
+
unless defined? @#{attr_symbol}
|
32
|
+
@#{attr_symbol} = defaults[:#{attr_symbol}]
|
33
|
+
end
|
34
|
+
@#{attr_symbol}
|
35
|
+
end
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/saseo/config.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'saseo/config/defaults'
|
2
|
+
require 'oj'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Saseo
|
6
|
+
extend self
|
7
|
+
class Config
|
8
|
+
|
9
|
+
include Defaults
|
10
|
+
|
11
|
+
ENV_PREFIX = 'SASEO'
|
12
|
+
|
13
|
+
def initialize(config={})
|
14
|
+
load_config config
|
15
|
+
end
|
16
|
+
|
17
|
+
def env
|
18
|
+
ENV['SASEO_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
|
19
|
+
end
|
20
|
+
|
21
|
+
def load_config(config)
|
22
|
+
config.each do |k, v|
|
23
|
+
mutator = "#{k}="
|
24
|
+
send(mutator, v) if respond_to? mutator
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_file(filename, env = 'development')
|
29
|
+
config = YAML.load_file(filename)
|
30
|
+
load_config(config[env])
|
31
|
+
end
|
32
|
+
|
33
|
+
def channels
|
34
|
+
@channels ||= _load_json_config :channels
|
35
|
+
end
|
36
|
+
|
37
|
+
def consumer_philotic_subscription
|
38
|
+
@consumer_philotic_subscription ||= _load_json_config :consumer_philotic_subscription
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def _load_json_config(config)
|
43
|
+
value = defaults[config]
|
44
|
+
Oj.load(value) rescue value
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def config
|
50
|
+
@config ||= Saseo::Config.new
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Saseo
|
2
|
+
module Extensions
|
3
|
+
module ActiveRecord
|
4
|
+
module Detector
|
5
|
+
extend self
|
6
|
+
def active_record_version
|
7
|
+
return nil unless (Object.const_get('ActiveRecord') rescue nil)
|
8
|
+
::ActiveRecord::VERSION::MAJOR
|
9
|
+
end
|
10
|
+
|
11
|
+
def active_record_detected?
|
12
|
+
!!active_record_version
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|