integration_base.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. module Import
  3. # This base class handles regular integrations.
  4. # It provides generic interfaces for settings and active state.
  5. # It ensures that all requirements for a regular integration are met before a import can start.
  6. # It handles the case of an Scheduler interruption.
  7. #
  8. # It's required to implement the +start_import+ method which only has to start the import.
  9. class IntegrationBase < Import::Base
  10. def self.inherited(subclass)
  11. subclass.extend(Forwardable)
  12. # delegate instance methods to the generic class implementations
  13. subclass.delegate %i[identifier active? config display_name] => subclass
  14. end
  15. # Defines the integration identifier used for
  16. # automatic config lookup and error message generation.
  17. #
  18. # @example
  19. # Import::Ldap.identifier
  20. # #=> "Ldap"
  21. #
  22. # return [String]
  23. def self.identifier
  24. name.split('::').last
  25. end
  26. # Provides the name that is used in texts visible to the user.
  27. #
  28. # @example
  29. # Import::Exchange.display_name
  30. # #=> "Exchange"
  31. #
  32. # return [String]
  33. def self.display_name
  34. identifier
  35. end
  36. # Checks if the integration is active.
  37. #
  38. # @example
  39. # Import::Ldap.active?
  40. # #=> true
  41. #
  42. # return [Boolean]
  43. def self.active?
  44. Setting.get("#{identifier.downcase}_integration") || false
  45. end
  46. # Provides the integration configuration.
  47. #
  48. # @example
  49. # Import::Ldap.config
  50. # #=> {"ssl_verify"=>true, "host_url"=>"ldaps://192...", ...}
  51. #
  52. # return [Hash] the configuration
  53. def self.config
  54. Setting.get("#{identifier.downcase}_config") || {}
  55. end
  56. # Stores the integration configuration.
  57. #
  58. # @example
  59. # Import::Ldap.config = {"ssl_verify"=>true, "host_url"=>"ldaps://192...", ...}
  60. #
  61. # return [nil]
  62. def self.config=(value)
  63. Setting.set("#{identifier.downcase}_config", value)
  64. end
  65. # Checks if the integration is activated and configured.
  66. # Otherwise it won't get queued since it will display
  67. # an error which is confusing and wrong.
  68. #
  69. # @example
  70. # Import::Ldap.queueable?
  71. # #=> true
  72. #
  73. # return [Boolean]
  74. def self.queueable?
  75. active? && config.present?
  76. end
  77. # Starts a live or dry run import.
  78. #
  79. # @example
  80. # instance = Import::Ldap.new(import_job)
  81. #
  82. # @raise [RuntimeError] Raised if an import should start but the integration is disabled
  83. #
  84. # return [nil]
  85. def start
  86. return if !requirements_completed?
  87. start_import
  88. end
  89. # Gets called when the Scheduler gets (re-)started and an ImportJob was still
  90. # in the queue. The job will always get restarted to avoid the gap till the next
  91. # run triggered by the Scheduler. The result will get updated to inform the user
  92. # in the agent interface result view.
  93. #
  94. # @example
  95. # instance = Import::Ldap.new(import_job)
  96. # instance.reschedule?(delayed_job)
  97. # #=> true
  98. #
  99. # return [true]
  100. def reschedule?(_delayed_job)
  101. inform('Restarting due to scheduler restart.')
  102. true
  103. end
  104. private
  105. def start_import
  106. raise "Missing implementation of method '#{__method__}' for #{self.class.name}"
  107. end
  108. def requirements_completed?
  109. return true if @import_job.dry_run
  110. if !active?
  111. message = "Sync cancelled. #{display_name} integration deactivated. Activate via the switch."
  112. elsif config.blank? && @import_job.payload.blank?
  113. message = "Sync cancelled. #{display_name} configration or ImportJob payload missing."
  114. end
  115. return true if !message
  116. inform(message)
  117. false
  118. end
  119. def inform(message)
  120. @import_job.update!(result: {
  121. info: message
  122. })
  123. end
  124. end
  125. end