summaryrefslogtreecommitdiff
path: root/spec/requests/api/internal/base_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/api/internal/base_spec.rb')
-rw-r--r--spec/requests/api/internal/base_spec.rb334
1 files changed, 202 insertions, 132 deletions
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 4a0a7c81781..ab5f09305ce 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe API::Internal::Base do
+ include APIInternalBaseHelpers
+
let_it_be(:user, reload: true) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :repository, :wiki_repo) }
let_it_be(:personal_snippet) { create(:personal_snippet, :repository, author: user) }
@@ -48,43 +50,63 @@ RSpec.describe API::Internal::Base do
end
end
- describe 'GET /internal/two_factor_recovery_codes' do
- it 'returns an error message when the key does not exist' do
- post api('/internal/two_factor_recovery_codes'),
- params: {
- secret_token: secret_token,
- key_id: non_existing_record_id
- }
+ shared_examples 'actor key validations' do
+ context 'key id is not provided' do
+ let(:key_id) { nil }
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find the given key')
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find a user without a key')
+ end
end
- it 'returns an error message when the key is a deploy key' do
- deploy_key = create(:deploy_key)
+ context 'key does not exist' do
+ let(:key_id) { non_existing_record_id }
- post api('/internal/two_factor_recovery_codes'),
- params: {
- secret_token: secret_token,
- key_id: deploy_key.id
- }
+ it 'returns an error message' do
+ subject
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Deploy keys cannot be used to retrieve recovery codes')
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find the given key')
+ end
+ end
+
+ context 'key without user' do
+ let(:key_id) { create(:key, user: nil).id }
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find a user for the given key')
+ end
end
+ end
- it 'returns an error message when the user does not exist' do
- key_without_user = create(:key, user: nil)
+ describe 'GET /internal/two_factor_recovery_codes' do
+ let(:key_id) { key.id }
+ subject do
post api('/internal/two_factor_recovery_codes'),
params: {
secret_token: secret_token,
- key_id: key_without_user.id
+ key_id: key_id
}
+ end
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find a user for the given key')
- expect(json_response['recovery_codes']).to be_nil
+ it_behaves_like 'actor key validations'
+
+ context 'key is a deploy key' do
+ let(:key_id) { create(:deploy_key).id }
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Deploy keys cannot be used to retrieve recovery codes')
+ end
end
context 'when two-factor is enabled' do
@@ -93,11 +115,7 @@ RSpec.describe API::Internal::Base do
allow_any_instance_of(User)
.to receive(:generate_otp_backup_codes!).and_return(%w(119135e5a3ebce8e 34bd7b74adbc8861))
- post api('/internal/two_factor_recovery_codes'),
- params: {
- secret_token: secret_token,
- key_id: key.id
- }
+ subject
expect(json_response['success']).to be_truthy
expect(json_response['recovery_codes']).to match_array(%w(119135e5a3ebce8e 34bd7b74adbc8861))
@@ -108,11 +126,7 @@ RSpec.describe API::Internal::Base do
it 'returns an error message' do
allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(false)
- post api('/internal/two_factor_recovery_codes'),
- params: {
- secret_token: secret_token,
- key_id: key.id
- }
+ subject
expect(json_response['success']).to be_falsey
expect(json_response['recovery_codes']).to be_nil
@@ -121,42 +135,27 @@ RSpec.describe API::Internal::Base do
end
describe 'POST /internal/personal_access_token' do
- it 'returns an error message when the key does not exist' do
- post api('/internal/personal_access_token'),
- params: {
- secret_token: secret_token,
- key_id: non_existing_record_id
- }
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find the given key')
- end
-
- it 'returns an error message when the key is a deploy key' do
- deploy_key = create(:deploy_key)
+ let(:key_id) { key.id }
+ subject do
post api('/internal/personal_access_token'),
params: {
secret_token: secret_token,
- key_id: deploy_key.id
+ key_id: key_id
}
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Deploy keys cannot be used to create personal access tokens')
end
- it 'returns an error message when the user does not exist' do
- key_without_user = create(:key, user: nil)
+ it_behaves_like 'actor key validations'
- post api('/internal/personal_access_token'),
- params: {
- secret_token: secret_token,
- key_id: key_without_user.id
- }
+ context 'key is a deploy key' do
+ let(:key_id) { create(:deploy_key).id }
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find a user for the given key')
- expect(json_response['token']).to be_nil
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Deploy keys cannot be used to create personal access tokens')
+ end
end
it 'returns an error message when given an non existent user' do
@@ -459,7 +458,7 @@ RSpec.describe API::Internal::Base do
end
it_behaves_like 'sets hook env' do
- let(:gl_repository) { Gitlab::GlRepository::WIKI.identifier_for_container(project) }
+ let(:gl_repository) { Gitlab::GlRepository::WIKI.identifier_for_container(project.wiki) }
end
end
@@ -1207,86 +1206,157 @@ RSpec.describe API::Internal::Base do
end
end
- def gl_repository_for(container)
- case container
- when ProjectWiki
- Gitlab::GlRepository::WIKI.identifier_for_container(container.project)
- when Project
- Gitlab::GlRepository::PROJECT.identifier_for_container(container)
- when Snippet
- Gitlab::GlRepository::SNIPPET.identifier_for_container(container)
- else
- nil
+ describe 'POST /internal/two_factor_config' do
+ let(:key_id) { key.id }
+
+ before do
+ stub_feature_flags(two_factor_for_cli: true)
end
- end
- def full_path_for(container)
- case container
- when PersonalSnippet
- "snippets/#{container.id}"
- when ProjectSnippet
- "#{container.project.full_path}/snippets/#{container.id}"
- else
- container.full_path
+ subject do
+ post api('/internal/two_factor_config'),
+ params: {
+ secret_token: secret_token,
+ key_id: key_id
+ }
end
- end
- def pull(key, container, protocol = 'ssh')
- post(
- api("/internal/allowed"),
- params: {
- key_id: key.id,
- project: full_path_for(container),
- gl_repository: gl_repository_for(container),
- action: 'git-upload-pack',
- secret_token: secret_token,
- protocol: protocol
- }
- )
- end
+ it_behaves_like 'actor key validations'
- def push(key, container, protocol = 'ssh', env: nil, changes: nil)
- push_with_path(key,
- full_path: full_path_for(container),
- gl_repository: gl_repository_for(container),
- protocol: protocol,
- env: env,
- changes: changes)
- end
+ context 'when the key is a deploy key' do
+ let(:key) { create(:deploy_key) }
- def push_with_path(key, full_path:, gl_repository: nil, protocol: 'ssh', env: nil, changes: nil)
- changes ||= 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master'
+ it 'does not required two factor' do
+ subject
- params = {
- changes: changes,
- key_id: key.id,
- project: full_path,
- action: 'git-receive-pack',
- secret_token: secret_token,
- protocol: protocol,
- env: env
- }
- params[:gl_repository] = gl_repository if gl_repository
+ expect(json_response['success']).to be_truthy
+ expect(json_response['two_factor_required']).to be_falsey
+ end
+ end
- post(
- api("/internal/allowed"),
- params: params
- )
+ context 'when two-factor is enabled' do
+ it 'returns user two factor config' do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
+
+ subject
+
+ expect(json_response['success']).to be_truthy
+ expect(json_response['two_factor_required']).to be_truthy
+ end
+ end
+
+ context 'when two-factor is not enabled' do
+ it 'returns an error message' do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(false)
+
+ subject
+
+ expect(json_response['success']).to be_truthy
+ expect(json_response['two_factor_required']).to be_falsey
+ end
+ end
+
+ context 'two_factor_for_cli feature is disabled' do
+ before do
+ stub_feature_flags(two_factor_for_cli: false)
+ end
+
+ context 'when two-factor is enabled for the user' do
+ it 'returns user two factor config' do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
+
+ subject
+
+ expect(json_response['success']).to be_falsey
+ end
+ end
+ end
end
- def archive(key, container)
- post(
- api("/internal/allowed"),
- params: {
- ref: 'master',
- key_id: key.id,
- project: full_path_for(container),
- gl_repository: gl_repository_for(container),
- action: 'git-upload-archive',
- secret_token: secret_token,
- protocol: 'ssh'
- }
- )
+ describe 'POST /internal/two_factor_otp_check' do
+ let(:key_id) { key.id }
+ let(:otp) { '123456'}
+
+ before do
+ stub_feature_flags(two_factor_for_cli: true)
+ end
+
+ subject do
+ post api('/internal/two_factor_otp_check'),
+ params: {
+ secret_token: secret_token,
+ key_id: key_id,
+ otp_attempt: otp
+ }
+ end
+
+ it_behaves_like 'actor key validations'
+
+ context 'when the key is a deploy key' do
+ let(:key_id) { create(:deploy_key).id }
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Deploy keys cannot be used for Two Factor')
+ end
+ end
+
+ context 'when the two factor is enabled' do
+ before do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
+ end
+
+ context 'when the OTP is valid' do
+ it 'returns success' do
+ allow_any_instance_of(Users::ValidateOtpService).to receive(:execute).with(otp).and_return(status: :success)
+
+ subject
+
+ expect(json_response['success']).to be_truthy
+ end
+ end
+
+ context 'when the OTP is invalid' do
+ it 'is not success' do
+ allow_any_instance_of(Users::ValidateOtpService).to receive(:execute).with(otp).and_return(status: :error)
+
+ subject
+
+ expect(json_response['success']).to be_falsey
+ end
+ end
+ end
+
+ context 'when the two factor is disabled' do
+ before do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(false)
+ end
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq 'Two-factor authentication is not enabled for this user'
+ end
+ end
+
+ context 'two_factor_for_cli feature is disabled' do
+ before do
+ stub_feature_flags(two_factor_for_cli: false)
+ end
+
+ context 'when two-factor is enabled for the user' do
+ it 'returns user two factor config' do
+ allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
+
+ subject
+
+ expect(json_response['success']).to be_falsey
+ end
+ end
+ end
end
def lfs_auth_project(project)