Merge pull request #5344 from amacarthur/thread-variable-fix
Fixing unsafe use of Thread.current variable :current_user
This commit is contained in:
commit
03dba1fd42
|
@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
|
|||
before_filter :authenticate_user!
|
||||
before_filter :reject_blocked!
|
||||
before_filter :check_password_expiration
|
||||
before_filter :set_current_user_for_thread
|
||||
around_filter :set_current_user_for_thread
|
||||
before_filter :add_abilities
|
||||
before_filter :dev_tools if Rails.env == 'development'
|
||||
before_filter :default_headers
|
||||
|
@ -50,6 +50,11 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def set_current_user_for_thread
|
||||
Thread.current[:current_user] = current_user
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
Thread.current[:current_user] = nil
|
||||
end
|
||||
end
|
||||
|
||||
def abilities
|
||||
|
|
|
@ -11,17 +11,22 @@ Gitlab::Seeder.quiet do
|
|||
next unless user
|
||||
|
||||
user_id = user.id
|
||||
Thread.current[:current_user] = user
|
||||
|
||||
Issue.seed(:id, [{
|
||||
id: i,
|
||||
project_id: project.id,
|
||||
author_id: user_id,
|
||||
assignee_id: user_id,
|
||||
state: ['opened', 'closed'].sample,
|
||||
milestone: project.milestones.sample,
|
||||
title: Faker::Lorem.sentence(6)
|
||||
}])
|
||||
begin
|
||||
Thread.current[:current_user] = user
|
||||
|
||||
Issue.seed(:id, [{
|
||||
id: i,
|
||||
project_id: project.id,
|
||||
author_id: user_id,
|
||||
assignee_id: user_id,
|
||||
state: ['opened', 'closed'].sample,
|
||||
milestone: project.milestones.sample,
|
||||
title: Faker::Lorem.sentence(6)
|
||||
}])
|
||||
ensure
|
||||
Thread.current[:current_user] = nil
|
||||
end
|
||||
print('.')
|
||||
end
|
||||
|
||||
|
|
|
@ -17,19 +17,23 @@ Gitlab::Seeder.quiet do
|
|||
next if branches.uniq.size < 2
|
||||
|
||||
user_id = user.id
|
||||
Thread.current[:current_user] = user
|
||||
begin
|
||||
Thread.current[:current_user] = user
|
||||
|
||||
MergeRequest.seed(:id, [{
|
||||
id: i,
|
||||
source_branch: branches.first,
|
||||
target_branch: branches.last,
|
||||
source_project_id: project.id,
|
||||
target_project_id: project.id,
|
||||
author_id: user_id,
|
||||
assignee_id: user_id,
|
||||
milestone: project.milestones.sample,
|
||||
title: Faker::Lorem.sentence(6)
|
||||
}])
|
||||
MergeRequest.seed(:id, [{
|
||||
id: i,
|
||||
source_branch: branches.first,
|
||||
target_branch: branches.last,
|
||||
source_project_id: project.id,
|
||||
target_project_id: project.id,
|
||||
author_id: user_id,
|
||||
assignee_id: user_id,
|
||||
milestone: project.milestones.sample,
|
||||
title: Faker::Lorem.sentence(6)
|
||||
}])
|
||||
ensure
|
||||
Thread.current[:current_user] = nil
|
||||
end
|
||||
print('.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,4 +51,6 @@ Spinach.hooks.before_run do
|
|||
RSpec::Mocks::setup self
|
||||
|
||||
include FactoryGirl::Syntax::Methods
|
||||
MergeRequestObserver.any_instance.stub(current_user: create(:user))
|
||||
end
|
||||
|
||||
|
|
|
@ -27,6 +27,15 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
def set_current_user_for_thread
|
||||
Thread.current[:current_user] = current_user
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
Thread.current[:current_user] = nil
|
||||
end
|
||||
end
|
||||
|
||||
def user_project
|
||||
@project ||= find_project(params[:id])
|
||||
@project || not_found!
|
||||
|
|
|
@ -2,7 +2,6 @@ module API
|
|||
# Issues API
|
||||
class Issues < Grape::API
|
||||
before { authenticate! }
|
||||
before { Thread.current[:current_user] = current_user }
|
||||
|
||||
resource :issues do
|
||||
# Get currently authenticated user's issues
|
||||
|
@ -49,15 +48,17 @@ module API
|
|||
# Example Request:
|
||||
# POST /projects/:id/issues
|
||||
post ":id/issues" do
|
||||
required_attributes! [:title]
|
||||
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
|
||||
attrs[:label_list] = params[:labels] if params[:labels].present?
|
||||
@issue = user_project.issues.new attrs
|
||||
@issue.author = current_user
|
||||
if @issue.save
|
||||
present @issue, with: Entities::Issue
|
||||
else
|
||||
not_found!
|
||||
set_current_user_for_thread do
|
||||
required_attributes! [:title]
|
||||
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
|
||||
attrs[:label_list] = params[:labels] if params[:labels].present?
|
||||
@issue = user_project.issues.new attrs
|
||||
@issue.author = current_user
|
||||
if @issue.save
|
||||
present @issue, with: Entities::Issue
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,16 +76,18 @@ module API
|
|||
# Example Request:
|
||||
# PUT /projects/:id/issues/:issue_id
|
||||
put ":id/issues/:issue_id" do
|
||||
@issue = user_project.issues.find(params[:issue_id])
|
||||
authorize! :modify_issue, @issue
|
||||
set_current_user_for_thread do
|
||||
@issue = user_project.issues.find(params[:issue_id])
|
||||
authorize! :modify_issue, @issue
|
||||
|
||||
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
|
||||
attrs[:label_list] = params[:labels] if params[:labels].present?
|
||||
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
|
||||
attrs[:label_list] = params[:labels] if params[:labels].present?
|
||||
|
||||
if @issue.update_attributes attrs
|
||||
present @issue, with: Entities::Issue
|
||||
else
|
||||
not_found!
|
||||
if @issue.update_attributes attrs
|
||||
present @issue, with: Entities::Issue
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ module API
|
|||
# MergeRequest API
|
||||
class MergeRequests < Grape::API
|
||||
before { authenticate! }
|
||||
before { Thread.current[:current_user] = current_user }
|
||||
|
||||
resource :projects do
|
||||
helpers do
|
||||
|
@ -70,28 +69,30 @@ module API
|
|||
# POST /projects/:id/merge_requests
|
||||
#
|
||||
post ":id/merge_requests" do
|
||||
authorize! :write_merge_request, user_project
|
||||
required_attributes! [:source_branch, :target_branch, :title]
|
||||
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id]
|
||||
merge_request = user_project.merge_requests.new(attrs)
|
||||
merge_request.author = current_user
|
||||
merge_request.source_project = user_project
|
||||
target_project_id = attrs[:target_project_id]
|
||||
if not_fork?(target_project_id, user_project)
|
||||
merge_request.target_project = user_project
|
||||
else
|
||||
if target_matches_fork(target_project_id,user_project)
|
||||
merge_request.target_project = Project.find_by_id(attrs[:target_project_id])
|
||||
set_current_user_for_thread do
|
||||
authorize! :write_merge_request, user_project
|
||||
required_attributes! [:source_branch, :target_branch, :title]
|
||||
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id]
|
||||
merge_request = user_project.merge_requests.new(attrs)
|
||||
merge_request.author = current_user
|
||||
merge_request.source_project = user_project
|
||||
target_project_id = attrs[:target_project_id]
|
||||
if not_fork?(target_project_id, user_project)
|
||||
merge_request.target_project = user_project
|
||||
else
|
||||
render_api_error!('(Bad Request) Specified target project that is not the source project, or the source fork of the project.', 400)
|
||||
if target_matches_fork(target_project_id,user_project)
|
||||
merge_request.target_project = Project.find_by_id(attrs[:target_project_id])
|
||||
else
|
||||
render_api_error!('(Bad Request) Specified target project that is not the source project, or the source fork of the project.', 400)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if merge_request.save
|
||||
merge_request.reload_code
|
||||
present merge_request, with: Entities::MergeRequest
|
||||
else
|
||||
handle_merge_request_errors! merge_request.errors
|
||||
if merge_request.save
|
||||
merge_request.reload_code
|
||||
present merge_request, with: Entities::MergeRequest
|
||||
else
|
||||
handle_merge_request_errors! merge_request.errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -109,17 +110,19 @@ module API
|
|||
# PUT /projects/:id/merge_request/:merge_request_id
|
||||
#
|
||||
put ":id/merge_request/:merge_request_id" do
|
||||
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event]
|
||||
merge_request = user_project.merge_requests.find(params[:merge_request_id])
|
||||
set_current_user_for_thread do
|
||||
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event]
|
||||
merge_request = user_project.merge_requests.find(params[:merge_request_id])
|
||||
|
||||
authorize! :modify_merge_request, merge_request
|
||||
authorize! :modify_merge_request, merge_request
|
||||
|
||||
if merge_request.update_attributes attrs
|
||||
merge_request.reload_code
|
||||
merge_request.mark_as_unchecked
|
||||
present merge_request, with: Entities::MergeRequest
|
||||
else
|
||||
handle_merge_request_errors! merge_request.errors
|
||||
if merge_request.update_attributes attrs
|
||||
merge_request.reload_code
|
||||
merge_request.mark_as_unchecked
|
||||
present merge_request, with: Entities::MergeRequest
|
||||
else
|
||||
handle_merge_request_errors! merge_request.errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -133,16 +136,18 @@ module API
|
|||
# POST /projects/:id/merge_request/:merge_request_id/comments
|
||||
#
|
||||
post ":id/merge_request/:merge_request_id/comments" do
|
||||
required_attributes! [:note]
|
||||
set_current_user_for_thread do
|
||||
required_attributes! [:note]
|
||||
|
||||
merge_request = user_project.merge_requests.find(params[:merge_request_id])
|
||||
note = merge_request.notes.new(note: params[:note], project_id: user_project.id)
|
||||
note.author = current_user
|
||||
merge_request = user_project.merge_requests.find(params[:merge_request_id])
|
||||
note = merge_request.notes.new(note: params[:note], project_id: user_project.id)
|
||||
note.author = current_user
|
||||
|
||||
if note.save
|
||||
present note, with: Entities::MRNote
|
||||
else
|
||||
not_found!
|
||||
if note.save
|
||||
present note, with: Entities::MRNote
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -40,15 +40,17 @@ module API
|
|||
# Example Request:
|
||||
# POST /projects/:id/milestones
|
||||
post ":id/milestones" do
|
||||
authorize! :admin_milestone, user_project
|
||||
required_attributes! [:title]
|
||||
set_current_user_for_thread do
|
||||
authorize! :admin_milestone, user_project
|
||||
required_attributes! [:title]
|
||||
|
||||
attrs = attributes_for_keys [:title, :description, :due_date]
|
||||
@milestone = user_project.milestones.new attrs
|
||||
if @milestone.save
|
||||
present @milestone, with: Entities::Milestone
|
||||
else
|
||||
not_found!
|
||||
attrs = attributes_for_keys [:title, :description, :due_date]
|
||||
@milestone = user_project.milestones.new attrs
|
||||
if @milestone.save
|
||||
present @milestone, with: Entities::Milestone
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -64,14 +66,16 @@ module API
|
|||
# Example Request:
|
||||
# PUT /projects/:id/milestones/:milestone_id
|
||||
put ":id/milestones/:milestone_id" do
|
||||
authorize! :admin_milestone, user_project
|
||||
set_current_user_for_thread do
|
||||
authorize! :admin_milestone, user_project
|
||||
|
||||
@milestone = user_project.milestones.find(params[:milestone_id])
|
||||
attrs = attributes_for_keys [:title, :description, :due_date, :state_event]
|
||||
if @milestone.update_attributes attrs
|
||||
present @milestone, with: Entities::Milestone
|
||||
else
|
||||
not_found!
|
||||
@milestone = user_project.milestones.find(params[:milestone_id])
|
||||
attrs = attributes_for_keys [:title, :description, :due_date, :state_event]
|
||||
if @milestone.update_attributes attrs
|
||||
present @milestone, with: Entities::Milestone
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,17 +41,19 @@ module API
|
|||
# Example Request:
|
||||
# POST /projects/:id/notes
|
||||
post ":id/notes" do
|
||||
required_attributes! [:body]
|
||||
set_current_user_for_thread do
|
||||
required_attributes! [:body]
|
||||
|
||||
@note = user_project.notes.new(note: params[:body])
|
||||
@note.author = current_user
|
||||
@note = user_project.notes.new(note: params[:body])
|
||||
@note.author = current_user
|
||||
|
||||
if @note.save
|
||||
present @note, with: Entities::Note
|
||||
else
|
||||
# :note is exposed as :body, but :note is set on error
|
||||
bad_request!(:note) if @note.errors[:note].any?
|
||||
not_found!
|
||||
if @note.save
|
||||
present @note, with: Entities::Note
|
||||
else
|
||||
# :note is exposed as :body, but :note is set on error
|
||||
bad_request!(:note) if @note.errors[:note].any?
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -97,17 +99,19 @@ module API
|
|||
# POST /projects/:id/issues/:noteable_id/notes
|
||||
# POST /projects/:id/snippets/:noteable_id/notes
|
||||
post ":id/#{noteables_str}/:#{noteable_id_str}/notes" do
|
||||
required_attributes! [:body]
|
||||
set_current_user_for_thread do
|
||||
required_attributes! [:body]
|
||||
|
||||
@noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
|
||||
@note = @noteable.notes.new(note: params[:body])
|
||||
@note.author = current_user
|
||||
@note.project = user_project
|
||||
@noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
|
||||
@note = @noteable.notes.new(note: params[:body])
|
||||
@note.author = current_user
|
||||
@note.project = user_project
|
||||
|
||||
if @note.save
|
||||
present @note, with: Entities::Note
|
||||
else
|
||||
not_found!
|
||||
if @note.save
|
||||
present @note, with: Entities::Note
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,14 +27,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Project do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
enable_observers
|
||||
Thread.current[:current_user] = user
|
||||
end
|
||||
|
||||
after { disable_observers }
|
||||
before { enable_observers }
|
||||
after { disable_observers }
|
||||
|
||||
describe "Associations" do
|
||||
it { should belong_to(:group) }
|
||||
|
|
|
@ -100,4 +100,16 @@ describe API::API do
|
|||
response.status.should == 405
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /projects/:id/issues/:issue_id to test observer on close" do
|
||||
before { enable_observers }
|
||||
after { disable_observers }
|
||||
|
||||
it "should create an activity event when an issue is closed" do
|
||||
Event.should_receive(:create)
|
||||
|
||||
put api("/projects/#{project.id}/issues/#{issue.id}", user),
|
||||
state_event: "close"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -90,4 +90,16 @@ describe API::API do
|
|||
json_response['state'].should == 'closed'
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /projects/:id/milestones/:milestone_id to test observer on close" do
|
||||
before { enable_observers }
|
||||
after { disable_observers }
|
||||
|
||||
it "should create an activity event when an milestone is closed" do
|
||||
Event.should_receive(:create)
|
||||
|
||||
put api("/projects/#{project.id}/milestones/#{milestone.id}", user),
|
||||
state_event: 'close'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -176,4 +176,16 @@ describe API::API do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /projects/:id/noteable/:noteable_id/notes to test observer on create" do
|
||||
before { enable_observers }
|
||||
after { disable_observers }
|
||||
|
||||
it "should create an activity event when an issue note is created" do
|
||||
Event.should_receive(:create)
|
||||
|
||||
post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -84,6 +84,11 @@ module TestEnv
|
|||
Repository.any_instance.stub(
|
||||
size: 12.45
|
||||
)
|
||||
|
||||
ActivityObserver.any_instance.stub(
|
||||
current_user: double("current_user", id: 1)
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
def clear_repo_dir(namespace, name)
|
||||
|
|
Loading…
Reference in New Issue