authorization.rb 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class Authorization < ApplicationModel
  3. belongs_to :user, optional: true
  4. after_create :delete_user_cache, :notification_send
  5. after_update :delete_user_cache
  6. after_destroy :delete_user_cache
  7. validates :user_id, presence: true
  8. validates :uid, presence: true, uniqueness: { case_sensitive: true, scope: :provider }
  9. validates :provider, presence: true
  10. def self.find_from_hash(hash)
  11. auth = Authorization.find_by(provider: hash['provider'], uid: hash['uid'])
  12. if auth
  13. # update auth tokens
  14. auth.update!(
  15. token: hash['credentials']['token'],
  16. secret: hash['credentials']['secret']
  17. )
  18. # update username of auth entry if empty
  19. if !auth.username && hash['info']['nickname'].present?
  20. auth.update!(
  21. username: hash['info']['nickname'],
  22. )
  23. end
  24. # update firstname/lastname if needed
  25. user = User.find(auth.user_id)
  26. if user.firstname.blank? && user.lastname.blank?
  27. if hash['info']['first_name'].present? && hash['info']['last_name'].present?
  28. user.firstname = hash['info']['first_name']
  29. user.lastname = hash['info']['last_name']
  30. elsif hash['info']['display_name'].present?
  31. user.firstname = hash['info']['display_name']
  32. end
  33. end
  34. # update image if needed
  35. if hash['info']['image'].present?
  36. avatar = Avatar.add(
  37. object: 'User',
  38. o_id: user.id,
  39. url: hash['info']['image'],
  40. source: hash['provider'],
  41. deletable: true,
  42. updated_by_id: user.id,
  43. created_by_id: user.id,
  44. )
  45. if avatar && user.image != avatar.store_hash
  46. user.image = avatar.store_hash
  47. end
  48. end
  49. if user.changed?
  50. user.save
  51. end
  52. end
  53. auth
  54. end
  55. def self.create_from_hash(hash, user = nil)
  56. if !user && Setting.get('auth_third_party_auto_link_at_inital_login') && hash['info'] && hash['info']['email'].present?
  57. user = User.find_by(email: hash['info']['email'].downcase)
  58. end
  59. if !user
  60. user = User.create_from_hash!(hash)
  61. end
  62. # save/update avatar
  63. if hash['info'].present? && hash['info']['image'].present?
  64. avatar = Avatar.add(
  65. object: 'User',
  66. o_id: user.id,
  67. url: hash['info']['image'],
  68. source: hash['provider'],
  69. deletable: true,
  70. updated_by_id: user.id,
  71. created_by_id: user.id,
  72. )
  73. # update user link
  74. if avatar && user.image != avatar.store_hash
  75. user.image = avatar.store_hash
  76. user.save
  77. end
  78. end
  79. Authorization.create!(
  80. user: user,
  81. uid: hash['uid'],
  82. username: hash['info']['nickname'] || hash['info']['username'] || hash['info']['name'] || hash['info']['email'] || hash['username'],
  83. provider: hash['provider'],
  84. token: hash['credentials']['token'],
  85. secret: hash['credentials']['secret']
  86. )
  87. end
  88. private
  89. def delete_user_cache
  90. return if !user
  91. user.touch # rubocop:disable Rails/SkipsModelValidations
  92. end
  93. # An account is considered linked if the user originates from a source other than the current authorization provider.
  94. def linked_account?
  95. user.source != provider
  96. end
  97. def notification_send
  98. # Send a notification only if the feature is turned on and the account is linked.
  99. return if !Setting.get('auth_third_party_linking_notification') || !user || !linked_account?
  100. template = 'user_auth_provider'
  101. if user.email.blank?
  102. Rails.logger.info { "Unable to send a notification (#{template}) to user_id: #{user.id} be cause of missing email address." }
  103. return
  104. end
  105. Rails.logger.debug { "Send notification (#{template}) to: #{user.email}" }
  106. NotificationFactory::Mailer.notification(
  107. template: template,
  108. user: user,
  109. objects: {
  110. user: user,
  111. provider: provider_name(provider),
  112. }
  113. )
  114. end
  115. def provider_name(provider)
  116. return saml_display_name(provider) if provider == 'saml'
  117. provider_title(provider)
  118. end
  119. # In case of SAML authentication provider, there is a separate display name setting that may be defined.
  120. def saml_display_name(provider)
  121. begin
  122. Setting.get('auth_saml_credentials')['display_name']
  123. rescue
  124. provider_title(provider)
  125. end
  126. end
  127. def provider_title(provider)
  128. begin
  129. Setting.find_by(name: "auth_#{provider}").preferences['title_i18n'].shift
  130. rescue
  131. provider
  132. end
  133. end
  134. end