user_device.rb 4.8 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 new device for user if device not already known
  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. # since gem browser 2 is not handling nil for user_agent, set it to ''
  18. if user_agent.nil?
  19. user_agent = ''
  20. end
  21. # get location info
  22. location_details = Service::GeoIp.location(ip)
  23. location = 'unknown'
  24. if location_details
  25. location = location_details['country_name']
  26. end
  27. # find device by fingerprint
  28. device_exists_by_fingerprint = false
  29. if fingerprint
  30. user_devices = UserDevice.where(
  31. user_id: user_id,
  32. fingerprint: fingerprint,
  33. )
  34. user_devices.each {|local_user_device|
  35. device_exists_by_fingerprint = true
  36. next if local_user_device.location != location
  37. return action(local_user_device.id, user_agent, ip, user_id) if local_user_device
  38. }
  39. end
  40. # for basic_auth|token_auth search for user agent
  41. if type == 'basic_auth' || type == 'token_auth'
  42. user_device = UserDevice.find_by(
  43. user_id: user_id,
  44. user_agent: user_agent,
  45. location: location,
  46. )
  47. return action(user_device.id, user_agent, ip, user_id) if user_device
  48. end
  49. # get browser details
  50. browser = Browser.new(user_agent, accept_language: 'en-us')
  51. browser = {
  52. plattform: browser.platform.to_s.camelize,
  53. name: browser.name,
  54. version: browser.version,
  55. full_version: browser.full_version,
  56. }
  57. # generate device name
  58. if browser[:name] == 'Generic Browser'
  59. browser[:name] = user_agent
  60. end
  61. name = ''
  62. if browser[:plattform] && browser[:plattform] != 'Other'
  63. name = browser[:plattform]
  64. end
  65. if browser[:name] && browser[:name] != 'Other'
  66. if name && !name.empty?
  67. name += ', '
  68. end
  69. name += browser[:name]
  70. end
  71. # if not identified, use user agent
  72. if !name || name == '' || name == 'Other, Other' || name == 'Other'
  73. name = user_agent
  74. browser[:name] = user_agent
  75. end
  76. # check if exists
  77. user_device = find_by(
  78. user_id: user_id,
  79. os: browser[:plattform],
  80. browser: browser[:name],
  81. location: location,
  82. )
  83. if user_device
  84. return action(user_device.id, user_agent, ip, user_id) if user_device
  85. end
  86. # create new device
  87. user_device = create(
  88. user_id: user_id,
  89. name: name,
  90. os: browser[:plattform],
  91. browser: browser[:name],
  92. location: location,
  93. device_details: browser,
  94. location_details: location_details,
  95. user_agent: user_agent,
  96. ip: ip,
  97. fingerprint: fingerprint,
  98. )
  99. # send notification if needed
  100. user_devices = UserDevice.where(user_id: user_id).count
  101. if user_devices >= 2
  102. # notify on now device of if country has changed
  103. if device_exists_by_fingerprint
  104. user_device.notification_send('user_device_new_location')
  105. else
  106. user_device.notification_send('user_device_new')
  107. end
  108. end
  109. user_device
  110. end
  111. =begin
  112. log user device action
  113. UserDevice.action(
  114. user_device_id,
  115. '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',
  116. '172.0.0.1',
  117. user.id,
  118. )
  119. =end
  120. def self.action(user_device_id, _user_agent, ip, _user_id)
  121. user_device = UserDevice.find(user_device_id)
  122. # update location if needed
  123. if user_device.ip != ip
  124. user_device.ip = ip
  125. location_details = Service::GeoIp.location(ip)
  126. user_device.location_details = location_details
  127. location = location_details['country_name']
  128. # notify if country has changed
  129. if user_device.location != location
  130. user_device.notification_send('user_device_new_location')
  131. end
  132. user_device.location = location
  133. end
  134. # update attributes
  135. user_device.updated_at = Time.zone.now # force update, also if no other attribute has changed
  136. user_device.save
  137. user_device
  138. end
  139. =begin
  140. send user notification about new device or new location for device
  141. user_device = UserDevice.find(id)
  142. user_device.notification_send('user_device_new_location')
  143. =end
  144. def notification_send(template)
  145. user = User.find(user_id)
  146. NotificationFactory.notification(
  147. template: template,
  148. user: user,
  149. objects: {
  150. user_device: self,
  151. user: user,
  152. }
  153. )
  154. end
  155. end