123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- module Import
- # This base class handles regular integrations.
- # It provides generic interfaces for settings and active state.
- # It ensures that all requirements for a regular integration are met before a import can start.
- # It handles the case of a background worker interruption.
- #
- # It's required to implement the +start_import+ method which only has to start the import.
- class IntegrationBase < Import::Base
- def self.inherited(subclass)
- super
- subclass.extend(Forwardable)
- # delegate instance methods to the generic class implementations
- subclass.delegate %i[identifier active? config display_name] => subclass
- end
- # Defines the integration identifier used for
- # automatic config lookup and error message generation.
- #
- # @example
- # Import::Ldap.identifier
- # #=> "Ldap"
- #
- # return [String]
- def self.identifier
- name.split('::').last
- end
- # Provides the name that is used in texts visible to the user.
- #
- # @example
- # Import::Exchange.display_name
- # #=> "Exchange"
- #
- # return [String]
- def self.display_name
- identifier
- end
- # Checks if the integration is active.
- #
- # @example
- # Import::Ldap.active?
- # #=> true
- #
- # return [Boolean]
- def self.active?
- Setting.get("#{identifier.downcase}_integration") || false
- end
- # Provides the integration configuration.
- #
- # return [Hash] the configuration
- def self.config
- Setting.get("#{identifier.downcase}_config") || {}
- end
- # Stores the integration configuration.
- #
- # return [nil]
- def self.config=(value)
- Setting.set("#{identifier.downcase}_config", value)
- end
- # Checks if the integration is activated and configured.
- # Otherwise it won't get queued since it will display
- # an error which is confusing and wrong.
- #
- # @example
- # Import::Exchange.queueable?
- # #=> true
- #
- # return [Boolean]
- def self.queueable?
- active? && config.present?
- end
- # Starts a live or dry run import.
- #
- # @example
- # instance = Import::Ldap.new(import_job)
- #
- # @raise [RuntimeError] Raised if an import should start but the integration is disabled
- #
- # return [nil]
- def start
- return if !requirements_completed?
- start_import
- end
- # Gets called when the background worker gets (re-)started and an ImportJob was still
- # in the queue. The job will always get restarted to avoid the gap till the next
- # run triggered by the background worker. The result will get updated to inform the user
- # in the agent interface result view.
- #
- # @example
- # instance = Import::Ldap.new(import_job)
- # instance.reschedule?(delayed_job)
- # #=> true
- #
- # return [true]
- def reschedule?(_delayed_job)
- inform('Restarting due to scheduler restart.')
- true
- end
- private
- def start_import
- raise "Missing implementation of method '#{__method__}' for #{self.class.name}"
- end
- def requirements_completed?
- return true if @import_job.dry_run
- if !active?
- message = "Sync cancelled. #{display_name} integration deactivated. Activate via the switch."
- end
- return true if !message
- inform(message)
- false
- end
- def inform(message)
- @import_job.update!(result: {
- info: message
- })
- end
- end
- end
|