loggable_activity 0.1.56 → 0.1.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -1
- data/CHANGELOG.md +9 -0
- data/GETTING-STARTED.md +8 -47
- data/PAYLOAD_EXAMPLE.md +63 -0
- data/docs/LoggableActivity/Activity.html +92 -241
- data/docs/LoggableActivity/Configuration.html +162 -15
- data/docs/LoggableActivity/ConfigurationError.html +148 -0
- data/docs/LoggableActivity/DataOwner.html +138 -0
- data/docs/LoggableActivity/Encryption.html +18 -14
- data/docs/LoggableActivity/EncryptionError.html +47 -1
- data/docs/LoggableActivity/EncryptionKey.html +54 -35
- data/docs/LoggableActivity/Error.html +48 -0
- data/docs/LoggableActivity/Hooks.html +221 -89
- data/docs/LoggableActivity/Payload.html +103 -27
- data/docs/LoggableActivity/Services/BasePayloadsBuilder.html +442 -0
- data/docs/LoggableActivity/Services/DestroyPayloadsBuilder.html +395 -0
- data/docs/LoggableActivity/Services/PayloadsBuilder.html +342 -0
- data/docs/LoggableActivity/Services/UpdatePayloadsBuilder.html +490 -0
- data/docs/LoggableActivity/Services.html +93 -0
- data/docs/created.rid +14 -10
- data/docs/index.html +10 -2
- data/docs/js/navigation.js.gz +0 -0
- data/docs/js/search_index.js +1 -1
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js.gz +0 -0
- data/docs/table_of_contents.html +253 -85
- data/lib/generators/loggable_activity/install_generator.rb +2 -18
- data/lib/generators/loggable_activity/templates/binary_ids/create_loggable_activities.rb +9 -10
- data/lib/generators/loggable_activity/templates/create_loggable_activities.rb +16 -13
- data/lib/loggable_activity/activity.rb +53 -102
- data/lib/loggable_activity/configuration.rb +60 -3
- data/lib/loggable_activity/data_owner.rb +18 -0
- data/lib/loggable_activity/encryption.rb +14 -14
- data/lib/loggable_activity/encryption_key.rb +26 -25
- data/lib/loggable_activity/error.rb +34 -0
- data/lib/loggable_activity/hooks.rb +78 -43
- data/lib/loggable_activity/payload.rb +70 -20
- data/lib/loggable_activity/services/base_payloads_builder.rb +127 -0
- data/lib/loggable_activity/services/destroy_payloads_builder.rb +127 -0
- data/lib/loggable_activity/services/payloads_builder.rb +98 -0
- data/lib/loggable_activity/services/update_payloads_builder.rb +168 -0
- data/lib/loggable_activity/version.rb +1 -1
- data/lib/loggable_activity.rb +6 -6
- data/lib/schemas/config_schema.json +90 -0
- metadata +37 -26
- data/docs/LoggableActivity/PayloadsBuilder.html +0 -441
- data/docs/LoggableActivity/UpdatePayloadsBuilder.html +0 -424
- data/lib/generators/loggable_activity/install_templates_generator.rb +0 -105
- data/lib/generators/loggable_activity/templates/helpers/activity_helper.rb +0 -37
- data/lib/generators/loggable_activity/templates/helpers/router.rb +0 -52
- data/lib/generators/loggable_activity/templates/helpers/routes_helper.rb +0 -20
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_create.html.erb +0 -23
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_create.html.slim +0 -18
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_destroy.html.erb +0 -18
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_destroy.html.slim +0 -17
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_show.html.erb +0 -18
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_show.html.slim +0 -17
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_update.html.erb +0 -18
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_update.html.slim +0 -12
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_activity_info.html.erb +0 -12
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_activity_info.html.slim +0 -11
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_list_attrs.html.erb +0 -8
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_list_attrs.html.slim +0 -6
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_update_attrs.html.erb +0 -17
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_update_attrs.html.slim +0 -14
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_updated_relations.html.erb +0 -23
- data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_updated_relations.html.slim +0 -21
- data/lib/loggable_activity/payloads_builder.rb +0 -153
- data/lib/loggable_activity/update_payloads_builder.rb +0 -127
@@ -2,30 +2,31 @@
|
|
2
2
|
|
3
3
|
require 'active_support/concern'
|
4
4
|
|
5
|
-
# This is the main module for loggable.
|
6
|
-
# When included to a model, it provides the features for creating the activities.
|
7
|
-
require 'loggable_activity/payloads_builder'
|
8
|
-
require 'loggable_activity/update_payloads_builder'
|
9
|
-
|
10
5
|
module LoggableActivity
|
11
6
|
# This module provides hooks for creating activities when included in a model.
|
7
|
+
# When included to a model, it provides the features for logging events regarding to the model.
|
8
|
+
# For this to work you have to update the configuration file 'config/loggable_activity.yaml
|
9
|
+
|
10
|
+
# When included to a model, it provides the features for logging events regarding to the model.
|
11
|
+
# For this to work you have to update the configuration file 'config/loggable_activity.yaml
|
12
12
|
module Hooks
|
13
13
|
extend ActiveSupport::Concern
|
14
|
-
|
15
|
-
|
14
|
+
# The disable_hooks attribute is used to disable hooks when a model is created or updated by a parent model.
|
15
|
+
attr_accessor :disable_hooks
|
16
16
|
|
17
17
|
# The included hook sets up configuration and callback hooks for the model.
|
18
18
|
included do
|
19
|
-
config = LoggableActivity::Configuration.for_class(name)
|
19
|
+
config = ::LoggableActivity::Configuration.for_class(name)
|
20
20
|
|
21
|
-
|
21
|
+
if config.nil?
|
22
|
+
raise LoggableActivity::Error, "Configuration not found for #{name}, Please add it to 'config/loggable_activity.yaml"
|
23
|
+
end
|
22
24
|
|
23
25
|
# Initializes attributes based on configuration.
|
24
26
|
self.loggable_attrs = config&.fetch('loggable_attrs', []) || []
|
25
27
|
self.relations = config&.fetch('relations', []) || []
|
26
28
|
self.auto_log = config&.fetch('auto_log', []) || []
|
27
|
-
self.
|
28
|
-
self.record_display_name = config&.fetch('record_display_name', nil)
|
29
|
+
self.fetch_record_name_from = config&.fetch('fetch_record_name_from', nil)
|
29
30
|
self.route = config&.fetch('route', nil)
|
30
31
|
|
31
32
|
after_create :log_create_activity
|
@@ -41,9 +42,7 @@ module LoggableActivity
|
|
41
42
|
def log(action, actor: nil, params: {})
|
42
43
|
@action = action
|
43
44
|
@actor = actor || Thread.current[:current_user]
|
44
|
-
|
45
|
-
|
46
|
-
return if @actor.nil?
|
45
|
+
return nil if @actor.nil?
|
47
46
|
|
48
47
|
@record = self
|
49
48
|
@params = params
|
@@ -80,21 +79,38 @@ module LoggableActivity
|
|
80
79
|
|
81
80
|
# Creates an activity with the specified payloads.
|
82
81
|
def create_activity(payloads)
|
83
|
-
return if nothing_to_log?(payloads)
|
82
|
+
return nil if nothing_to_log?(payloads)
|
84
83
|
|
85
|
-
LoggableActivity::Activity.create!(
|
86
|
-
|
87
|
-
encrypted_record_display_name: encrypted_record_name,
|
84
|
+
::LoggableActivity::Activity.create!(
|
85
|
+
encrypted_actor_name:,
|
88
86
|
action: action_key,
|
89
87
|
actor: @actor,
|
90
|
-
record:
|
88
|
+
record: self,
|
91
89
|
payloads:
|
92
90
|
)
|
93
91
|
end
|
94
92
|
|
93
|
+
# Builds update payloads for the current action.
|
94
|
+
def build_update_payloads
|
95
|
+
::LoggableActivity::Services::UpdatePayloadsBuilder
|
96
|
+
.new(self, @payloads).build
|
97
|
+
end
|
98
|
+
|
99
|
+
# Builds payloads for the current action.
|
100
|
+
def build_payloads
|
101
|
+
::LoggableActivity::Services::PayloadsBuilder
|
102
|
+
.new(self, @payloads).build
|
103
|
+
end
|
104
|
+
|
105
|
+
# Builds destroy payloads for the current action.
|
106
|
+
def build_destroy_payload
|
107
|
+
::LoggableActivity::Services::DestroyPayloadsBuilder
|
108
|
+
.new(self, @payloads).build
|
109
|
+
end
|
110
|
+
|
95
111
|
# Returns true if there are no payloads to log.
|
96
|
-
def nothing_to_log?(
|
97
|
-
payloads.empty?
|
112
|
+
def nothing_to_log?(_payloads)
|
113
|
+
@payloads.empty?
|
98
114
|
end
|
99
115
|
|
100
116
|
# Logs a custom activity.
|
@@ -102,60 +118,78 @@ module LoggableActivity
|
|
102
118
|
|
103
119
|
# Logs an update activity automatically if configured.
|
104
120
|
def log_update_activity
|
121
|
+
return unless hooks_enabled?
|
122
|
+
|
105
123
|
log(:update) if self.class.auto_log.include?('update')
|
106
124
|
end
|
107
125
|
|
126
|
+
# Hooks can disabled when a model is created or updated
|
127
|
+
# by a parrent model.
|
128
|
+
def hooks_enabled?
|
129
|
+
enabled = disable_hooks.nil? || disable_hooks == false
|
130
|
+
self.disable_hooks = false
|
131
|
+
enabled
|
132
|
+
end
|
133
|
+
|
108
134
|
# Logs a create activity automatically if configured.
|
109
135
|
def log_create_activity
|
136
|
+
return unless hooks_enabled?
|
137
|
+
|
110
138
|
log(:create) if self.class.auto_log.include?('create')
|
111
139
|
end
|
112
140
|
|
113
141
|
# Logs a destroy activity automatically if configured.
|
114
142
|
def log_destroy_activity
|
115
|
-
|
143
|
+
mark_encryption_keys_as_deleted
|
144
|
+
return unless hooks_enabled?
|
145
|
+
|
116
146
|
log(:destroy) if self.class.auto_log.include?('destroy')
|
117
147
|
end
|
118
148
|
|
149
|
+
# Fullfill the needs of the data owners.
|
150
|
+
# Mostly this will be performend a few one, from 1 to 5.
|
151
|
+
# Enumeration for different payload relation types
|
152
|
+
def mark_encryption_keys_as_deleted
|
153
|
+
::LoggableActivity::EncryptionKey.for_record(self)&.mark_as_deleted!
|
154
|
+
# data_owners = ::LoggableActivity::DataOwner.where(record: self)
|
155
|
+
::LoggableActivity::DataOwner
|
156
|
+
.where(record: self)
|
157
|
+
.each(&:mark_as_deleted!)
|
158
|
+
end
|
159
|
+
|
119
160
|
# Returns the encrypted name of the actor.
|
120
161
|
def encrypted_actor_name
|
121
|
-
|
122
|
-
LoggableActivity::Encryption.encrypt(
|
162
|
+
name = @actor.send(fetch_current_user_name_from)
|
163
|
+
::LoggableActivity::Encryption.encrypt(name, actor_secret_key)
|
123
164
|
end
|
124
165
|
|
125
|
-
#
|
126
|
-
def
|
127
|
-
|
128
|
-
if self.class.record_display_name.nil?
|
129
|
-
"#{self.class.name} id: #{id}"
|
130
|
-
else
|
131
|
-
send(self.class.record_display_name.to_sym)
|
132
|
-
end
|
133
|
-
LoggableActivity::Encryption.encrypt(display_name, primary_encryption_key)
|
166
|
+
# Reads the field to feetch the record name from.
|
167
|
+
def fetch_current_user_name_from
|
168
|
+
::LoggableActivity::Configuration.fetch_current_user_name_from
|
134
169
|
end
|
135
170
|
|
136
171
|
# Returns the action key for the current action.
|
137
172
|
def action_key
|
138
|
-
|
173
|
+
self.class.base_action + ".#{@action}"
|
139
174
|
end
|
140
175
|
|
141
176
|
# Returns the primary encryption key for the activity
|
142
177
|
def primary_encryption_key
|
143
|
-
|
144
|
-
LoggableActivity::EncryptionKey.for_record(self)&.key
|
178
|
+
encryption_key_for_record
|
145
179
|
end
|
146
180
|
|
147
|
-
# Returns
|
148
|
-
def
|
149
|
-
|
181
|
+
# Returns the encryption key for the record.
|
182
|
+
def encryption_key_for_record(record = @record)
|
183
|
+
::LoggableActivity::EncryptionKey.for_record(record)
|
150
184
|
end
|
151
185
|
|
152
186
|
# Returns the encryption key for the actor.
|
153
|
-
def
|
154
|
-
|
187
|
+
def actor_secret_key
|
188
|
+
encryption_key_for_record(@actor)&.secret_key
|
155
189
|
end
|
156
190
|
|
157
191
|
# Returns the display name of the actor.
|
158
|
-
def
|
192
|
+
def actor__name_field
|
159
193
|
Rails.application.config.loggable_activity.actor_display_name || "id: #{@actor.id}, class: #{@actor.class.name}"
|
160
194
|
end
|
161
195
|
|
@@ -165,7 +199,8 @@ module LoggableActivity
|
|
165
199
|
end
|
166
200
|
|
167
201
|
class_methods do
|
168
|
-
|
202
|
+
# The loggable_attrs attribute is used read the configuration for the model that included LoggableActivity::Hooks.
|
203
|
+
attr_accessor :loggable_attrs, :relations, :auto_log, :fetch_record_name_from, :route
|
169
204
|
|
170
205
|
# Convert the model name and name space in to 'base_action'.
|
171
206
|
def base_action
|
@@ -8,23 +8,50 @@ module LoggableActivity
|
|
8
8
|
# Payloads come in different types, each serving a specific purpose.
|
9
9
|
class Payload < ActiveRecord::Base
|
10
10
|
self.table_name = 'loggable_payloads'
|
11
|
+
validates :related_to_activity_as, presence: true
|
11
12
|
|
12
13
|
# Associations
|
13
14
|
belongs_to :activity
|
15
|
+
belongs_to :encryption_key, class_name: '::LoggableActivity::EncryptionKey'
|
14
16
|
belongs_to :record, polymorphic: true, optional: true
|
15
17
|
|
18
|
+
# Enumeration for different payload types
|
19
|
+
DECRYPT_ATTRS_TYPES = %w[
|
20
|
+
primary_payload
|
21
|
+
has_many_payload
|
22
|
+
belongs_to_payload
|
23
|
+
has_one_payload
|
24
|
+
belongs_to_update_payload
|
25
|
+
has_many_create_payload
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
# Enumeration for different updatepayload types
|
29
|
+
DECRYPT_UPDATE_ATTRS_TYPES = %w[
|
30
|
+
primary_update_payload
|
31
|
+
has_one_update_payload
|
32
|
+
has_many_update_payload
|
33
|
+
].freeze
|
16
34
|
# Validations
|
17
35
|
validates :encrypted_attrs, presence: true
|
18
36
|
|
19
|
-
# Enumeration for different payload types
|
20
|
-
enum
|
37
|
+
# Enumeration for different payload relation types
|
38
|
+
enum related_to_activity_as: {
|
21
39
|
primary_payload: 0,
|
22
|
-
|
23
|
-
|
24
|
-
|
40
|
+
has_one_payload: 1,
|
41
|
+
belongs_to_payload: 2,
|
42
|
+
has_many_payload: 3,
|
43
|
+
primary_destroy_payload: 4,
|
44
|
+
primary_update_payload: 5,
|
45
|
+
has_one_update_payload: 6,
|
46
|
+
has_many_update_payload: 7,
|
47
|
+
has_many_create_payload: 8,
|
48
|
+
belongs_to_update_payload: 9,
|
49
|
+
belongs_to_destroy_payload: 10,
|
50
|
+
has_one_destroy_payload: 11,
|
51
|
+
has_many_destroy_payload: 12
|
25
52
|
}
|
26
53
|
|
27
|
-
# Returns the decrypted
|
54
|
+
# Returns the decrypted attrs.
|
28
55
|
#
|
29
56
|
# @return [Hash] The decrypted attributes.
|
30
57
|
#
|
@@ -32,38 +59,59 @@ module LoggableActivity
|
|
32
59
|
# payload.attrs
|
33
60
|
#
|
34
61
|
# Returns:
|
35
|
-
# {
|
36
|
-
# "street" => "Machu Picchu",
|
37
|
-
# "city" => "Aguas Calientes",
|
38
|
-
# "country" => "Peru",
|
39
|
-
# "postal_code" => "08680"
|
40
|
-
# }
|
62
|
+
# { "street" => "Machu Picchu", "city" => "Cusco" }
|
41
63
|
#
|
42
64
|
def attrs
|
43
65
|
return deleted_attrs if record.nil?
|
44
66
|
|
45
|
-
case
|
46
|
-
when
|
67
|
+
case related_to_activity_as
|
68
|
+
when *DECRYPT_ATTRS_TYPES
|
47
69
|
decrypted_attrs
|
48
|
-
when
|
70
|
+
when *DECRYPT_UPDATE_ATTRS_TYPES
|
49
71
|
decrypted_update_attrs
|
72
|
+
else
|
73
|
+
{}
|
50
74
|
end
|
51
75
|
end
|
52
76
|
|
53
|
-
# Returns the route for the payload.
|
77
|
+
# Returns the route for the payload unless the encryption_key is deleted.
|
78
|
+
#
|
79
|
+
# Example:
|
80
|
+
# payload.payload_route
|
81
|
+
#
|
82
|
+
# @return [String] The route for the payload.
|
54
83
|
def payload_route
|
55
|
-
return
|
84
|
+
return '' if deleted?
|
56
85
|
|
57
86
|
route
|
58
87
|
end
|
59
88
|
|
89
|
+
# Returns the display name for the record.
|
90
|
+
#
|
91
|
+
# Example:
|
92
|
+
# payload.record_display_name
|
93
|
+
#
|
94
|
+
# @return [String] The display name for the record.
|
95
|
+
def record_display_name
|
96
|
+
return I18n.t('loggable.activity.deleted') if deleted?
|
97
|
+
|
98
|
+
::LoggableActivity::Encryption.decrypt(encrypted_record_name, secret_key)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Check if the record has been deleted.
|
102
|
+
#
|
103
|
+
# @return [Boolean] True if the record has been deleted.
|
104
|
+
def deleted?
|
105
|
+
encryption_key.deleted?
|
106
|
+
end
|
107
|
+
|
60
108
|
private
|
61
109
|
|
62
110
|
# Retrieves the encryption key for the payload.
|
63
111
|
#
|
64
112
|
# @return [String, nil] The encryption key.
|
65
|
-
def
|
66
|
-
|
113
|
+
def secret_key
|
114
|
+
encryption_key.secret_key
|
67
115
|
end
|
68
116
|
|
69
117
|
# Helper method to handle deleted attributes.
|
@@ -77,6 +125,7 @@ module LoggableActivity
|
|
77
125
|
#
|
78
126
|
# @return [Array<Hash>] The array of decrypted changes.
|
79
127
|
def decrypted_update_attrs
|
128
|
+
# return encrypted_attrs
|
80
129
|
encrypted_attrs['changes'].map do |change|
|
81
130
|
decrypted_from_to_attr(change)
|
82
131
|
end
|
@@ -108,7 +157,8 @@ module LoggableActivity
|
|
108
157
|
# @param value [String] The encrypted value to decrypt.
|
109
158
|
# @return [String] The decrypted value.
|
110
159
|
def decrypt_attr(value)
|
111
|
-
|
160
|
+
# return 'loggable_activity.attr.deleted' if secret_key.nil?
|
161
|
+
::LoggableActivity::Encryption.decrypt(value, secret_key)
|
112
162
|
end
|
113
163
|
end
|
114
164
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LoggableActivity
|
4
|
+
module Services
|
5
|
+
# This service class provides the base payloads builder for the loggable activity.
|
6
|
+
# Other service modules related to the loggable activity will inherit from this module.
|
7
|
+
class BasePayloadsBuilder
|
8
|
+
# Initializes the PayloadsBuilder with a record and an initial collection of payloads,
|
9
|
+
def initialize(record, payloads)
|
10
|
+
@record = record
|
11
|
+
@payloads = payloads
|
12
|
+
@loggable_attrs = record.class.loggable_attrs
|
13
|
+
# @relation_config = record.relation_config
|
14
|
+
@relations = record.class.relations
|
15
|
+
@auto_log = record.class.auto_log
|
16
|
+
# @fetch_record_name_from = record.class.fetch_record_name_from
|
17
|
+
@route = record.class.route
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Returns saved changes for a record.
|
23
|
+
def saved_changes(record)
|
24
|
+
[record.saved_changes.transform_values(&:first), record.saved_changes.transform_values(&:last)]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Fetch the previous and current values for a record.
|
28
|
+
def changes_to_save(record)
|
29
|
+
changes = record.changes_to_save
|
30
|
+
previous_values = {}
|
31
|
+
current_values = {}
|
32
|
+
|
33
|
+
changes.map do |key, value|
|
34
|
+
previous_values[key] = value[0]
|
35
|
+
current_values[key] = value[1]
|
36
|
+
end
|
37
|
+
[previous_values, current_values]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Encrypts the record name for the record.
|
41
|
+
# If the record has a fetch_record_name_from the configuration,
|
42
|
+
# it will use that method to fetch the record name.
|
43
|
+
# Otherwise, it will use the class name and the record id.
|
44
|
+
def encrypt_record_name_for_record(record, secret_key)
|
45
|
+
record_name = fetch_record_name_for_record(record) || "#{record.class.name}##{record.id}"
|
46
|
+
|
47
|
+
::LoggableActivity::Encryption.encrypt(record_name, secret_key)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return the record name for the record.
|
51
|
+
# If the record has a fetch_record_name_from the configuration,
|
52
|
+
def fetch_record_name_for_record(record)
|
53
|
+
fetch_from = record.class.fetch_record_name_from
|
54
|
+
return nil if fetch_from.nil?
|
55
|
+
|
56
|
+
record.send(fetch_from)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the encryption key for the record.
|
60
|
+
def encryption_key_for_record(record)
|
61
|
+
::LoggableActivity::EncryptionKey.for_record(record)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Build a encrypted payload for a record
|
65
|
+
def build_encrypted_payload(record, options = {})
|
66
|
+
encryption_key = encryption_key_for_record(record)
|
67
|
+
return if encryption_key.deleted?
|
68
|
+
|
69
|
+
secret_key = encryption_key.secret_key
|
70
|
+
encrypted_attrs = encrypt_attributes(record, secret_key)
|
71
|
+
|
72
|
+
build_payload(
|
73
|
+
record,
|
74
|
+
encryption_key,
|
75
|
+
encrypted_attrs,
|
76
|
+
options
|
77
|
+
)
|
78
|
+
{ encryption_key:, encrypted_attrs: }
|
79
|
+
end
|
80
|
+
|
81
|
+
# Builds the payload for a record
|
82
|
+
def build_payload(record, encryption_key, encrypted_attrs, options = {})
|
83
|
+
return if encryption_key.deleted?
|
84
|
+
|
85
|
+
related_to_activity_as = options[:related_to_activity_as]
|
86
|
+
current_payload = options[:current_payload]
|
87
|
+
data_owner = options[:data_owner]
|
88
|
+
|
89
|
+
secret_key = encryption_key.secret_key
|
90
|
+
encrypted_record_name = encrypt_record_name_for_record(record, secret_key)
|
91
|
+
payload = ::LoggableActivity::Payload.new(
|
92
|
+
encryption_key:,
|
93
|
+
record:,
|
94
|
+
encrypted_record_name:,
|
95
|
+
encrypted_attrs:,
|
96
|
+
related_to_activity_as:,
|
97
|
+
route: record.class.route,
|
98
|
+
current_payload:,
|
99
|
+
data_owner:
|
100
|
+
)
|
101
|
+
unless payload.valid?
|
102
|
+
error_message = "Payload validation failed: #{payload.errors.full_messages.join(', ')}"
|
103
|
+
raise LoggableActivity::Error, error_message
|
104
|
+
end
|
105
|
+
|
106
|
+
@payloads << payload
|
107
|
+
end
|
108
|
+
|
109
|
+
# Encrypts the attributes for the record.
|
110
|
+
def encrypt_attributes(record, secret_key)
|
111
|
+
encrypt_attrs(record.attributes, record.class.loggable_attrs, secret_key)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Encrypt one attributes for only loggable_attrs, configured
|
115
|
+
def encrypt_attrs(attrs, loggable_attrs, secret_key)
|
116
|
+
attrs.slice(*loggable_attrs).transform_values do |value|
|
117
|
+
::LoggableActivity::Encryption.encrypt(value, secret_key)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Encrypt a single attribute.
|
122
|
+
def encrypt_attr(value, secret_key)
|
123
|
+
::LoggableActivity::Encryption.encrypt(value, secret_key)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LoggableActivity
|
4
|
+
# Namespace for services
|
5
|
+
module Services
|
6
|
+
# This class is responsible for building destroy payloads used in loggable activities.
|
7
|
+
class DestroyPayloadsBuilder < BasePayloadsBuilder
|
8
|
+
# Build payloads for a ::LoggableActivity::Activity.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
# build_payloads
|
12
|
+
#
|
13
|
+
# Returns:
|
14
|
+
# #<::LoggableActivity::Payload:0x0000000109658718> {
|
15
|
+
# :id => 129,
|
16
|
+
# :record_type => "Demo::Club",
|
17
|
+
# :record_id => 4,
|
18
|
+
# :encrypted_attrs => {
|
19
|
+
# "name" => "z/jigjcm3Fb89L7QT8XiNhvVgjtRXKkmg/xohR6wIc0=\n"
|
20
|
+
# },
|
21
|
+
#
|
22
|
+
def build
|
23
|
+
build_primary_destroy_payload
|
24
|
+
build_relations_destroy_payloads
|
25
|
+
@payloads
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def build_primary_destroy_payload
|
31
|
+
encryption_key = encryption_key_for_record(@record)
|
32
|
+
secret_key = encryption_key.secret_key
|
33
|
+
encrypt_attrs(@record.attributes, @record.class.loggable_attrs, secret_key)
|
34
|
+
encrypt_record_name_for_record(@record, secret_key)
|
35
|
+
|
36
|
+
build_encrypted_destroy_payload(@record, 'primary_destroy_payload')
|
37
|
+
|
38
|
+
# @payloads << ::LoggableActivity::Payload.new(
|
39
|
+
# encryption_key:,
|
40
|
+
# record_id: nil,
|
41
|
+
# record_type: @record.class.name,
|
42
|
+
# encrypted_record_name:,
|
43
|
+
# encrypted_attrs:,
|
44
|
+
# related_to_activity_as: 'primary_destroy_payload',
|
45
|
+
# data_owner: true,
|
46
|
+
# route: @record.class.route
|
47
|
+
# )
|
48
|
+
# encryption_key
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_relations_destroy_payloads
|
52
|
+
@relations.each do |relation_config|
|
53
|
+
build_relation_destroy_payload(relation_config)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_relation_destroy_payload(relation_config)
|
58
|
+
relation_config.each_key do |key|
|
59
|
+
case key
|
60
|
+
when 'belongs_to'
|
61
|
+
# build_belongs_to_destroy_payload(relation_config)
|
62
|
+
when 'has_one'
|
63
|
+
build_has_one_destroy_payload(relation_config)
|
64
|
+
when 'has_many'
|
65
|
+
build_has_many_destroy_payloads(relation_config) # if relation_config['data_owner']
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_belongs_to_destroy_payload(relation_config)
|
71
|
+
relation = (relation_config['belongs_to']).to_s
|
72
|
+
record = @record.send(relation)
|
73
|
+
return if record.nil? ||
|
74
|
+
|
75
|
+
build_encrypted_destroy_payload(record, 'belongs_to_destroy_payload')
|
76
|
+
|
77
|
+
encryption_key_for_record(record).mark_as_deleted!
|
78
|
+
# payload[:encryption_key].mark_as_deleted!
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_has_one_destroy_payload(relation_config)
|
82
|
+
relation = (relation_config['has_one']).to_s
|
83
|
+
record = @record.send(relation)
|
84
|
+
return nil if record.nil?
|
85
|
+
|
86
|
+
record.disable_hooks = true
|
87
|
+
|
88
|
+
build_encrypted_destroy_payload(record, 'has_one_destroy_payload')
|
89
|
+
end
|
90
|
+
|
91
|
+
def build_has_many_destroy_payloads(relation_config)
|
92
|
+
relation = (relation_config['has_many']).to_s
|
93
|
+
records = @record.send(relation)
|
94
|
+
records.each do |record|
|
95
|
+
record.disable_hooks = true
|
96
|
+
build_encrypted_destroy_payload(record, 'has_many_destroy_payload')
|
97
|
+
# build_encrypted_payload(
|
98
|
+
# record,
|
99
|
+
# 'has_many_destroy_payload',
|
100
|
+
# relation_config['data_owner'],
|
101
|
+
# true
|
102
|
+
# )
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_encrypted_destroy_payload(record, related_to_activity_as)
|
107
|
+
encryption_key = encryption_key_for_record(record)
|
108
|
+
secret_key = encryption_key.secret_key
|
109
|
+
encrypted_attrs = encrypt_attrs(record.attributes, record.class.loggable_attrs, secret_key)
|
110
|
+
encrypted_record_name = encrypt_record_name_for_record(record, secret_key)
|
111
|
+
|
112
|
+
@payloads << ::LoggableActivity::Payload.new(
|
113
|
+
encryption_key:,
|
114
|
+
record_id: nil,
|
115
|
+
record_type: @record.class.name,
|
116
|
+
encrypted_record_name:,
|
117
|
+
encrypted_attrs:,
|
118
|
+
related_to_activity_as:,
|
119
|
+
data_owner: true,
|
120
|
+
route: '',
|
121
|
+
current_payload: true
|
122
|
+
)
|
123
|
+
encryption_key
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|