Remove SslRequirement and associated logic
[gitorious:mainline.git] / test / functional / repositories_controller_test.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2012 Gitorious AS
4 #   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
5 #
6 #   This program is free software: you can redistribute it and/or modify
7 #   it under the terms of the GNU Affero General Public License as published by
8 #   the Free Software Foundation, either version 3 of the License, or
9 #   (at your option) any later version.
10 #
11 #   This program is distributed in the hope that it will be useful,
12 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #   GNU Affero General Public License for more details.
15 #
16 #   You should have received a copy of the GNU Affero General Public License
17 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #++
19
20 require "test_helper"
21
22 class RepositoriesControllerTest < ActionController::TestCase
23   def setup
24     GitoriousConfig["enable_private_repositories"] = false
25     setup_ssl_from_config
26     @project = projects(:johans)
27     @repo = repositories(:johans)
28     @grit = Grit::Repo.new(grit_test_repo("dot_git"), :is_bare => true)
29     Repository.any_instance.stubs(:git).returns(@grit)
30   end
31
32   should_render_in_site_specific_context :except => [:writable_by, :repository_config]
33
34   context "#index" do
35     setup do
36       @project = projects(:johans)
37     end
38
39     should "gets all the projects repositories" do
40       get :index, :project_id => @project.slug
41       assert_response :success
42       assert_equal @project.repositories, assigns(:repositories)
43     end
44
45     should "render xml if requested" do
46       get :index, :project_id => @project.slug, :format => "xml"
47       assert_response :success
48     end
49
50     context "paginating repositories" do
51       setup { @params = { :project_id => @project.slug } }
52       should_scope_pagination_to(:index, Repository)
53     end
54  end
55
56   context "Searching" do
57     setup do
58       @project = projects(:johans)
59     end
60
61     should "render repositories matching a search term" do
62       get :index, :project_id => @project.to_param, :filter => "clone", :format => "json"
63       assert_response :success
64       assert_equal([repositories(:johans2)], assigns(:repositories))
65     end
66   end
67
68   context "showing a user namespaced repo" do
69     setup do
70       @user = users(:johan)
71       @project = projects(:johans)
72     end
73
74     should "GET users/johan/repositories/foo is successful" do
75       repo = @user.repositories.first
76       repo.stubs(:git).returns(stub_everything("git mock"))
77       get :show, :user_id => @user.to_param, :project_id => repo.project.to_param,
78         :id => repo.to_param
79       assert_response :success
80       assert_equal @user, assigns(:owner)
81     end
82
83     should "set the correct atom feed discovery url" do
84       repo = @user.repositories.first
85       repo.kind = Repository::KIND_USER_REPO
86       repo.owner = @user
87       repo.save!
88       repo.stubs(:git).returns(stub_everything("git mock"))
89
90       get :show, {
91         :user_id => @user.to_param,
92         :project_id => repo.project.to_param,
93         :id => repo.to_param
94       }
95
96       assert_response :success
97       atom_url = project_repository_path(repo.project, repo, :format => :atom)
98       assert_equal atom_url, assigns(:atom_auto_discovery_url)
99     end
100
101     should "find the correct owner for clone, if the project is owned by someone else" do
102       clone_repo = @project.repositories.clones.first
103       clone_repo.owner = users(:moe)
104       clone_repo.save!
105       clone_repo.stubs(:git).returns(stub_everything("git mock"))
106
107       get :show, :user_id => users(:moe).to_param,
108         :project_id => clone_repo.project.to_param, :id => clone_repo.to_param
109       assert_response :success
110       assert_equal clone_repo, assigns(:repository)
111       assert_equal users(:moe), assigns(:owner)
112     end
113
114     should "find the correct repository, even if the repo is named similar to another one in another project" do
115       repo_clone = Repository.new_by_cloning(repositories(:moes), users(:johan).login)
116       repo_clone.owner = users(:johan)
117       repo_clone.user = users(:johan)
118       repo_clone.name = "johansprojectrepos"
119       repo_clone.save!
120
121       get :show, :user_id => users(:johan).to_param,
122         :project_id => projects(:moes).to_param, :id => repo_clone.to_param
123       assert_response :success
124       assert_equal users(:johan), assigns(:owner)
125       assert_equal repo_clone, assigns(:repository)
126     end
127
128     should "find the project repository" do
129       get :show, :project_id => repositories(:johans).project.to_param,
130         :id => repositories(:johans).to_param
131       assert_response :success
132       assert_equal repositories(:johans).project, assigns(:owner)
133       assert_equal repositories(:johans), assigns(:repository)
134     end
135
136     context "paginating repository events" do
137       setup do
138         @params = {
139           :project_id => repositories(:johans).project.to_param,
140           :id => repositories(:johans).to_param
141         }
142       end
143
144       should_scope_pagination_to(:show, Event)
145     end
146   end
147
148   context "showing a team namespaced repo" do
149     setup do
150       @group = groups(:team_thunderbird)
151     end
152
153     should "GET teams/foo/repositories/bar is successful" do
154       repo = @group.repositories.first
155       repo.stubs(:git).returns(stub_everything("git mock"))
156       get :show, :project_id => repo.project.to_param,
157         :group_id => @group.to_param, :id => repo.to_param
158       assert_response :success
159       assert_equal @group, assigns(:owner)
160     end
161   end
162
163   def do_show_get(repos)
164     get :show, :project_id => @project.slug, :id => repos.name
165   end
166
167   context "#show" do
168     setup do
169       @project = projects(:johans)
170       @repo = @project.repositories.mainlines.first
171     end
172
173     should "GET projects/1/repositories/1 is successful" do
174       @repo.stubs(:git).returns(stub_everything("git mock"))
175       do_show_get @repo
176       assert_response :success
177     end
178
179     should "scopes GET :show to the project_id" do
180       repo = repositories(:moes)
181       repo.stubs(:git).returns(stub_everything("git mock"))
182       do_show_get repo
183       assert_response 404
184     end
185
186     should "issues a Refresh header if repo is not ready yet" do
187       @repo.stubs(:ready).returns(false)
188       do_show_get @repo
189       assert_response :success
190       assert_not_nil @response.headers["Refresh"]
191     end
192   end
193
194   context "#show as XML" do
195
196     setup do
197       @project = projects(:johans)
198     end
199
200     should "GET projects/1/repositories/1.xml is successful" do
201       repo = @project.repositories.mainlines.first
202       repo.stubs(:has_commits?).returns(false)
203       repo.stubs(:git).returns(stub_everything("git mock"))
204       get :show, :project_id => @project.to_param, :id => repo.to_param, :format => "xml"
205       assert_response :success
206       assert_equal repo.to_xml, @response.body
207     end
208   end
209
210   def do_clone_get()
211     get :clone, :project_id => @project.slug, :id => @repository.name
212   end
213
214   context "#clone" do
215     setup do
216       login_as :johan
217       @project = projects(:johans)
218       @repository = @project.repositories.mainlines.first
219     end
220
221     should "require login" do
222       session[:user_id] = nil
223       do_clone_get
224       assert_redirected_to(new_sessions_path)
225     end
226
227     should "GET projects/1/repositories/3/clone is successful" do
228       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
229       @repository.stubs(:has_commits?).returns(true)
230       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
231       do_clone_get
232       assert_equal nil, flash[:error]
233       assert_response :success
234       assert_equal @repository, assigns(:repository_to_clone)
235       assert_instance_of Repository, assigns(:repository)
236       assert_equal "johans-johansprojectrepos", assigns(:repository).name
237     end
238
239     should "redirects to new_account_key_path if no keys on user" do
240       users(:johan).ssh_keys.destroy_all
241       login_as :johan
242       do_clone_get
243       assert_redirected_to(new_user_key_path(users(:johan)))
244     end
245
246     should "redirects with a flash if repos cannot be cloned" do
247       login_as :johan
248       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
249       @repository.stubs(:has_commits?).returns(false)
250       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
251       do_clone_get
252       assert_redirected_to(project_repository_path(@project, @repository))
253       assert_match(/cannot clone an empty/i, flash[:error])
254     end
255   end
256
257   def do_create_clone_post(opts={})
258     post(:create_clone, :project_id => @project.slug, :id => @repository.name,
259       :repository => {:owner_type => "User"}.merge(opts))
260   end
261
262   context "#create_clone" do
263     setup do
264       login_as :johan
265       @project = projects(:johans)
266       @repository = @project.repositories.mainlines.first
267     end
268
269     should "require login" do
270       session[:user_id] = nil
271       do_create_clone_post
272       assert_redirected_to(new_sessions_path)
273     end
274
275     should "post projects/1/repositories/3/create_clone is successful" do
276       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
277       @repository.stubs(:has_commits?).returns(true)
278       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
279       do_create_clone_post(:name => "foo-clone")
280       assert_response :redirect
281     end
282
283     should "post projects/1/repositories/3/create_clone is successful sets the owner to the user" do
284       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
285       @repository.stubs(:has_commits?).returns(true)
286       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
287       do_create_clone_post(:name => "foo-clone", :owner_type => "User")
288       assert_response :redirect
289       assert_equal users(:johan), assigns(:repository).owner
290       assert_equal Repository::KIND_USER_REPO, assigns(:repository).kind
291     end
292
293     should "post projects/1/repositories/3/create_clone is successful sets the owner to the group" do
294       groups(:team_thunderbird).add_member(users(:johan), Role.admin)
295       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
296       @repository.stubs(:has_commits?).returns(true)
297       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
298       do_create_clone_post(:name => "foo-clone", :owner_type => "Group", :owner_id => groups(:team_thunderbird).id)
299       assert_response :redirect
300       assert_equal groups(:team_thunderbird), assigns(:repository).owner
301       assert_equal Repository::KIND_TEAM_REPO, assigns(:repository).kind
302     end
303
304     should "redirects to new_user_key_path if no keys on user" do
305       users(:johan).ssh_keys.destroy_all
306       login_as :johan
307       do_create_clone_post
308       assert_redirected_to(new_user_key_path(users(:johan)))
309     end
310
311     should "redirects with a flash if repos cannot be cloned" do
312       login_as :johan
313       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
314       @repository.stubs(:has_commits?).returns(false)
315       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
316       do_create_clone_post(:name => "foobar")
317       assert_redirected_to(project_repository_path(@project, @repository))
318       assert_match(/cannot clone an empty/i, flash[:error])
319     end
320   end
321
322   context "#create_clone as XML" do
323
324     setup do
325       authorize_as :johan
326       @project = projects(:johans)
327       @repository = @project.repositories.mainlines.first
328       @request.env["HTTP_ACCEPT"] = "application/xml"
329     end
330
331     should "require login" do
332       authorize_as(nil)
333       do_create_clone_post(:name => "foo")
334       assert_response 401
335     end
336
337     should "post projects/1/repositories/3/create_copy is successful" do
338       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
339       @repository.stubs(:has_commits?).returns(true)
340       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
341       do_create_clone_post(:name => "foo-clone")
342       assert_response 201
343     end
344
345     should "renders text if repos cannot be cloned" do
346       Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
347       @repository.stubs(:has_commits?).returns(false)
348       @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
349       do_create_clone_post(:name => "foobar")
350       assert_response 422
351       assert_match(/cannot clone an empty/i, @response.body)
352     end
353   end
354
355   def do_writable_by_get(options={})
356     post(:writable_by, {:project_id => @project.slug, :id => @repository.name,
357       :username => "johan"}.merge(options))
358   end
359
360   context "#writable_by" do
361     setup do
362       login_as :johan
363       @project = projects(:johans)
364       @repository = @project.repositories.mainlines.first
365     end
366
367     should "not require login" do
368       session[:user_id] = nil
369       do_writable_by_get :username => "johan"
370       assert_response :success
371     end
372
373     should "get projects/1/repositories/3/writable_by?username=johan is true" do
374       do_writable_by_get :username => "johan"
375       assert_response :success
376       assert_equal "true", @response.body
377     end
378
379     should "get projects/1/repositories/2/writable_by?username=johan is false" do
380       do_writable_by_get :username => "johan", :project_id => projects(:moes).slug,
381         :id => projects(:moes).repositories.first.name
382       assert_response :success
383       assert_equal "false", @response.body
384     end
385
386     should "get projects/1/repositories/2/writable_by?username=nonexistinguser is false" do
387       do_writable_by_get :username => "nonexistinguser"
388       assert_response :success
389       assert_equal "false", @response.body
390     end
391
392     should "finds the repository in the whole project realm, if the (url) root is a project" do
393       # in case someone changes a mainline to be owned by a group
394       assert_equal @project, repositories(:johans2).project
395       do_writable_by_get :id => repositories(:johans2).to_param
396       assert_response :success
397       assert_equal @project, assigns(:project)
398       assert_equal repositories(:johans2), assigns(:repository)
399     end
400
401     should "scope to the correc project" do
402       repo_clone = Repository.new_by_cloning(repositories(:moes), users(:johan).login)
403       repo_clone.owner = users(:johan)
404       repo_clone.user = users(:johan)
405       repo_clone.name = "johansprojectrepos"
406       repo_clone.save!
407
408       do_writable_by_get({
409         :user_id => users(:johan).to_param,
410         :project_id => projects(:moes).to_param,
411         :id => repo_clone.to_param,
412       })
413       assert_response :success
414       assert_nil assigns(:project)
415       assert_equal repo_clone.project, assigns(:containing_project)
416       assert_equal repo_clone, assigns(:repository)
417     end
418
419     should "not require any particular subdomain (if Project belongs_to a site)" do
420       project = projects(:johans)
421       assert_not_nil project.site
422       do_writable_by_get :project_id => project.to_param,
423         :id => project.repositories.mainlines.first.to_param
424       assert_response :success
425     end
426
427     should "not identify a non-merge request git path as a merge request" do
428       do_writable_by_get({
429         :git_path => "refs/heads/master"})
430       assert_response :success
431       assert_equal "true", @response.body
432     end
433
434     should "identify that a merge request is being pushed to" do
435       @merge_request = merge_requests(:mikes_to_johans)
436       assert !can_push?(@merge_request.user, @merge_request.target_repository)
437       do_writable_by_get({
438         :username => @merge_request.user.to_param,
439         :project_id => @merge_request.target_repository.project.to_param,
440         :id => @merge_request.target_repository.to_param,
441         :git_path => "refs/merge-requests/#{@merge_request.to_param}"})
442       assert_response :success
443       assert_equal "true", @response.body
444     end
445
446     should "not allow other users than the owner of a merge request push to a merge request" do
447       @merge_request = merge_requests(:mikes_to_johans)
448       do_writable_by_get({
449         :username => "johan",
450         :project_id => @merge_request.target_repository.project.to_param,
451         :id => @merge_request.target_repository.to_param,
452         :git_path => "refs/merge-requests/#{@merge_request.to_param}"})
453       assert_response :success
454       assert_equal "false", @response.body
455     end
456
457     should "not allow pushes to non-existing merge requests" do
458       @merge_request = merge_requests(:mikes_to_johans)
459       do_writable_by_get({
460         :username => "johan",
461         :project_id => @merge_request.target_repository.project.to_param,
462         :id => @merge_request.target_repository.to_param,
463         :git_path => "refs/merge-requests/42"})
464       assert_response :success
465       assert_equal "false", @response.body
466     end
467
468
469     should "allow pushing to wiki repositories" do
470       project = projects(:johans)
471       wiki = project.wiki_repository
472       user = users(:johan)
473       do_writable_by_get(:id => wiki.to_param)
474       assert_response :success
475     end
476   end
477
478   def do_config_get(options={})
479     get(:repository_config, {:project_id => @project.slug, :id => @repository.name}.merge(options))
480   end
481
482   context "#config" do
483     setup do
484       login_as :johan
485       @project = projects(:johans)
486       @repository = @project.repositories.mainlines.first
487     end
488
489     should "not require login" do
490       session[:user_id] = nil
491       do_config_get
492       assert_response :success
493     end
494
495     should "get projects/1/repositories/3/config is true" do
496       do_config_get
497       assert_response :success
498       exp = "real_path:#{@repository.real_gitdir}\nforce_pushing_denied:false"
499       assert_equal exp, @response.body
500     end
501
502     should "expose the wiki repository" do
503       wiki = @project.wiki_repository
504       assert_not_nil wiki
505       do_config_get(:id => wiki.to_param)
506       expected = "real_path:#{wiki.real_gitdir}\nforce_pushing_denied:false"
507       assert_equal expected, @response.body
508     end
509
510     should "not use a session cookie" do
511       do_config_get
512
513       assert_nil @response.headers["Set-Cookie"]
514     end
515
516     should "send cache friendly headers" do
517       do_config_get
518
519       assert_equal "public, max-age=600", @response.headers["Cache-Control"]
520     end
521   end
522
523   def do_delete(repos)
524     delete :destroy, :project_id => @project.slug, :id => repos.name
525   end
526
527   context "#destroy" do
528     setup do
529       @project = projects(:johans)
530       @repo = @project.repositories.first
531       assert admin?(users(:johan), @repo)
532       login_as :johan
533     end
534
535     should "require login" do
536       session[:user_id] = nil
537       do_delete(@repo)
538       assert_redirected_to(new_sessions_path)
539     end
540
541     should "can only be deleted by the admins" do
542       login_as :mike
543       assert !admin?(users(:mike), @repo)
544       do_delete(@repo)
545       assert_redirected_to([@project, @repo])
546       assert_match(/only repository admins are allowed/i, flash[:error])
547     end
548
549     should "the owner can delete his own repos" do
550       repo = repositories(:johans2)
551       repo.user = users(:johan)
552       repo.save!
553       repo.committerships.create_with_permissions!({
554           :committer => users(:johan)
555         }, (Committership::CAN_ADMIN | Committership::CAN_COMMIT))
556       assert admin?(users(:johan), repo.reload)
557       delete :destroy, :project_id => repo.project.to_param,
558         :group_id => repo.owner.to_param, :id => repo.to_param
559       assert_equal nil, flash[:error]
560       assert_equal "The repository was deleted", flash[:notice]
561       assert_redirected_to(group_path(repo.owner))
562     end
563
564     should "destroying a project creates an event in the project" do
565       assert_difference("@project.events.count") do
566         do_delete(@repo)
567         assert_response :redirect
568         assert_nil flash[:error]
569       end
570     end
571
572     should "work for user/group clones" do
573       repo = repositories(:johans2)
574       repo.user = users(:mike)
575       repo.committerships.create_with_permissions!({
576           :committer => users(:mike)
577         }, (Committership::CAN_ADMIN | Committership::CAN_COMMIT))
578       repo.save!
579       login_as :mike
580       get :confirm_delete, :group_id => repo.owner.to_param,
581         :project_id => repo.project.to_param, :id => repo.to_param
582       assert_response :success
583       assert_template "confirm_delete"
584     end
585   end
586
587   context "new / create" do
588     setup do
589       @project = projects(:johans)
590       @user = users(:johan)
591       @group = groups(:team_thunderbird)
592       @group.add_member(@user, Role.admin)
593       login_as :johan
594     end
595
596     should "require login" do
597       logout
598       get :new, :project_id => @project.to_param
599       assert_redirected_to(new_sessions_path)
600     end
601
602     should "require adminship" do
603       login_as :moe
604       get :new, :project_id => @project.to_param
605       assert_match(/only repository admins are allowed/, flash[:error])
606       assert_redirected_to(project_path(@project))
607
608       post :create, :project_id => @project.to_param, :repository => {}
609       assert_match(/only repository admins are allowed/, flash[:error])
610       assert_redirected_to(project_path(@project))
611     end
612
613     should "only be allowed to add new repositories to Project" do
614       get :new, :project_id => @project.to_param, :group_id => @group.to_param
615       assert_match(/can only add new repositories directly to a project/, flash[:error])
616       assert_redirected_to(group_path(@group))
617
618       get :new, :project_id => @project.to_param, :user_id => @user.to_param
619       assert_match(/can only add new repositories directly to a project/, flash[:error])
620       assert_redirected_to(user_path(@user))
621
622       post :create, :project_id => @project.to_param, :group_id => @group.to_param, :repository => {}
623       assert_match(/can only add new repositories directly to a project/, flash[:error])
624       assert_redirected_to(group_path(@group))
625
626       post :create, :project_id => @project.to_param, :user_id => @user.to_param, :repository => {}
627       assert_match(/can only add new repositories directly to a project/, flash[:error])
628       assert_redirected_to(user_path(@user))
629     end
630
631     should "GET new successfully, and set the owner to a project" do
632       get :new, :project_id => @project.to_param
633       assert_response :success
634       assert_equal @project, assigns(:owner)
635     end
636
637     should "creates a new repository belonging to a Project" do
638       assert_difference("Repository.count") do
639         post :create, :project_id => @project.to_param, :repository => {:name => "my-new-repo"}
640       end
641       assert_equal @project.owner, assigns(:repository).owner
642       assert_equal Repository::KIND_PROJECT_REPO, assigns(:repository).kind
643       assert_response :redirect
644       assert_redirected_to(project_repository_path(@project, assigns(:repository)))
645     end
646
647     should "respect the creator's choice of merge requests or not" do
648       post :create, :project_id => @project.to_param, :repository => {
649         :name => "mine"
650       }
651       assert_not_nil repo = assigns(:repository)
652       assert !repo.merge_requests_enabled?
653       post :create, :project_id => @project.to_param, :repository => {
654         :name => "mine",
655         :merge_requests_enabled => "1"
656       }
657       assert_not_nil repo = assigns(:repository)
658       assert repo.merge_requests_enabled?
659     end
660   end
661
662   context "edit / update" do
663     setup do
664       @project = projects(:johans)
665       @repository = @project.repositories.mainlines.first
666       login_as :johan
667     end
668
669     should "requires login" do
670       logout
671       get :edit, :project_id => @project.to_param, :id => @repository.to_param
672       assert_redirected_to(new_sessions_path)
673
674       put :update, :project_id => @project.to_param, :id => @repository.to_param
675       assert_redirected_to(new_sessions_path)
676     end
677
678     should "requires adminship on the project if owner is a project" do
679       login_as :moe
680       get :edit, :project_id => @project.to_param, :id => @repository.to_param
681       assert_match(/only repository admins are allowed/, flash[:error])
682       assert_response :redirect
683     end
684
685     should "requires adminship on the user if owner is a user" do
686       login_as :moe
687       @repository.owner = users(:moe)
688       @repository.kind = Repository::KIND_USER_REPO
689       @repository.committerships.create_with_permissions!({
690           :committer => users(:moe)
691         }, Committership::CAN_ADMIN)
692       @repository.save!
693
694       get :edit, {
695         :project_id => @project.to_param,
696         :user_id => users(:moe).to_param,
697         :id => @repository.to_param
698       }
699
700       assert_response :success
701     end
702
703     should "requires adminship on the repo" do
704       login_as :mike
705       @repository.committerships.create_with_permissions!({
706           :committer => groups(:team_thunderbird)
707         }, Committership::CAN_ADMIN)
708       @repository.kind = Repository::KIND_TEAM_REPO
709       @repository.owner = groups(:team_thunderbird)
710       @repository.save!
711       assert admin?(users(:mike), @repository)
712       get :edit, :project_id => @repository.project.to_param,
713         :group_id => groups(:team_thunderbird).to_param, :id => @repository.to_param
714       assert_response :success
715     end
716
717     should "GETs edit/n successfully" do
718       get :edit, :project_id => @project.to_param, :id => @repository.to_param
719       assert_response :success
720       assert_equal @repository, assigns(:repository)
721       assert_equal @grit.heads, assigns(:heads)
722     end
723
724     should "PUT update successfully and creates an event when changing the description" do
725       assert_incremented_by(@repository.events, :size, 1) do
726         put :update, :project_id => @project.to_param, :id => @repository.to_param,
727           :repository => {:description => "blablabla"}
728         @repository.events.reload
729       end
730       assert_redirected_to(project_repository_path(@project, @repository))
731       assert_equal "blablabla", @repository.reload.description
732     end
733
734     should "be able to remove the repository description" do
735       @repository.update_attribute(:description, "blabla bla")
736       put :update, :project_id => @project.to_param, :id => @repository.to_param,
737         :repository => {:description => ""}
738       assert @repository.reload.description.blank?,
739         "descr: #{@repository.description.inspect}"
740     end
741
742     should "update the repository name and create an event if a new name is provided" do
743       description = @repository.description
744       assert_incremented_by(@repository.events, :size, 1) do
745         put :update, :project_id => @project.to_param, :id => @repository.to_param,
746           :repository => {:name => "new_name"}
747         @repository.events.reload
748         @repository.reload
749         assert_redirected_to project_repository_path(@project, @repository)
750       end
751       assert_equal "new_name", @repository.name
752       assert_equal description, @repository.description
753     end
754
755
756     should "not create an event on update if the description is not changed" do
757       assert_no_difference("@repository.events.size") do
758         put :update, :project_id => @project.to_param, :id => @repository.to_param,
759           :repository => {:description => @repository.description}
760         @repository.events.reload
761       end
762     end
763
764     should "gets a list of the users' groups on edit" do
765       groups(:team_thunderbird).add_member(users(:johan), Role.admin)
766       get :edit, :project_id => @project.to_param, :id => @repository.to_param
767       assert_response :success
768       assert_equal users(:johan).groups, assigns(:groups)
769     end
770
771     should "gets a list of the users' groups on update" do
772       groups(:team_thunderbird).add_member(users(:johan), Role.admin)
773       put :update, :project_id => @project.to_param, :id => @repository.to_param,
774             :repository => {:description => "foo"}
775       assert_equal users(:johan).groups, assigns(:groups)
776     end
777
778     should "changes the owner" do
779       group = groups(:team_thunderbird)
780       group.add_member(users(:johan), Role.admin)
781       put :update, :project_id => @project.to_param, :id => @repository.to_param,
782       :repository => { :owner_id => group.id}
783       assert_redirected_to(project_repository_path(@repository.project, @repository))
784       assert_equal group, @repository.reload.owner
785     end
786
787     should "changes the owner, only if the original owner was a user" do
788       group = groups(:team_thunderbird)
789       group.add_member(users(:johan), Role.admin)
790       @repository.owner = group
791       @repository.kind = Repository::KIND_TEAM_REPO
792       @repository.save!
793       new_group = Group.create!(:name => "temp")
794       new_group.add_member(users(:johan), Role.admin)
795
796       put :update, :project_id => @repository.project.to_param,
797         :group_id => group.to_param, :id => @repository.to_param, :repository => {
798           :owner_id => new_group.id
799         }
800       assert_response :redirect
801       assert_redirected_to(project_repository_path(@project, @repository))
802       assert_equal group, @repository.reload.owner
803     end
804
805     should "be able to deny force pushing" do
806       @repository.update_attribute(:deny_force_pushing, false)
807       put :update, :project_id => @repository.project.to_param, :id => @repository.to_param,
808         :repository => { :deny_force_pushing => true }
809       assert_response :redirect
810       assert @repository.reload.deny_force_pushing?
811     end
812
813     should "be able to disable merge requests" do
814       @repository.update_attribute(:merge_requests_enabled, true)
815       put :update, :project_id => @repository.project.to_param, :id => @repository.to_param,
816         :repository => {}
817       assert_response :redirect
818       assert !@repository.reload.merge_requests_enabled?
819       put :update, :project_id => @repository.project.to_param, :id => @repository.to_param,
820         :repository => {:merge_requests_enabled => 1}
821       assert_response :redirect
822       assert @repository.reload.merge_requests_enabled?
823     end
824
825     should "be able to turn off notify_committers_on_new_merge_request" do
826       @repository.update_attribute(:notify_committers_on_new_merge_request, true)
827       put :update, :project_id => @repository.project.to_param, :id => @repository.to_param,
828         :repository => { :notify_committers_on_new_merge_request => false }
829       assert_response :redirect
830       assert !@repository.reload.notify_committers_on_new_merge_request?
831     end
832
833     context "Changing the HEAD" do
834       should "update the HEAD if it is changed" do
835         the_head = @grit.get_head("test/master")
836         @grit.expects(:update_head).with(the_head).returns(true)
837         put :update, :project_id => @project.to_param, :id => @repository.to_param,
838               :repository => { :head => the_head.name }
839         assert_equal @grit.heads, assigns(:heads)
840       end
841     end
842   end
843
844   context "with committer (not owner) logged in" do
845     should "GET projects/1/repositories/3 and have merge request link" do
846       login_as :mike
847       project = projects(:johans)
848       repository = project.repositories.clones.first
849       committership = repository.committerships.new
850       committership.committer = users(:mike)
851       committership.permissions = Committership::CAN_REVIEW | Committership::CAN_COMMIT
852       committership.save!
853
854       Project.expects(:find_by_slug!).with(project.slug).returns(project)
855       repository.stubs(:has_commits?).returns(true)
856
857       get :show, :project_id => project.to_param, :id => repository.to_param
858       assert_equal nil, flash[:error]
859       assert_select("#sidebar ul.links li a[href=?]",
860         new_project_repository_merge_request_path(project, repository),
861         :content => "Request merge")
862     end
863   end
864
865   context "search clones" do
866     setup do
867       @repo = repositories(:johans)
868       @clone_repo = repositories(:johans2)
869     end
870
871     should "return a list of clones matching the query" do
872       get :search_clones, :project_id => @repo.project.to_param, :id => @repo.to_param,
873         :filter => "projectrepos", :format => "json"
874       assert_response :success
875       assert assigns(:repositories).include?(@clone_repo)
876     end
877   end
878
879   context "when hiding git:// URLs" do
880     setup do
881       @hide_setting = GitoriousConfig["hide_git_clone_urls"]
882       GitoriousConfig["hide_git_clone_urls"] = true
883     end
884
885     teardown do
886       GitoriousConfig["hide_git_clone_urls"] = @hide_setting
887     end
888
889     should "not display git:// link" do
890       project = projects(:johans)
891       repository = project.repositories.mainlines.first
892       repository.update_attribute(:ready, true)
893
894       get :show, :project_id => project.to_param, :id => repository.to_param
895
896       assert_no_match(/git:\/\//, @response.body)
897     end
898   end
899
900   context "With private projects" do
901     setup do
902       enable_private_repositories
903       @group = groups(:team_thunderbird)
904       @repository = @project.repositories.first
905     end
906
907     should "disallow unauthorized users to get project repositories" do
908       get :index, :project_id => @project.to_param
909       assert_response 403
910     end
911
912     should "disallow unauthorized users to get group repositories" do
913       get :index, :group_id => @group.to_param, :project_id => @project.to_param
914       assert_response 403
915     end
916
917     should "disallow unauthorized users to get user repositories" do
918       get :index, :user_id => users(:johan).to_param, :project_id => @project.to_param
919       assert_response 403
920     end
921
922     should "allow authorize users to get project repositories" do
923       login_as :johan
924       get :index, :project_id => @project.to_param
925       assert_response 200
926     end
927
928     should "allow authorize users to get group repositories" do
929       login_as :johan
930       get :index, :group_id => @group.to_param, :project_id => @project.to_param
931       assert_response 200
932     end
933
934     should "allow authorize users to get user repositories" do
935       login_as :johan
936       get :index, :user_id => users(:johan).to_param, :project_id => @project.to_param
937       assert_response 200
938     end
939
940     should "disallow unauthorized users to show repository" do
941       get :show, :project_id => @project.to_param, :id => @repository.to_param
942       assert_response 403
943     end
944
945     should "allow authorized users to get show repository" do
946       login_as :johan
947       get :show, :project_id => @project.to_param, :id => @repository.to_param
948       assert_response 200
949     end
950
951     should "disallow unauthorized users to get new" do
952       login_as :mike
953       get :new, :project_id => @project.to_param
954       assert_response 403
955     end
956
957     should "allow authorized users to get new" do
958       login_as :johan
959       get :new, :project_id => @project.to_param
960       assert_response 200
961     end
962
963     should "disallow unauthorized users to create repository" do
964       login_as :mike
965       post :create, :project_id => @project.to_param, :repository => {}
966       assert_response 403
967     end
968
969     should "allow authorized users to create repository" do
970       login_as :johan
971       post :create, :project_id => @project.to_param, :repository => {}
972       assert_response 200
973     end
974
975     should "disallow unauthenticated users to clone repo" do
976       login_as :mike
977       do_clone_get
978       assert_response 403
979     end
980
981     should "allow authenticated users to clone repo" do
982       login_as :johan
983       do_clone_get
984       assert_response 302
985     end
986
987     should "disallow unauthorized users to create clones" do
988       login_as :mike
989       do_create_clone_post(:name => "foo-clone")
990       assert_response 403
991     end
992
993     should "allow authorized users to create clones" do
994       login_as :johan
995       do_create_clone_post(:name => "foo-clone")
996       assert_response 302
997     end
998
999     should "disallow unauthorized user to edit repository" do
1000       login_as :mike
1001       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1002       assert_response 403
1003     end
1004
1005     should "allow authorized user to edit repository" do
1006       login_as :johan
1007       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1008       assert_response 200
1009     end
1010
1011     should "disallow unauthorized users to search clones" do
1012       get :search_clones, :project_id => @project.to_param, :id => @repository.to_param,
1013         :filter => "projectrepos", :format => "json"
1014       assert_response 403
1015     end
1016
1017     should "allow authorized users to search clones" do
1018       login_as :johan
1019       get :search_clones, :project_id => @project.to_param, :id => @repository.to_param,
1020         :filter => "projectrepos", :format => "json"
1021       assert_response 200
1022     end
1023
1024     should "disallow unauthorized user to update repository" do
1025       login_as :mike
1026       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1027       assert_response 403
1028     end
1029
1030     should "allow authorized user to update repository" do
1031       login_as :johan
1032       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1033       assert_response 200
1034     end
1035
1036     should "not disallow writable_by? action" do
1037       do_writable_by_get :username => "mike"
1038       assert_response :success
1039       assert_equal "false", @response.body
1040     end
1041
1042     should "allow owner to write to repo" do
1043       do_writable_by_get :username => "johan"
1044       assert_response :success
1045       assert_equal "true", @response.body
1046     end
1047
1048     should "disallow unauthorized user to access repository configuration" do
1049       do_config_get(:username => "mike")
1050       assert_response 403
1051     end
1052
1053     should "disallow anonymous user to access repository configuration" do
1054       do_config_get
1055       assert_response 403
1056     end
1057
1058     should "allow authorized user to access repository configuration" do
1059       do_config_get(:username => "johan")
1060       assert_response 200
1061     end
1062
1063     should "disallow unauthorized user to confirm deletion" do
1064       login_as :mike
1065       get :confirm_delete, :project_id => @project.to_param, :id => @repository.to_param
1066       assert_response 403
1067     end
1068
1069     should "allow authorized user to confirm deletion" do
1070       login_as :johan
1071       get :confirm_delete, :project_id => @project.to_param, :id => @repository.to_param
1072       assert_response 200
1073     end
1074
1075     should "disallow unauthorized user to destroy repository" do
1076       login_as :mike
1077       do_delete @repository
1078       assert_response 403
1079     end
1080
1081     should "allow authorized user to destroy repository" do
1082       login_as :johan
1083       do_delete @repository
1084       assert_response 302
1085     end
1086   end
1087
1088   context "With private repositories" do
1089     setup do
1090       enable_private_repositories(@repo)
1091       @group = groups(:team_thunderbird)
1092       @repository = @project.repositories.first
1093     end
1094
1095     teardown do
1096       user = users(:mike)
1097       user.is_admin = false
1098       user.save
1099     end
1100
1101     should "exclude private repositories in project" do
1102       get :index, :project_id => @project.to_param
1103       assert_equal 1, assigns(:repositories).length
1104     end
1105
1106     should "exclude filtered private repositories in project" do
1107       get :index, :project_id => @project.to_param, :filter => "o", :format => "json"
1108       assert_equal 1, assigns(:repositories).length
1109     end
1110
1111     should "exclude private repositories in group" do
1112       Repository.all.each { |r| r.make_private }
1113       get :index, :group_id => @group.to_param, :project_id => @project.to_param
1114       assert_equal 0, assigns(:repositories).length
1115     end
1116
1117     should "exclude private repositories in user" do
1118       get :index, :user_id => users(:johan).to_param, :project_id => @project.to_param
1119       assert_equal 1, assigns(:repositories).length
1120     end
1121
1122     should "include authorized private repositories in project" do
1123       login_as :johan
1124       get :index, :project_id => @project.to_param
1125       assert_equal 2, assigns(:repositories).length
1126     end
1127
1128     should "include authorized private repositories in group" do
1129       login_as :johan
1130       get :index, :group_id => @group.to_param, :project_id => @project.to_param
1131       assert_equal 1, assigns(:repositories).length
1132     end
1133
1134     should "include authorized private repositories in user" do
1135       login_as :johan
1136       get :index, :user_id => users(:johan).to_param, :project_id => @project.to_param
1137       assert_equal 2, assigns(:repositories).length
1138     end
1139
1140     should "disallow unauthorized users to show repository" do
1141       get :show, :project_id => @project.to_param, :id => @repository.to_param
1142       assert_response 403
1143     end
1144
1145     should "allow authorized users to get show repository" do
1146       login_as :johan
1147       get :show, :project_id => @project.to_param, :id => @repository.to_param
1148       assert_response 200
1149     end
1150
1151     should "allow site admin to get show repository" do
1152       user = users(:mike)
1153       user.is_admin = true
1154       user.save
1155       login_as :mike
1156       get :show, :project_id => @project.to_param, :id => @repository.to_param
1157       assert_response 200
1158     end
1159
1160     should "disallow unauthenticated users to clone repo" do
1161       login_as :mike
1162       do_clone_get
1163       assert_response 403
1164     end
1165
1166     should "allow authenticated users to clone repo" do
1167       login_as :johan
1168       do_clone_get
1169       assert_response 302
1170     end
1171
1172     should "disallow unauthorized users to create clones" do
1173       login_as :mike
1174       do_create_clone_post(:name => "foo-clone")
1175       assert_response 403
1176     end
1177
1178     should "allow authorized users to create clones" do
1179       login_as :johan
1180       do_create_clone_post(:name => "foo-clone")
1181       assert_response 302
1182     end
1183
1184     should "disallow unauthorized user to edit repository" do
1185       login_as :mike
1186       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1187       assert_response 403
1188     end
1189
1190     should "allow authorized user to edit repository" do
1191       login_as :johan
1192       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1193       assert_response 200
1194     end
1195
1196     should "disallow unauthorized users to search clones" do
1197       get :search_clones, :project_id => @project.to_param, :id => @repository.to_param,
1198         :filter => "projectrepos", :format => "json"
1199       assert_response 403
1200     end
1201
1202     should "exclude private repositories when searching clones" do
1203       @repository.make_public
1204       @repository.clones.each(&:make_private)
1205       get :search_clones, :project_id => @project.to_param, :id => @repository.to_param,
1206         :filter => "projectrepos", :format => "json"
1207       assert_equal 0, assigns(:repositories).length
1208     end
1209
1210     should "allow authorized users to search clones" do
1211       login_as :johan
1212       get :search_clones, :project_id => @project.to_param, :id => @repository.to_param,
1213         :filter => "projectrepos", :format => "json"
1214       assert_response 200
1215     end
1216
1217     should "disallow unauthorized user to update repository" do
1218       login_as :mike
1219       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1220       assert_response 403
1221     end
1222
1223     should "allow authorized user to update repository" do
1224       login_as :johan
1225       get :edit, :project_id => @project.to_param, :id => @repository.to_param
1226       assert_response 200
1227     end
1228
1229     should "not disallow writable_by? action" do
1230       do_writable_by_get :username => "mike"
1231       assert_response :success
1232       assert_equal "false", @response.body
1233     end
1234
1235     should "allow owner to write to repo" do
1236       do_writable_by_get :username => "johan"
1237       assert_response :success
1238       assert_equal "true", @response.body
1239     end
1240
1241     should "disallow unauthorized user to access repository configuration" do
1242       do_config_get(:username => "mike")
1243       assert_response 403
1244     end
1245
1246     should "disallow anonymous user to access repository configuration" do
1247       do_config_get
1248       assert_response 403
1249     end
1250
1251     should "allow authorized user to access repository configuration" do
1252       do_config_get(:username => "johan")
1253       assert_response 200
1254     end
1255
1256     should "disallow unauthorized user to confirm deletion" do
1257       login_as :mike
1258       get :confirm_delete, :project_id => @project.to_param, :id => @repository.to_param
1259       assert_response 403
1260     end
1261
1262     should "allow authorized user to confirm deletion" do
1263       login_as :johan
1264       get :confirm_delete, :project_id => @project.to_param, :id => @repository.to_param
1265       assert_response 200
1266     end
1267
1268     should "disallow unauthorized user to destroy repository" do
1269       login_as :mike
1270       do_delete @repository
1271       assert_response 403
1272     end
1273
1274     should "allow authorized user to destroy repository" do
1275       login_as :johan
1276       do_delete @repository
1277       assert_response 302
1278     end
1279
1280     should "create private repository" do
1281       login_as :johan
1282
1283       assert_difference "Repository.count" do
1284         post :create, :project_id => @project.to_param, :repository => {:name => "my-new-repo"}, :private_repository => "1"
1285
1286         assert_response :redirect
1287         assert Repository.last.private?
1288       end
1289     end
1290
1291     context "cloning" do
1292       setup do
1293         login_as :moe
1294         Project.expects(:find_by_slug!).with(@project.slug).returns(@project)
1295         @repository.stubs(:has_commits?).returns(true)
1296         @project.repositories.expects(:find_by_name_in_project!).with(@repository.name, nil).returns(@repository)
1297       end
1298
1299       should "clone private repository" do
1300         @repository.make_private
1301         @repository.add_member(users(:moe))
1302         do_create_clone_post(:name => "foo-clone")
1303         assert Repository.last.private?
1304       end
1305
1306       should "clone public repository" do
1307         do_create_clone_post(:name => "foo-clone")
1308         assert !Repository.last.private?
1309       end
1310
1311       should "add parent members to new repository" do
1312         @repository.make_private
1313         @repository.add_member(users(:moe))
1314         @repository.add_member(users(:old_timer))
1315         do_create_clone_post(:name => "foo-clone")
1316         assert can_read?(users(:old_timer), Repository.last)
1317         assert can_read?(users(:moe), Repository.last)
1318         assert can_read?(@repository.owner, Repository.last)
1319         assert_equal 3, @repository.content_memberships.length
1320       end
1321     end
1322   end
1323 end