Commit 285c5341 authored by Vinnie Okada's avatar Vinnie Okada

Allow admins to override restricted visibility

Allow admins to use restricted visibility levels when creating or
updating projects.
parent cacac147
...@@ -11,6 +11,7 @@ v 7.9.0 (unreleased) ...@@ -11,6 +11,7 @@ v 7.9.0 (unreleased)
- Improve error messages for file edit failures - Improve error messages for file edit failures
- Improve UI for commits, issues and merge request lists - Improve UI for commits, issues and merge request lists
- Fix commit comments on first line of diff not rendering in Merge Request Discussion view. - Fix commit comments on first line of diff not rendering in Merge Request Discussion view.
- Allow admins to override restricted project visibility settings.
- Move restricted visibility settings from gitlab.yml into the web UI. - Move restricted visibility settings from gitlab.yml into the web UI.
- Improve trigger merge request hook when source project branch has been updated (Kirill Zaitsev) - Improve trigger merge request hook when source project branch has been updated (Kirill Zaitsev)
- Save web edit in new branch - Save web edit in new branch
......
...@@ -34,8 +34,6 @@ require 'file_size_validator' ...@@ -34,8 +34,6 @@ require 'file_size_validator'
class Project < ActiveRecord::Base class Project < ActiveRecord::Base
include Sortable include Sortable
include Gitlab::CurrentSettings
extend Gitlab::CurrentSettings
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
include Gitlab::VisibilityLevel include Gitlab::VisibilityLevel
include Gitlab::ConfigHelper include Gitlab::ConfigHelper
...@@ -133,9 +131,6 @@ class Project < ActiveRecord::Base ...@@ -133,9 +131,6 @@ class Project < ActiveRecord::Base
message: Gitlab::Regex.path_regex_message } message: Gitlab::Regex.path_regex_message }
validates :issues_enabled, :merge_requests_enabled, validates :issues_enabled, :merge_requests_enabled,
:wiki_enabled, inclusion: { in: [true, false] } :wiki_enabled, inclusion: { in: [true, false] }
validates :visibility_level,
exclusion: { in: current_application_settings.restricted_visibility_levels },
if: -> { current_application_settings.restricted_visibility_levels.any? }
validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true
validates :namespace, presence: true validates :namespace, presence: true
validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :name, scope: :namespace_id
......
module Projects
class BaseService < ::BaseService
# Add an error to the project for restricted visibility levels
def deny_visibility_level(project, denied_visibility_level = nil)
denied_visibility_level ||= project.visibility_level
level_name = 'Unknown'
Gitlab::VisibilityLevel.options.each do |name, level|
level_name = name if level == denied_visibility_level
end
project.errors.add(
:visibility_level,
"#{level_name} visibility has been restricted by your GitLab administrator"
)
end
end
end
module Projects module Projects
class CreateService < BaseService class CreateService < Projects::BaseService
def initialize(user, params) def initialize(user, params)
@current_user, @params = user, params.dup @current_user, @params = user, params.dup
end end
...@@ -7,9 +7,12 @@ module Projects ...@@ -7,9 +7,12 @@ module Projects
def execute def execute
@project = Project.new(params) @project = Project.new(params)
# Reset visibility level if is not allowed to set it # Make sure that the user is allowed to use the specified visibility
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) # level
@project.visibility_level = default_features.visibility_level unless Gitlab::VisibilityLevel.allowed_for?(current_user,
params[:visibility_level])
deny_visibility_level(@project)
return @project
end end
# Set project name from path # Set project name from path
......
module Projects module Projects
class UpdateService < BaseService class UpdateService < Projects::BaseService
def execute def execute
# check that user is allowed to set specified visibility_level # check that user is allowed to set specified visibility_level
unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) new_visibility = params[:visibility_level]
params[:visibility_level] = project.visibility_level if new_visibility && new_visibility.to_i != project.visibility_level
unless can?(current_user, :change_visibility_level, project) &&
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
deny_visibility_level(project, new_visibility)
return project
end
end end
new_branch = params[:default_branch] new_branch = params[:default_branch]
......
...@@ -41,4 +41,4 @@ When visiting the public page of an user, you will only see listed projects whic ...@@ -41,4 +41,4 @@ When visiting the public page of an user, you will only see listed projects whic
## Restricting the use of public or internal projects ## Restricting the use of public or internal projects
In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident. The restricted visibility settings do not apply to admin users.
...@@ -204,7 +204,7 @@ module API ...@@ -204,7 +204,7 @@ module API
end end
def render_validation_error!(model) def render_validation_error!(model)
unless model.valid? if model.errors.any?
render_api_error!(model.errors.messages || '400 Bad Request', 400) render_api_error!(model.errors.messages || '400 Bad Request', 400)
end end
end end
......
...@@ -233,10 +233,10 @@ module API ...@@ -233,10 +233,10 @@ module API
::Projects::UpdateService.new(user_project, ::Projects::UpdateService.new(user_project,
current_user, attrs).execute current_user, attrs).execute
if user_project.valid? if user_project.errors.any?
present user_project, with: Entities::Project
else
render_validation_error!(user_project) render_validation_error!(user_project)
else
present user_project, with: Entities::Project
end end
end end
......
...@@ -3,6 +3,7 @@ require 'spec_helper' ...@@ -3,6 +3,7 @@ require 'spec_helper'
describe API::API, api: true do describe API::API, api: true do
include ApiHelpers include ApiHelpers
include Gitlab::CurrentSettings
let(:user) { create(:user) } let(:user) { create(:user) }
let(:user2) { create(:user) } let(:user2) { create(:user) }
let(:user3) { create(:user) } let(:user3) { create(:user) }
...@@ -202,6 +203,31 @@ describe API::API, api: true do ...@@ -202,6 +203,31 @@ describe API::API, api: true do
expect(json_response['public']).to be_falsey expect(json_response['public']).to be_falsey
expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE) expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
end end
context 'when a visibility level is restricted' do
before do
@project = attributes_for(:project, { public: true })
allow_any_instance_of(ApplicationSetting).to(
receive(:restricted_visibility_levels).and_return([20])
)
end
it 'should not allow a non-admin to use a restricted visibility level' do
post api('/projects', user), @project
expect(response.status).to eq(400)
expect(json_response['message']['visibility_level'].first).to(
match('restricted by your GitLab administrator')
)
end
it 'should allow an admin to override restricted visibility settings' do
post api('/projects', admin), @project
expect(json_response['public']).to be_truthy
expect(json_response['visibility_level']).to(
eq(Gitlab::VisibilityLevel::PUBLIC)
)
end
end
end end
describe 'POST /projects/user/:id' do describe 'POST /projects/user/:id' do
......
...@@ -55,6 +55,33 @@ describe Projects::CreateService do ...@@ -55,6 +55,33 @@ describe Projects::CreateService do
it { expect(File.exists?(@path)).to be_falsey } it { expect(File.exists?(@path)).to be_falsey }
end end
end end
context 'restricted visibility level' do
before do
allow_any_instance_of(ApplicationSetting).to(
receive(:restricted_visibility_levels).and_return([20])
)
@opts.merge!(
visibility_level: Gitlab::VisibilityLevel.options['Public']
)
end
it 'should not allow a restricted visibility level for non-admins' do
project = create_project(@user, @opts)
expect(project).to respond_to(:errors)
expect(project.errors.messages).to have_key(:visibility_level)
expect(project.errors.messages[:visibility_level].first).to(
match('restricted by your GitLab administrator')
)
end
it 'should allow a restricted visibility level for admins' do
project = create_project(@admin, @opts)
expect(project.errors.any?).to be(false)
expect(project.saved?).to be(true)
end
end
end end
def create_project(user, opts) def create_project(user, opts)
......
...@@ -47,9 +47,9 @@ describe Projects::UpdateService do ...@@ -47,9 +47,9 @@ describe Projects::UpdateService do
context 'respect configured visibility restrictions setting' do context 'respect configured visibility restrictions setting' do
before(:each) do before(:each) do
@restrictions = double("restrictions") allow_any_instance_of(ApplicationSetting).to(
allow(@restrictions).to receive(:restricted_visibility_levels) { [ "public" ] } receive(:restricted_visibility_levels).and_return([20])
Settings.stub_chain(:gitlab).and_return(@restrictions) )
end end
context 'should be private when updated to private' do context 'should be private when updated to private' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment