data_privacy_task.rb 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class DataPrivacyTask < ApplicationModel
  3. include HasDefaultModelUserRelations
  4. include DataPrivacyTask::HasActivityStreamLog
  5. include ChecksClientNotification
  6. store :preferences
  7. # optional because related data will get deleted and it would
  8. # cause validation errors if e.g. the created_by_id of the task
  9. # would need to get mapped by a deletion
  10. belongs_to :deletable, polymorphic: true, optional: true
  11. before_create :prepare_deletion_preview
  12. validates_with Validations::DataPrivacyTaskValidator
  13. MAX_PREVIEW_TICKETS = 1000
  14. def perform
  15. perform_deletable
  16. update!(state: 'completed')
  17. rescue => e
  18. handle_exception(e)
  19. end
  20. def self.cleanup(diff = 12.months)
  21. where(created_at: ...diff.ago)
  22. .destroy_all
  23. true
  24. end
  25. private
  26. # set user inactive before destroy to prevent
  27. # new online notifications or other events while
  28. # the deletion process is running
  29. # https://github.com/zammad/zammad/issues/3942
  30. def update_inactive(object)
  31. object.update(active: false)
  32. end
  33. def perform_deletable
  34. return if !deletable_type.constantize.exists?(id: deletable_id)
  35. prepare_deletion_preview
  36. save!
  37. case deletable
  38. when User
  39. perform_user_or_organization
  40. when Ticket
  41. perform_ticket
  42. end
  43. end
  44. def perform_user_or_organization
  45. if delete_organization?
  46. perform_organization(deletable.organization)
  47. return
  48. end
  49. perform_user
  50. end
  51. def perform_organization(organization)
  52. update_inactive(organization)
  53. organization.members.find_each { |user| update_inactive(user) }
  54. organization.destroy(associations: true)
  55. end
  56. def perform_user
  57. update_inactive(deletable)
  58. deletable.destroy
  59. end
  60. def perform_ticket
  61. deletable.destroy
  62. end
  63. def handle_exception(e)
  64. Rails.logger.error e
  65. preferences[:error] = "ERROR: #{e.inspect}"
  66. self.state = 'failed'
  67. save!
  68. end
  69. def delete_organization?
  70. return false if preferences[:delete_organization].blank?
  71. return false if preferences[:delete_organization] != 'true'
  72. return false if !deletable.organization
  73. return false if deletable.organization.members.count != 1
  74. true
  75. end
  76. def prepare_deletion_preview
  77. prepare_deletion_preview_tickets
  78. prepare_deletion_preview_user
  79. prepare_deletion_preview_organization
  80. prepare_deletion_preview_anonymize
  81. end
  82. def prepare_deletion_preview_tickets
  83. case deletable
  84. when User
  85. prepare_deletion_preview_user_tickets
  86. when Ticket
  87. prepare_deletion_preview_ticket
  88. end
  89. end
  90. def prepare_deletion_preview_user_tickets
  91. prepare_deletion_preview_owner_tickets
  92. prepare_deletion_preview_customer_tickets
  93. end
  94. def prepare_deletion_preview_owner_tickets
  95. preferences[:owner_tickets] = owner_tickets.limit(MAX_PREVIEW_TICKETS).map(&:number)
  96. preferences[:owner_tickets_count] = owner_tickets.count
  97. end
  98. def prepare_deletion_preview_customer_tickets
  99. preferences[:customer_tickets] = customer_tickets.limit(MAX_PREVIEW_TICKETS).map(&:number)
  100. preferences[:customer_tickets_count] = customer_tickets.count
  101. end
  102. def prepare_deletion_preview_ticket
  103. preferences[:ticket] = {
  104. title: deletable.title,
  105. }
  106. preferences[:customer_tickets] = [deletable.number]
  107. preferences[:customer_tickets_count] = 1
  108. end
  109. def prepare_deletion_preview_user
  110. return if !deletable.is_a?(User)
  111. preferences[:user] = {
  112. firstname: deletable.firstname,
  113. lastname: deletable.lastname,
  114. email: deletable.email,
  115. }
  116. end
  117. def prepare_deletion_preview_organization
  118. return if !deletable.is_a?(User)
  119. return if !deletable.organization
  120. preferences[:user][:organization] = deletable.organization.name
  121. end
  122. def prepare_deletion_preview_anonymize
  123. case deletable
  124. when User
  125. preferences[:user] = Pseudonymisation.of_hash(preferences[:user])
  126. when Ticket
  127. preferences[:ticket] = Pseudonymisation.of_hash(preferences[:ticket])
  128. end
  129. end
  130. def owner_tickets
  131. @owner_tickets ||= deletable.owner_tickets.reorder(id: 'DESC')
  132. end
  133. def customer_tickets
  134. @customer_tickets ||= deletable.customer_tickets.reorder(id: 'DESC')
  135. end
  136. end