email_account_uniqueness_validator.rb 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Validations::EmailAccountUniquenessValidator < ActiveModel::Validator
  3. MATCHED_KEYS = %i[adapter].freeze
  4. MATCHED_OPTIONS_KEYS = %i[host port user folder].freeze
  5. MATCHED_AREAS = %w[Email::Account Google::Account Microsoft365::Account].freeze
  6. def validate(record)
  7. return if MATCHED_AREAS.exclude?(record.area)
  8. record_data = extract_matched_data(record)
  9. return if scope(record).none? { matches?(record_data, _1) }
  10. record.errors.add :base, __('The provided email account is already in use.')
  11. end
  12. private
  13. def scope(record)
  14. record
  15. .class
  16. .where(area: record.area)
  17. .then { record.persisted? ? _1.where.not(id: record.id) : _1 }
  18. end
  19. def matches?(record_data, other_record)
  20. other_record_data = extract_matched_data(other_record)
  21. return false if other_record_data.blank?
  22. record_data == other_record_data
  23. end
  24. def extract_matched_data(record)
  25. server_data = record.options&.dig(:inbound)
  26. return if !server_data
  27. values = server_data.slice(*MATCHED_KEYS)
  28. options_values = server_data[:options]&.slice(*MATCHED_OPTIONS_KEYS) || {}
  29. values
  30. .merge(options_values)
  31. .transform_values(&:to_s)
  32. end
  33. end