diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 32b1246601de7fbd3eca5fce5938fdb29a352713..c2ca23fae53d2a88d57d1f2901142a423b503f95 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -88,7 +88,7 @@ def authorize_project!(action) end def authorize_code_access! - return access_denied! unless can?(current_user, :download_code, project) + return access_denied! unless can?(current_user, :download_code, project) or project.public? end def authorize_create_team! diff --git a/app/models/ability.rb b/app/models/ability.rb index 5b49104da8a8fe949c6a3ef30521ca551cbfb8fd..c5e4524b8ceb70ca56dd229098bca0fe9efd6f90 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -37,7 +37,7 @@ def project_abilities(user, project) elsif team.reporters.include?(user) rules << project_report_rules - elsif team.guests.include?(user) + elsif team.guests.include?(user) or project.public? rules << project_guest_rules end diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 4d635e3dc68b9b78e5a751e5ff356f5f8a567d80..0e1fd2380053e32e68f630ecc1d8f10702119eff 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -48,7 +48,7 @@ Public mode: .control-group = f.label :public, class: 'control-label' do - %span Public clone access + %span Public access .controls = f.check_box :public %span.descr @@ -56,6 +56,8 @@ %em without any authentication. It will also be listed on the #{link_to "public access directory", public_root_path}. + %em Any + user will have #{link_to "Guest", help_permissions_path} permissions on the repository. %fieldset.features %legend diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml index 3d0d793b2d2edee6e0eac2982ec0d7f7a3595257..e66851ead5b3ecc66c1121d2aed9e8f51a7a9365 100644 --- a/app/views/public/projects/index.html.haml +++ b/app/views/public/projects/index.html.haml @@ -9,7 +9,7 @@ %li.clearfix %h5 %i.icon-share - = project.name_with_namespace + = link_to_project project .pull-right %pre.dark.tiny git clone #{project.http_url_to_repo} %p.description diff --git a/features/project/public_projects.feature b/features/project/public_projects.feature new file mode 100644 index 0000000000000000000000000000000000000000..c5a9da14c541653fb6afdaa7f83f9672bd4d21a6 --- /dev/null +++ b/features/project/public_projects.feature @@ -0,0 +1,8 @@ +Feature: Public Projects + Background: + Given I sign in as a user + + Scenario: I should see the list of public projects + When I visit the public projects area + Then I should see the list of public projects + diff --git a/features/steps/project/public_projects.rb b/features/steps/project/public_projects.rb new file mode 100644 index 0000000000000000000000000000000000000000..7063e7d56aefcc27c7312af6750dfbfaade94c04 --- /dev/null +++ b/features/steps/project/public_projects.rb @@ -0,0 +1,9 @@ +class PublicProjects < Spinach::FeatureSteps + include SharedAuthentication + include SharedProject + include SharedPaths + + Then 'I should see the list of public projects' do + page.should have_content "Public Projects" + end +end diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index 27ca65b22dd662d13695d0d89307e36bca73aabc..38730cc2cd61a017dfc5cfd96ea217bde3f88549 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -263,6 +263,14 @@ module SharedPaths visit project_wiki_path(@project, :home) end + # ---------------------------------------- + # Public Projects + # ---------------------------------------- + + Given 'I visit the public projects area' do + visit public_root_path + end + def root_ref @project.repository.root_ref end diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb index cfbb8f135ab0c05fb8d373732cf6f0eb2cc26138..a00b2b0375ab7d01bcf92ed22f6a1c7921a2a3e8 100644 --- a/spec/features/security/project_access_spec.rb +++ b/spec/features/security/project_access_spec.rb @@ -229,4 +229,246 @@ it { should be_denied_for :visitor } end end + + + describe "PublicProject" do + let(:project) { create(:project) } + + let(:master) { create(:user) } + let(:guest) { create(:user) } + let(:reporter) { create(:user) } + + let(:admin) { create(:user) } + + before do + # public project + project.public = true + project.save! + + # full access + project.team << [master, :master] + + # readonly + project.team << [reporter, :reporter] + + end + + describe "Project should be public" do + subject { project } + + its(:public?) { should be_true } + end + + describe "GET /project_code" do + subject { project_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/tree/master" do + subject { project_tree_path(project, project.repository.root_ref) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/commits/master" do + subject { project_commits_path(project, project.repository.root_ref, limit: 1) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/commit/:sha" do + subject { project_commit_path(project, project.repository.commit) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/compare" do + subject { project_compare_index_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/team" do + subject { project_team_index_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/wall" do + subject { project_wall_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/blob" do + before do + commit = project.repository.commit + path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name + @blob_path = project_blob_path(project, File.join(commit.id, path)) + end + + it { @blob_path.should be_allowed_for master } + it { @blob_path.should be_allowed_for reporter } + it { @blob_path.should be_allowed_for :admin } + it { @blob_path.should be_allowed_for guest } + it { @blob_path.should be_allowed_for :user } + it { @blob_path.should be_denied_for :visitor } + end + + describe "GET /project_code/edit" do + subject { edit_project_path(project) } + + it { should be_allowed_for master } + it { should be_denied_for reporter } + it { should be_denied_for :admin } + it { should be_denied_for guest } + it { should be_denied_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/deploy_keys" do + subject { project_deploy_keys_path(project) } + + it { should be_allowed_for master } + it { should be_denied_for reporter } + it { should be_denied_for :admin } + it { should be_denied_for guest } + it { should be_denied_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/issues" do + subject { project_issues_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/snippets" do + subject { project_snippets_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/snippets/new" do + subject { new_project_snippet_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_denied_for :admin } + it { should be_denied_for guest } + it { should be_denied_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/merge_requests" do + subject { project_merge_requests_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/repository" do + subject { project_repository_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/repository/branches" do + subject { branches_project_repository_path(project) } + + before do + # Speed increase + Project.any_instance.stub(:branches).and_return([]) + end + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/repository/tags" do + subject { tags_project_repository_path(project) } + + before do + # Speed increase + Project.any_instance.stub(:tags).and_return([]) + end + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + + describe "GET /project_code/hooks" do + subject { project_hooks_path(project) } + + it { should be_allowed_for master } + it { should be_allowed_for reporter } + it { should be_allowed_for :admin } + it { should be_allowed_for guest } + it { should be_allowed_for :user } + it { should be_denied_for :visitor } + end + end end