loggable_activity 0.1.56 → 0.1.58
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 +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
|