PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/spec/requests/api/members_spec.rb

https://gitlab.com/Munken/gitlab-ce
Ruby | 342 lines | 275 code | 65 blank | 2 comment | 8 complexity | 4497f82fbc8840bdb993d13f3ea74d86 MD5 | raw file
  1. require 'spec_helper'
  2. describe API::Members, api: true do
  3. include ApiHelpers
  4. let(:master) { create(:user) }
  5. let(:developer) { create(:user) }
  6. let(:access_requester) { create(:user) }
  7. let(:stranger) { create(:user) }
  8. let(:project) do
  9. create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project|
  10. project.team << [developer, :developer]
  11. project.team << [master, :master]
  12. project.request_access(access_requester)
  13. end
  14. end
  15. let!(:group) do
  16. create(:group, :public, :access_requestable) do |group|
  17. group.add_developer(developer)
  18. group.add_owner(master)
  19. group.request_access(access_requester)
  20. end
  21. end
  22. shared_examples 'GET /:sources/:id/members' do |source_type|
  23. context "with :sources == #{source_type.pluralize}" do
  24. it_behaves_like 'a 404 response when source is private' do
  25. let(:route) { get api("/#{source_type.pluralize}/#{source.id}/members", stranger) }
  26. end
  27. %i[master developer access_requester stranger].each do |type|
  28. context "when authenticated as a #{type}" do
  29. it 'returns 200' do
  30. user = public_send(type)
  31. get api("/#{source_type.pluralize}/#{source.id}/members", user)
  32. expect(response).to have_http_status(200)
  33. expect(json_response.size).to eq(2)
  34. expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id]
  35. end
  36. end
  37. end
  38. it 'does not return invitees' do
  39. create(:"#{source_type}_member", invite_token: '123', invite_email: 'test@abc.com', source: source, user: nil)
  40. get api("/#{source_type.pluralize}/#{source.id}/members", developer)
  41. expect(response).to have_http_status(200)
  42. expect(json_response.size).to eq(2)
  43. expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id]
  44. end
  45. it 'finds members with query string' do
  46. get api("/#{source_type.pluralize}/#{source.id}/members", developer), query: master.username
  47. expect(response).to have_http_status(200)
  48. expect(json_response.count).to eq(1)
  49. expect(json_response.first['username']).to eq(master.username)
  50. end
  51. end
  52. end
  53. shared_examples 'GET /:sources/:id/members/:user_id' do |source_type|
  54. context "with :sources == #{source_type.pluralize}" do
  55. it_behaves_like 'a 404 response when source is private' do
  56. let(:route) { get api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger) }
  57. end
  58. context 'when authenticated as a non-member' do
  59. %i[access_requester stranger].each do |type|
  60. context "as a #{type}" do
  61. it 'returns 200' do
  62. user = public_send(type)
  63. get api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user)
  64. expect(response).to have_http_status(200)
  65. # User attributes
  66. expect(json_response['id']).to eq(developer.id)
  67. expect(json_response['name']).to eq(developer.name)
  68. expect(json_response['username']).to eq(developer.username)
  69. expect(json_response['state']).to eq(developer.state)
  70. expect(json_response['avatar_url']).to eq(developer.avatar_url)
  71. expect(json_response['web_url']).to eq(Gitlab::Routing.url_helpers.user_url(developer))
  72. # Member attributes
  73. expect(json_response['access_level']).to eq(Member::DEVELOPER)
  74. end
  75. end
  76. end
  77. end
  78. end
  79. end
  80. shared_examples 'POST /:sources/:id/members' do |source_type|
  81. context "with :sources == #{source_type.pluralize}" do
  82. it_behaves_like 'a 404 response when source is private' do
  83. let(:route) do
  84. post api("/#{source_type.pluralize}/#{source.id}/members", stranger),
  85. user_id: access_requester.id, access_level: Member::MASTER
  86. end
  87. end
  88. context 'when authenticated as a non-member or member with insufficient rights' do
  89. %i[access_requester stranger developer].each do |type|
  90. context "as a #{type}" do
  91. it 'returns 403' do
  92. user = public_send(type)
  93. post api("/#{source_type.pluralize}/#{source.id}/members", user),
  94. user_id: access_requester.id, access_level: Member::MASTER
  95. expect(response).to have_http_status(403)
  96. end
  97. end
  98. end
  99. end
  100. context 'when authenticated as a master/owner' do
  101. context 'and new member is already a requester' do
  102. it 'transforms the requester into a proper member' do
  103. expect do
  104. post api("/#{source_type.pluralize}/#{source.id}/members", master),
  105. user_id: access_requester.id, access_level: Member::MASTER
  106. expect(response).to have_http_status(201)
  107. end.to change { source.members.count }.by(1)
  108. expect(source.requesters.count).to eq(0)
  109. expect(json_response['id']).to eq(access_requester.id)
  110. expect(json_response['access_level']).to eq(Member::MASTER)
  111. end
  112. end
  113. it 'creates a new member' do
  114. expect do
  115. post api("/#{source_type.pluralize}/#{source.id}/members", master),
  116. user_id: stranger.id, access_level: Member::DEVELOPER, expires_at: '2016-08-05'
  117. expect(response).to have_http_status(201)
  118. end.to change { source.members.count }.by(1)
  119. expect(json_response['id']).to eq(stranger.id)
  120. expect(json_response['access_level']).to eq(Member::DEVELOPER)
  121. expect(json_response['expires_at']).to eq('2016-08-05')
  122. end
  123. end
  124. it "returns #{source_type == 'project' ? 201 : 409} if member already exists" do
  125. post api("/#{source_type.pluralize}/#{source.id}/members", master),
  126. user_id: master.id, access_level: Member::MASTER
  127. expect(response).to have_http_status(source_type == 'project' ? 201 : 409)
  128. end
  129. it 'returns 400 when user_id is not given' do
  130. post api("/#{source_type.pluralize}/#{source.id}/members", master),
  131. access_level: Member::MASTER
  132. expect(response).to have_http_status(400)
  133. end
  134. it 'returns 400 when access_level is not given' do
  135. post api("/#{source_type.pluralize}/#{source.id}/members", master),
  136. user_id: stranger.id
  137. expect(response).to have_http_status(400)
  138. end
  139. it 'returns 422 when access_level is not valid' do
  140. post api("/#{source_type.pluralize}/#{source.id}/members", master),
  141. user_id: stranger.id, access_level: 1234
  142. expect(response).to have_http_status(422)
  143. end
  144. end
  145. end
  146. shared_examples 'PUT /:sources/:id/members/:user_id' do |source_type|
  147. context "with :sources == #{source_type.pluralize}" do
  148. it_behaves_like 'a 404 response when source is private' do
  149. let(:route) do
  150. put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger),
  151. access_level: Member::MASTER
  152. end
  153. end
  154. context 'when authenticated as a non-member or member with insufficient rights' do
  155. %i[access_requester stranger developer].each do |type|
  156. context "as a #{type}" do
  157. it 'returns 403' do
  158. user = public_send(type)
  159. put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user),
  160. access_level: Member::MASTER
  161. expect(response).to have_http_status(403)
  162. end
  163. end
  164. end
  165. end
  166. context 'when authenticated as a master/owner' do
  167. it 'updates the member' do
  168. put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master),
  169. access_level: Member::MASTER, expires_at: '2016-08-05'
  170. expect(response).to have_http_status(200)
  171. expect(json_response['id']).to eq(developer.id)
  172. expect(json_response['access_level']).to eq(Member::MASTER)
  173. expect(json_response['expires_at']).to eq('2016-08-05')
  174. end
  175. end
  176. it 'returns 409 if member does not exist' do
  177. put api("/#{source_type.pluralize}/#{source.id}/members/123", master),
  178. access_level: Member::MASTER
  179. expect(response).to have_http_status(404)
  180. end
  181. it 'returns 400 when access_level is not given' do
  182. put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master)
  183. expect(response).to have_http_status(400)
  184. end
  185. it 'returns 422 when access level is not valid' do
  186. put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master),
  187. access_level: 1234
  188. expect(response).to have_http_status(422)
  189. end
  190. end
  191. end
  192. shared_examples 'DELETE /:sources/:id/members/:user_id' do |source_type|
  193. context "with :sources == #{source_type.pluralize}" do
  194. it_behaves_like 'a 404 response when source is private' do
  195. let(:route) { delete api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger) }
  196. end
  197. context 'when authenticated as a non-member or member with insufficient rights' do
  198. %i[access_requester stranger].each do |type|
  199. context "as a #{type}" do
  200. it 'returns 403' do
  201. user = public_send(type)
  202. delete api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user)
  203. expect(response).to have_http_status(403)
  204. end
  205. end
  206. end
  207. end
  208. context 'when authenticated as a member and deleting themself' do
  209. it 'deletes the member' do
  210. expect do
  211. delete api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", developer)
  212. expect(response).to have_http_status(200)
  213. end.to change { source.members.count }.by(-1)
  214. end
  215. end
  216. context 'when authenticated as a master/owner' do
  217. context 'and member is a requester' do
  218. it "returns #{source_type == 'project' ? 200 : 404}" do
  219. expect do
  220. delete api("/#{source_type.pluralize}/#{source.id}/members/#{access_requester.id}", master)
  221. expect(response).to have_http_status(source_type == 'project' ? 200 : 404)
  222. end.not_to change { source.requesters.count }
  223. end
  224. end
  225. it 'deletes the member' do
  226. expect do
  227. delete api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master)
  228. expect(response).to have_http_status(200)
  229. end.to change { source.members.count }.by(-1)
  230. end
  231. end
  232. it "returns #{source_type == 'project' ? 200 : 404} if member does not exist" do
  233. delete api("/#{source_type.pluralize}/#{source.id}/members/123", master)
  234. expect(response).to have_http_status(source_type == 'project' ? 200 : 404)
  235. end
  236. end
  237. end
  238. it_behaves_like 'GET /:sources/:id/members', 'project' do
  239. let(:source) { project }
  240. end
  241. it_behaves_like 'GET /:sources/:id/members', 'group' do
  242. let(:source) { group }
  243. end
  244. it_behaves_like 'GET /:sources/:id/members/:user_id', 'project' do
  245. let(:source) { project }
  246. end
  247. it_behaves_like 'GET /:sources/:id/members/:user_id', 'group' do
  248. let(:source) { group }
  249. end
  250. it_behaves_like 'POST /:sources/:id/members', 'project' do
  251. let(:source) { project }
  252. end
  253. it_behaves_like 'POST /:sources/:id/members', 'group' do
  254. let(:source) { group }
  255. end
  256. it_behaves_like 'PUT /:sources/:id/members/:user_id', 'project' do
  257. let(:source) { project }
  258. end
  259. it_behaves_like 'PUT /:sources/:id/members/:user_id', 'group' do
  260. let(:source) { group }
  261. end
  262. it_behaves_like 'DELETE /:sources/:id/members/:user_id', 'project' do
  263. let(:source) { project }
  264. end
  265. it_behaves_like 'DELETE /:sources/:id/members/:user_id', 'group' do
  266. let(:source) { group }
  267. end
  268. context 'Adding owner to project' do
  269. it 'returns 403' do
  270. expect do
  271. post api("/projects/#{project.id}/members", master),
  272. user_id: stranger.id, access_level: Member::OWNER
  273. expect(response).to have_http_status(422)
  274. end.to change { project.members.count }.by(0)
  275. end
  276. end
  277. end