Commit 40f7c788 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Unify finding an actor in the internal API

Reuse the `Support::GitAccessActor` to find an actor for the internal
API.

That way we're a bit closer to having a single way of accessing the
user.
parent 7a0325ce
...@@ -52,12 +52,6 @@ class UserFinder ...@@ -52,12 +52,6 @@ class UserFinder
end end
end end
def find_by_ssh_key_id
return unless input_is_id?
User.find_by_ssh_key_id(@username_or_id)
end
def input_is_id? def input_is_id?
@username_or_id.is_a?(Numeric) || @username_or_id =~ /^\d+$/ @username_or_id.is_a?(Numeric) || @username_or_id =~ /^\d+$/
end end
......
...@@ -7,6 +7,10 @@ module API ...@@ -7,6 +7,10 @@ module API
delegate :wiki?, to: :repo_type delegate :wiki?, to: :repo_type
def actor
@actor ||= Support::GitAccessActor.from_params(params)
end
def repo_type def repo_type
set_project unless defined?(@repo_type) # rubocop:disable Gitlab/ModuleWithInstanceVariables set_project unless defined?(@repo_type) # rubocop:disable Gitlab/ModuleWithInstanceVariables
@repo_type # rubocop:disable Gitlab/ModuleWithInstanceVariables @repo_type # rubocop:disable Gitlab/ModuleWithInstanceVariables
......
...@@ -7,7 +7,6 @@ module API ...@@ -7,7 +7,6 @@ module API
before { authenticate_by_gitlab_shell_token! } before { authenticate_by_gitlab_shell_token! }
helpers ::API::Helpers::InternalHelpers helpers ::API::Helpers::InternalHelpers
helpers ::Gitlab::Identifier
UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze
...@@ -35,7 +34,6 @@ module API ...@@ -35,7 +34,6 @@ module API
env = parse_env env = parse_env
Gitlab::Git::HookEnv.set(gl_repository, env) if project Gitlab::Git::HookEnv.set(gl_repository, env) if project
actor = Support::GitAccessActor.from_params(params)
actor.update_last_used_at! actor.update_last_used_at!
access_checker = access_checker_for(actor, params[:protocol]) access_checker = access_checker_for(actor, params[:protocol])
...@@ -103,36 +101,30 @@ module API ...@@ -103,36 +101,30 @@ module API
check_allowed(params) check_allowed(params)
end end
# rubocop: disable CodeReuse/ActiveRecord
post "/lfs_authenticate" do post "/lfs_authenticate" do
status 200 status 200
if params[:key_id] unless actor.key_or_user
actor = Key.find(params[:key_id]) raise ActiveRecord::RecordNotFound.new('User not found!')
actor.update_last_used_at
elsif params[:user_id]
actor = User.find_by(id: params[:user_id])
raise ActiveRecord::RecordNotFound.new("No such user id!") unless actor
else
raise ActiveRecord::RecordNotFound.new("No key_id or user_id passed!")
end end
actor.update_last_used_at!
Gitlab::LfsToken Gitlab::LfsToken
.new(actor) .new(actor.key_or_user)
.authentication_payload(lfs_authentication_url(project)) .authentication_payload(lfs_authentication_url(project))
end end
# rubocop: enable CodeReuse/ActiveRecord
# #
# Get a ssh key using the fingerprint # Get a ssh key using the fingerprint
# #
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
get "/authorized_keys" do get '/authorized_keys' do
fingerprint = params.fetch(:fingerprint) do fingerprint = params.fetch(:fingerprint) do
Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
end end
key = Key.find_by(fingerprint: fingerprint) key = Key.find_by(fingerprint: fingerprint)
not_found!("Key") if key.nil? not_found!('Key') if key.nil?
present key, with: Entities::SSHKey present key, with: Entities::SSHKey
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
...@@ -141,16 +133,10 @@ module API ...@@ -141,16 +133,10 @@ module API
# Discover user by ssh key, user id or username # Discover user by ssh key, user id or username
# #
get '/discover' do get '/discover' do
if params[:key_id] present actor.user, with: Entities::UserSafe
user = UserFinder.new(params[:key_id]).find_by_ssh_key_id
elsif params[:username]
user = UserFinder.new(params[:username]).find_by_username
end
present user, with: Entities::UserSafe
end end
get "/check" do get '/check' do
{ {
api_version: API.version, api_version: API.version,
gitlab_version: Gitlab::VERSION, gitlab_version: Gitlab::VERSION,
...@@ -158,35 +144,26 @@ module API ...@@ -158,35 +144,26 @@ module API
redis: redis_ping redis: redis_ping
} }
end end
# rubocop: disable CodeReuse/ActiveRecord
post '/two_factor_recovery_codes' do post '/two_factor_recovery_codes' do
status 200 status 200
if params[:key_id] actor.update_last_used_at!
key = Key.find_by(id: params[:key_id]) user = actor.user
if key if params[:key_id]
key.update_last_used_at unless actor.key
else break { success: false, message: 'Could not find the given key' }
break { 'success' => false, 'message' => 'Could not find the given key' }
end end
if key.is_a?(DeployKey) if actor.key.is_a?(DeployKey)
break { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' } break { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' }
end end
user = key.user
unless user unless user
break { success: false, message: 'Could not find a user for the given key' } break { success: false, message: 'Could not find a user for the given key' }
end end
elsif params[:user_id] elsif params[:user_id] && user.nil?
user = User.find_by(id: params[:user_id]) break { success: false, message: 'Could not find the given user' }
unless user
break { success: false, message: 'Could not find the given user' }
end
end end
unless user.two_factor_enabled? unless user.two_factor_enabled?
...@@ -201,7 +178,6 @@ module API ...@@ -201,7 +178,6 @@ module API
{ success: true, recovery_codes: codes } { success: true, recovery_codes: codes }
end end
# rubocop: enable CodeReuse/ActiveRecord
post '/pre_receive' do post '/pre_receive' do
status 200 status 200
...@@ -211,7 +187,7 @@ module API ...@@ -211,7 +187,7 @@ module API
{ reference_counter_increased: reference_counter_increased } { reference_counter_increased: reference_counter_increased }
end end
post "/notify_post_receive" do post '/notify_post_receive' do
status 200 status 200
# TODO: Re-enable when Gitaly is processing the post-receive notification # TODO: Re-enable when Gitaly is processing the post-receive notification
...@@ -229,8 +205,7 @@ module API ...@@ -229,8 +205,7 @@ module API
status 200 status 200
response = Gitlab::InternalPostReceive::Response.new response = Gitlab::InternalPostReceive::Response.new
user = identify(params[:identifier]) user = actor.user
project = Gitlab::GlRepository.parse(params[:gl_repository]).first
push_options = Gitlab::PushOptions.new(params[:push_options]) push_options = Gitlab::PushOptions.new(params[:push_options])
response.reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease response.reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
......
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
module API module API
module Support module Support
class GitAccessActor class GitAccessActor
attr_reader :user extend ::Gitlab::Identifier
attr_reader :user, :key
def initialize(user: nil, key: nil) def initialize(user: nil, key: nil)
@user = user @user = user
...@@ -19,6 +21,10 @@ module API ...@@ -19,6 +21,10 @@ module API
new(user: UserFinder.new(params[:user_id]).find_by_id) new(user: UserFinder.new(params[:user_id]).find_by_id)
elsif params[:username] elsif params[:username]
new(user: UserFinder.new(params[:username]).find_by_username) new(user: UserFinder.new(params[:username]).find_by_username)
elsif params[:identifier]
new(user: identify(params[:identifier]))
else
new
end end
end end
...@@ -33,10 +39,6 @@ module API ...@@ -33,10 +39,6 @@ module API
def update_last_used_at! def update_last_used_at!
key&.update_last_used_at key&.update_last_used_at
end end
private
attr_reader :key
end end
end end
end end
...@@ -176,26 +176,4 @@ describe UserFinder do ...@@ -176,26 +176,4 @@ describe UserFinder do
end end
end end
end end
describe '#find_by_ssh_key_id' do
let_it_be(:ssh_key) { create(:key, user: user) }
it 'returns the user when passing the ssh key id' do
found = described_class.new(ssh_key.id).find_by_ssh_key_id
expect(found).to eq(user)
end
it 'returns the user when passing the ssh key id (string)' do
found = described_class.new(ssh_key.id.to_s).find_by_ssh_key_id
expect(found).to eq(user)
end
it 'returns nil when the id does not exist' do
found = described_class.new(-1).find_by_ssh_key_id
expect(found).to be_nil
end
end
end end
...@@ -9,17 +9,26 @@ describe API::Support::GitAccessActor do ...@@ -9,17 +9,26 @@ describe API::Support::GitAccessActor do
subject { described_class.new(user: user, key: key) } subject { described_class.new(user: user, key: key) }
describe '.from_params' do describe '.from_params' do
let(:key) { create(:key) }
context 'with params that are valid' do context 'with params that are valid' do
it 'returns an instance of API::Support::GitAccessActor' do it 'returns an instance of API::Support::GitAccessActor' do
params = { key_id: create(:key).id } params = { key_id: key.id }
expect(described_class.from_params(params)).to be_instance_of(described_class) expect(described_class.from_params(params)).to be_instance_of(described_class)
end end
end end
context 'with params that are invalid' do context 'with params that are invalid' do
it 'returns nil' do it "returns an instance of #{described_class}" do
expect(described_class.from_params({})).to be_nil expect(described_class.from_params({})).to be_instance_of(described_class)
end
end
context 'when passing an identifier used gitaly' do
it 'finds the user based on an identifier' do
expect(described_class).to receive(:identify).and_call_original
expect(described_class.from_params(identifier: "key-#{key.id}").user).to eq(key.user)
end end
end end
end end
......
...@@ -193,7 +193,15 @@ describe API::Internal::Base do ...@@ -193,7 +193,15 @@ describe API::Internal::Base do
end end
it 'responds successfully when a user is not found' do it 'responds successfully when a user is not found' do
get(api("/internal/discover"), params: { username: 'noone', secret_token: secret_token }) get(api('/internal/discover'), params: { username: 'noone', secret_token: secret_token })
expect(response).to have_gitlab_http_status(200)
expect(response.body).to eq('null')
end
it 'response successfully when passing invalid params' do
get(api('/internal/discover'), params: { nothing: 'to find a user', secret_token: secret_token })
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
...@@ -819,7 +827,6 @@ describe API::Internal::Base do ...@@ -819,7 +827,6 @@ describe API::Internal::Base do
before do before do
project.add_developer(user) project.add_developer(user)
allow(described_class).to receive(:identify).and_return(user)
allow_any_instance_of(Gitlab::Identifier).to receive(:identify).and_return(user) allow_any_instance_of(Gitlab::Identifier).to receive(:identify).and_return(user)
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