Commit 03dba1fd authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge pull request #5344 from amacarthur/thread-variable-fix

Fixing unsafe use of Thread.current variable :current_user
parents dad83166 aefe2e95
...@@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base ...@@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :reject_blocked! before_filter :reject_blocked!
before_filter :check_password_expiration 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 :add_abilities
before_filter :dev_tools if Rails.env == 'development' before_filter :dev_tools if Rails.env == 'development'
before_filter :default_headers before_filter :default_headers
...@@ -50,6 +50,11 @@ class ApplicationController < ActionController::Base ...@@ -50,6 +50,11 @@ class ApplicationController < ActionController::Base
def set_current_user_for_thread def set_current_user_for_thread
Thread.current[:current_user] = current_user Thread.current[:current_user] = current_user
begin
yield
ensure
Thread.current[:current_user] = nil
end
end end
def abilities def abilities
......
...@@ -11,6 +11,8 @@ Gitlab::Seeder.quiet do ...@@ -11,6 +11,8 @@ Gitlab::Seeder.quiet do
next unless user next unless user
user_id = user.id user_id = user.id
begin
Thread.current[:current_user] = user Thread.current[:current_user] = user
Issue.seed(:id, [{ Issue.seed(:id, [{
...@@ -22,6 +24,9 @@ Gitlab::Seeder.quiet do ...@@ -22,6 +24,9 @@ Gitlab::Seeder.quiet do
milestone: project.milestones.sample, milestone: project.milestones.sample,
title: Faker::Lorem.sentence(6) title: Faker::Lorem.sentence(6)
}]) }])
ensure
Thread.current[:current_user] = nil
end
print('.') print('.')
end end
......
...@@ -17,6 +17,7 @@ Gitlab::Seeder.quiet do ...@@ -17,6 +17,7 @@ Gitlab::Seeder.quiet do
next if branches.uniq.size < 2 next if branches.uniq.size < 2
user_id = user.id user_id = user.id
begin
Thread.current[:current_user] = user Thread.current[:current_user] = user
MergeRequest.seed(:id, [{ MergeRequest.seed(:id, [{
...@@ -30,6 +31,9 @@ Gitlab::Seeder.quiet do ...@@ -30,6 +31,9 @@ Gitlab::Seeder.quiet do
milestone: project.milestones.sample, milestone: project.milestones.sample,
title: Faker::Lorem.sentence(6) title: Faker::Lorem.sentence(6)
}]) }])
ensure
Thread.current[:current_user] = nil
end
print('.') print('.')
end end
end end
......
...@@ -51,4 +51,6 @@ Spinach.hooks.before_run do ...@@ -51,4 +51,6 @@ Spinach.hooks.before_run do
RSpec::Mocks::setup self RSpec::Mocks::setup self
include FactoryGirl::Syntax::Methods include FactoryGirl::Syntax::Methods
MergeRequestObserver.any_instance.stub(current_user: create(:user))
end end
...@@ -27,6 +27,15 @@ module API ...@@ -27,6 +27,15 @@ module API
end end
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 def user_project
@project ||= find_project(params[:id]) @project ||= find_project(params[:id])
@project || not_found! @project || not_found!
......
...@@ -2,7 +2,6 @@ module API ...@@ -2,7 +2,6 @@ module API
# Issues API # Issues API
class Issues < Grape::API class Issues < Grape::API
before { authenticate! } before { authenticate! }
before { Thread.current[:current_user] = current_user }
resource :issues do resource :issues do
# Get currently authenticated user's issues # Get currently authenticated user's issues
...@@ -49,6 +48,7 @@ module API ...@@ -49,6 +48,7 @@ module API
# Example Request: # Example Request:
# POST /projects/:id/issues # POST /projects/:id/issues
post ":id/issues" do post ":id/issues" do
set_current_user_for_thread do
required_attributes! [:title] required_attributes! [:title]
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id] attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
attrs[:label_list] = params[:labels] if params[:labels].present? attrs[:label_list] = params[:labels] if params[:labels].present?
...@@ -60,6 +60,7 @@ module API ...@@ -60,6 +60,7 @@ module API
not_found! not_found!
end end
end end
end
# Update an existing issue # Update an existing issue
# #
...@@ -75,6 +76,7 @@ module API ...@@ -75,6 +76,7 @@ module API
# Example Request: # Example Request:
# PUT /projects/:id/issues/:issue_id # PUT /projects/:id/issues/:issue_id
put ":id/issues/:issue_id" do put ":id/issues/:issue_id" do
set_current_user_for_thread do
@issue = user_project.issues.find(params[:issue_id]) @issue = user_project.issues.find(params[:issue_id])
authorize! :modify_issue, @issue authorize! :modify_issue, @issue
...@@ -87,6 +89,7 @@ module API ...@@ -87,6 +89,7 @@ module API
not_found! not_found!
end end
end end
end
# Delete a project issue (deprecated) # Delete a project issue (deprecated)
# #
......
...@@ -2,7 +2,6 @@ module API ...@@ -2,7 +2,6 @@ module API
# MergeRequest API # MergeRequest API
class MergeRequests < Grape::API class MergeRequests < Grape::API
before { authenticate! } before { authenticate! }
before { Thread.current[:current_user] = current_user }
resource :projects do resource :projects do
helpers do helpers do
...@@ -70,6 +69,7 @@ module API ...@@ -70,6 +69,7 @@ module API
# POST /projects/:id/merge_requests # POST /projects/:id/merge_requests
# #
post ":id/merge_requests" do post ":id/merge_requests" do
set_current_user_for_thread do
authorize! :write_merge_request, user_project authorize! :write_merge_request, user_project
required_attributes! [:source_branch, :target_branch, :title] required_attributes! [:source_branch, :target_branch, :title]
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id] attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id]
...@@ -94,6 +94,7 @@ module API ...@@ -94,6 +94,7 @@ module API
handle_merge_request_errors! merge_request.errors handle_merge_request_errors! merge_request.errors
end end
end end
end
# Update MR # Update MR
# #
...@@ -109,6 +110,7 @@ module API ...@@ -109,6 +110,7 @@ module API
# PUT /projects/:id/merge_request/:merge_request_id # PUT /projects/:id/merge_request/:merge_request_id
# #
put ":id/merge_request/:merge_request_id" do put ":id/merge_request/:merge_request_id" do
set_current_user_for_thread do
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event] attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event]
merge_request = user_project.merge_requests.find(params[:merge_request_id]) merge_request = user_project.merge_requests.find(params[:merge_request_id])
...@@ -122,6 +124,7 @@ module API ...@@ -122,6 +124,7 @@ module API
handle_merge_request_errors! merge_request.errors handle_merge_request_errors! merge_request.errors
end end
end end
end
# Post comment to merge request # Post comment to merge request
# #
...@@ -133,6 +136,7 @@ module API ...@@ -133,6 +136,7 @@ module API
# POST /projects/:id/merge_request/:merge_request_id/comments # POST /projects/:id/merge_request/:merge_request_id/comments
# #
post ":id/merge_request/:merge_request_id/comments" do post ":id/merge_request/:merge_request_id/comments" do
set_current_user_for_thread do
required_attributes! [:note] required_attributes! [:note]
merge_request = user_project.merge_requests.find(params[:merge_request_id]) merge_request = user_project.merge_requests.find(params[:merge_request_id])
...@@ -145,6 +149,7 @@ module API ...@@ -145,6 +149,7 @@ module API
not_found! not_found!
end end
end end
end
end end
end end
......
...@@ -40,6 +40,7 @@ module API ...@@ -40,6 +40,7 @@ module API
# Example Request: # Example Request:
# POST /projects/:id/milestones # POST /projects/:id/milestones
post ":id/milestones" do post ":id/milestones" do
set_current_user_for_thread do
authorize! :admin_milestone, user_project authorize! :admin_milestone, user_project
required_attributes! [:title] required_attributes! [:title]
...@@ -51,6 +52,7 @@ module API ...@@ -51,6 +52,7 @@ module API
not_found! not_found!
end end
end end
end
# Update an existing project milestone # Update an existing project milestone
# #
...@@ -64,6 +66,7 @@ module API ...@@ -64,6 +66,7 @@ module API
# Example Request: # Example Request:
# PUT /projects/:id/milestones/:milestone_id # PUT /projects/:id/milestones/:milestone_id
put ":id/milestones/:milestone_id" do put ":id/milestones/:milestone_id" do
set_current_user_for_thread do
authorize! :admin_milestone, user_project authorize! :admin_milestone, user_project
@milestone = user_project.milestones.find(params[:milestone_id]) @milestone = user_project.milestones.find(params[:milestone_id])
...@@ -76,4 +79,5 @@ module API ...@@ -76,4 +79,5 @@ module API
end end
end end
end end
end
end end
...@@ -41,6 +41,7 @@ module API ...@@ -41,6 +41,7 @@ module API
# Example Request: # Example Request:
# POST /projects/:id/notes # POST /projects/:id/notes
post ":id/notes" do post ":id/notes" do
set_current_user_for_thread do
required_attributes! [:body] required_attributes! [:body]
@note = user_project.notes.new(note: params[:body]) @note = user_project.notes.new(note: params[:body])
...@@ -54,6 +55,7 @@ module API ...@@ -54,6 +55,7 @@ module API
not_found! not_found!
end end
end end
end
NOTEABLE_TYPES.each do |noteable_type| NOTEABLE_TYPES.each do |noteable_type|
noteables_str = noteable_type.to_s.underscore.pluralize noteables_str = noteable_type.to_s.underscore.pluralize
...@@ -97,6 +99,7 @@ module API ...@@ -97,6 +99,7 @@ module API
# POST /projects/:id/issues/:noteable_id/notes # POST /projects/:id/issues/:noteable_id/notes
# POST /projects/:id/snippets/:noteable_id/notes # POST /projects/:id/snippets/:noteable_id/notes
post ":id/#{noteables_str}/:#{noteable_id_str}/notes" do post ":id/#{noteables_str}/:#{noteable_id_str}/notes" do
set_current_user_for_thread do
required_attributes! [:body] required_attributes! [:body]
@noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
...@@ -113,4 +116,5 @@ module API ...@@ -113,4 +116,5 @@ module API
end end
end end
end end
end
end end
...@@ -27,13 +27,7 @@ ...@@ -27,13 +27,7 @@
require 'spec_helper' require 'spec_helper'
describe Project do describe Project do
let(:user) { create(:user) } before { enable_observers }
before do
enable_observers
Thread.current[:current_user] = user
end
after { disable_observers } after { disable_observers }
describe "Associations" do describe "Associations" do
......
...@@ -100,4 +100,16 @@ describe API::API do ...@@ -100,4 +100,16 @@ describe API::API do
response.status.should == 405 response.status.should == 405
end end
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 end
...@@ -90,4 +90,16 @@ describe API::API do ...@@ -90,4 +90,16 @@ describe API::API do
json_response['state'].should == 'closed' json_response['state'].should == 'closed'
end end
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 end
...@@ -176,4 +176,16 @@ describe API::API do ...@@ -176,4 +176,16 @@ describe API::API do
end end
end 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 end
...@@ -84,6 +84,11 @@ module TestEnv ...@@ -84,6 +84,11 @@ module TestEnv
Repository.any_instance.stub( Repository.any_instance.stub(
size: 12.45 size: 12.45
) )
ActivityObserver.any_instance.stub(
current_user: double("current_user", id: 1)
)
end end
def clear_repo_dir(namespace, name) def clear_repo_dir(namespace, name)
......
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