cia 0.6.0 → 1.0.0
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.
- checksums.yaml +5 -5
- data/Readme.md +29 -6
- data/lib/cia/attribute_change_methods.rb +53 -0
- data/lib/cia/auditable.rb +9 -1
- data/lib/cia/{event.rb → event_methods.rb} +15 -8
- data/lib/cia/source_validation.rb +4 -3
- data/lib/cia/version.rb +1 -1
- data/lib/cia.rb +2 -4
- metadata +26 -41
- data/lib/cia/attribute_change.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 800cc7be6c9f8e8287f0972939691bda201fce06afe9403c0d028410bb2f5d96
|
4
|
+
data.tar.gz: 0dd6a0d4b02b3c05fef5a4fd13dde1c409cb693d2780cd77859619b5e20f7896
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85a58c3adbd2e81c480e3b9dcd595b7bfef0f6ed337d4b83b3f196a411f3cf81715101a92efd27b86eddb2e4711cba5cd7539271425a4d8cd5c4adf9a9a96c47
|
7
|
+
data.tar.gz: 8068af8866e84e832503d0a2e45fcada45b082f13f8b29ea893151b71b0d8f041cf56ca657b289d80532e8a71105cb7d7c67185e37294d93a2c08b1e34e63fa7
|
data/Readme.md
CHANGED
@@ -5,7 +5,7 @@ Audit model actions like update/create/destroy/<custom> + attribute changes.
|
|
5
5
|
|
6
6
|
- normalized and queryable through table layout
|
7
7
|
- actors and subjects are polymorphic
|
8
|
-
- works on ActiveRecord
|
8
|
+
- works on ActiveRecord 5.2+
|
9
9
|
|
10
10
|
Table layout:
|
11
11
|
|
@@ -22,6 +22,29 @@ gem install cia
|
|
22
22
|
|
23
23
|
`rails g migration add_cia` + paste [Migration](https://raw.github.com/grosser/cia/master/MIGRATION.rb)
|
24
24
|
|
25
|
+
Then, create these two models in `app/models/cia`:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# app/models/cia/event.rb
|
29
|
+
|
30
|
+
module CIA
|
31
|
+
class Event < ActiveRecord::Base
|
32
|
+
include EventMethods
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# app/models/cia/attribute_change.rb
|
39
|
+
|
40
|
+
module CIA
|
41
|
+
class AttributeChange < ActiveRecord::Base
|
42
|
+
include AttributeChangeMethods
|
43
|
+
end
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
If you’re using multiple databases, these models should inherit from an abstract class that specifies a database connection, not directly from ActiveRecord::Base.
|
25
48
|
|
26
49
|
Usage
|
27
50
|
=====
|
@@ -29,7 +52,7 @@ Usage
|
|
29
52
|
```Ruby
|
30
53
|
class User < ActiveRecord::Base
|
31
54
|
include CIA::Auditable
|
32
|
-
|
55
|
+
audit_attribute :email, :crypted_password
|
33
56
|
end
|
34
57
|
|
35
58
|
class ApplicationController < ActionController::Base
|
@@ -50,7 +73,7 @@ CIA.exception_handler = -> (e) { raise e unless Rails.env.production? }
|
|
50
73
|
|
51
74
|
# conditional auditing
|
52
75
|
class User < ActiveRecord::Base
|
53
|
-
|
76
|
+
audit_attribute :email, if: :interesting?
|
54
77
|
|
55
78
|
def interesting?
|
56
79
|
...
|
@@ -63,14 +86,14 @@ CIA.current_actor = @user
|
|
63
86
|
# custom changes
|
64
87
|
class User < ActiveRecord::Base
|
65
88
|
def cia_changes
|
66
|
-
|
89
|
+
super.merge("this" => ["always", "changes"])
|
67
90
|
end
|
68
91
|
end
|
69
92
|
|
70
93
|
# using after_commit, useful if the CIA::Event is stored in a different database then the audited class
|
71
94
|
class User < ActiveRecord::Base
|
72
95
|
include CIA::Auditable
|
73
|
-
|
96
|
+
audit_attribute :email, :crypted_password, callback: :after_commit
|
74
97
|
end
|
75
98
|
|
76
99
|
# passing arbitrary attributes into the .audit method
|
@@ -101,4 +124,4 @@ Author
|
|
101
124
|
[Michael Grosser](http://grosser.it)<br/>
|
102
125
|
michael@grosser.it<br/>
|
103
126
|
License: MIT<br/>
|
104
|
-
[](https://github.com/grosser/cia/actions/workflows/actions.yml)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "json"
|
2
|
+
require_relative "./source_validation"
|
3
|
+
|
4
|
+
module CIA
|
5
|
+
module AttributeChangeMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include SourceValidation
|
8
|
+
|
9
|
+
included do
|
10
|
+
self.table_name = "cia_attribute_changes"
|
11
|
+
|
12
|
+
belongs_to :event, foreign_key: "cia_event_id", inverse_of: :attribute_changes
|
13
|
+
belongs_to :source, polymorphic: true
|
14
|
+
|
15
|
+
validates_presence_of :event, :attribute_name
|
16
|
+
|
17
|
+
scope :previous, lambda { order("id desc") }
|
18
|
+
|
19
|
+
delegate :created_at, to: :event
|
20
|
+
end
|
21
|
+
|
22
|
+
class_methods do
|
23
|
+
def on_attribute(attribute)
|
24
|
+
where(attribute_name: attribute)
|
25
|
+
end
|
26
|
+
|
27
|
+
def max_value_size
|
28
|
+
@max_value_size ||= (columns.detect { |c| c.name == "old_value" }.limit || 255)
|
29
|
+
end
|
30
|
+
|
31
|
+
def serialize_for_storage(item, &block)
|
32
|
+
raise "Pass me a block to reduce size" unless block_given?
|
33
|
+
before, json = nil
|
34
|
+
|
35
|
+
loop do
|
36
|
+
json = JSON.dump(item)
|
37
|
+
raise "The block did not reduce the size" if before && json.bytesize >= before
|
38
|
+
before = json.bytesize
|
39
|
+
break if max_value_size >= before
|
40
|
+
item = yield(item)
|
41
|
+
end
|
42
|
+
|
43
|
+
json
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def source_must_be_present?
|
50
|
+
event.present? && event.source_must_be_present?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/cia/auditable.rb
CHANGED
@@ -1,16 +1,23 @@
|
|
1
|
+
require_relative "./source_validation"
|
2
|
+
|
1
3
|
module CIA
|
2
|
-
|
4
|
+
module EventMethods
|
5
|
+
extend ActiveSupport::Concern
|
3
6
|
include SourceValidation
|
4
|
-
self.table_name = "cia_events"
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
included do
|
9
|
+
self.table_name = "cia_events"
|
10
|
+
belongs_to :actor, polymorphic: true
|
11
|
+
belongs_to :source, polymorphic: true
|
12
|
+
has_many :attribute_changes, foreign_key: :cia_event_id, inverse_of: :event, dependent: :destroy
|
9
13
|
|
10
|
-
|
14
|
+
validates_presence_of :action
|
15
|
+
end
|
11
16
|
|
12
|
-
|
13
|
-
|
17
|
+
class_methods do
|
18
|
+
def previous
|
19
|
+
order("created_at desc")
|
20
|
+
end
|
14
21
|
end
|
15
22
|
|
16
23
|
def attribute_change_hash
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module CIA
|
2
2
|
module SourceValidation
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
validates_presence_of :source_id, :source_type, unless: :source_must_be_present?
|
6
|
+
validates_presence_of :source, if: :source_must_be_present?
|
6
7
|
end
|
7
8
|
end
|
8
9
|
end
|
data/lib/cia/version.rb
CHANGED
data/lib/cia.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'cia/version'
|
3
3
|
require 'cia/auditable'
|
4
|
+
require 'cia/event_methods'
|
5
|
+
require 'cia/attribute_change_methods'
|
4
6
|
|
5
7
|
module CIA
|
6
|
-
autoload 'Event', 'cia/event'
|
7
|
-
autoload 'AttributeChange', 'cia/attribute_change'
|
8
|
-
autoload 'SourceValidation', 'cia/source_validation'
|
9
|
-
|
10
8
|
class << self
|
11
9
|
attr_accessor :exception_handler
|
12
10
|
attr_accessor :non_recordable_attributes
|
metadata
CHANGED
@@ -1,45 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '4.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
type: :
|
33
|
+
version: '4.2'
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '4.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: bump
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,21 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '3.4'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '3.4'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: wwtd
|
56
|
+
name: rake
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - ">="
|
@@ -81,34 +67,34 @@ dependencies:
|
|
81
67
|
- !ruby/object:Gem::Version
|
82
68
|
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: rspec
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - ">="
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
75
|
+
version: '3.4'
|
90
76
|
type: :development
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - ">="
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
82
|
+
version: '3.4'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: sqlite3
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
|
-
- - "
|
87
|
+
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
89
|
+
version: 1.6.0
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
|
-
- - "
|
94
|
+
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
111
|
-
description:
|
96
|
+
version: 1.6.0
|
97
|
+
description:
|
112
98
|
email: michael@grosser.it
|
113
99
|
executables: []
|
114
100
|
extensions: []
|
@@ -116,16 +102,16 @@ extra_rdoc_files: []
|
|
116
102
|
files:
|
117
103
|
- Readme.md
|
118
104
|
- lib/cia.rb
|
119
|
-
- lib/cia/
|
105
|
+
- lib/cia/attribute_change_methods.rb
|
120
106
|
- lib/cia/auditable.rb
|
121
|
-
- lib/cia/
|
107
|
+
- lib/cia/event_methods.rb
|
122
108
|
- lib/cia/source_validation.rb
|
123
109
|
- lib/cia/version.rb
|
124
110
|
homepage: https://github.com/grosser/cia
|
125
111
|
licenses:
|
126
112
|
- MIT
|
127
113
|
metadata: {}
|
128
|
-
post_install_message:
|
114
|
+
post_install_message:
|
129
115
|
rdoc_options: []
|
130
116
|
require_paths:
|
131
117
|
- lib
|
@@ -133,16 +119,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
119
|
requirements:
|
134
120
|
- - ">="
|
135
121
|
- !ruby/object:Gem::Version
|
136
|
-
version: 2.
|
122
|
+
version: 2.7.0
|
137
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
124
|
requirements:
|
139
125
|
- - ">="
|
140
126
|
- !ruby/object:Gem::Version
|
141
127
|
version: '0'
|
142
128
|
requirements: []
|
143
|
-
|
144
|
-
|
145
|
-
signing_key:
|
129
|
+
rubygems_version: 3.1.6
|
130
|
+
signing_key:
|
146
131
|
specification_version: 4
|
147
132
|
summary: Audit model events like update/create/delete + attribute changes + group
|
148
133
|
them by transaction, in normalized table layout for easy query access.
|
data/lib/cia/attribute_change.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
|
3
|
-
module CIA
|
4
|
-
class AttributeChange < ActiveRecord::Base
|
5
|
-
include SourceValidation
|
6
|
-
self.table_name = "cia_attribute_changes"
|
7
|
-
|
8
|
-
belongs_to :event, foreign_key: "cia_event_id", inverse_of: :attribute_changes
|
9
|
-
belongs_to :source, polymorphic: true
|
10
|
-
|
11
|
-
validates_presence_of :event, :attribute_name
|
12
|
-
|
13
|
-
scope :previous, lambda { order("id desc") }
|
14
|
-
|
15
|
-
delegate :created_at, to: :event
|
16
|
-
|
17
|
-
def self.on_attribute(attribute)
|
18
|
-
where(attribute_name: attribute)
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.max_value_size
|
22
|
-
@max_value_size ||= (columns.detect { |c| c.name == "old_value" }.limit || 255)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.serialize_for_storage(item, &block)
|
26
|
-
raise "Pass me a block to reduce size" unless block_given?
|
27
|
-
before, json = nil
|
28
|
-
|
29
|
-
loop do
|
30
|
-
json = JSON.dump(item)
|
31
|
-
raise "The block did not reduce the size" if before && json.bytesize >= before
|
32
|
-
before = json.bytesize
|
33
|
-
break if max_value_size >= before
|
34
|
-
item = yield(item)
|
35
|
-
end
|
36
|
-
|
37
|
-
json
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def source_must_be_present?
|
43
|
-
event.present? && event.source_must_be_present?
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|