PageRenderTime 60ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/spec/requests/api/internal_spec.rb

https://gitlab.com/leandroico/gitlab-ce
Ruby | 461 lines | 454 code | 7 blank | 0 comment | 1 complexity | f27bf2719fbb5130438b5b7bb3ba6d52 MD5 | raw file
  1. require 'spec_helper'
  2. describe API::Internal, api: true do
  3. include ApiHelpers
  4. let(:user) { create(:user) }
  5. let(:key) { create(:key, user: user) }
  6. let(:project) { create(:project) }
  7. let(:secret_token) { Gitlab::Shell.secret_token }
  8. describe "GET /internal/check", no_db: true do
  9. it do
  10. get api("/internal/check"), secret_token: secret_token
  11. expect(response).to have_http_status(200)
  12. expect(json_response['api_version']).to eq(API::API.version)
  13. end
  14. end
  15. describe "GET /internal/broadcast_message" do
  16. context "broadcast message exists" do
  17. let!(:broadcast_message) { create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow ) }
  18. it do
  19. get api("/internal/broadcast_message"), secret_token: secret_token
  20. expect(response).to have_http_status(200)
  21. expect(json_response["message"]).to eq(broadcast_message.message)
  22. end
  23. end
  24. context "broadcast message doesn't exist" do
  25. it do
  26. get api("/internal/broadcast_message"), secret_token: secret_token
  27. expect(response).to have_http_status(200)
  28. expect(json_response).to be_empty
  29. end
  30. end
  31. end
  32. describe 'GET /internal/two_factor_recovery_codes' do
  33. it 'returns an error message when the key does not exist' do
  34. post api('/internal/two_factor_recovery_codes'),
  35. secret_token: secret_token,
  36. key_id: 12345
  37. expect(json_response['success']).to be_falsey
  38. expect(json_response['message']).to eq('Could not find the given key')
  39. end
  40. it 'returns an error message when the key is a deploy key' do
  41. deploy_key = create(:deploy_key)
  42. post api('/internal/two_factor_recovery_codes'),
  43. secret_token: secret_token,
  44. key_id: deploy_key.id
  45. expect(json_response['success']).to be_falsey
  46. expect(json_response['message']).to eq('Deploy keys cannot be used to retrieve recovery codes')
  47. end
  48. it 'returns an error message when the user does not exist' do
  49. key_without_user = create(:key, user: nil)
  50. post api('/internal/two_factor_recovery_codes'),
  51. secret_token: secret_token,
  52. key_id: key_without_user.id
  53. expect(json_response['success']).to be_falsey
  54. expect(json_response['message']).to eq('Could not find a user for the given key')
  55. expect(json_response['recovery_codes']).to be_nil
  56. end
  57. context 'when two-factor is enabled' do
  58. it 'returns new recovery codes when the user exists' do
  59. allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
  60. allow_any_instance_of(User)
  61. .to receive(:generate_otp_backup_codes!).and_return(%w(119135e5a3ebce8e 34bd7b74adbc8861))
  62. post api('/internal/two_factor_recovery_codes'),
  63. secret_token: secret_token,
  64. key_id: key.id
  65. expect(json_response['success']).to be_truthy
  66. expect(json_response['recovery_codes']).to match_array(%w(119135e5a3ebce8e 34bd7b74adbc8861))
  67. end
  68. end
  69. context 'when two-factor is not enabled' do
  70. it 'returns an error message' do
  71. allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(false)
  72. post api('/internal/two_factor_recovery_codes'),
  73. secret_token: secret_token,
  74. key_id: key.id
  75. expect(json_response['success']).to be_falsey
  76. expect(json_response['recovery_codes']).to be_nil
  77. end
  78. end
  79. end
  80. describe "POST /internal/lfs_authenticate" do
  81. before do
  82. project.team << [user, :developer]
  83. end
  84. context 'user key' do
  85. it 'returns the correct information about the key' do
  86. lfs_auth(key.id, project)
  87. expect(response).to have_http_status(200)
  88. expect(json_response['username']).to eq(user.username)
  89. expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).token)
  90. expect(json_response['repository_http_path']).to eq(project.http_url_to_repo)
  91. end
  92. it 'returns a 404 when the wrong key is provided' do
  93. lfs_auth(nil, project)
  94. expect(response).to have_http_status(404)
  95. end
  96. end
  97. context 'deploy key' do
  98. let(:key) { create(:deploy_key) }
  99. it 'returns the correct information about the key' do
  100. lfs_auth(key.id, project)
  101. expect(response).to have_http_status(200)
  102. expect(json_response['username']).to eq("lfs+deploy-key-#{key.id}")
  103. expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).token)
  104. expect(json_response['repository_http_path']).to eq(project.http_url_to_repo)
  105. end
  106. end
  107. end
  108. describe "GET /internal/discover" do
  109. it do
  110. get(api("/internal/discover"), key_id: key.id, secret_token: secret_token)
  111. expect(response).to have_http_status(200)
  112. expect(json_response['name']).to eq(user.name)
  113. end
  114. end
  115. describe "POST /internal/allowed" do
  116. context "access granted" do
  117. before do
  118. project.team << [user, :developer]
  119. end
  120. context "git push with project.wiki" do
  121. it 'responds with success' do
  122. push(key, project.wiki)
  123. expect(response).to have_http_status(200)
  124. expect(json_response["status"]).to be_truthy
  125. expect(json_response["repository_path"]).to eq(project.wiki.repository.path_to_repo)
  126. end
  127. end
  128. context "git pull with project.wiki" do
  129. it 'responds with success' do
  130. pull(key, project.wiki)
  131. expect(response).to have_http_status(200)
  132. expect(json_response["status"]).to be_truthy
  133. expect(json_response["repository_path"]).to eq(project.wiki.repository.path_to_repo)
  134. end
  135. end
  136. context "git pull" do
  137. it do
  138. pull(key, project)
  139. expect(response).to have_http_status(200)
  140. expect(json_response["status"]).to be_truthy
  141. expect(json_response["repository_path"]).to eq(project.repository.path_to_repo)
  142. end
  143. end
  144. context "git push" do
  145. it do
  146. push(key, project)
  147. expect(response).to have_http_status(200)
  148. expect(json_response["status"]).to be_truthy
  149. expect(json_response["repository_path"]).to eq(project.repository.path_to_repo)
  150. end
  151. context 'project as /namespace/project' do
  152. it do
  153. pull(key, project_with_repo_path('/' + project.path_with_namespace))
  154. expect(response).to have_http_status(200)
  155. expect(json_response["status"]).to be_truthy
  156. expect(json_response["repository_path"]).to eq(project.repository.path_to_repo)
  157. end
  158. end
  159. context 'project as namespace/project' do
  160. it do
  161. pull(key, project_with_repo_path(project.path_with_namespace))
  162. expect(response).to have_http_status(200)
  163. expect(json_response["status"]).to be_truthy
  164. expect(json_response["repository_path"]).to eq(project.repository.path_to_repo)
  165. end
  166. end
  167. end
  168. end
  169. context "access denied" do
  170. before do
  171. project.team << [user, :guest]
  172. end
  173. context "git pull" do
  174. it do
  175. pull(key, project)
  176. expect(response).to have_http_status(200)
  177. expect(json_response["status"]).to be_falsey
  178. end
  179. end
  180. context "git push" do
  181. it do
  182. push(key, project)
  183. expect(response).to have_http_status(200)
  184. expect(json_response["status"]).to be_falsey
  185. end
  186. end
  187. end
  188. context "blocked user" do
  189. let(:personal_project) { create(:empty_project, namespace: user.namespace) }
  190. before do
  191. user.block
  192. end
  193. context "git pull" do
  194. it do
  195. pull(key, personal_project)
  196. expect(response).to have_http_status(200)
  197. expect(json_response["status"]).to be_falsey
  198. end
  199. end
  200. context "git push" do
  201. it do
  202. push(key, personal_project)
  203. expect(response).to have_http_status(200)
  204. expect(json_response["status"]).to be_falsey
  205. end
  206. end
  207. end
  208. context "archived project" do
  209. let(:personal_project) { create(:empty_project, namespace: user.namespace) }
  210. before do
  211. project.team << [user, :developer]
  212. project.archive!
  213. end
  214. context "git pull" do
  215. it do
  216. pull(key, project)
  217. expect(response).to have_http_status(200)
  218. expect(json_response["status"]).to be_truthy
  219. end
  220. end
  221. context "git push" do
  222. it do
  223. push(key, project)
  224. expect(response).to have_http_status(200)
  225. expect(json_response["status"]).to be_falsey
  226. end
  227. end
  228. end
  229. context "deploy key" do
  230. let(:key) { create(:deploy_key) }
  231. context "added to project" do
  232. before do
  233. key.projects << project
  234. end
  235. it do
  236. archive(key, project)
  237. expect(response).to have_http_status(200)
  238. expect(json_response["status"]).to be_truthy
  239. end
  240. end
  241. context "not added to project" do
  242. it do
  243. archive(key, project)
  244. expect(response).to have_http_status(200)
  245. expect(json_response["status"]).to be_falsey
  246. end
  247. end
  248. end
  249. context 'project does not exist' do
  250. it do
  251. pull(key, project_with_repo_path('gitlab/notexist'))
  252. expect(response).to have_http_status(200)
  253. expect(json_response["status"]).to be_falsey
  254. end
  255. end
  256. context 'user does not exist' do
  257. it do
  258. pull(OpenStruct.new(id: 0), project)
  259. expect(response).to have_http_status(200)
  260. expect(json_response["status"]).to be_falsey
  261. end
  262. end
  263. context 'ssh access has been disabled' do
  264. before do
  265. stub_application_setting(enabled_git_access_protocol: 'http')
  266. end
  267. it 'rejects the SSH push' do
  268. push(key, project)
  269. expect(response.status).to eq(200)
  270. expect(json_response['status']).to be_falsey
  271. expect(json_response['message']).to eq 'Git access over SSH is not allowed'
  272. end
  273. it 'rejects the SSH pull' do
  274. pull(key, project)
  275. expect(response.status).to eq(200)
  276. expect(json_response['status']).to be_falsey
  277. expect(json_response['message']).to eq 'Git access over SSH is not allowed'
  278. end
  279. end
  280. context 'http access has been disabled' do
  281. before do
  282. stub_application_setting(enabled_git_access_protocol: 'ssh')
  283. end
  284. it 'rejects the HTTP push' do
  285. push(key, project, 'http')
  286. expect(response.status).to eq(200)
  287. expect(json_response['status']).to be_falsey
  288. expect(json_response['message']).to eq 'Git access over HTTP is not allowed'
  289. end
  290. it 'rejects the HTTP pull' do
  291. pull(key, project, 'http')
  292. expect(response.status).to eq(200)
  293. expect(json_response['status']).to be_falsey
  294. expect(json_response['message']).to eq 'Git access over HTTP is not allowed'
  295. end
  296. end
  297. context 'web actions are always allowed' do
  298. it 'allows WEB push' do
  299. stub_application_setting(enabled_git_access_protocol: 'ssh')
  300. project.team << [user, :developer]
  301. push(key, project, 'web')
  302. expect(response.status).to eq(200)
  303. expect(json_response['status']).to be_truthy
  304. end
  305. end
  306. end
  307. describe 'GET /internal/merge_request_urls' do
  308. let(:repo_name) { "#{project.namespace.name}/#{project.path}" }
  309. let(:changes) { URI.escape("#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new_branch") }
  310. before do
  311. project.team << [user, :developer]
  312. get api("/internal/merge_request_urls?project=#{repo_name}&changes=#{changes}"), secret_token: secret_token
  313. end
  314. it 'returns link to create new merge request' do
  315. expect(json_response).to match [{
  316. "branch_name" => "new_branch",
  317. "url" => "http://#{Gitlab.config.gitlab.host}/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch",
  318. "new_merge_request" => true
  319. }]
  320. end
  321. end
  322. def project_with_repo_path(path)
  323. double().tap do |fake_project|
  324. allow(fake_project).to receive_message_chain('repository.path_to_repo' => path)
  325. end
  326. end
  327. def pull(key, project, protocol = 'ssh')
  328. post(
  329. api("/internal/allowed"),
  330. key_id: key.id,
  331. project: project.repository.path_to_repo,
  332. action: 'git-upload-pack',
  333. secret_token: secret_token,
  334. protocol: protocol
  335. )
  336. end
  337. def push(key, project, protocol = 'ssh')
  338. post(
  339. api("/internal/allowed"),
  340. changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master',
  341. key_id: key.id,
  342. project: project.repository.path_to_repo,
  343. action: 'git-receive-pack',
  344. secret_token: secret_token,
  345. protocol: protocol
  346. )
  347. end
  348. def archive(key, project)
  349. post(
  350. api("/internal/allowed"),
  351. ref: 'master',
  352. key_id: key.id,
  353. project: project.repository.path_to_repo,
  354. action: 'git-upload-archive',
  355. secret_token: secret_token,
  356. protocol: 'ssh'
  357. )
  358. end
  359. def lfs_auth(key_id, project)
  360. post(
  361. api("/internal/lfs_authenticate"),
  362. key_id: key_id,
  363. secret_token: secret_token,
  364. project: project.repository.path_to_repo
  365. )
  366. end
  367. end