permissions_spec.rb 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Auth::Permissions, type: :request do
  4. shared_examples 'verify permissions checking' do
  5. let(:permission) { create(:permission, name: permission_name) }
  6. let(:permission_names) { [permission.name] }
  7. let(:role) { create(:role, permission_names:) }
  8. context 'with privileges for a root permission (e.g., "foo", not "foo.bar")' do
  9. let(:permission_name) { 'foo' }
  10. context 'when given that exact permission' do
  11. it 'returns true' do
  12. expect(described_class).to be_authorized(object, 'foo')
  13. end
  14. end
  15. context 'when given an active sub-permission' do
  16. before { create(:permission, name: 'foo.bar') }
  17. it 'returns true' do
  18. expect(described_class).to be_authorized(object, 'foo.bar')
  19. end
  20. end
  21. describe 'chain-of-ancestry quirk' do
  22. context 'when given an inactive sub-permission' do
  23. before { create(:permission, name: 'foo.bar.baz', active: false) }
  24. it 'returns false, even with active ancestors' do
  25. expect(described_class).not_to be_authorized(object, 'foo.bar.baz')
  26. end
  27. end
  28. context 'when given a sub-permission that does not exist' do
  29. before { create(:permission, name: 'foo.bar', active: false) }
  30. it 'can return true, even with inactive ancestors' do
  31. expect(described_class).to be_authorized(object, 'foo.bar.baz')
  32. end
  33. end
  34. end
  35. context 'when given a glob' do
  36. context 'when matching that permission' do
  37. it 'returns true' do
  38. expect(described_class).to be_authorized(object, 'foo.*')
  39. end
  40. end
  41. context 'when NOT matching that permission' do
  42. it 'returns false' do
  43. expect(described_class).not_to be_authorized(object, 'bar.*')
  44. end
  45. end
  46. end
  47. end
  48. context 'with privileges for a sub-permission (e.g., "foo.bar", not "foo")' do
  49. let(:permission_name) { 'foo.bar' }
  50. context 'when given that exact sub-permission' do
  51. it 'returns true' do
  52. expect(described_class).to be_authorized(object, 'foo.bar')
  53. end
  54. context 'when the permission is inactive' do
  55. before { permission.update(active: false) }
  56. it 'returns false' do
  57. expect(described_class).not_to be_authorized(object, 'foo.bar')
  58. end
  59. end
  60. end
  61. context 'when given a sibling sub-permission' do
  62. let(:sibling_permission) { create(:permission, name: 'foo.baz') }
  63. context 'when sibling exists' do
  64. before { sibling_permission }
  65. it 'returns false' do
  66. expect(described_class).not_to be_authorized(object, 'foo.baz')
  67. end
  68. end
  69. context 'when sibling does not exist' do
  70. it 'returns false' do
  71. expect(described_class).not_to be_authorized(object, 'foo.baz')
  72. end
  73. end
  74. end
  75. context 'when given the parent permission' do
  76. it 'returns false' do
  77. expect(described_class).not_to be_authorized(object, 'foo')
  78. end
  79. end
  80. context 'when given a glob' do
  81. context 'when matching that sub-permission' do
  82. it 'returns true' do
  83. expect(described_class).to be_authorized(object, 'foo.*')
  84. end
  85. context 'when the permission is inactive' do
  86. before { permission.update(active: false) }
  87. it 'returns false' do
  88. expect(described_class).not_to be_authorized(object, 'foo.*')
  89. end
  90. end
  91. end
  92. context 'when NOT matching that sub-permission' do
  93. it 'returns false' do
  94. expect(described_class).not_to be_authorized(object, 'bar.*')
  95. end
  96. end
  97. end
  98. context 'when given a plus' do
  99. let(:permission_names) { [permission.name, 'ticket.agent'] }
  100. context 'when matching both permissions' do
  101. it 'returns true' do
  102. expect(described_class).to be_authorized(object, 'foo.bar+ticket.agent')
  103. end
  104. it 'returns true if vice versa order given' do
  105. expect(described_class).to be_authorized(object, 'ticket.agent+foo.bar')
  106. end
  107. it 'returns true if given a glob' do
  108. expect(described_class).to be_authorized(object, 'foo.*+ticket.agent')
  109. end
  110. context 'when one of the permissions is inactive' do
  111. before { permission.update(active: false) }
  112. it 'returns false' do
  113. expect(described_class).not_to be_authorized(object, 'ticket.agent+foo.bar')
  114. end
  115. end
  116. end
  117. context 'when not matching one of permissions' do
  118. it 'returns false' do
  119. expect(described_class).not_to be_authorized(object, 'bar+ticket.agent')
  120. end
  121. it 'returns false if vice versa order given' do
  122. expect(described_class).not_to be_authorized(object, 'ticket.agent+bar')
  123. end
  124. end
  125. end
  126. end
  127. end
  128. describe 'user handling' do
  129. let(:object) { create(:user, roles: [role]) }
  130. include_examples 'verify permissions checking'
  131. end
  132. describe 'token handling' do
  133. let(:user) { create(:user, roles: [role]) }
  134. let(:object) { create(:token, user:, preferences: { permission: permission_names }) }
  135. include_examples 'verify permissions checking'
  136. end
  137. describe 'caching' do
  138. let(:user) { create(:agent) }
  139. before do
  140. allow(described_class).to receive(:new).and_call_original
  141. end
  142. it 'caches response with same arguments' do
  143. described_class.authorized?(user, 'ticket.agent')
  144. described_class.authorized?(user, 'ticket.agent')
  145. expect(described_class).to have_received(:new).once
  146. end
  147. it 'does not cache response with different queries' do
  148. described_class.authorized?(user, 'ticket.agent')
  149. described_class.authorized?(user, 'other')
  150. expect(described_class).to have_received(:new).twice
  151. end
  152. it 'does not cache response with different objects' do
  153. described_class.authorized?(user, 'ticket.agent')
  154. described_class.authorized?(create(:user), 'ticket.agent')
  155. expect(described_class).to have_received(:new).twice
  156. end
  157. end
  158. end