Commit 4dfdef2d authored by Timothy Andrew's avatar Timothy Andrew

Allow admins to sudo to blocked users.

- Currently, (for example) admins can't delete snippets for blocked users, which
  is an unexpected limitation.

- We modify `authenticate!` to conduct the `access_api` policy check against the
  `initial_current_user`, instead of the user being impersonated.

- Update CHANGELOG for !10842
parent 6c65b63c
---
title: Allow admins to sudo to blocked users via the API
merge_request: 10842
author:
...@@ -102,7 +102,7 @@ module API ...@@ -102,7 +102,7 @@ module API
end end
def authenticate! def authenticate!
unauthorized! unless current_user && can?(current_user, :access_api) unauthorized! unless current_user && can?(initial_current_user, :access_api)
end end
def authenticate_non_get! def authenticate_non_get!
......
...@@ -427,6 +427,7 @@ describe API::Helpers, api: true do ...@@ -427,6 +427,7 @@ describe API::Helpers, api: true do
context 'current_user is nil' do context 'current_user is nil' do
before do before do
expect_any_instance_of(self.class).to receive(:current_user).and_return(nil) expect_any_instance_of(self.class).to receive(:current_user).and_return(nil)
allow_any_instance_of(self.class).to receive(:initial_current_user).and_return(nil)
end end
it 'returns a 401 response' do it 'returns a 401 response' do
...@@ -435,13 +436,38 @@ describe API::Helpers, api: true do ...@@ -435,13 +436,38 @@ describe API::Helpers, api: true do
end end
context 'current_user is present' do context 'current_user is present' do
let(:user) { build(:user) }
before do before do
expect_any_instance_of(self.class).to receive(:current_user).at_least(:once).and_return(User.new) expect_any_instance_of(self.class).to receive(:current_user).at_least(:once).and_return(user)
expect_any_instance_of(self.class).to receive(:initial_current_user).and_return(user)
end end
it 'does not raise an error' do it 'does not raise an error' do
expect { authenticate! }.not_to raise_error expect { authenticate! }.not_to raise_error
end end
end end
context 'current_user is blocked' do
let(:user) { build(:user, :blocked) }
before do
expect_any_instance_of(self.class).to receive(:current_user).at_least(:once).and_return(user)
end
it 'raises an error' do
expect_any_instance_of(self.class).to receive(:initial_current_user).and_return(user)
expect { authenticate! }.to raise_error '401 - {"message"=>"401 Unauthorized"}'
end
it "doesn't raise an error if an admin user is impersonating a blocked user (via sudo)" do
admin_user = build(:user, :admin)
expect_any_instance_of(self.class).to receive(:initial_current_user).and_return(admin_user)
expect { authenticate! }.not_to raise_error
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