setting.rb 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class Setting < ApplicationModel
  3. store :options
  4. store :state_current
  5. store :state_initial
  6. store :preferences
  7. before_create :state_check, :set_initial, :check_broadcast
  8. before_update :state_check, :check_broadcast
  9. after_create :reset_cache
  10. after_update :reset_cache
  11. after_destroy :reset_cache
  12. attr_accessor :state
  13. @@current = {} # rubocop:disable Style/ClassVars
  14. @@change_id = nil # rubocop:disable Style/ClassVars
  15. @@lookup_at = nil # rubocop:disable Style/ClassVars
  16. @@lookup_timeout = if ENV['ZAMMAD_SETTING_TTL'] # rubocop:disable Style/ClassVars
  17. ENV['ZAMMAD_SETTING_TTL'].to_i.seconds
  18. elsif Rails.env.production?
  19. 2.minutes
  20. else
  21. 15.seconds
  22. end
  23. =begin
  24. set config setting
  25. Setting.set('some_config_name', some_value)
  26. =end
  27. def self.set(name, value)
  28. setting = Setting.find_by(name: name)
  29. if !setting
  30. raise "Can't find config setting '#{name}'"
  31. end
  32. setting.state_current = { value: value }
  33. setting.save
  34. logger.info "Setting.set(#{name}, #{value.inspect})"
  35. end
  36. =begin
  37. get config setting
  38. value = Setting.get('some_config_name')
  39. =end
  40. def self.get(name)
  41. load
  42. @@current[:settings_config][name]
  43. end
  44. =begin
  45. reset config setting to default
  46. Setting.reset('some_config_name')
  47. =end
  48. def self.reset(name)
  49. setting = Setting.find_by(name: name)
  50. if !setting
  51. raise "Can't find config setting '#{name}'"
  52. end
  53. setting.state_current = setting.state_initial
  54. setting.save
  55. logger.info "Setting.reset(#{name}, #{setting.state_current.inspect})"
  56. load
  57. @@current[:settings_config][name]
  58. end
  59. =begin
  60. reload config settings
  61. Setting.reload
  62. =end
  63. def self.reload
  64. load(true)
  65. end
  66. private
  67. # load values and cache them
  68. def self.load(force = false)
  69. # check if config is already generated
  70. if !force && @@current[:settings_config]
  71. return false if cache_valid?
  72. end
  73. # read all config settings
  74. config = {}
  75. Setting.select('name, state_current').order(:id).each { |setting|
  76. config[setting.name] = setting.state_current[:value]
  77. }
  78. # config lookups
  79. config.each { |key, value|
  80. next if value.class.to_s != 'String'
  81. config[key].gsub!(/\#\{config\.(.+?)\}/) {
  82. config[$1].to_s
  83. }
  84. }
  85. # store for class requests
  86. cache(config)
  87. true
  88. end
  89. private_class_method :load
  90. # set initial value in state_initial
  91. def set_initial
  92. self.state_initial = state_current
  93. end
  94. # set new cache
  95. def self.cache(config)
  96. @@change_id = Cache.get('Setting::ChangeId') # rubocop:disable Style/ClassVars
  97. @@current[:settings_config] = config
  98. logger.debug "Setting.cache: set cache, #{@@change_id}"
  99. @@lookup_at = Time.zone.now # rubocop:disable Style/ClassVars
  100. end
  101. private_class_method :cache
  102. # reset cache
  103. def reset_cache
  104. @@change_id = rand(999_999_999).to_s # rubocop:disable Style/ClassVars
  105. logger.debug "Setting.reset_cache: set new cache, #{@@change_id}"
  106. Cache.write('Setting::ChangeId', @@change_id, { expires_in: 24.hours })
  107. @@current[:settings_config] = nil
  108. end
  109. # check if cache is still valid
  110. def self.cache_valid?
  111. if @@lookup_at && @@lookup_at > Time.zone.now - @@lookup_timeout
  112. #logger.debug 'Setting.cache_valid?: cache_id has beed set within last 2 minutes'
  113. return true
  114. end
  115. change_id = Cache.get('Setting::ChangeId')
  116. if change_id == @@change_id
  117. @@lookup_at = Time.zone.now # rubocop:disable Style/ClassVars
  118. logger.debug "Setting.cache_valid?: cache still valid, #{@@change_id}/#{change_id}"
  119. return true
  120. end
  121. logger.debug "Setting.cache_valid?: cache has changed, #{@@change_id}/#{change_id}"
  122. false
  123. end
  124. private_class_method :cache_valid?
  125. # convert state into hash to be able to store it as store
  126. def state_check
  127. return if !state
  128. return if state && state.respond_to?('has_key?') && state.key?(:value)
  129. self.state_current = { value: state }
  130. end
  131. # notify clients about public config changes
  132. def check_broadcast
  133. return if frontend != true
  134. value = state_current
  135. if state_current.key?(:value)
  136. value = state_current[:value]
  137. end
  138. Sessions.broadcast(
  139. {
  140. event: 'config_update',
  141. data: { name: name, value: value }
  142. },
  143. 'public'
  144. )
  145. end
  146. end