permission_spec.rb 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'User endpoint', type: :request do
  4. let(:role_with_admin_user_permissions) do
  5. create(:role).tap do |role|
  6. role.permission_grant('admin.user')
  7. end
  8. end
  9. let(:admin_with_admin_user_permissions) { create(:user, roles: [role_with_admin_user_permissions]) }
  10. let(:role_without_admin_user_permissions) do
  11. create(:role).tap do |role|
  12. role.permission_grant('admin.tag')
  13. end
  14. end
  15. let(:admin_without_admin_user_permissions) { create(:user, roles: [role_without_admin_user_permissions]) }
  16. describe 'User creation' do
  17. let(:attributes) { attributes_params_for(:user) }
  18. it 'responds forbidden for customer' do
  19. requester = create(:customer)
  20. authenticated_as(requester)
  21. expect do
  22. post api_v1_users_path, params: attributes
  23. end.to not_change {
  24. User.count
  25. }
  26. expect(response).to have_http_status(:forbidden)
  27. end
  28. context 'privileged attributes' do
  29. context 'group assignment' do
  30. # group access assignment is in general only valid for agents
  31. # see HasGroups.groups_access_permission?
  32. let(:agent_attributes) do
  33. attributes.merge(
  34. roles: Role.where(name: 'Agent').map(&:name),
  35. )
  36. end
  37. shared_examples 'group assignment' do |map_method_id|
  38. it 'responds success for admin.user' do
  39. authenticated_as(admin_with_admin_user_permissions)
  40. expect do
  41. post api_v1_users_path, params: payload
  42. end.to change(User, :count).by(1)
  43. expect(response).to have_http_status(:success)
  44. expect(User.last.send(map_method_id)).to eq(send(map_method_id))
  45. end
  46. it 'responds forbidden for sub admin without admin.user' do
  47. authenticated_as(admin_without_admin_user_permissions)
  48. expect do
  49. post api_v1_users_path, params: payload
  50. end.to not_change {
  51. User.count
  52. }
  53. expect(response).to have_http_status(:forbidden)
  54. end
  55. it 'responds successful for agent but removes assignment' do
  56. requester = create(:agent)
  57. authenticated_as(requester)
  58. expect do
  59. post api_v1_users_path, params: payload
  60. end.to change(User, :count).by(1)
  61. expect(response).to have_http_status(:success)
  62. expect(User.last.send(map_method_id)).to be_blank
  63. end
  64. end
  65. context 'parameter groups' do
  66. let(:group_names_access_map) do
  67. Group.all.to_h { |g| [g.name, ['full']] }
  68. end
  69. let(:payload) do
  70. agent_attributes.merge(
  71. groups: group_names_access_map,
  72. )
  73. end
  74. it_behaves_like 'group assignment', :group_names_access_map
  75. end
  76. context 'parameter group_ids' do
  77. let(:group_ids_access_map) do
  78. Group.all.to_h { |g| [g.id, ['full']] }
  79. end
  80. let(:payload) do
  81. agent_attributes.merge(
  82. group_ids: group_ids_access_map,
  83. )
  84. end
  85. it_behaves_like 'group assignment', :group_ids_access_map
  86. end
  87. end
  88. context 'role assignment' do
  89. shared_examples 'role assignment' do
  90. let(:privileged) { Role.where(name: 'Admin') }
  91. it 'responds success for admin.user' do
  92. authenticated_as(admin_with_admin_user_permissions)
  93. expect do
  94. post api_v1_users_path, params: payload
  95. end.to change(User, :count).by(1)
  96. expect(response).to have_http_status(:success)
  97. expect(User.last.roles).to eq(privileged)
  98. end
  99. it 'responds forbidden for sub admin without admin.user' do
  100. authenticated_as(admin_without_admin_user_permissions)
  101. expect do
  102. post api_v1_users_path, params: payload
  103. end.to not_change {
  104. User.count
  105. }
  106. expect(response).to have_http_status(:forbidden)
  107. end
  108. it 'responds successful for agent but removes assignment' do
  109. requester = create(:agent)
  110. authenticated_as(requester)
  111. expect do
  112. post api_v1_users_path, params: payload
  113. end.to change(User, :count).by(1)
  114. expect(response).to have_http_status(:success)
  115. expect(User.last.roles).to eq(Role.signup_roles)
  116. end
  117. end
  118. context 'parameter roles' do
  119. let(:payload) do
  120. attributes.merge(
  121. roles: privileged.map(&:name),
  122. )
  123. end
  124. it_behaves_like 'role assignment'
  125. end
  126. context 'parameter role_ids' do
  127. let(:payload) do
  128. attributes.merge(
  129. role_ids: privileged.map(&:id),
  130. )
  131. end
  132. it_behaves_like 'role assignment'
  133. end
  134. end
  135. end
  136. end
  137. describe 'User update' do
  138. def authorized_update_request(requester:, requested:)
  139. authenticated_as(requester)
  140. expect do
  141. put api_v1_update_user_path(requested), params: cleaned_params_for(requested).merge(firstname: 'Changed')
  142. end.to change {
  143. requested.reload.firstname
  144. }
  145. expect(response).to have_http_status(:success)
  146. end
  147. def forbidden_update_request(requester:, requested:)
  148. authenticated_as(requester)
  149. expect do
  150. put api_v1_update_user_path(requested), params: cleaned_params_for(requested).merge(firstname: 'Changed')
  151. end.to not_change {
  152. requested.reload.attributes.tap do |attributes|
  153. # take attributes as they are for different users
  154. next if requester != requested
  155. # last_login and updated_at change every time
  156. # even if the record itself should not change
  157. attributes.delete_if do |key, _value|
  158. %w[last_login updated_at].include?(key)
  159. end
  160. end
  161. }
  162. expect(response).to have_http_status(:forbidden)
  163. end
  164. context 'request by admin.user' do
  165. let(:requester) { admin_with_admin_user_permissions }
  166. it 'is successful for same admin' do
  167. authorized_update_request(
  168. requester: requester,
  169. requested: requester,
  170. )
  171. end
  172. it 'is successful for other admin' do
  173. authorized_update_request(
  174. requester: requester,
  175. requested: create(:admin),
  176. )
  177. end
  178. it 'is successful for agent' do
  179. authorized_update_request(
  180. requester: requester,
  181. requested: create(:agent),
  182. )
  183. end
  184. it 'is successful for customer' do
  185. authorized_update_request(
  186. requester: requester,
  187. requested: create(:customer),
  188. )
  189. end
  190. end
  191. context 'request by sub admin without admin.user' do
  192. let(:requester) { admin_without_admin_user_permissions }
  193. it 'is forbidden for same admin' do
  194. forbidden_update_request(
  195. requester: requester,
  196. requested: requester,
  197. )
  198. end
  199. it 'is forbidden for other admin' do
  200. forbidden_update_request(
  201. requester: requester,
  202. requested: create(:admin),
  203. )
  204. end
  205. it 'is forbidden for agent' do
  206. forbidden_update_request(
  207. requester: requester,
  208. requested: create(:agent),
  209. )
  210. end
  211. it 'is forbidden for customer' do
  212. forbidden_update_request(
  213. requester: requester,
  214. requested: create(:customer),
  215. )
  216. end
  217. end
  218. context 'request by agent' do
  219. let(:requester) { create(:agent) }
  220. it 'is forbidden for admin' do
  221. forbidden_update_request(
  222. requester: requester,
  223. requested: create(:admin),
  224. )
  225. end
  226. it 'is forbidden same agent' do
  227. forbidden_update_request(
  228. requester: requester,
  229. requested: requester,
  230. )
  231. end
  232. it 'is forbidden for other agent' do
  233. forbidden_update_request(
  234. requester: requester,
  235. requested: create(:agent),
  236. )
  237. end
  238. it 'is successful for customer' do
  239. authorized_update_request(
  240. requester: requester,
  241. requested: create(:customer),
  242. )
  243. end
  244. end
  245. context 'request by customer' do
  246. let(:requester) { create(:customer) }
  247. it 'is forbidden for admin' do
  248. forbidden_update_request(
  249. requester: requester,
  250. requested: create(:admin),
  251. )
  252. end
  253. it 'is forbidden for agent' do
  254. forbidden_update_request(
  255. requester: requester,
  256. requested: create(:agent),
  257. )
  258. end
  259. it 'is forbidden for same customer' do
  260. forbidden_update_request(
  261. requester: requester,
  262. requested: requester,
  263. )
  264. end
  265. it 'is forbidden for other customer' do
  266. forbidden_update_request(
  267. requester: requester,
  268. requested: create(:customer),
  269. )
  270. end
  271. it 'is forbidden for same organization' do
  272. same_organization = create(:organization)
  273. requester.update!(organization: same_organization)
  274. forbidden_update_request(
  275. requester: requester,
  276. requested: create(:customer, organization: same_organization),
  277. )
  278. end
  279. end
  280. context 'privileged attributes' do
  281. let(:requested) { create(:user) }
  282. let(:attribute) { privileged.keys.first }
  283. let(:payload) { cleaned_params_for(requested).merge(privileged) }
  284. def value_of_attribute
  285. # we need to call .to_a otherwise Rails will load the
  286. # ActiveRecord::Associations::CollectionProxy
  287. # on comparsion which is to late
  288. requested.reload.public_send(attribute).to_a
  289. end
  290. shared_examples 'admin types requests' do
  291. it 'responds success for admin.user' do
  292. authenticated_as(admin_with_admin_user_permissions)
  293. expect do
  294. put api_v1_update_user_path(requested), params: payload
  295. end.to change {
  296. value_of_attribute
  297. }
  298. expect(response).to have_http_status(:success)
  299. end
  300. it 'responds forbidden for sub admin without admin.user' do
  301. authenticated_as(admin_without_admin_user_permissions)
  302. expect do
  303. put api_v1_update_user_path(requested), params: payload
  304. end.to not_change {
  305. value_of_attribute
  306. }
  307. expect(response).to have_http_status(:forbidden)
  308. end
  309. end
  310. shared_examples 'permitted agent update' do
  311. it 'responds successful for agent but removes assignment' do
  312. requester = create(:agent)
  313. authenticated_as(requester)
  314. expect do
  315. put api_v1_update_user_path(requested), params: payload
  316. end.to change {
  317. value_of_attribute
  318. }
  319. expect(response).to have_http_status(:success)
  320. end
  321. end
  322. shared_examples 'forbidden agent update' do
  323. it 'responds successful for agent but removes assignment' do
  324. requester = create(:agent)
  325. authenticated_as(requester)
  326. expect do
  327. put api_v1_update_user_path(requested), params: payload
  328. end.to not_change {
  329. value_of_attribute
  330. }
  331. expect(response).to have_http_status(:success)
  332. end
  333. end
  334. context 'group assignment' do
  335. context 'parameter groups' do
  336. let(:privileged) do
  337. {
  338. groups: Group.all.to_h { |g| [g.name, ['full']] }
  339. }
  340. end
  341. it_behaves_like 'admin types requests'
  342. it_behaves_like 'forbidden agent update'
  343. end
  344. context 'parameter group_ids' do
  345. let(:privileged) do
  346. {
  347. group_ids: Group.all.to_h { |g| [g.id, ['full']] }
  348. }
  349. end
  350. it_behaves_like 'admin types requests'
  351. it_behaves_like 'forbidden agent update'
  352. end
  353. end
  354. context 'role assignment' do
  355. let(:admin_role) { Role.where(name: 'Admin') }
  356. context 'parameter roles' do
  357. let(:privileged) do
  358. {
  359. roles: admin_role.map(&:name),
  360. }
  361. end
  362. it_behaves_like 'admin types requests'
  363. it_behaves_like 'forbidden agent update'
  364. end
  365. context 'parameter role_ids' do
  366. let(:privileged) do
  367. {
  368. role_ids: admin_role.map(&:id),
  369. }
  370. end
  371. it_behaves_like 'admin types requests'
  372. it_behaves_like 'forbidden agent update'
  373. end
  374. end
  375. context 'organization assignment' do
  376. # We need a primary org to be able to assign secondary orgs.
  377. let(:requested) { create(:user, organization: create(:organization)) }
  378. let(:new_organizations) { create_list(:organization, 2) }
  379. context 'parameter organizations' do
  380. let(:privileged) do
  381. {
  382. organizations: new_organizations.map(&:name),
  383. }
  384. end
  385. it_behaves_like 'admin types requests'
  386. it_behaves_like 'permitted agent update'
  387. end
  388. context 'parameter organization_ids' do
  389. let(:privileged) do
  390. {
  391. organization_ids: new_organizations.map(&:id),
  392. }
  393. end
  394. it_behaves_like 'admin types requests'
  395. it_behaves_like 'permitted agent update'
  396. end
  397. end
  398. end
  399. end
  400. describe 'User deletion' do
  401. def authorized_destroy_request(requester:, requested:)
  402. authenticated_as(requester)
  403. delete api_v1_delete_user_path(requested)
  404. expect(response).to have_http_status(:success)
  405. expect(requested).not_to exist_in_database
  406. end
  407. def forbidden_destroy_request(requester:, requested:)
  408. authenticated_as(requester)
  409. delete api_v1_delete_user_path(requested)
  410. expect(response).to have_http_status(:forbidden)
  411. expect(requested).to exist_in_database
  412. end
  413. context 'request by admin.user' do
  414. let(:requester) { admin_with_admin_user_permissions }
  415. it 'is successful for same admin' do
  416. authorized_destroy_request(
  417. requester: requester,
  418. requested: requester,
  419. )
  420. end
  421. it 'is successful for other admin' do
  422. authorized_destroy_request(
  423. requester: requester,
  424. requested: create(:admin),
  425. )
  426. end
  427. it 'is successful for agent' do
  428. authorized_destroy_request(
  429. requester: requester,
  430. requested: create(:agent),
  431. )
  432. end
  433. it 'is successful for customer' do
  434. authorized_destroy_request(
  435. requester: requester,
  436. requested: create(:customer),
  437. )
  438. end
  439. end
  440. context 'request by sub admin without admin.user' do
  441. let(:requester) { admin_without_admin_user_permissions }
  442. it 'is forbidden for same admin' do
  443. forbidden_destroy_request(
  444. requester: requester,
  445. requested: requester,
  446. )
  447. end
  448. it 'is forbidden for other admin' do
  449. forbidden_destroy_request(
  450. requester: requester,
  451. requested: create(:admin),
  452. )
  453. end
  454. it 'is forbidden for agent' do
  455. forbidden_destroy_request(
  456. requester: requester,
  457. requested: create(:agent),
  458. )
  459. end
  460. it 'is forbidden for customer' do
  461. forbidden_destroy_request(
  462. requester: requester,
  463. requested: create(:customer),
  464. )
  465. end
  466. end
  467. context 'request by agent' do
  468. let(:requester) { create(:agent) }
  469. it 'is forbidden for admin' do
  470. forbidden_destroy_request(
  471. requester: requester,
  472. requested: create(:admin),
  473. )
  474. end
  475. it 'is forbidden same agent' do
  476. forbidden_destroy_request(
  477. requester: requester,
  478. requested: requester,
  479. )
  480. end
  481. it 'is forbidden for other agent' do
  482. forbidden_destroy_request(
  483. requester: requester,
  484. requested: create(:agent),
  485. )
  486. end
  487. it 'is forbidden for customer' do
  488. forbidden_destroy_request(
  489. requester: requester,
  490. requested: create(:customer),
  491. )
  492. end
  493. end
  494. context 'request by customer' do
  495. let(:requester) { create(:customer) }
  496. it 'is forbidden for admin' do
  497. forbidden_destroy_request(
  498. requester: requester,
  499. requested: create(:admin),
  500. )
  501. end
  502. it 'is forbidden for agent' do
  503. forbidden_destroy_request(
  504. requester: requester,
  505. requested: create(:agent),
  506. )
  507. end
  508. it 'is forbidden for same customer' do
  509. forbidden_destroy_request(
  510. requester: requester,
  511. requested: requester,
  512. )
  513. end
  514. it 'is forbidden for other customer' do
  515. forbidden_destroy_request(
  516. requester: requester,
  517. requested: create(:customer),
  518. )
  519. end
  520. it 'is forbidden for same organization' do
  521. same_organization = create(:organization)
  522. requester.update!(organization: same_organization)
  523. forbidden_destroy_request(
  524. requester: requester,
  525. requested: create(:customer, organization: same_organization),
  526. )
  527. end
  528. end
  529. end
  530. end