token_spec.rb 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Token, type: :model do
  4. subject(:token) { create(:password_reset_token) }
  5. describe '.check' do
  6. context 'with name and action matching existing token' do
  7. it 'returns the token’s user' do
  8. expect(described_class.check(action: token.action, name: token.name)).to eq(token.user)
  9. end
  10. end
  11. context 'with invalid name' do
  12. it 'returns nil' do
  13. expect(described_class.check(action: token.action, name: '1NV4L1D')).to be_nil
  14. end
  15. end
  16. context 'with invalid action' do
  17. it 'returns nil' do
  18. expect(described_class.check(action: 'PasswordReset_NotExisting', name: token.name)).to be_nil
  19. end
  20. end
  21. describe 'persistence handling' do
  22. context 'for persistent token' do
  23. subject(:token) { create(:ical_token, persistent: true, created_at: created_at) }
  24. context 'at any time' do
  25. let(:created_at) { 1.month.ago }
  26. it 'returns the token’s user' do
  27. expect(described_class.check(action: token.action, name: token.name)).to eq(token.user)
  28. end
  29. it 'does not delete the token' do
  30. token # create token
  31. expect { described_class.check(action: token.action, name: token.name) }
  32. .not_to change(described_class, :count)
  33. end
  34. end
  35. end
  36. context 'for non-persistent token' do
  37. subject(:token) { create(:password_reset_token, persistent: false, created_at: created_at) }
  38. context 'less than one day after creation' do
  39. let(:created_at) { 1.day.ago + 5 }
  40. it 'returns the token’s user' do
  41. expect(described_class.check(action: token.action, name: token.name)).to eq(token.user)
  42. end
  43. it 'does not delete the token' do
  44. token # create token
  45. expect { described_class.check(action: token.action, name: token.name) }
  46. .not_to change(described_class, :count)
  47. end
  48. end
  49. context 'at least one day after creation' do
  50. let(:created_at) { 1.day.ago }
  51. it 'returns nil' do
  52. expect(described_class.check(action: token.action, name: token.name)).to be_nil
  53. end
  54. it 'deletes the token' do
  55. token # create token
  56. expect { described_class.check(action: token.action, name: token.name) }
  57. .to change(described_class, :count).by(-1)
  58. end
  59. end
  60. end
  61. end
  62. describe 'permission matching' do
  63. subject(:token) { create(:api_token, user: agent, preferences: preferences) }
  64. let(:agent) { create(:agent) }
  65. let(:preferences) { { permission: %w[admin ticket.agent] } } # agent has no access to admin.*
  66. context 'with a permission shared by both token.user and token.preferences' do
  67. it 'returns token.user' do
  68. expect(described_class.check(action: token.action, name: token.name, permission: 'ticket.agent')).to eq(agent)
  69. end
  70. end
  71. context 'with the child of a permission shared by both token.user and token.preferences' do
  72. it 'returns token.user' do
  73. expect(described_class.check(action: token.action, name: token.name, permission: 'ticket.agent.foo')).to eq(agent)
  74. end
  75. end
  76. context 'with the parent of a permission shared by both token.user and token.preferences' do
  77. it 'returns nil' do
  78. expect(described_class.check(action: token.action, name: token.name, permission: 'ticket')).to be_nil
  79. end
  80. end
  81. context 'with a permission in token.preferences, but not on token.user' do
  82. it 'returns nil' do
  83. expect(described_class.check(action: token.action, name: token.name, permission: 'admin')).to be_nil
  84. end
  85. end
  86. context 'with a permission not in token.preferences, but on token.user' do
  87. it 'returns nil' do
  88. expect(described_class.check(action: token.action, name: token.name, permission: 'cti.agent')).to be_nil
  89. end
  90. end
  91. context 'with non-existent permission' do
  92. it 'returns nil' do
  93. expect(described_class.check(action: token.action, name: token.name, permission: 'foo')).to be_nil
  94. end
  95. end
  96. context 'with multiple permissions, where at least one is shared by both token.user and token.preferences' do
  97. it 'returns token.user' do
  98. expect(described_class.check(action: token.action, name: token.name, permission: %w[foo ticket.agent])).to eq(agent)
  99. end
  100. end
  101. end
  102. end
  103. describe '#permissions?' do
  104. subject(:token) do
  105. create(:token, user: user, preferences: { permission: [permission_name] })
  106. end
  107. let(:user) { create(:user, roles: [role]) }
  108. let(:role) { create(:role, permissions: [permission]) }
  109. let(:permission) { create(:permission, name: permission_name) }
  110. context 'with privileges for a root permission (e.g., "foo", not "foo.bar")' do
  111. let(:permission_name) { 'foo' }
  112. context 'when given that exact permission' do
  113. it 'returns true' do
  114. expect(token.permissions?('foo')).to be(true)
  115. end
  116. end
  117. context 'when given a sub-permission (i.e., child permission)' do
  118. let(:subpermission) { create(:permission, name: 'foo.bar') }
  119. context 'that exists' do
  120. before { subpermission }
  121. it 'returns true' do
  122. expect(token.permissions?('foo.bar')).to be(true)
  123. end
  124. end
  125. context 'that is inactive' do
  126. before { subpermission.update(active: false) }
  127. it 'returns false' do
  128. expect(token.permissions?('foo.bar')).to be(false)
  129. end
  130. end
  131. context 'that does not exist' do
  132. it 'returns true' do
  133. expect(token.permissions?('foo.bar')).to be(true)
  134. end
  135. end
  136. end
  137. context 'when given a glob' do
  138. context 'matching that permission' do
  139. it 'returns true' do
  140. expect(token.permissions?('foo.*')).to be(true)
  141. end
  142. end
  143. context 'NOT matching that permission' do
  144. it 'returns false' do
  145. expect(token.permissions?('bar.*')).to be(false)
  146. end
  147. end
  148. end
  149. end
  150. context 'with privileges for a sub-permission (e.g., "foo.bar", not "foo")' do
  151. let(:permission_name) { 'foo.bar' }
  152. context 'when given that exact sub-permission' do
  153. it 'returns true' do
  154. expect(token.permissions?('foo.bar')).to be(true)
  155. end
  156. context 'but the permission is inactive' do
  157. before { permission.update(active: false) }
  158. it 'returns false' do
  159. expect(token.permissions?('foo.bar')).to be(false)
  160. end
  161. end
  162. end
  163. context 'when given a sibling sub-permission' do
  164. let(:sibling_permission) { create(:permission, name: 'foo.baz') }
  165. context 'that exists' do
  166. before { sibling_permission }
  167. it 'returns false' do
  168. expect(token.permissions?('foo.baz')).to be(false)
  169. end
  170. end
  171. context 'that does not exist' do
  172. it 'returns false' do
  173. expect(token.permissions?('foo.baz')).to be(false)
  174. end
  175. end
  176. end
  177. context 'when given the parent permission' do
  178. it 'returns false' do
  179. expect(token.permissions?('foo')).to be(false)
  180. end
  181. end
  182. context 'when given a glob' do
  183. context 'matching that sub-permission' do
  184. it 'returns true' do
  185. expect(token.permissions?('foo.*')).to be(true)
  186. end
  187. context 'but the permission is inactive' do
  188. before { permission.update(active: false) }
  189. context 'and user.permissions?(...) doesn’t fail' do
  190. let(:role) { create(:role, permissions: [parent_permission]) }
  191. let(:parent_permission) { create(:permission, name: permission_name.split('.').first) }
  192. it 'returns false' do
  193. expect(token.permissions?('foo.*')).to be(false)
  194. end
  195. end
  196. end
  197. end
  198. context 'NOT matching that sub-permission' do
  199. it 'returns false' do
  200. expect(token.permissions?('bar.*')).to be(false)
  201. end
  202. end
  203. end
  204. end
  205. end
  206. describe 'Attributes:' do
  207. describe '#persistent' do
  208. context 'when not set on creation' do
  209. subject(:token) { described_class.create(action: 'foo', user_id: User.first.id) }
  210. it 'defaults to nil' do
  211. expect(token.persistent).to be_nil
  212. end
  213. end
  214. end
  215. end
  216. end