Commit d9bb4230 authored by Jason Hollingsworth's avatar Jason Hollingsworth
Browse files

Adding authenticated public mode (internal).

Added visibility_level icons to project view (rather than just text).
Added public projects to search results.
Added ability to restrict visibility levels standard users can set.
parent 8cc172aa8c0e
......@@ -58,7 +58,7 @@ def auth!
end
else
return unauthorized unless project.public
return unauthorized unless project.public?
end
if authorized_git_request?
......@@ -80,7 +80,7 @@ def authenticate_user(login, password)
def authorize_request(service)
case service
when 'git-upload-pack'
project.public || can?(user, :download_code, project)
can?(user, :download_code, project)
when'git-receive-pack'
refs.each do |ref|
action = if project.protected_branch?(ref)
......
# Gitlab::VisibilityLevel module
#
# Define allowed public modes that can be used for
# GitLab projects to determine project public mode
#
module Gitlab
module VisibilityLevel
PRIVATE = 0
INTERNAL = 10
PUBLIC = 20
class << self
def values
options.values
end
def options
{
'Private' => PRIVATE,
'Internal' => INTERNAL,
'Public' => PUBLIC
}
end
def allowed_for?(user, level)
user.is_admin? || !Gitlab.config.gitlab.restricted_visibility_levels.include?(level)
end
end
def private?
visibility_level_field == PRIVATE
end
def internal?
visibility_level_field == INTERNAL
end
def public?
visibility_level_field == PUBLIC
end
end
end
......@@ -7,6 +7,7 @@
describe :create_by_user do
before do
@user = create :user
@admin = create :user, admin: true
@opts = {
name: "GitLab",
namespace: @user.namespace
......@@ -37,7 +38,7 @@
it { @project.namespace.should == @group }
end
context 'respect configured public setting' do
context 'respect configured visibility setting' do
before(:each) do
@settings = double("settings")
@settings.stub(:issues) { true }
......@@ -46,25 +47,90 @@
@settings.stub(:wall) { true }
@settings.stub(:snippets) { true }
stub_const("Settings", Class.new)
@restrictions = double("restrictions")
@restrictions.stub(:restricted_visibility_levels) { [] }
Settings.stub_chain(:gitlab).and_return(@restrictions)
Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings)
end
context 'should be public when setting is public' do
before do
@settings.stub(:public) { true }
@settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
@project = create_project(@user, @opts)
end
it { @project.public.should be_true }
it { @project.public?.should be_true }
end
context 'should be private when setting is not public' do
context 'should be private when setting is private' do
before do
@settings.stub(:public) { false }
@settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
@project = create_project(@user, @opts)
end
it { @project.public.should be_false }
it { @project.private?.should be_true }
end
context 'should be internal when setting is internal' do
before do
@settings.stub(:visibility_level) { Gitlab::VisibilityLevel::INTERNAL }
@project = create_project(@user, @opts)
end
it { @project.internal?.should be_true }
end
end
context 'respect configured visibility restrictions setting' do
before(:each) do
@settings = double("settings")
@settings.stub(:issues) { true }
@settings.stub(:merge_requests) { true }
@settings.stub(:wiki) { true }
@settings.stub(:wall) { true }
@settings.stub(:snippets) { true }
@settings.stub(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
stub_const("Settings", Class.new)
@restrictions = double("restrictions")
@restrictions.stub(:restricted_visibility_levels) { [ Gitlab::VisibilityLevel::PUBLIC ] }
Settings.stub_chain(:gitlab).and_return(@restrictions)
Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings)
end
context 'should be private when option is public' do
before do
@opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
@project = create_project(@user, @opts)
end
it { @project.private?.should be_true }
end
context 'should be public when option is public for admin' do
before do
@opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
@project = create_project(@admin, @opts)
end
it { @project.public?.should be_true }
end
context 'should be private when option is private' do
before do
@opts.merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@project = create_project(@user, @opts)
end
it { @project.private?.should be_true }
end
context 'should be internal when option is internal' do
before do
@opts.merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
@project = create_project(@user, @opts)
end
it { @project.internal?.should be_true }
end
end
end
......@@ -73,3 +139,4 @@ def create_project(user, opts)
Projects::CreateContext.new(user, opts).execute
end
end
require 'spec_helper'
describe Projects::UpdateContext do
before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
describe :update_by_user do
before do
@user = create :user
@admin = create :user, admin: true
@project = create :project, creator_id: @user.id, namespace: @user.namespace
@opts = { project: {} }
end
context 'should be private when updated to private' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
update_project(@project, @user, @opts)
end
it { @created_private.should be_true }
it { @project.private?.should be_true }
end
context 'should be internal when updated to internal' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
update_project(@project, @user, @opts)
end
it { @created_private.should be_true }
it { @project.internal?.should be_true }
end
context 'should be public when updated to public' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
update_project(@project, @user, @opts)
end
it { @created_private.should be_true }
it { @project.public?.should be_true }
end
context 'respect configured visibility restrictions setting' do
before(:each) do
@restrictions = double("restrictions")
@restrictions.stub(:restricted_visibility_levels) { [ Gitlab::VisibilityLevel::PUBLIC ] }
Settings.stub_chain(:gitlab).and_return(@restrictions)
end
context 'should be private when updated to private' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
update_project(@project, @user, @opts)
end
it { @created_private.should be_true }
it { @project.private?.should be_true }
end
context 'should be internal when updated to internal' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
update_project(@project, @user, @opts)
end
it { @created_private.should be_true }
it { @project.internal?.should be_true }
end
context 'should be private when updated to public' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
update_project(@project, @user, @opts)
end
it { @created_private.should be_true }
it { @project.private?.should be_true }
end
context 'should be public when updated to public by admin' do
before do
@created_private = @project.private?
@opts[:project].merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
update_project(@project, @admin, @opts)
end
it { @created_private.should be_true }
it { @project.public?.should be_true }
end
end
end
def update_project(project, user, opts)
Projects::UpdateContext.new(project, user, opts).execute
end
end
\ No newline at end of file
......@@ -3,23 +3,39 @@
describe SearchContext do
let(:found_namespace) { create(:namespace, name: 'searchable namespace', path:'another_thing') }
let(:user) { create(:user, namespace: found_namespace) }
let!(:found_project) { create(:project, name: 'searchable_project', creator_id: user.id, namespace: found_namespace, public: false) }
let!(:found_project) { create(:project, name: 'searchable_project', creator_id: user.id, namespace: found_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
let(:unfound_namespace) { create(:namespace, name: 'unfound namespace', path: 'yet_something_else') }
let!(:unfound_project) { create(:project, name: 'unfound_project', creator_id: user.id, namespace: unfound_namespace, public: false) }
let(:public_namespace) { create(:namespace, path: 'something_else',name: 'searchable public namespace') }
let(:other_user) { create(:user, namespace: public_namespace) }
let!(:public_project) { create(:project, name: 'searchable_public_project', creator_id: other_user.id, namespace: public_namespace, public: true) }
let!(:unfound_project) { create(:project, name: 'unfound_project', creator_id: user.id, namespace: unfound_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
let(:internal_namespace) { create(:namespace, path: 'something_internal',name: 'searchable internal namespace') }
let(:internal_user) { create(:user, namespace: internal_namespace) }
let!(:internal_project) { create(:project, name: 'searchable_internal_project', creator_id: internal_user.id, namespace: internal_namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
let(:public_namespace) { create(:namespace, path: 'something_public',name: 'searchable public namespace') }
let(:public_user) { create(:user, namespace: public_namespace) }
let!(:public_project) { create(:project, name: 'searchable_public_project', creator_id: public_user.id, namespace: public_namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
describe '#execute' do
it 'public projects should be searchable' do
context = SearchContext.new([found_project.id], {search_code: false, search: "searchable"})
context = SearchContext.new([found_project.id], nil, {search_code: false, search: "searchable"})
results = context.execute
results[:projects].should == [found_project, public_project]
end
it 'internal projects should be searchable' do
context = SearchContext.new([found_project.id], user, {search_code: false, search: "searchable"})
results = context.execute
# can't seem to rely on the return order, so check this way
#subject { results[:projects] }
results[:projects].should have(3).items
results[:projects].should include(found_project)
results[:projects].should include(internal_project)
results[:projects].should include(public_project)
end
it 'namespace name should be searchable' do
context = SearchContext.new([found_project.id], {search_code: false, search: "searchable namespace"})
context = SearchContext.new([found_project.id], user, {search_code: false, search: "searchable namespace"})
results = context.execute
results[:projects].should == [found_project]
end
......
require 'spec_helper'
describe "Internal Project Access" do
let(:project) { create(:project_with_code) }
let(:master) { create(:user) }
let(:guest) { create(:user) }
let(:reporter) { create(:user) }
before do
# internal project
project.visibility_level = Gitlab::VisibilityLevel::INTERNAL
project.save!
# full access
project.team << [master, :master]
# readonly
project.team << [reporter, :reporter]
end
describe "Project should be internal" do
subject { project }
its(:internal?) { should be_true }
end
describe "GET /:project_path" 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_path/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_path/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_path/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_path/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_path/team" do
subject { project_team_index_path(project) }
it { should be_allowed_for master }
it { should be_denied_for reporter }
it { should be_allowed_for :admin }
it { should be_denied_for guest }
it { should be_denied_for :user }
it { should be_denied_for :visitor }
end
describe "GET /:project_path/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_path/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_path/edit" do
subject { edit_project_path(project) }
it { should be_allowed_for master }
it { should be_denied_for reporter }
it { should be_allowed_for :admin }
it { should be_denied_for guest }
it { should be_denied_for :user }
it { should be_denied_for :visitor }
end
describe "GET /:project_path/deploy_keys" do
subject { project_deploy_keys_path(project) }
it { should be_allowed_for master }
it { should be_denied_for reporter }
it { should be_allowed_for :admin }
it { should be_denied_for guest }
it { should be_denied_for :user }
it { should be_denied_for :visitor }
end
describe "GET /:project_path/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_path/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_path/snippets/new" do
subject { new_project_snippet_path(project) }
it { should be_allowed_for master }
it { should be_allowed_for reporter }
it { should be_allowed_for :admin }
it { should be_denied_for guest }
it { should be_denied_for :user }
it { should be_denied_for :visitor }
end
describe "GET /:project_path/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_path/merge_requests/new" do
subject { new_project_merge_request_path(project) }
it { should be_allowed_for master }
it { should be_denied_for reporter }
it { should be_allowed_for :admin }
it { should be_denied_for guest }
it { should be_denied_for :user }
it { should be_denied_for :visitor }
end
describe "GET /:project_path/branches/recent" do
subject { recent_project_branches_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_path/branches" do
subject { project_branches_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_path/tags" do
subject { project_tags_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_path/hooks" do
subject { project_hooks_path(project) }
it { should be_allowed_for master }
it { should be_denied_for reporter }
it { should be_allowed_for :admin }
it { should be_denied_for guest }
it { should be_denied_for :user }
it { should be_denied_for :visitor }
end
end
......@@ -15,6 +15,12 @@
project.team << [reporter, :reporter]
end