1# frozen_string_literal: true
2
3# This module searches and redacts sensitive information in
4# redactable fields. Currently only unsubscribe link is redacted.
5# Add following lines into your model:
6#
7#     include Redactable
8#     redact_field :foo
9#
10module Redactable
11  extend ActiveSupport::Concern
12
13  UNSUBSCRIBE_PATTERN = %r{/sent_notifications/\h{32}/unsubscribe}.freeze
14
15  class_methods do
16    def redact_field(field)
17      before_validation do
18        redact_field!(field) if attribute_changed?(field)
19      end
20    end
21  end
22
23  private
24
25  def redact_field!(field)
26    text = public_send(field) # rubocop:disable GitlabSecurity/PublicSend
27    return unless text.present?
28
29    redacted = text.gsub(UNSUBSCRIBE_PATTERN, '/sent_notifications/REDACTED/unsubscribe')
30
31    public_send("#{field}=", redacted) # rubocop:disable GitlabSecurity/PublicSend
32  end
33end
34