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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -1
  3. data/CHANGELOG.md +9 -0
  4. data/GETTING-STARTED.md +8 -47
  5. data/PAYLOAD_EXAMPLE.md +63 -0
  6. data/docs/LoggableActivity/Activity.html +92 -241
  7. data/docs/LoggableActivity/Configuration.html +162 -15
  8. data/docs/LoggableActivity/ConfigurationError.html +148 -0
  9. data/docs/LoggableActivity/DataOwner.html +138 -0
  10. data/docs/LoggableActivity/Encryption.html +18 -14
  11. data/docs/LoggableActivity/EncryptionError.html +47 -1
  12. data/docs/LoggableActivity/EncryptionKey.html +54 -35
  13. data/docs/LoggableActivity/Error.html +48 -0
  14. data/docs/LoggableActivity/Hooks.html +221 -89
  15. data/docs/LoggableActivity/Payload.html +103 -27
  16. data/docs/LoggableActivity/Services/BasePayloadsBuilder.html +442 -0
  17. data/docs/LoggableActivity/Services/DestroyPayloadsBuilder.html +395 -0
  18. data/docs/LoggableActivity/Services/PayloadsBuilder.html +342 -0
  19. data/docs/LoggableActivity/Services/UpdatePayloadsBuilder.html +490 -0
  20. data/docs/LoggableActivity/Services.html +93 -0
  21. data/docs/created.rid +14 -10
  22. data/docs/index.html +10 -2
  23. data/docs/js/navigation.js.gz +0 -0
  24. data/docs/js/search_index.js +1 -1
  25. data/docs/js/search_index.js.gz +0 -0
  26. data/docs/js/searcher.js.gz +0 -0
  27. data/docs/table_of_contents.html +253 -85
  28. data/lib/generators/loggable_activity/install_generator.rb +2 -18
  29. data/lib/generators/loggable_activity/templates/binary_ids/create_loggable_activities.rb +9 -10
  30. data/lib/generators/loggable_activity/templates/create_loggable_activities.rb +16 -13
  31. data/lib/loggable_activity/activity.rb +53 -102
  32. data/lib/loggable_activity/configuration.rb +60 -3
  33. data/lib/loggable_activity/data_owner.rb +18 -0
  34. data/lib/loggable_activity/encryption.rb +14 -14
  35. data/lib/loggable_activity/encryption_key.rb +26 -25
  36. data/lib/loggable_activity/error.rb +34 -0
  37. data/lib/loggable_activity/hooks.rb +78 -43
  38. data/lib/loggable_activity/payload.rb +70 -20
  39. data/lib/loggable_activity/services/base_payloads_builder.rb +127 -0
  40. data/lib/loggable_activity/services/destroy_payloads_builder.rb +127 -0
  41. data/lib/loggable_activity/services/payloads_builder.rb +98 -0
  42. data/lib/loggable_activity/services/update_payloads_builder.rb +168 -0
  43. data/lib/loggable_activity/version.rb +1 -1
  44. data/lib/loggable_activity.rb +6 -6
  45. data/lib/schemas/config_schema.json +90 -0
  46. metadata +37 -26
  47. data/docs/LoggableActivity/PayloadsBuilder.html +0 -441
  48. data/docs/LoggableActivity/UpdatePayloadsBuilder.html +0 -424
  49. data/lib/generators/loggable_activity/install_templates_generator.rb +0 -105
  50. data/lib/generators/loggable_activity/templates/helpers/activity_helper.rb +0 -37
  51. data/lib/generators/loggable_activity/templates/helpers/router.rb +0 -52
  52. data/lib/generators/loggable_activity/templates/helpers/routes_helper.rb +0 -20
  53. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_create.html.erb +0 -23
  54. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_create.html.slim +0 -18
  55. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_destroy.html.erb +0 -18
  56. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_destroy.html.slim +0 -17
  57. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_show.html.erb +0 -18
  58. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_show.html.slim +0 -17
  59. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_update.html.erb +0 -18
  60. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_update.html.slim +0 -12
  61. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_activity_info.html.erb +0 -12
  62. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_activity_info.html.slim +0 -11
  63. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_list_attrs.html.erb +0 -8
  64. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_list_attrs.html.slim +0 -6
  65. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_update_attrs.html.erb +0 -17
  66. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_update_attrs.html.slim +0 -14
  67. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_updated_relations.html.erb +0 -23
  68. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_updated_relations.html.slim +0 -21
  69. data/lib/loggable_activity/payloads_builder.rb +0 -153
  70. 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
- include LoggableActivity::PayloadsBuilder
15
- include LoggableActivity::UpdatePayloadsBuilder
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
- raise "Loggable::Configuration not found for #{name}, Please add it to 'config/loggable_activity.yaml'" if config.nil?
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.actor_display_name = config&.fetch('actor_display_name', nil)
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
- # LoggableActivity::EncryptionKey.for_record(self)
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
- encrypted_actor_display_name: encrypted_actor_name,
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: @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?(payloads)
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
- LoggableActivity::EncryptionKey.for_record(self)&.mark_as_deleted
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
- actor_display_name = @actor.send(actor_display_name_field)
122
- LoggableActivity::Encryption.encrypt(actor_display_name, actor_encryption_key)
162
+ name = @actor.send(fetch_current_user_name_from)
163
+ ::LoggableActivity::Encryption.encrypt(name, actor_secret_key)
123
164
  end
124
165
 
125
- # Returns the encrypted name of the record.
126
- def encrypted_record_name
127
- display_name =
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
- @action_key ||= self.class.base_action + ".#{@action}"
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
- @primary_encryption_key ||=
144
- LoggableActivity::EncryptionKey.for_record(self)&.key
178
+ encryption_key_for_record
145
179
  end
146
180
 
147
- # Returns true if the primary encryption key is deleted.
148
- def primary_encryption_key_deleted?
149
- primary_encryption_key.nil?
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 actor_encryption_key
154
- LoggableActivity::EncryptionKey.for_record(@actor)&.key
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 actor_display_name_field
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
- attr_accessor :loggable_attrs, :relations, :auto_log, :actor_display_name, :record_display_name, :route
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 payload_type: {
37
+ # Enumeration for different payload relation types
38
+ enum related_to_activity_as: {
21
39
  primary_payload: 0,
22
- update_payload: 1,
23
- current_association: 2,
24
- previous_association: 3
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 attributes of the payload based on its type.
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 payload_type
46
- when 'current_association', 'primary_payload', 'previous_association'
67
+ case related_to_activity_as
68
+ when *DECRYPT_ATTRS_TYPES
47
69
  decrypted_attrs
48
- when 'update_payload'
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 nil if payload_encryption_key.nil?
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 payload_encryption_key
66
- @payload_encryption_key ||= LoggableActivity::EncryptionKey.for_record(record)&.key
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
- LoggableActivity::Encryption.decrypt(value, payload_encryption_key)
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