user_device.rb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
  2. class UserDevice < ApplicationModel
  3. store :device_details
  4. store :location_details
  5. validates :name, presence: true
  6. =begin
  7. store device for user
  8. user_device = UserDevice.add(
  9. 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36',
  10. '172.0.0.1',
  11. user.id,
  12. 'fingerprintABC123',
  13. 'session', # session|basic_auth|token_auth|sso
  14. )
  15. =end
  16. def self.add(user_agent, ip, user_id, fingerprint, type)
  17. # get location info
  18. location_details = Service::GeoIp.location(ip)
  19. location = location_details['country_name']
  20. # find device by fingerprint
  21. if fingerprint
  22. user_device = UserDevice.find_by(
  23. user_id: user_id,
  24. fingerprint: fingerprint,
  25. location: location,
  26. )
  27. return action(user_device.id, user_agent, ip, user_id) if user_device
  28. end
  29. # for basic_auth|token_auth search for user agent
  30. if type == 'basic_auth' || type == 'token_auth'
  31. user_device = UserDevice.find_by(
  32. user_id: user_id,
  33. user_agent: user_agent,
  34. location: location,
  35. )
  36. return action(user_device.id, user_agent, ip, user_id) if user_device
  37. end
  38. # get browser details
  39. browser = Browser.new(ua: user_agent, accept_language: 'en-us')
  40. browser = {
  41. plattform: browser.platform.to_s.camelize,
  42. name: browser.name,
  43. version: browser.version,
  44. full_version: browser.full_version,
  45. }
  46. # generate device name
  47. name = ''
  48. if browser[:plattform] && browser[:plattform] != 'Other'
  49. name = browser[:plattform]
  50. end
  51. if browser[:name] && browser[:name] != 'Other'
  52. if name && !name.empty?
  53. name += ', '
  54. end
  55. name += browser[:name]
  56. end
  57. # if not identified, use user agent
  58. if !name || name == '' || name == 'Other, Other' || name == 'Other'
  59. name = user_agent
  60. browser[:name] = user_agent
  61. end
  62. # check if exists
  63. user_device = find_by(
  64. user_id: user_id,
  65. os: browser[:plattform],
  66. browser: browser[:name],
  67. location: location,
  68. )
  69. if user_device
  70. return action(user_device.id, user_agent, ip, user_id) if user_device
  71. end
  72. # create new device
  73. user_device = create(
  74. user_id: user_id,
  75. name: name,
  76. os: browser[:plattform],
  77. browser: browser[:name],
  78. location: location,
  79. device_details: browser,
  80. location_details: location_details,
  81. user_agent: user_agent,
  82. ip: ip,
  83. fingerprint: fingerprint,
  84. )
  85. # send notification if needed
  86. user_devices = UserDevice.where(user_id: user_id).count
  87. if user_devices >= 2
  88. user_device.send_notification
  89. end
  90. user_device
  91. end
  92. =begin
  93. log user device action
  94. UserDevice.action(
  95. user_device_id,
  96. 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36',
  97. '172.0.0.1',
  98. user.id,
  99. )
  100. =end
  101. def self.action(user_device_id, _user_agent, ip, _user_id)
  102. user_device = UserDevice.find(user_device_id)
  103. # update location if needed
  104. if user_device.ip != ip
  105. user_device.ip = ip
  106. location_details = Service::GeoIp.location(ip)
  107. user_device.location_details = location_details
  108. location = location_details['country_name']
  109. user_device.location = location
  110. end
  111. # update attributes
  112. user_device.save
  113. user_device
  114. end
  115. =begin
  116. send new user device info
  117. user_device = UserDevice.find(id)
  118. user_device.send_notification
  119. =end
  120. def send_notification
  121. user = User.find(user_id)
  122. # send mail
  123. data = {}
  124. data[:subject] = '#{config.product_name} signin detected from a new device'
  125. data[:body] = 'Hi #{user.firstname},
  126. it looks like you signed into your #{config.product_name} account using a new device on "#{user_device.created_at}":
  127. Your Location: #{user_device.location}
  128. Your IP: #{user_device.ip}
  129. Your device has been added to your list of known devices, which you can view here:
  130. #{config.http_type}://#{config.fqdn}/#profile/devices
  131. If this wasn\'t you, remove the device, changing your account password, and contacting your administrator. Somebody might have gained unauthorized access to your account.
  132. Your #{config.product_name} Team'
  133. # prepare subject & body
  134. [:subject, :body].each { |key|
  135. data[key.to_sym] = NotificationFactory.build(
  136. locale: user.preferences[:locale],
  137. string: data[key.to_sym],
  138. objects: {
  139. user_device: self,
  140. user: user,
  141. }
  142. )
  143. }
  144. # send notification
  145. NotificationFactory.send(
  146. recipient: user,
  147. subject: data[:subject],
  148. body: data[:body]
  149. )
  150. end
  151. end