role_spec.rb 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. require 'models/application_model_examples'
  4. require 'models/concerns/can_be_imported_examples'
  5. require 'models/concerns/has_groups_examples'
  6. require 'models/concerns/has_collection_update_examples'
  7. require 'models/concerns/has_xss_sanitized_note_examples'
  8. RSpec.describe Role do
  9. subject(:role) { create(:role) }
  10. it_behaves_like 'ApplicationModel'
  11. it_behaves_like 'CanBeImported'
  12. it_behaves_like 'HasGroups', group_access_factory: :role
  13. it_behaves_like 'HasCollectionUpdate', collection_factory: :role
  14. it_behaves_like 'HasXssSanitizedNote', model_factory: :role
  15. describe 'Default state' do
  16. describe 'of whole table:' do
  17. it 'has three records ("Admin", "Agent", and "Customer")' do
  18. expect(described_class.pluck(:name)).to match_array(%w[Admin Agent Customer])
  19. end
  20. end
  21. describe 'of "Admin" role:' do
  22. it 'has default admin permissions' do
  23. expect(described_class.find_by(name: 'Admin').permissions.pluck(:name))
  24. .to match_array(%w[admin user_preferences report knowledge_base.editor])
  25. end
  26. end
  27. describe 'of "Agent" role:' do
  28. it 'has default agent permissions' do
  29. expect(described_class.find_by(name: 'Agent').permissions.pluck(:name))
  30. .to match_array(%w[ticket.agent chat.agent cti.agent user_preferences knowledge_base.reader])
  31. end
  32. end
  33. describe 'of "Customer" role:' do
  34. it 'has default customer permissions' do
  35. expect(described_class.find_by(name: 'Customer').permissions.pluck(:name))
  36. .to match_array(
  37. %w[
  38. user_preferences.password
  39. user_preferences.language
  40. user_preferences.linked_accounts
  41. user_preferences.avatar
  42. user_preferences.appearance
  43. ticket.customer
  44. ]
  45. )
  46. end
  47. end
  48. end
  49. describe 'Callbacks -' do
  50. describe 'Permission validation:' do
  51. context 'with normal permission' do
  52. let(:permission) { create(:permission) }
  53. it 'can be created' do
  54. expect { create(:role, permissions: [permission]) }
  55. .to change(described_class, :count).by(1)
  56. end
  57. it 'can be added' do
  58. expect { role.permissions << permission }
  59. .to change { role.permissions.count }.by(1)
  60. end
  61. end
  62. context 'with disabled permission' do
  63. let(:permission) { create(:permission, preferences: { disabled: true }) }
  64. it 'cannot be created' do
  65. expect { create(:role, permissions: [permission]) }
  66. .to raise_error(%r{is disabled})
  67. .and not_change(described_class, :count)
  68. end
  69. it 'cannot be added' do
  70. expect { role.permissions << permission }
  71. .to raise_error(%r{is disabled})
  72. .and not_change { role.permissions.count }
  73. end
  74. end
  75. context 'with multiple, explicitly incompatible permissions' do
  76. let(:permission) { create(:permission, preferences: { not: [Permission.first.name] }) }
  77. it 'cannot be created' do
  78. expect { create(:role, permissions: [Permission.first, permission]) }
  79. .to raise_error(%r{conflicts with})
  80. .and not_change(described_class, :count)
  81. end
  82. it 'cannot be added' do
  83. role.permissions << Permission.first
  84. expect { role.permissions << permission }
  85. .to raise_error(%r{conflicts with})
  86. .and not_change { role.permissions.count }
  87. end
  88. end
  89. context 'with multiple, compatible permissions' do
  90. let(:permission) { create(:permission, preferences: { not: [Permission.pluck(:name).max.next] }) }
  91. it 'can be created' do
  92. expect { create(:role, permissions: [Permission.first, permission]) }
  93. .to change(described_class, :count).by(1)
  94. end
  95. it 'can be added' do
  96. role.permissions << Permission.first
  97. expect { role.permissions << permission }
  98. .to change { role.permissions.count }.by(1)
  99. end
  100. end
  101. end
  102. describe 'System-wide agent limit checks:' do
  103. let(:agents) { User.with_permissions('ticket.agent') }
  104. describe '#validate_agent_limit_by_attributes' do
  105. context 'when reactivating a role adds new agents' do
  106. subject(:role) { create(:role, :agent, active: false) }
  107. before { create(:user, roles: [role]) }
  108. context 'exceeding the system limit' do
  109. before { Setting.set('system_agent_limit', agents.count) }
  110. it 'fails and raises an error' do
  111. expect { role.update!(active: true) }
  112. .to raise_error(Exceptions::UnprocessableEntity)
  113. .and not_change(agents, :count)
  114. end
  115. end
  116. end
  117. end
  118. end
  119. describe 'Restrictions on #default_at_signup:' do
  120. context 'for roles with "admin" permissions' do
  121. subject(:role) { build(:role, permissions: Permission.where(name: 'admin')) }
  122. it 'cannot be set to true on creation' do
  123. role.default_at_signup = true
  124. expect { role.save }
  125. .to raise_error(Exceptions::UnprocessableEntity, %r{Cannot set default at signup})
  126. end
  127. it 'cannot be changed to true' do
  128. role.save
  129. expect { role.update(default_at_signup: true) }
  130. .to raise_error(Exceptions::UnprocessableEntity, %r{Cannot set default at signup})
  131. end
  132. end
  133. context 'for roles with permissions that are children of "admin"' do
  134. subject(:role) { build(:role, permissions: [permission]) }
  135. let(:permission) { create(:permission, name: 'admin.foo') }
  136. it 'cannot be set to true on creation' do
  137. role.default_at_signup = true
  138. expect { role.save }
  139. .to raise_error(Exceptions::UnprocessableEntity, %r{Cannot set default at signup})
  140. end
  141. it 'cannot be changed to true' do
  142. role.save
  143. expect { role.update(default_at_signup: true) }
  144. .to raise_error(Exceptions::UnprocessableEntity, %r{Cannot set default at signup})
  145. end
  146. end
  147. context 'for roles with "ticket.agent" permissions' do
  148. subject(:role) { build(:role, permissions: Permission.where(name: 'ticket.agent')) }
  149. it 'cannot be set to true on creation' do
  150. role.default_at_signup = true
  151. expect { role.save }
  152. .to raise_error(Exceptions::UnprocessableEntity, %r{Cannot set default at signup})
  153. end
  154. it 'cannot be changed to true' do
  155. role.save
  156. expect { role.update(default_at_signup: true) }
  157. .to raise_error(Exceptions::UnprocessableEntity, %r{Cannot set default at signup})
  158. end
  159. end
  160. end
  161. end
  162. describe '.with_permissions' do
  163. context 'when given a name not matching any permissions' do
  164. let(:permission) { 'foo' }
  165. let(:result) { [] }
  166. it 'returns an empty array' do
  167. expect(described_class.with_permissions(permission)).to match_array(result)
  168. end
  169. end
  170. context 'when given the name of a top-level permission' do
  171. let(:permission) { 'user_preferences' }
  172. let(:result) { described_class.where(name: %w[Admin Agent]) }
  173. it 'returns an array of roles with that permission' do
  174. expect(described_class.with_permissions(permission)).to match_array(result)
  175. end
  176. end
  177. context 'when given the name of a child permission' do
  178. let(:permission) { 'user_preferences.language' }
  179. let(:result) { described_class.all }
  180. it 'returns an array of roles with either that permission or an ancestor' do
  181. expect(described_class.with_permissions(permission)).to match_array(result)
  182. end
  183. end
  184. context 'when given the names of multiple permissions' do
  185. let(:permissions) { %w[ticket.agent ticket.customer] }
  186. let(:result) { described_class.where(name: %w[Agent Customer]) }
  187. it 'returns an array of roles matching ANY given permission' do
  188. expect(described_class.with_permissions(permissions)).to match_array(result)
  189. end
  190. end
  191. end
  192. describe '#with_permission?' do
  193. subject(:role) { described_class.find_by(name: 'Admin') }
  194. context 'when given the name of a permission it has' do
  195. it 'returns true' do
  196. expect(role.with_permission?('admin')).to be(true)
  197. end
  198. end
  199. context 'when given the name of a permission it does NOT have' do
  200. it 'returns false' do
  201. expect(role.with_permission?('ticket.customer')).to be(false)
  202. end
  203. end
  204. context 'when given the name of multiple permissions' do
  205. it 'returns true as long as ANY match' do
  206. expect(role.with_permission?(['admin', 'ticket.customer'])).to be(true)
  207. end
  208. end
  209. end
  210. end