Commit 4c44c5ef9a569c65bca8e70078205ef2ce7d6396

Authored by Stephen Lottermoser
Committed by Stephen Lottermoser
1 parent 4f5aae1d

Internally public projects

Public projects listed in the public section will be linked to the
actual project's page. Public projects now give any user Guest
permissions to the project, allowing them to download the code, read
and create issues, and view anything else in the project's pages.

Ample access tests have been added to the project_access_spec to
verify correct permissions and behavior on public projects.
- Visitors to the site who are not logged in still cannot view the
  project's pages.
- Logged-in users visiting a public project where they are not a team
  member can create issues, but not snippets. They can view the projects
  code, issues, merge requests, etc, just as if they were a Guest member
  of the project.
- Since this is a public project, the user is also granted :download_code
  permissions, a permission normally reserved for Reporters, since they
  can clone the repo anyways and browse commits and branches locally.
app/controllers/application_controller.rb
@@ -88,7 +88,7 @@ class ApplicationController < ActionController::Base @@ -88,7 +88,7 @@ class ApplicationController < ActionController::Base
88 end 88 end
89 89
90 def authorize_code_access! 90 def authorize_code_access!
91 - return access_denied! unless can?(current_user, :download_code, project) 91 + return access_denied! unless can?(current_user, :download_code, project) or project.public?
92 end 92 end
93 93
94 def authorize_create_team! 94 def authorize_create_team!
app/models/ability.rb
@@ -37,7 +37,7 @@ class Ability @@ -37,7 +37,7 @@ class Ability
37 elsif team.reporters.include?(user) 37 elsif team.reporters.include?(user)
38 rules << project_report_rules 38 rules << project_report_rules
39 39
40 - elsif team.guests.include?(user) 40 + elsif team.guests.include?(user) or project.public?
41 rules << project_guest_rules 41 rules << project_guest_rules
42 end 42 end
43 43
app/views/projects/_form.html.haml
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 Public mode: 48 Public mode:
49 .control-group 49 .control-group
50 = f.label :public, class: 'control-label' do 50 = f.label :public, class: 'control-label' do
51 - %span Public clone access 51 + %span Public access
52 .controls 52 .controls
53 = f.check_box :public 53 = f.check_box :public
54 %span.descr 54 %span.descr
@@ -56,6 +56,8 @@ @@ -56,6 +56,8 @@
56 %em without any 56 %em without any
57 authentication. 57 authentication.
58 It will also be listed on the #{link_to "public access directory", public_root_path}. 58 It will also be listed on the #{link_to "public access directory", public_root_path}.
  59 + %em Any
  60 + user will have #{link_to "Guest", help_permissions_path} permissions on the repository.
59 61
60 %fieldset.features 62 %fieldset.features
61 %legend 63 %legend
app/views/public/projects/index.html.haml
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 %li.clearfix 9 %li.clearfix
10 %h5 10 %h5
11 %i.icon-share 11 %i.icon-share
12 - = project.name_with_namespace 12 + = link_to_project project
13 .pull-right 13 .pull-right
14 %pre.dark.tiny git clone #{project.http_url_to_repo} 14 %pre.dark.tiny git clone #{project.http_url_to_repo}
15 %p.description 15 %p.description
features/project/public_projects.feature 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +Feature: Public Projects
  2 + Background:
  3 + Given I sign in as a user
  4 +
  5 + Scenario: I should see the list of public projects
  6 + When I visit the public projects area
  7 + Then I should see the list of public projects
  8 +
features/steps/project/public_projects.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class PublicProjects < Spinach::FeatureSteps
  2 + include SharedAuthentication
  3 + include SharedProject
  4 + include SharedPaths
  5 +
  6 + Then 'I should see the list of public projects' do
  7 + page.should have_content "Public Projects"
  8 + end
  9 +end
features/steps/shared/paths.rb
@@ -263,6 +263,14 @@ module SharedPaths @@ -263,6 +263,14 @@ module SharedPaths
263 visit project_wiki_path(@project, :home) 263 visit project_wiki_path(@project, :home)
264 end 264 end
265 265
  266 + # ----------------------------------------
  267 + # Public Projects
  268 + # ----------------------------------------
  269 +
  270 + Given 'I visit the public projects area' do
  271 + visit public_root_path
  272 + end
  273 +
266 def root_ref 274 def root_ref
267 @project.repository.root_ref 275 @project.repository.root_ref
268 end 276 end
spec/features/security/project_access_spec.rb
@@ -229,4 +229,246 @@ describe &quot;Application access&quot; do @@ -229,4 +229,246 @@ describe &quot;Application access&quot; do
229 it { should be_denied_for :visitor } 229 it { should be_denied_for :visitor }
230 end 230 end
231 end 231 end
  232 +
  233 +
  234 + describe "PublicProject" do
  235 + let(:project) { create(:project) }
  236 +
  237 + let(:master) { create(:user) }
  238 + let(:guest) { create(:user) }
  239 + let(:reporter) { create(:user) }
  240 +
  241 + let(:admin) { create(:user) }
  242 +
  243 + before do
  244 + # public project
  245 + project.public = true
  246 + project.save!
  247 +
  248 + # full access
  249 + project.team << [master, :master]
  250 +
  251 + # readonly
  252 + project.team << [reporter, :reporter]
  253 +
  254 + end
  255 +
  256 + describe "Project should be public" do
  257 + subject { project }
  258 +
  259 + its(:public?) { should be_true }
  260 + end
  261 +
  262 + describe "GET /project_code" do
  263 + subject { project_path(project) }
  264 +
  265 + it { should be_allowed_for master }
  266 + it { should be_allowed_for reporter }
  267 + it { should be_allowed_for admin }
  268 + it { should be_allowed_for guest }
  269 + it { should be_allowed_for :user }
  270 + it { should be_denied_for :visitor }
  271 + end
  272 +
  273 + describe "GET /project_code/tree/master" do
  274 + subject { project_tree_path(project, project.repository.root_ref) }
  275 +
  276 + it { should be_allowed_for master }
  277 + it { should be_allowed_for reporter }
  278 + it { should be_allowed_for :admin }
  279 + it { should be_allowed_for guest }
  280 + it { should be_allowed_for :user }
  281 + it { should be_denied_for :visitor }
  282 + end
  283 +
  284 + describe "GET /project_code/commits/master" do
  285 + subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
  286 +
  287 + it { should be_allowed_for master }
  288 + it { should be_allowed_for reporter }
  289 + it { should be_allowed_for :admin }
  290 + it { should be_allowed_for guest }
  291 + it { should be_allowed_for :user }
  292 + it { should be_denied_for :visitor }
  293 + end
  294 +
  295 + describe "GET /project_code/commit/:sha" do
  296 + subject { project_commit_path(project, project.repository.commit) }
  297 +
  298 + it { should be_allowed_for master }
  299 + it { should be_allowed_for reporter }
  300 + it { should be_allowed_for :admin }
  301 + it { should be_allowed_for guest }
  302 + it { should be_allowed_for :user }
  303 + it { should be_denied_for :visitor }
  304 + end
  305 +
  306 + describe "GET /project_code/compare" do
  307 + subject { project_compare_index_path(project) }
  308 +
  309 + it { should be_allowed_for master }
  310 + it { should be_allowed_for reporter }
  311 + it { should be_allowed_for :admin }
  312 + it { should be_allowed_for guest }
  313 + it { should be_allowed_for :user }
  314 + it { should be_denied_for :visitor }
  315 + end
  316 +
  317 + describe "GET /project_code/team" do
  318 + subject { project_team_index_path(project) }
  319 +
  320 + it { should be_allowed_for master }
  321 + it { should be_allowed_for reporter }
  322 + it { should be_allowed_for :admin }
  323 + it { should be_allowed_for guest }
  324 + it { should be_allowed_for :user }
  325 + it { should be_denied_for :visitor }
  326 + end
  327 +
  328 + describe "GET /project_code/wall" do
  329 + subject { project_wall_path(project) }
  330 +
  331 + it { should be_allowed_for master }
  332 + it { should be_allowed_for reporter }
  333 + it { should be_allowed_for :admin }
  334 + it { should be_allowed_for guest }
  335 + it { should be_allowed_for :user }
  336 + it { should be_denied_for :visitor }
  337 + end
  338 +
  339 + describe "GET /project_code/blob" do
  340 + before do
  341 + commit = project.repository.commit
  342 + path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name
  343 + @blob_path = project_blob_path(project, File.join(commit.id, path))
  344 + end
  345 +
  346 + it { @blob_path.should be_allowed_for master }
  347 + it { @blob_path.should be_allowed_for reporter }
  348 + it { @blob_path.should be_allowed_for :admin }
  349 + it { @blob_path.should be_allowed_for guest }
  350 + it { @blob_path.should be_allowed_for :user }
  351 + it { @blob_path.should be_denied_for :visitor }
  352 + end
  353 +
  354 + describe "GET /project_code/edit" do
  355 + subject { edit_project_path(project) }
  356 +
  357 + it { should be_allowed_for master }
  358 + it { should be_denied_for reporter }
  359 + it { should be_denied_for :admin }
  360 + it { should be_denied_for guest }
  361 + it { should be_denied_for :user }
  362 + it { should be_denied_for :visitor }
  363 + end
  364 +
  365 + describe "GET /project_code/deploy_keys" do
  366 + subject { project_deploy_keys_path(project) }
  367 +
  368 + it { should be_allowed_for master }
  369 + it { should be_denied_for reporter }
  370 + it { should be_denied_for :admin }
  371 + it { should be_denied_for guest }
  372 + it { should be_denied_for :user }
  373 + it { should be_denied_for :visitor }
  374 + end
  375 +
  376 + describe "GET /project_code/issues" do
  377 + subject { project_issues_path(project) }
  378 +
  379 + it { should be_allowed_for master }
  380 + it { should be_allowed_for reporter }
  381 + it { should be_allowed_for :admin }
  382 + it { should be_allowed_for guest }
  383 + it { should be_allowed_for :user }
  384 + it { should be_denied_for :visitor }
  385 + end
  386 +
  387 + describe "GET /project_code/snippets" do
  388 + subject { project_snippets_path(project) }
  389 +
  390 + it { should be_allowed_for master }
  391 + it { should be_allowed_for reporter }
  392 + it { should be_allowed_for :admin }
  393 + it { should be_allowed_for guest }
  394 + it { should be_allowed_for :user }
  395 + it { should be_denied_for :visitor }
  396 + end
  397 +
  398 + describe "GET /project_code/snippets/new" do
  399 + subject { new_project_snippet_path(project) }
  400 +
  401 + it { should be_allowed_for master }
  402 + it { should be_allowed_for reporter }
  403 + it { should be_denied_for :admin }
  404 + it { should be_denied_for guest }
  405 + it { should be_denied_for :user }
  406 + it { should be_denied_for :visitor }
  407 + end
  408 +
  409 + describe "GET /project_code/merge_requests" do
  410 + subject { project_merge_requests_path(project) }
  411 +
  412 + it { should be_allowed_for master }
  413 + it { should be_allowed_for reporter }
  414 + it { should be_allowed_for :admin }
  415 + it { should be_allowed_for guest }
  416 + it { should be_allowed_for :user }
  417 + it { should be_denied_for :visitor }
  418 + end
  419 +
  420 + describe "GET /project_code/repository" do
  421 + subject { project_repository_path(project) }
  422 +
  423 + it { should be_allowed_for master }
  424 + it { should be_allowed_for reporter }
  425 + it { should be_allowed_for :admin }
  426 + it { should be_allowed_for guest }
  427 + it { should be_allowed_for :user }
  428 + it { should be_denied_for :visitor }
  429 + end
  430 +
  431 + describe "GET /project_code/repository/branches" do
  432 + subject { branches_project_repository_path(project) }
  433 +
  434 + before do
  435 + # Speed increase
  436 + Project.any_instance.stub(:branches).and_return([])
  437 + end
  438 +
  439 + it { should be_allowed_for master }
  440 + it { should be_allowed_for reporter }
  441 + it { should be_allowed_for :admin }
  442 + it { should be_allowed_for guest }
  443 + it { should be_allowed_for :user }
  444 + it { should be_denied_for :visitor }
  445 + end
  446 +
  447 + describe "GET /project_code/repository/tags" do
  448 + subject { tags_project_repository_path(project) }
  449 +
  450 + before do
  451 + # Speed increase
  452 + Project.any_instance.stub(:tags).and_return([])
  453 + end
  454 +
  455 + it { should be_allowed_for master }
  456 + it { should be_allowed_for reporter }
  457 + it { should be_allowed_for :admin }
  458 + it { should be_allowed_for guest }
  459 + it { should be_allowed_for :user }
  460 + it { should be_denied_for :visitor }
  461 + end
  462 +
  463 + describe "GET /project_code/hooks" do
  464 + subject { project_hooks_path(project) }
  465 +
  466 + it { should be_allowed_for master }
  467 + it { should be_allowed_for reporter }
  468 + it { should be_allowed_for :admin }
  469 + it { should be_allowed_for guest }
  470 + it { should be_allowed_for :user }
  471 + it { should be_denied_for :visitor }
  472 + end
  473 + end
232 end 474 end