From a2021e0bb3ca7de217ba3547909a5f8db84831df Mon Sep 17 00:00:00 2001 From: Igor Drozdov <idrozdov@gitlab.com> Date: Fri, 15 Dec 2023 17:19:50 +0100 Subject: [PATCH] Refactor find certificate logic into a service This service/logic is going to be reused --- .../groups/ssh_certificates/find_service.rb | 35 +++++++ ee/lib/ee/api/internal/base.rb | 10 +- ee/spec/requests/api/internal/base_spec.rb | 10 +- .../ssh_certificates/find_service_spec.rb | 92 +++++++++++++++++++ 4 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 ee/app/services/groups/ssh_certificates/find_service.rb create mode 100644 ee/spec/services/groups/ssh_certificates/find_service_spec.rb diff --git a/ee/app/services/groups/ssh_certificates/find_service.rb b/ee/app/services/groups/ssh_certificates/find_service.rb new file mode 100644 index 000000000000..4b70f09017cf --- /dev/null +++ b/ee/app/services/groups/ssh_certificates/find_service.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Groups + module SshCertificates + class FindService + def initialize(ca_fingerprint, user_identifier) + @ca_fingerprint = ca_fingerprint + @user_identifier = user_identifier + end + + def execute + certificate = ::Groups::SshCertificate.find_by_fingerprint(ca_fingerprint) + return error('Certificate Not Found', :not_found) unless certificate + + group = certificate.group + return error('Feature is not available', :forbidden) unless group.licensed_feature_available?(:ssh_certificates) + + user = group.users.find_by_login(user_identifier) + + return error('User Not Found', :not_found) unless user + return error('Not an Enterprise User of the group', :forbidden) unless user.enterprise_user_of_group?(group) + + ServiceResponse.success(payload: { user: user, group: group }) + end + + private + + attr_reader :ca_fingerprint, :user_identifier + + def error(message, reason) + ServiceResponse.error(message: message, reason: reason) + end + end + end +end diff --git a/ee/lib/ee/api/internal/base.rb b/ee/lib/ee/api/internal/base.rb index 53d27576d7ea..0a212d470cc8 100644 --- a/ee/lib/ee/api/internal/base.rb +++ b/ee/lib/ee/api/internal/base.rb @@ -88,15 +88,11 @@ def two_factor_push_otp_check namespace 'internal' do get '/authorized_certs', feature_category: :source_code_management, urgency: :high do - certificate = ::Groups::SshCertificate.find_by_fingerprint!(params[:key]) - group = certificate.group + response = ::Groups::SshCertificates::FindService.new(params[:key], params[:user_identifier]).execute - forbidden!('Feature is not available') unless group.licensed_feature_available?(:ssh_certificates) + render_api_error!(response.message, response.reason) if response.error? - user = group.users.find_by_login(params[:user_identifier]) - - not_found!('User') unless user - forbidden!('Not an Enterprise User of the group') unless user.enterprise_user_of_group?(group) + group, user = response.payload.values_at(:group, :user) status 200 diff --git a/ee/spec/requests/api/internal/base_spec.rb b/ee/spec/requests/api/internal/base_spec.rb index 0baa1d98ad80..581919183822 100644 --- a/ee/spec/requests/api/internal/base_spec.rb +++ b/ee/spec/requests/api/internal/base_spec.rb @@ -1038,7 +1038,7 @@ def lfs_auth_user(user_id, project) get(api('/internal/authorized_certs'), params: params, headers: gitlab_shell_internal_api_request_header) expect(response).to have_gitlab_http_status(:forbidden) - expect(json_response['message']).to eq('403 Forbidden - Not an Enterprise User of the group') + expect(json_response['message']).to eq('Not an Enterprise User of the group') end end @@ -1062,7 +1062,7 @@ def lfs_auth_user(user_id, project) get(api('/internal/authorized_certs'), params: params, headers: gitlab_shell_internal_api_request_header) expect(response).to have_gitlab_http_status(:not_found) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('Certificate Not Found') end end @@ -1073,7 +1073,7 @@ def lfs_auth_user(user_id, project) get(api('/internal/authorized_certs'), params: params, headers: gitlab_shell_internal_api_request_header) expect(response).to have_gitlab_http_status(:not_found) - expect(json_response['message']).to eq('404 User Not Found') + expect(json_response['message']).to eq('User Not Found') end end end @@ -1083,7 +1083,7 @@ def lfs_auth_user(user_id, project) get(api('/internal/authorized_certs'), params: params, headers: gitlab_shell_internal_api_request_header) expect(response).to have_gitlab_http_status(:not_found) - expect(json_response['message']).to eq('404 User Not Found') + expect(json_response['message']).to eq('User Not Found') end end @@ -1094,7 +1094,7 @@ def lfs_auth_user(user_id, project) get(api('/internal/authorized_certs'), params: params, headers: gitlab_shell_internal_api_request_header) expect(response).to have_gitlab_http_status(:forbidden) - expect(json_response['message']).to eq('403 Forbidden - Feature is not available') + expect(json_response['message']).to eq('Feature is not available') end end end diff --git a/ee/spec/services/groups/ssh_certificates/find_service_spec.rb b/ee/spec/services/groups/ssh_certificates/find_service_spec.rb new file mode 100644 index 000000000000..31478438a34c --- /dev/null +++ b/ee/spec/services/groups/ssh_certificates/find_service_spec.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Groups::SshCertificates::FindService, feature_category: :source_code_management do + let_it_be(:ssh_certificate) { create(:group_ssh_certificate) } + let_it_be(:group) { ssh_certificate.group } + let_it_be(:user) { create(:user, :enterprise_user, enterprise_group: group) } + + let(:ca_fingerprint) { ssh_certificate.fingerprint } + let(:user_identifier) { user.username } + let(:service) { described_class.new(ca_fingerprint, user_identifier) } + + before_all do + group.add_developer(user) + end + + before do + stub_licensed_features(ssh_certificates: true) + end + + describe '#execute' do + it 'returns successful response with payload' do + response = service.execute + + expect(response).to be_success + expect(response.payload).to eq({ user: user, group: group }) + end + + context 'when a certificate not found' do + let(:ca_fingerprint) { 'does not exist' } + + it 'returns not found error' do + response = service.execute + + expect(response).to be_error + expect(response.message).to eq('Certificate Not Found') + expect(response.reason).to eq(:not_found) + end + end + + context 'when ssh_certificates feature is not available' do + it 'returns forbidden error' do + stub_licensed_features(ssh_certificates: false) + + response = service.execute + + expect(response).to be_error + expect(response.message).to eq('Feature is not available') + expect(response.reason).to eq(:forbidden) + end + end + + context 'when a user is not found' do + let(:user_identifier) { 'does not exist' } + + it 'returns not found error' do + response = service.execute + + expect(response).to be_error + expect(response.message).to eq('User Not Found') + expect(response.reason).to eq(:not_found) + end + end + + context 'when a user is not a member' do + let_it_be(:user) { create(:user) } + + it 'returns not found error' do + response = service.execute + + expect(response).to be_error + expect(response.message).to eq('User Not Found') + expect(response.reason).to eq(:not_found) + end + end + + context 'when a user is not an enterprise user' do + let_it_be(:user) { create(:user) } + + it 'returns not found error' do + group.add_developer(user) + + response = service.execute + + expect(response).to be_error + expect(response.message).to eq('Not an Enterprise User of the group') + expect(response.reason).to eq(:forbidden) + end + end + end +end -- GitLab