Commit f4bdefdf authored by Rémy Coutable's avatar Rémy Coutable

Ensure private project snippets are not viewable by unauthorized people

Fix https://gitlab.com/gitlab-org/gitlab-ce/issues/14607.
parent 63c8a05b
...@@ -3,7 +3,7 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -3,7 +3,7 @@ class Projects::SnippetsController < Projects::ApplicationController
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw] before_action :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read any snippet # Allow read any snippet
before_action :authorize_read_project_snippet! before_action :authorize_read_project_snippet!, except: [:index]
# Allow write(create) snippet # Allow write(create) snippet
before_action :authorize_create_project_snippet!, only: [:new, :create] before_action :authorize_create_project_snippet!, only: [:new, :create]
...@@ -81,6 +81,10 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -81,6 +81,10 @@ class Projects::SnippetsController < Projects::ApplicationController
@snippet ||= @project.snippets.find(params[:id]) @snippet ||= @project.snippets.find(params[:id])
end end
def authorize_read_project_snippet!
return render_404 unless can?(current_user, :read_project_snippet, @snippet)
end
def authorize_update_project_snippet! def authorize_update_project_snippet!
return render_404 unless can?(current_user, :update_project_snippet, @snippet) return render_404 unless can?(current_user, :update_project_snippet, @snippet)
end end
......
...@@ -27,6 +27,8 @@ class Ability ...@@ -27,6 +27,8 @@ class Ability
case true case true
when subject.is_a?(PersonalSnippet) when subject.is_a?(PersonalSnippet)
anonymous_personal_snippet_abilities(subject) anonymous_personal_snippet_abilities(subject)
when subject.is_a?(ProjectSnippet)
anonymous_project_snippet_abilities(subject)
when subject.is_a?(CommitStatus) when subject.is_a?(CommitStatus)
anonymous_commit_status_abilities(subject) anonymous_commit_status_abilities(subject)
when subject.is_a?(Project) || subject.respond_to?(:project) when subject.is_a?(Project) || subject.respond_to?(:project)
...@@ -100,6 +102,14 @@ class Ability ...@@ -100,6 +102,14 @@ class Ability
end end
end end
def anonymous_project_snippet_abilities(snippet)
if snippet.public?
[:read_project_snippet]
else
[]
end
end
def global_abilities(user) def global_abilities(user)
rules = [] rules = []
rules << :create_group if user.can_create_group rules << :create_group if user.can_create_group
......
require 'spec_helper'
describe Projects::SnippetsController do
let(:project) { create(:project_empty_repo, :public, snippets_enabled: true) }
let(:user) { create(:user) }
let(:user2) { create(:user) }
before do
project.team << [user, :master]
project.team << [user2, :master]
end
describe 'GET #index' do
context 'when the project snippet is private' do
let!(:project_snippet) { create(:project_snippet, :private, project: project, author: user) }
context 'when anonymous' do
it 'does not include the private snippet' do
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(assigns(:snippets)).not_to include(project_snippet)
expect(response.status).to eq(200)
end
end
context 'when signed in as the author' do
before { sign_in(user) }
it 'renders the snippet' do
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(assigns(:snippets)).to include(project_snippet)
expect(response.status).to eq(200)
end
end
context 'when signed in as a project member' do
before { sign_in(user2) }
it 'renders the snippet' do
get :index, namespace_id: project.namespace.path, project_id: project.path
expect(assigns(:snippets)).to include(project_snippet)
expect(response.status).to eq(200)
end
end
end
end
%w[show raw].each do |action|
describe "GET ##{action}" do
context 'when the project snippet is private' do
let(:project_snippet) { create(:project_snippet, :private, project: project, author: user) }
context 'when anonymous' do
it 'responds with status 404' do
get action, namespace_id: project.namespace.path, project_id: project.path, id: project_snippet.to_param
expect(response.status).to eq(404)
end
end
context 'when signed in as the author' do
before { sign_in(user) }
it 'renders the snippet' do
get action, namespace_id: project.namespace.path, project_id: project.path, id: project_snippet.to_param
expect(assigns(:snippet)).to eq(project_snippet)
expect(response.status).to eq(200)
end
end
context 'when signed in as a project member' do
before { sign_in(user2) }
it 'renders the snippet' do
get action, namespace_id: project.namespace.path, project_id: project.path, id: project_snippet.to_param
expect(assigns(:snippet)).to eq(project_snippet)
expect(response.status).to eq(200)
end
end
end
context 'when the project snippet does not exist' do
context 'when anonymous' do
it 'responds with status 404' do
get action, namespace_id: project.namespace.path, project_id: project.path, id: 42
expect(response.status).to eq(404)
end
end
context 'when signed in' do
before { sign_in(user) }
it 'responds with status 404' do
get action, namespace_id: project.namespace.path, project_id: project.path, id: 42
expect(response.status).to eq(404)
end
end
end
end
end
end
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