saseo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.saseo.standalone_migrations +6 -0
  7. data/.saseo_source.standalone_migrations +6 -0
  8. data/.travis.yml +38 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE +22 -0
  11. data/README.md +38 -0
  12. data/Rakefile +12 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +7 -0
  15. data/db/saseo/migrate/20151028181502_initial_schema.rb +18 -0
  16. data/db/saseo/schema.rb +32 -0
  17. data/db/saseo_source/migrate/20151028181502_initial_schema.rb +16 -0
  18. data/db/saseo_source/schema.rb +30 -0
  19. data/exe/saseo_consumer +6 -0
  20. data/exe/saseo_publisher +6 -0
  21. data/lib/generators/saseo/install_generator.rb +35 -0
  22. data/lib/generators/saseo/templates/add_saseo_trigger.rb.erb +14 -0
  23. data/lib/generators/saseo/templates/add_saseo_trigger_function.rb +105 -0
  24. data/lib/generators/saseo/trigger_generator.rb +42 -0
  25. data/lib/saseo/config/defaults.rb +41 -0
  26. data/lib/saseo/config/saseo_database.yml +14 -0
  27. data/lib/saseo/config/saseo_source_database.yml +14 -0
  28. data/lib/saseo/config.rb +52 -0
  29. data/lib/saseo/extensions/active_record/detector.rb +17 -0
  30. data/lib/saseo/extensions/active_record/patcher.rb +32 -0
  31. data/lib/saseo/extensions/active_record/v_3/connection_adapters/postgresql_adapter.rb +26 -0
  32. data/lib/saseo/extensions/active_record/v_3.rb +11 -0
  33. data/lib/saseo/extensions/active_record/v_4/connection_adapters/postgresql/database_statements.rb +29 -0
  34. data/lib/saseo/extensions/active_record/v_4.rb +11 -0
  35. data/lib/saseo/extensions/active_record.rb +9 -0
  36. data/lib/saseo/extensions.rb +7 -0
  37. data/lib/saseo/models/base.rb +51 -0
  38. data/lib/saseo/models/source/base.rb +22 -0
  39. data/lib/saseo/models/source/version.rb +20 -0
  40. data/lib/saseo/models/version.rb +19 -0
  41. data/lib/saseo/persistence/consumer.rb +25 -0
  42. data/lib/saseo/persistence/persistor.rb +37 -0
  43. data/lib/saseo/persistence.rb +8 -0
  44. data/lib/saseo/publishing/data_change_message.rb +43 -0
  45. data/lib/saseo/publishing/publisher.rb +95 -0
  46. data/lib/saseo/publishing.rb +8 -0
  47. data/lib/saseo/version.rb +3 -0
  48. data/lib/saseo/whodunnit.rb +41 -0
  49. data/lib/saseo.rb +10 -0
  50. data/saseo.example.yml +12 -0
  51. data/saseo.gemspec +34 -0
  52. data/tasks/bump.rake +30 -0
  53. 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
@@ -0,0 +1,12 @@
1
+ /.ruby-version/
2
+ /.ruby-gemset/
3
+ /.bundle/
4
+ /.yardoc
5
+ /Gemfile.lock
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+ /.idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ saseo
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.2
@@ -0,0 +1,6 @@
1
+ db:
2
+ seeds: db/saseo/seeds.rb
3
+ migrate: db/saseo/migrate
4
+ schema: db/saseo/schema.rb
5
+ config:
6
+ database: lib/saseo/config/saseo_database.yml
@@ -0,0 +1,6 @@
1
+ db:
2
+ seeds: db/saseo_source/seeds.rb
3
+ migrate: db/saseo_source/migrate
4
+ schema: db/saseo_source/schema.rb
5
+ config:
6
+ database: lib/saseo/config/saseo_source_database.yml
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
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in saseo.gemspec
4
+ gemspec
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,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -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
@@ -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
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'saseo/persistence/consumer'
5
+
6
+ Saseo::Persistence::Consumer.subscribe.endure
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'saseo/publishing/publisher'
5
+ publisher = Saseo::Publishing::Publisher.new
6
+ publisher.run
@@ -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
@@ -0,0 +1,14 @@
1
+ defaults: &defaults
2
+ adapter: postgresql
3
+ encoding: utf8
4
+
5
+ development:
6
+ <<: *defaults
7
+ database: saseo_dev
8
+
9
+ test:
10
+ <<: *defaults
11
+ database: saseo_test
12
+ load_seeds: true
13
+ verbosity: silent
14
+ migrate: false
@@ -0,0 +1,14 @@
1
+ defaults: &defaults
2
+ adapter: postgresql
3
+ encoding: utf8
4
+
5
+ development:
6
+ <<: *defaults
7
+ database: saseo_source_dev
8
+
9
+ test:
10
+ <<: *defaults
11
+ database: saseo_source_test
12
+ load_seeds: true
13
+ verbosity: silent
14
+ migrate: false
@@ -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