software_update_check_service.rb 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # frozen_string_literal: true
  2. class SoftwareUpdateCheckService < BaseService
  3. def call
  4. clean_outdated_updates!
  5. return unless SoftwareUpdate.check_enabled?
  6. process_update_notices!(fetch_update_notices)
  7. end
  8. private
  9. def clean_outdated_updates!
  10. SoftwareUpdate.find_each do |software_update|
  11. software_update.delete if Mastodon::Version.gem_version >= software_update.gem_version
  12. rescue ArgumentError
  13. software_update.delete
  14. end
  15. end
  16. def fetch_update_notices
  17. Request.new(:get, "#{api_url}?version=#{version}").add_headers('Accept' => 'application/json', 'User-Agent' => 'Mastodon update checker').perform do |res|
  18. return Oj.load(res.body_with_limit, mode: :strict) if res.code == 200
  19. end
  20. rescue HTTP::Error, OpenSSL::SSL::SSLError, Oj::ParseError
  21. nil
  22. end
  23. def api_url
  24. ENV.fetch('UPDATE_CHECK_URL', 'https://api.joinmastodon.org/update-check')
  25. end
  26. def version
  27. @version ||= Mastodon::Version.to_s.split('+')[0]
  28. end
  29. def process_update_notices!(update_notices)
  30. return if update_notices.blank? || update_notices['updatesAvailable'].nil?
  31. # Clear notices that are not listed by the update server anymore
  32. SoftwareUpdate.where.not(version: update_notices['updatesAvailable'].pluck('version')).delete_all
  33. return if update_notices['updatesAvailable'].blank?
  34. # Check if any of the notices is new, and issue notifications
  35. known_versions = SoftwareUpdate.where(version: update_notices['updatesAvailable'].pluck('version')).pluck(:version)
  36. new_update_notices = update_notices['updatesAvailable'].filter { |notice| known_versions.exclude?(notice['version']) }
  37. return if new_update_notices.blank?
  38. new_updates = new_update_notices.map do |notice|
  39. SoftwareUpdate.create!(version: notice['version'], urgent: notice['urgent'], type: notice['type'], release_notes: notice['releaseNotes'])
  40. end
  41. notify_devops!(new_updates)
  42. end
  43. def should_notify_user?(user, urgent_version, patch_version)
  44. case user.settings['notification_emails.software_updates']
  45. when 'none'
  46. false
  47. when 'critical'
  48. urgent_version
  49. when 'patch'
  50. urgent_version || patch_version
  51. when 'all'
  52. true
  53. end
  54. end
  55. def notify_devops!(new_updates)
  56. has_new_urgent_version = new_updates.any?(&:urgent?)
  57. has_new_patch_version = new_updates.any?(&:patch_type?)
  58. User.those_who_can(:view_devops).includes(:account).find_each do |user|
  59. next unless should_notify_user?(user, has_new_urgent_version, has_new_patch_version)
  60. if has_new_urgent_version
  61. AdminMailer.with(recipient: user.account).new_critical_software_updates.deliver_later
  62. else
  63. AdminMailer.with(recipient: user.account).new_software_updates.deliver_later
  64. end
  65. end
  66. end
  67. end