user_device_spec.rb 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe UserDevice, type: :model do
  4. describe '.add' do
  5. let(:existing_record) { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  6. let(:ip) { '91.115.248.231' }
  7. let(:agent) { create(:agent) }
  8. context 'with existing record of type: "session"' do
  9. before { existing_record } # create existing record
  10. let(:user_agent) { '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' }
  11. let(:fingerprint) { 'fingerprint1234' }
  12. let(:type) { 'session' }
  13. context 'when called with same parameters as existing record' do
  14. it 'returns the original record' do
  15. expect(described_class.add(user_agent, ip, agent.id, fingerprint, type))
  16. .to eq(existing_record)
  17. end
  18. end
  19. context 'when called with different IP from existing record' do
  20. let(:other_ip) { '176.198.137.254' }
  21. it 'returns a new record' do
  22. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  23. .to be_a(described_class)
  24. .and not_eq(existing_record)
  25. end
  26. end
  27. context 'when called with invalid IP, not matching existing record' do
  28. let(:other_ip) { 'foo' }
  29. it 'returns a new record' do
  30. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  31. .to be_a(described_class)
  32. .and not_eq(existing_record)
  33. end
  34. end
  35. context 'when called with different fingerprint from existing record' do
  36. let(:other_fingerprint) { 'fingerprintABCD' }
  37. it 'returns a new record' do
  38. expect(described_class.add(user_agent, ip, agent.id, other_fingerprint, type))
  39. .to be_a(described_class)
  40. .and not_eq(existing_record)
  41. end
  42. end
  43. context 'with recognized user_agent (Mac/Chrome)' do
  44. it 'assigns #user_agent attribute to given value' do
  45. expect(existing_record.user_agent).to eq(user_agent)
  46. end
  47. it 'derives #name attribute from given value' do
  48. expect(existing_record.name).to eq('Mac, Chrome')
  49. end
  50. it 'derives #browser attribute from given value' do
  51. expect(existing_record.browser).to eq('Chrome')
  52. end
  53. end
  54. context 'with recognized user_agent (iOS/Safari)' do
  55. let(:user_agent) { 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H143 Safari/600.1.4' }
  56. it 'assigns #user_agent attribute to given value' do
  57. expect(existing_record.user_agent).to eq(user_agent)
  58. end
  59. it 'derives #name attribute from given value' do
  60. expect(existing_record.name).to eq('Ios, Safari')
  61. end
  62. it 'derives #browser attribute from given value' do
  63. expect(existing_record.browser).to eq('Safari')
  64. end
  65. end
  66. context 'with partially recognized user_agent (Mac/CalendarAgent)' do
  67. let(:user_agent) { 'Mac+OS+X/10.10.5 (14F27) CalendarAgent/316.1' }
  68. it 'assigns #user_agent and #browser attributes to given value' do
  69. expect([existing_record.user_agent, existing_record.browser])
  70. .to all(eq(user_agent))
  71. end
  72. it 'derives #name attribute from given value' do
  73. expect(existing_record.name).to eq("Mac, #{user_agent}")
  74. end
  75. end
  76. context 'with unrecognized user_agent' do
  77. let(:user_agent) { 'foo' }
  78. it 'assigns #user_agent, #name, and #browser attributes to given value' do
  79. expect([existing_record.user_agent, existing_record.name, existing_record.browser])
  80. .to all(eq(user_agent))
  81. end
  82. end
  83. end
  84. context 'with existing record of type: "basic_auth"' do
  85. before { existing_record } # create existing record
  86. let(:user_agent) { 'curl/7.43.0' }
  87. let(:fingerprint) { nil }
  88. let(:type) { 'basic_auth' }
  89. context 'when called with same parameters as existing record' do
  90. it 'returns the original record' do
  91. expect(described_class.add(user_agent, ip, agent.id, fingerprint, type))
  92. .to eq(existing_record)
  93. end
  94. end
  95. context 'when called with different IP from existing record' do
  96. let(:other_ip) { '176.198.137.254' }
  97. it 'returns a new record' do
  98. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  99. .to be_a(described_class)
  100. .and not_eq(existing_record)
  101. end
  102. end
  103. context 'when called with different type from existing record ("token_auth")' do
  104. let(:other_type) { 'token_auth' }
  105. it 'returns the original record' do
  106. expect(described_class.add(user_agent, ip, agent.id, fingerprint, other_type))
  107. .to eq(existing_record)
  108. end
  109. end
  110. context 'when called without existing record’s user agent' do
  111. let(:other_user_agent) { '' }
  112. it 'returns a new record' do
  113. expect(described_class.add(other_user_agent, ip, agent.id, fingerprint, type))
  114. .to be_a(described_class)
  115. .and not_eq(existing_record)
  116. end
  117. end
  118. context 'when existing record’s user agent is blank, and given is nil' do
  119. let(:user_agent) { '' }
  120. let(:other_user_agent) { nil }
  121. it 'returns the original record' do
  122. expect(described_class.add(other_user_agent, ip, agent.id, fingerprint, type))
  123. .to eq(existing_record)
  124. end
  125. end
  126. context 'when existing record and given args have nil user agent, but IPs don’t match' do
  127. let(:user_agent) { nil }
  128. let(:other_ip) { '176.198.137.254' }
  129. it 'returns a new record' do
  130. expect(described_class.add(user_agent, other_ip, agent.id, fingerprint, type))
  131. .to be_a(described_class)
  132. .and not_eq(existing_record)
  133. end
  134. end
  135. end
  136. context 'with exceedingly long fingerprint (161+ chars)' do
  137. let(:user_agent) { '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' }
  138. let(:fingerprint) { 'x' * 161 }
  139. let(:type) { 'session' }
  140. it 'raises an error' do
  141. expect { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  142. .to raise_error(Exceptions::UnprocessableEntity)
  143. end
  144. end
  145. end
  146. describe '.action' do
  147. let(:user_device) { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  148. let(:user_agent) { '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' }
  149. let(:ip) { '91.115.248.231' }
  150. let(:agent) { create(:agent) }
  151. let(:fingerprint) { 'fingerprint1234' }
  152. let(:type) { 'session' }
  153. context 'when called with parameters matching given user_device' do
  154. it 'returns the given user_device' do
  155. expect(described_class.action(user_device.id, user_agent, ip, agent.id, type))
  156. .to eq(user_device)
  157. end
  158. end
  159. context 'when called with different IP from given user_device' do
  160. let(:other_ip) { '176.198.137.254' }
  161. it 'returns a new user_device' do
  162. expect(described_class.action(user_device.id, user_agent, other_ip, agent.id, type))
  163. .to be_a(described_class)
  164. .and not_eq(user_device)
  165. end
  166. end
  167. context 'when called with invalid IP, not matching given user_device' do
  168. let(:other_ip) { 'foo' }
  169. it 'returns the given user_device' do
  170. expect(described_class.action(user_device.id, user_agent, other_ip, agent.id, type))
  171. .to eq(user_device)
  172. end
  173. it 'sets user_device.ip to the given (invalid) IP' do
  174. expect { described_class.action(user_device.id, user_agent, other_ip, agent.id, type) }
  175. .to change { user_device.reload.ip }.to(other_ip)
  176. end
  177. end
  178. end
  179. describe '#notification_send' do
  180. let(:user_device) { described_class.add(user_agent, ip, agent.id, fingerprint, type) }
  181. let(:user_agent) { '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' }
  182. let(:ip) { '91.115.248.231' }
  183. let(:fingerprint) { 'fingerprint1234' }
  184. let(:type) { 'session' }
  185. context 'user with email address' do
  186. let(:agent) { create(:agent, email: 'somebody@example.com') }
  187. it 'returns true' do
  188. expect(user_device.notification_send('user_device_new_location'))
  189. .to be(true)
  190. end
  191. end
  192. context 'user without email address' do
  193. let(:agent) { create(:agent, email: '') }
  194. it 'returns false' do
  195. expect(user_device.notification_send('user_device_new_location'))
  196. .to be(false)
  197. end
  198. end
  199. end
  200. end