permission_spec.rb 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. # Copyright (C) 2012-2022 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. let(:new_organizations) { create_list(:organization, 2) }
  377. context 'parameter organizations' do
  378. let(:privileged) do
  379. {
  380. organizations: new_organizations.map(&:name),
  381. }
  382. end
  383. it_behaves_like 'admin types requests'
  384. it_behaves_like 'permitted agent update'
  385. end
  386. context 'parameter organization_ids' do
  387. let(:privileged) do
  388. {
  389. organization_ids: new_organizations.map(&:id),
  390. }
  391. end
  392. it_behaves_like 'admin types requests'
  393. it_behaves_like 'permitted agent update'
  394. end
  395. end
  396. end
  397. end
  398. describe 'User deletion' do
  399. def authorized_destroy_request(requester:, requested:)
  400. authenticated_as(requester)
  401. delete api_v1_delete_user_path(requested)
  402. expect(response).to have_http_status(:success)
  403. expect(requested).not_to exist_in_database
  404. end
  405. def forbidden_destroy_request(requester:, requested:)
  406. authenticated_as(requester)
  407. delete api_v1_delete_user_path(requested)
  408. expect(response).to have_http_status(:forbidden)
  409. expect(requested).to exist_in_database
  410. end
  411. context 'request by admin.user' do
  412. let(:requester) { admin_with_admin_user_permissions }
  413. it 'is successful for same admin' do
  414. authorized_destroy_request(
  415. requester: requester,
  416. requested: requester,
  417. )
  418. end
  419. it 'is successful for other admin' do
  420. authorized_destroy_request(
  421. requester: requester,
  422. requested: create(:admin),
  423. )
  424. end
  425. it 'is successful for agent' do
  426. authorized_destroy_request(
  427. requester: requester,
  428. requested: create(:agent),
  429. )
  430. end
  431. it 'is successful for customer' do
  432. authorized_destroy_request(
  433. requester: requester,
  434. requested: create(:customer),
  435. )
  436. end
  437. end
  438. context 'request by sub admin without admin.user' do
  439. let(:requester) { admin_without_admin_user_permissions }
  440. it 'is forbidden for same admin' do
  441. forbidden_destroy_request(
  442. requester: requester,
  443. requested: requester,
  444. )
  445. end
  446. it 'is forbidden for other admin' do
  447. forbidden_destroy_request(
  448. requester: requester,
  449. requested: create(:admin),
  450. )
  451. end
  452. it 'is forbidden for agent' do
  453. forbidden_destroy_request(
  454. requester: requester,
  455. requested: create(:agent),
  456. )
  457. end
  458. it 'is forbidden for customer' do
  459. forbidden_destroy_request(
  460. requester: requester,
  461. requested: create(:customer),
  462. )
  463. end
  464. end
  465. context 'request by agent' do
  466. let(:requester) { create(:agent) }
  467. it 'is forbidden for admin' do
  468. forbidden_destroy_request(
  469. requester: requester,
  470. requested: create(:admin),
  471. )
  472. end
  473. it 'is forbidden same agent' do
  474. forbidden_destroy_request(
  475. requester: requester,
  476. requested: requester,
  477. )
  478. end
  479. it 'is forbidden for other agent' do
  480. forbidden_destroy_request(
  481. requester: requester,
  482. requested: create(:agent),
  483. )
  484. end
  485. it 'is forbidden for customer' do
  486. forbidden_destroy_request(
  487. requester: requester,
  488. requested: create(:customer),
  489. )
  490. end
  491. end
  492. context 'request by customer' do
  493. let(:requester) { create(:customer) }
  494. it 'is forbidden for admin' do
  495. forbidden_destroy_request(
  496. requester: requester,
  497. requested: create(:admin),
  498. )
  499. end
  500. it 'is forbidden for agent' do
  501. forbidden_destroy_request(
  502. requester: requester,
  503. requested: create(:agent),
  504. )
  505. end
  506. it 'is forbidden for same customer' do
  507. forbidden_destroy_request(
  508. requester: requester,
  509. requested: requester,
  510. )
  511. end
  512. it 'is forbidden for other customer' do
  513. forbidden_destroy_request(
  514. requester: requester,
  515. requested: create(:customer),
  516. )
  517. end
  518. it 'is forbidden for same organization' do
  519. same_organization = create(:organization)
  520. requester.update!(organization: same_organization)
  521. forbidden_destroy_request(
  522. requester: requester,
  523. requested: create(:customer, organization: same_organization),
  524. )
  525. end
  526. end
  527. end
  528. end