loggable_activity 0.1.56 → 0.1.59

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) 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/.DS_Store +0 -0
  30. data/lib/generators/loggable_activity/templates/binary_ids/create_loggable_activities.rb +9 -10
  31. data/lib/generators/loggable_activity/templates/create_loggable_activities.rb +16 -13
  32. data/lib/loggable_activity/activity.rb +53 -102
  33. data/lib/loggable_activity/configuration.rb +60 -3
  34. data/lib/loggable_activity/data_owner.rb +18 -0
  35. data/lib/loggable_activity/encryption.rb +14 -14
  36. data/lib/loggable_activity/encryption_key.rb +26 -25
  37. data/lib/loggable_activity/error.rb +34 -0
  38. data/lib/loggable_activity/hooks.rb +78 -43
  39. data/lib/loggable_activity/payload.rb +70 -20
  40. data/lib/loggable_activity/services/base_payloads_builder.rb +127 -0
  41. data/lib/loggable_activity/services/destroy_payloads_builder.rb +127 -0
  42. data/lib/loggable_activity/services/payloads_builder.rb +98 -0
  43. data/lib/loggable_activity/services/update_payloads_builder.rb +170 -0
  44. data/lib/loggable_activity/version.rb +1 -1
  45. data/lib/loggable_activity.rb +6 -6
  46. data/lib/schemas/config_schema.json +90 -0
  47. metadata +37 -26
  48. data/docs/LoggableActivity/PayloadsBuilder.html +0 -441
  49. data/docs/LoggableActivity/UpdatePayloadsBuilder.html +0 -424
  50. data/lib/generators/loggable_activity/install_templates_generator.rb +0 -105
  51. data/lib/generators/loggable_activity/templates/helpers/activity_helper.rb +0 -37
  52. data/lib/generators/loggable_activity/templates/helpers/router.rb +0 -52
  53. data/lib/generators/loggable_activity/templates/helpers/routes_helper.rb +0 -20
  54. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_create.html.erb +0 -23
  55. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_create.html.slim +0 -18
  56. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_destroy.html.erb +0 -18
  57. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_destroy.html.slim +0 -17
  58. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_show.html.erb +0 -18
  59. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_show.html.slim +0 -17
  60. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_update.html.erb +0 -18
  61. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/default/_update.html.slim +0 -12
  62. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_activity_info.html.erb +0 -12
  63. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_activity_info.html.slim +0 -11
  64. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_list_attrs.html.erb +0 -8
  65. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_list_attrs.html.slim +0 -6
  66. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_update_attrs.html.erb +0 -17
  67. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_update_attrs.html.slim +0 -14
  68. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_updated_relations.html.erb +0 -23
  69. data/lib/generators/loggable_activity/templates/views/loggable_activity/templates/shared/_updated_relations.html.slim +0 -21
  70. data/lib/loggable_activity/payloads_builder.rb +0 -153
  71. 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