users_spec.rb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'Manage > Users', type: :system do
  4. describe 'switching to an alternative user', authenticated_as: :authenticate, authentication_type: :form do
  5. let(:original_user) { create(:admin) }
  6. let(:alternative_one_user) { create(:admin) }
  7. let(:alternative_two_user) { create(:admin) }
  8. let(:alternative_three_user) { create(:customer) }
  9. def authenticate
  10. alternative_one_user
  11. alternative_two_user
  12. alternative_three_user
  13. original_user
  14. end
  15. it 'starts as original user' do
  16. expect(current_user).to eq original_user
  17. end
  18. it 'switches to alternative user' do
  19. switch_to(alternative_one_user)
  20. expect(current_user).to eq alternative_one_user
  21. end
  22. it 'switches to another alternative user' do
  23. switch_to(alternative_one_user)
  24. switch_to(alternative_two_user)
  25. expect(current_user).to eq alternative_two_user
  26. end
  27. it 'switches back to original user' do
  28. switch_to(alternative_one_user)
  29. switch_to(alternative_two_user)
  30. click '.switchBackToUser-close'
  31. expect(current_user).to eq original_user
  32. end
  33. it 'switches to customer user while maintenance mode is active' do
  34. Setting.set('maintenance_mode', true)
  35. switch_to(alternative_three_user)
  36. expect(current_user).to eq alternative_three_user
  37. end
  38. def switch_to(user)
  39. visit 'manage/users'
  40. within(:active_content) do
  41. row = find("tr[data-id=\"#{user.id}\"]")
  42. row.find('.js-action').click
  43. row.find('.js-switchTo').click
  44. end
  45. expect(page).to have_text("Zammad looks like this for \"#{user.firstname} #{user.lastname}\"")
  46. end
  47. end
  48. # Fixes GitHub Issue #3050 - Newly created users are only shown in the admin interface after reload
  49. describe 'adding a new user', authenticated_as: -> { user } do
  50. let(:user) { create(:admin) }
  51. it 'newly added user is visible in the user list' do
  52. visit '#manage/users'
  53. within(:active_content) do
  54. find('[data-type=new]').click
  55. find('[name=firstname]').fill_in with: 'NewTestUserFirstName'
  56. find('[name=lastname]').fill_in with: 'User'
  57. find('span.label-text', text: 'Customer').first(:xpath, './/..').click
  58. click '.js-submit'
  59. expect(page).to have_css('table.user-list td', text: 'NewTestUserFirstName')
  60. end
  61. end
  62. describe 'select an Organization' do
  63. before do
  64. create(:organization, name: 'Example Inc.', active: true)
  65. create(:organization, name: 'Inactive Inc.', active: false)
  66. end
  67. it 'check for inactive Organizations in Organization selection' do
  68. visit '#manage/users'
  69. within(:active_content) do
  70. find('[data-type=new]').click
  71. find('[name=organization_id] ~ .searchableSelect-main').fill_in with: '**'
  72. expect(page).to have_css('ul.js-optionsList > li.js-option', minimum: 2)
  73. expect(page).to have_css('ul.js-optionsList > li.js-option .is-inactive', count: 1)
  74. end
  75. end
  76. end
  77. describe 'with email with umlauts' do
  78. it 'is valid' do
  79. visit '#manage/users'
  80. within(:active_content) do
  81. find('[data-type=new]').click
  82. find('[name=firstname]').fill_in with: 'NewTestUserFirstName'
  83. find('[name=lastname]').fill_in with: 'User'
  84. find('[name=email]').fill_in with: 'üser@äcme.corp'
  85. find('span.label-text', text: 'Customer').first(:xpath, './/..').click
  86. click '.js-submit'
  87. expect(page).to have_css('table.user-list td', text: 'üser@äcme.corp')
  88. end
  89. end
  90. end
  91. end
  92. describe 'show/unlock a user', authenticated_as: :authenticate do
  93. let(:user) { create(:admin) }
  94. let(:locked_user) { create(:user, login_failed: 6) }
  95. def authenticate
  96. locked_user
  97. user
  98. end
  99. it 'check marked locked user and execute unlock action' do
  100. visit '#manage/users'
  101. within(:active_content) do
  102. row = find("tr[data-id=\"#{locked_user.id}\"]")
  103. expect(row).to have_css('.icon-lock')
  104. row.find('.js-action').click
  105. row.find('li.unlock').click
  106. expect(row).to have_no_css('.icon-lock')
  107. end
  108. end
  109. end
  110. context 'updating a user' do
  111. let(:user) { create(:admin, firstname: 'Dummy') }
  112. let(:row) { find "table.user-list tbody tr[data-id='#{user.id}']" }
  113. let(:group) { Group.first }
  114. let(:group2) { Group.second }
  115. before do
  116. user
  117. visit '#manage/users'
  118. within(:active_content) do
  119. row.click
  120. end
  121. end
  122. it 'handles permission checkboxes correctly' do
  123. in_modal do
  124. scroll_into_view '[data-attribute-name="group_ids"]'
  125. within '.js-groupListNewItemRow' do
  126. click '.js-input'
  127. click 'li', text: group.name
  128. click 'input[value="full"]', visible: :all
  129. expect(find('input[value="full"]', visible: :all)).to be_checked
  130. click 'input[value="read"]', visible: :all
  131. expect(find('input[value="full"]', visible: :all)).not_to be_checked
  132. expect(find('input[value="read"]', visible: :all)).to be_checked
  133. click 'input[value="full"]', visible: :all
  134. expect(find('input[value="full"]', visible: :all)).to be_checked
  135. expect(find('input[value="read"]', visible: :all)).not_to be_checked
  136. end
  137. end
  138. end
  139. it 'adds group permissions correctly' do
  140. in_modal do
  141. scroll_into_view '[data-attribute-name="group_ids"]'
  142. expect(page).to have_no_css '[data-attribute-name="group_ids"] tbody tr[data-id]'
  143. within '.js-groupListNewItemRow' do
  144. click '.js-input'
  145. click 'li', text: group.name
  146. click 'input[value="full"]', visible: :all
  147. click '.js-add'
  148. end
  149. expect(page).to have_css "table.settings-list tbody tr[data-id='#{group.id}']"
  150. within '.js-groupListNewItemRow' do
  151. click '.js-input'
  152. click 'li', text: group2.name
  153. click 'input[value="read"]', visible: :all
  154. end
  155. click_on 'Submit'
  156. end
  157. # only the first group is added
  158. # because add button is not clicked for the 2nd group
  159. expect(user.reload.user_groups).to contain_exactly(
  160. have_attributes(group: group, access: 'full')
  161. )
  162. end
  163. context 'when user already has a group configured', authenticated_as: :authenticate do
  164. def authenticate
  165. user.groups << group
  166. user.groups << group2
  167. true
  168. end
  169. it 'toggles groups on (un)checking agent role' do
  170. in_modal do
  171. scroll_into_view '.user_permission'
  172. expect(page).to have_css('[data-attribute-name="group_ids"]')
  173. click 'span', text: 'Agent'
  174. expect(page).to have_no_css('[data-attribute-name="group_ids"]')
  175. click 'span', text: 'Agent'
  176. expect(page).to have_css('[data-attribute-name="group_ids"]')
  177. end
  178. end
  179. it 'removes group correctly' do
  180. in_modal do
  181. scroll_into_view '[data-attribute-name="group_ids"]'
  182. within "[data-attribute-name='group_ids'] tbody tr[data-id='#{group.id}']" do
  183. click '.js-remove'
  184. end
  185. click_on 'Submit'
  186. end
  187. expect(user.reload.user_groups).to contain_exactly(
  188. have_attributes(group: group2, access: 'full')
  189. )
  190. end
  191. end
  192. it 'allows to update a user with no email/first/last/phone if login is present' do
  193. in_modal do
  194. fill_in 'firstname', with: ''
  195. fill_in 'lastname', with: ''
  196. fill_in 'Email', with: ''
  197. fill_in 'Phone', with: ''
  198. click_on 'Submit'
  199. end
  200. within :active_content do
  201. expect(page).to have_no_text(user.firstname)
  202. end
  203. end
  204. context 'when user has auto login' do
  205. let(:user) { create(:admin, login: "auto-#{SecureRandom.uuid}") }
  206. it 'does not allow to update a user with no email/first/last/phone' do
  207. in_modal do
  208. fill_in 'firstname', with: ''
  209. fill_in 'lastname', with: ''
  210. fill_in 'Email', with: ''
  211. fill_in 'Phone', with: ''
  212. click_on 'Submit'
  213. expect(page).to have_text('At least one identifier')
  214. end
  215. end
  216. end
  217. context 'when user has email with umlauts' do
  218. let(:user) { create(:admin, login: 'üser@äcme.corp', email: 'üser@äcme.corp') }
  219. it 'does allow to update' do
  220. in_modal do
  221. fill_in 'firstname', with: 'Üser'
  222. click_on 'Submit'
  223. end
  224. expect(page).to have_no_text('Invalid email')
  225. end
  226. end
  227. end
  228. describe 'check user edit permissions', authenticated_as: -> { user } do
  229. shared_examples 'user permission' do |allow|
  230. it(allow ? 'allows editing' : 'forbids editing') do
  231. visit "#user/profile/#{record.id}"
  232. find('.js-action .icon-arrow-down').click
  233. selector = '.js-action [data-type="edit"]'
  234. expect(page).to(allow ? have_css(selector) : have_no_css(selector))
  235. end
  236. end
  237. context 'when admin tries to change admin' do
  238. let(:user) { create(:admin) }
  239. let(:record) { create(:admin) }
  240. include_examples 'user permission', true
  241. end
  242. context 'when admin tries to change agent' do
  243. let(:user) { create(:admin) }
  244. let(:record) { create(:agent) }
  245. include_examples 'user permission', true
  246. end
  247. context 'when admin tries to change customer' do
  248. let(:user) { create(:admin) }
  249. let(:record) { create(:customer) }
  250. include_examples 'user permission', true
  251. end
  252. context 'when agent tries to change admin' do
  253. let(:user) { create(:agent) }
  254. let(:record) { create(:admin) }
  255. include_examples 'user permission', false
  256. end
  257. context 'when agent tries to change agent' do
  258. let(:user) { create(:agent) }
  259. let(:record) { create(:agent) }
  260. include_examples 'user permission', false
  261. end
  262. context 'when agent tries to change customer' do
  263. let(:user) { create(:agent) }
  264. let(:record) { create(:customer) }
  265. include_examples 'user permission', true
  266. end
  267. context 'when agent tries to change customer who is also admin' do
  268. let(:user) { create(:agent) }
  269. let(:record) { create(:customer, role_ids: Role.signup_role_ids.push(Role.find_by(name: 'Admin').id)) }
  270. include_examples 'user permission', false
  271. end
  272. context 'when agent tries to change customer who is also agent' do
  273. let(:user) { create(:agent) }
  274. let(:record) { create(:customer, role_ids: Role.signup_role_ids.push(Role.find_by(name: 'Agent').id)) }
  275. include_examples 'user permission', false
  276. end
  277. end
  278. describe 'UI is not updated right after importing users csv file #3919' do
  279. before do
  280. visit '#manage/users'
  281. ensure_websocket
  282. User.csv_import(
  283. string: Rails.root.join('spec/fixtures/files/csv_import/user/simple.csv').read,
  284. parse_params: {
  285. col_sep: ';',
  286. },
  287. try: false,
  288. delete: false,
  289. )
  290. end
  291. it 'does update the user list after import of new users' do
  292. expect(page).to have_text('firstname-simple-import1')
  293. end
  294. end
  295. describe 'Missing secondary organizations in user profile after refreshing with many secondary organizations. #4331' do
  296. let(:organizations) { create_list(:organization, 20) }
  297. let(:customer) { create(:customer, organization: organizations[0], organizations: organizations[1..]) }
  298. before do
  299. customer
  300. visit '#manage/users'
  301. click "tr[data-id='#{customer.id}']"
  302. end
  303. it 'does show all secondary organizations on edit' do
  304. tokens = page.all('div[data-attribute-name="organization_ids"] .token')
  305. expect(tokens.count).to eq(19)
  306. end
  307. end
  308. describe 'Two-Factor Authentication', authenticated_as: :authenticate do
  309. let(:admin) { create(:admin) }
  310. let(:agent) { create(:agent) }
  311. let(:two_factor_pref) { create(:user_two_factor_preference, :authenticator_app, user: agent) }
  312. let(:enabled) { true }
  313. def authenticate
  314. Setting.set('two_factor_authentication_method_authenticator_app', true)
  315. Setting.set('two_factor_authentication_enforce_role_ids', [])
  316. two_factor_pref
  317. agent.reload
  318. Setting.set('two_factor_authentication_method_authenticator_app', enabled)
  319. admin
  320. end
  321. def open_configure_two_factor
  322. row = find("tr[data-id=\"#{agent.id}\"]")
  323. row.find('.js-action').click
  324. row.find('.js-manageTwoFactor span').click
  325. end
  326. def expect_no_two_factor
  327. row = find("tr[data-id=\"#{agent.id}\"]")
  328. row.find('.js-action').click
  329. expect(row).to have_no_css('.js-manageTwoFactor')
  330. end
  331. before do
  332. visit '#manage/users'
  333. end
  334. it 'does remove the two-factor method' do
  335. open_configure_two_factor
  336. select 'Authenticator App', from: 'method'
  337. click_on 'Remove method'
  338. wait.until { !User::TwoFactorPreference.exists?(id: two_factor_pref.id) }
  339. expect_no_two_factor
  340. end
  341. it 'does remove all two-factor methods' do
  342. open_configure_two_factor
  343. click_on 'Remove all methods'
  344. click_on 'Yes'
  345. wait.until { !User::TwoFactorPreference.exists?(id: two_factor_pref.id) }
  346. expect_no_two_factor
  347. end
  348. describe 'when Two-Factor is disabled' do
  349. let(:enabled) { false }
  350. it 'does remove all two-factor methods' do
  351. open_configure_two_factor
  352. click_on 'Remove all methods'
  353. click_on 'Yes'
  354. wait.until { !User::TwoFactorPreference.exists?(id: two_factor_pref.id) }
  355. expect_no_two_factor
  356. end
  357. end
  358. end
  359. end