580 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			580 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
require 'spec_helper'
 | 
						|
require 'raven/transports/dummy'
 | 
						|
require_relative '../../../config/initializers/sentry'
 | 
						|
 | 
						|
RSpec.describe API::Helpers, :enable_admin_mode, feature_category: :authentication_and_authorization do
 | 
						|
  include API::APIGuard::HelperMethods
 | 
						|
  include described_class
 | 
						|
  include TermsHelper
 | 
						|
 | 
						|
  let_it_be(:user, reload: true) { create(:user) }
 | 
						|
 | 
						|
  let(:admin) { create(:admin) }
 | 
						|
  let(:key) { create(:key, user: user) }
 | 
						|
 | 
						|
  let(:csrf_token) { SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) }
 | 
						|
  let(:env) do
 | 
						|
    {
 | 
						|
      'rack.input' => '',
 | 
						|
      'rack.session' => {
 | 
						|
        _csrf_token: csrf_token
 | 
						|
      },
 | 
						|
      'REQUEST_METHOD' => 'GET',
 | 
						|
      'CONTENT_TYPE' => 'text/plain;charset=utf-8'
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  let(:header) {}
 | 
						|
  let(:request) { Grape::Request.new(env) }
 | 
						|
  let(:params) { request.params }
 | 
						|
 | 
						|
  before do
 | 
						|
    allow_any_instance_of(self.class).to receive(:options).and_return({})
 | 
						|
  end
 | 
						|
 | 
						|
  def warden_authenticate_returns(value)
 | 
						|
    warden = double("warden", authenticate: value)
 | 
						|
    env['warden'] = warden
 | 
						|
  end
 | 
						|
 | 
						|
  def error!(message, status, header)
 | 
						|
    raise StandardError, "#{status} - #{message}"
 | 
						|
  end
 | 
						|
 | 
						|
  def set_param(key, value)
 | 
						|
    request.update_param(key, value)
 | 
						|
  end
 | 
						|
 | 
						|
  describe ".current_user" do
 | 
						|
    subject { current_user }
 | 
						|
 | 
						|
    describe "Warden authentication", :allow_forgery_protection do
 | 
						|
      context "with invalid credentials" do
 | 
						|
        context "GET request" do
 | 
						|
          before do
 | 
						|
            env['REQUEST_METHOD'] = 'GET'
 | 
						|
          end
 | 
						|
 | 
						|
          it { is_expected.to be_nil }
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context "with valid credentials" do
 | 
						|
        before do
 | 
						|
          warden_authenticate_returns user
 | 
						|
        end
 | 
						|
 | 
						|
        context "GET request" do
 | 
						|
          before do
 | 
						|
            env['REQUEST_METHOD'] = 'GET'
 | 
						|
          end
 | 
						|
 | 
						|
          it { is_expected.to eq(user) }
 | 
						|
 | 
						|
          it 'sets the environment with data of the current user' do
 | 
						|
            subject
 | 
						|
 | 
						|
            expect(env[API::Helpers::API_USER_ENV]).to eq({ user_id: subject.id, username: subject.username })
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context "HEAD request" do
 | 
						|
          before do
 | 
						|
            env['REQUEST_METHOD'] = 'HEAD'
 | 
						|
          end
 | 
						|
 | 
						|
          it { is_expected.to eq(user) }
 | 
						|
 | 
						|
          context 'when user should have 2fa enabled' do
 | 
						|
            before do
 | 
						|
              allow(user).to receive(:require_two_factor_authentication_from_group?).and_return(true)
 | 
						|
              allow_next_instance_of(Gitlab::Auth::TwoFactorAuthVerifier) do |verifier|
 | 
						|
                allow(verifier).to receive(:two_factor_grace_period_expired?).and_return(true)
 | 
						|
              end
 | 
						|
            end
 | 
						|
 | 
						|
            context 'when 2fa is not enabled' do
 | 
						|
              it { is_expected.to be_nil }
 | 
						|
            end
 | 
						|
 | 
						|
            context 'when 2fa is enabled' do
 | 
						|
              before do
 | 
						|
                allow(user).to receive(:two_factor_enabled?).and_return(true)
 | 
						|
              end
 | 
						|
 | 
						|
              it { is_expected.to eq(user) }
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context "PUT request" do
 | 
						|
          before do
 | 
						|
            env['REQUEST_METHOD'] = 'PUT'
 | 
						|
          end
 | 
						|
 | 
						|
          context 'without CSRF token' do
 | 
						|
            it { is_expected.to be_nil }
 | 
						|
          end
 | 
						|
 | 
						|
          context 'with CSRF token' do
 | 
						|
            before do
 | 
						|
              env['HTTP_X_CSRF_TOKEN'] = csrf_token
 | 
						|
            end
 | 
						|
 | 
						|
            it { is_expected.to eq(user) }
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context "POST request" do
 | 
						|
          before do
 | 
						|
            env['REQUEST_METHOD'] = 'POST'
 | 
						|
          end
 | 
						|
 | 
						|
          context 'without CSRF token' do
 | 
						|
            it { is_expected.to be_nil }
 | 
						|
          end
 | 
						|
 | 
						|
          context 'with CSRF token' do
 | 
						|
            before do
 | 
						|
              env['HTTP_X_CSRF_TOKEN'] = csrf_token
 | 
						|
            end
 | 
						|
 | 
						|
            it { is_expected.to eq(user) }
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context "DELETE request" do
 | 
						|
          before do
 | 
						|
            env['REQUEST_METHOD'] = 'DELETE'
 | 
						|
          end
 | 
						|
 | 
						|
          context 'without CSRF token' do
 | 
						|
            it { is_expected.to be_nil }
 | 
						|
          end
 | 
						|
 | 
						|
          context 'with CSRF token' do
 | 
						|
            before do
 | 
						|
              env['HTTP_X_CSRF_TOKEN'] = csrf_token
 | 
						|
            end
 | 
						|
 | 
						|
            it { is_expected.to eq(user) }
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe "when authenticating using a user's personal access tokens" do
 | 
						|
      let(:personal_access_token) { create(:personal_access_token, user: user) }
 | 
						|
 | 
						|
      it "returns a 401 response for an invalid token" do
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = 'invalid token'
 | 
						|
 | 
						|
        expect { current_user }.to raise_error /401/
 | 
						|
      end
 | 
						|
 | 
						|
      it "returns a 403 response for a user without access" do
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
        allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
 | 
						|
 | 
						|
        expect { current_user }.to raise_error /403/
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns a 403 response for a user who is blocked' do
 | 
						|
        user.block!
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
 | 
						|
        expect { current_user }.to raise_error /403/
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when terms are enforced' do
 | 
						|
        before do
 | 
						|
          enforce_terms
 | 
						|
          env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
        end
 | 
						|
 | 
						|
        it 'returns a 403 when a user has not accepted the terms' do
 | 
						|
          expect { current_user }.to raise_error /must accept the Terms of Service/
 | 
						|
        end
 | 
						|
 | 
						|
        it 'sets the current user when the user accepted the terms' do
 | 
						|
          accept_terms(user)
 | 
						|
 | 
						|
          expect(current_user).to eq(user)
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      it "sets current_user" do
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
        expect(current_user).to eq(user)
 | 
						|
      end
 | 
						|
 | 
						|
      it "does not allow tokens without the appropriate scope" do
 | 
						|
        personal_access_token = create(:personal_access_token, user: user, scopes: ['read_user'])
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
 | 
						|
        expect { current_user }.to raise_error Gitlab::Auth::InsufficientScopeError
 | 
						|
      end
 | 
						|
 | 
						|
      it 'does not allow revoked tokens' do
 | 
						|
        personal_access_token.revoke!
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
 | 
						|
        expect { current_user }.to raise_error Gitlab::Auth::RevokedError
 | 
						|
      end
 | 
						|
 | 
						|
      it 'does not allow expired tokens' do
 | 
						|
        personal_access_token.update!(expires_at: 1.day.ago)
 | 
						|
        env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
 | 
						|
        expect { current_user }.to raise_error Gitlab::Auth::ExpiredError
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when impersonation is disabled' do
 | 
						|
        let(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
 | 
						|
 | 
						|
        before do
 | 
						|
          stub_config_setting(impersonation_enabled: false)
 | 
						|
          env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
 | 
						|
        end
 | 
						|
 | 
						|
        it 'does not allow impersonation tokens' do
 | 
						|
          expect { current_user }.to raise_error Gitlab::Auth::ImpersonationDisabled
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe "when authenticating using a job token" do
 | 
						|
      let_it_be(:job, reload: true) do
 | 
						|
        create(:ci_build, user: user, status: :running)
 | 
						|
      end
 | 
						|
 | 
						|
      let(:route_authentication_setting) { {} }
 | 
						|
 | 
						|
      before do
 | 
						|
        allow_any_instance_of(self.class).to receive(:route_authentication_setting)
 | 
						|
          .and_return(route_authentication_setting)
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when route is allowed to be authenticated' do
 | 
						|
        let(:route_authentication_setting) { { job_token_allowed: true } }
 | 
						|
 | 
						|
        it "returns a 401 response for an invalid token" do
 | 
						|
          env[Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER] = 'invalid token'
 | 
						|
 | 
						|
          expect { current_user }.to raise_error /401/
 | 
						|
        end
 | 
						|
 | 
						|
        it "returns a 401 response for a job that's not running" do
 | 
						|
          job.update!(status: :success)
 | 
						|
          env[Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER] = job.token
 | 
						|
 | 
						|
          expect { current_user }.to raise_error /401/
 | 
						|
        end
 | 
						|
 | 
						|
        it "returns a 403 response for a user without access" do
 | 
						|
          env[Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER] = job.token
 | 
						|
          allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
 | 
						|
 | 
						|
          expect { current_user }.to raise_error /403/
 | 
						|
        end
 | 
						|
 | 
						|
        it 'returns a 403 response for a user who is blocked' do
 | 
						|
          user.block!
 | 
						|
          env[Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER] = job.token
 | 
						|
 | 
						|
          expect { current_user }.to raise_error /403/
 | 
						|
        end
 | 
						|
 | 
						|
        it "sets current_user" do
 | 
						|
          env[Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER] = job.token
 | 
						|
 | 
						|
          expect(current_user).to eq(user)
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when route is not allowed to be authenticated' do
 | 
						|
        let(:route_authentication_setting) { { job_token_allowed: false } }
 | 
						|
 | 
						|
        it "sets current_user to nil" do
 | 
						|
          env[Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER] = job.token
 | 
						|
          allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(true)
 | 
						|
 | 
						|
          expect(current_user).to be_nil
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe '.handle_api_exception' do
 | 
						|
    before do
 | 
						|
      allow_any_instance_of(self.class).to receive(:rack_response)
 | 
						|
 | 
						|
      stub_sentry_settings
 | 
						|
 | 
						|
      expect(Gitlab::ErrorTracking).to receive(:sentry_dsn).and_return(Gitlab.config.sentry.dsn)
 | 
						|
      Gitlab::ErrorTracking.configure
 | 
						|
    end
 | 
						|
 | 
						|
    it 'does not report a MethodNotAllowed exception to Sentry' do
 | 
						|
      exception = Grape::Exceptions::MethodNotAllowed.new({ 'X-GitLab-Test' => '1' })
 | 
						|
      allow(exception).to receive(:backtrace).and_return(caller)
 | 
						|
 | 
						|
      expect(Gitlab::ErrorTracking).not_to receive(:track_exception).with(exception)
 | 
						|
 | 
						|
      handle_api_exception(exception)
 | 
						|
    end
 | 
						|
 | 
						|
    it 'does report RuntimeError to Sentry' do
 | 
						|
      exception = RuntimeError.new('test error')
 | 
						|
      allow(exception).to receive(:backtrace).and_return(caller)
 | 
						|
 | 
						|
      expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception)
 | 
						|
 | 
						|
      Labkit::Correlation::CorrelationId.use_id('new-correlation-id') do
 | 
						|
        handle_api_exception(exception)
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'with a personal access token given' do
 | 
						|
      let(:token) { create(:personal_access_token, scopes: ['api'], user: user) }
 | 
						|
 | 
						|
      # Regression test for https://gitlab.com/gitlab-org/gitlab-foss/issues/38571
 | 
						|
      it 'does not raise an additional exception because of missing `request`' do
 | 
						|
        # We need to stub at a lower level than #sentry_enabled? otherwise
 | 
						|
        # Sentry is not enabled when the request below is made, and the test
 | 
						|
        # would pass even without the fix
 | 
						|
        expect(ProjectsFinder).to receive(:new).and_raise('Runtime Error!')
 | 
						|
 | 
						|
        get api('/projects', personal_access_token: token)
 | 
						|
 | 
						|
        # The 500 status is expected as we're testing a case where an exception
 | 
						|
        # is raised, but Grape shouldn't raise an additional exception
 | 
						|
        expect(response).to have_gitlab_http_status(:internal_server_error)
 | 
						|
        expect(json_response['message']).not_to include("undefined local variable or method `request'")
 | 
						|
        expect(json_response['message']).to start_with("\nRuntimeError (Runtime Error!):")
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe '.authenticate_non_get!' do
 | 
						|
    %w[HEAD GET].each do |method_name|
 | 
						|
      context "method is #{method_name}" do
 | 
						|
        before do
 | 
						|
          expect_any_instance_of(self.class).to receive(:route).and_return(double(request_method: method_name))
 | 
						|
        end
 | 
						|
 | 
						|
        it 'does not raise an error' do
 | 
						|
          expect_any_instance_of(self.class).not_to receive(:authenticate!)
 | 
						|
 | 
						|
          expect { authenticate_non_get! }.not_to raise_error
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    %w[POST PUT PATCH DELETE].each do |method_name|
 | 
						|
      context "method is #{method_name}" do
 | 
						|
        before do
 | 
						|
          expect_any_instance_of(self.class).to receive(:route).and_return(double(request_method: method_name))
 | 
						|
        end
 | 
						|
 | 
						|
        it 'calls authenticate!' do
 | 
						|
          expect_any_instance_of(self.class).to receive(:authenticate!)
 | 
						|
 | 
						|
          authenticate_non_get!
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe '.authenticate!' do
 | 
						|
    context 'current_user is nil' do
 | 
						|
      before do
 | 
						|
        expect_any_instance_of(self.class).to receive(:current_user).and_return(nil)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns a 401 response' do
 | 
						|
        expect { authenticate! }.to raise_error /401/
 | 
						|
 | 
						|
        expect(env[described_class::API_RESPONSE_STATUS_CODE]).to eq(401)
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'current_user is present' do
 | 
						|
      let(:user) { build(:user) }
 | 
						|
 | 
						|
      before do
 | 
						|
        expect_any_instance_of(self.class).to receive(:current_user).and_return(user)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'does not raise an error' do
 | 
						|
        expect { authenticate! }.not_to raise_error
 | 
						|
 | 
						|
        expect(env[described_class::API_RESPONSE_STATUS_CODE]).to be_nil
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  context 'sudo' do
 | 
						|
    include_context 'custom session'
 | 
						|
 | 
						|
    shared_examples 'successful sudo' do
 | 
						|
      it 'sets current_user' do
 | 
						|
        expect(current_user).to eq(user)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'sets sudo?' do
 | 
						|
        expect(sudo?).to be_truthy
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    shared_examples 'sudo' do
 | 
						|
      context 'when admin' do
 | 
						|
        before do
 | 
						|
          token.user = admin
 | 
						|
          token.save!
 | 
						|
        end
 | 
						|
 | 
						|
        context 'when token has sudo scope' do
 | 
						|
          before do
 | 
						|
            token.scopes = %w[sudo]
 | 
						|
            token.save!
 | 
						|
          end
 | 
						|
 | 
						|
          context 'when user exists' do
 | 
						|
            context 'when using header' do
 | 
						|
              context 'when providing username' do
 | 
						|
                before do
 | 
						|
                  env[API::Helpers::SUDO_HEADER] = user.username
 | 
						|
                end
 | 
						|
 | 
						|
                it_behaves_like 'successful sudo'
 | 
						|
              end
 | 
						|
 | 
						|
              context 'when providing username (case insensitive)' do
 | 
						|
                before do
 | 
						|
                  env[API::Helpers::SUDO_HEADER] = user.username.upcase
 | 
						|
                end
 | 
						|
 | 
						|
                it_behaves_like 'successful sudo'
 | 
						|
              end
 | 
						|
 | 
						|
              context 'when providing user ID' do
 | 
						|
                before do
 | 
						|
                  env[API::Helpers::SUDO_HEADER] = user.id.to_s
 | 
						|
                end
 | 
						|
 | 
						|
                it_behaves_like 'successful sudo'
 | 
						|
              end
 | 
						|
            end
 | 
						|
 | 
						|
            context 'when using param' do
 | 
						|
              context 'when providing username' do
 | 
						|
                before do
 | 
						|
                  set_param(API::Helpers::SUDO_PARAM, user.username)
 | 
						|
                end
 | 
						|
 | 
						|
                it_behaves_like 'successful sudo'
 | 
						|
              end
 | 
						|
 | 
						|
              context 'when providing username (case insensitive)' do
 | 
						|
                before do
 | 
						|
                  set_param(API::Helpers::SUDO_PARAM, user.username.upcase)
 | 
						|
                end
 | 
						|
 | 
						|
                it_behaves_like 'successful sudo'
 | 
						|
              end
 | 
						|
 | 
						|
              context 'when providing user ID' do
 | 
						|
                before do
 | 
						|
                  set_param(API::Helpers::SUDO_PARAM, user.id.to_s)
 | 
						|
                end
 | 
						|
 | 
						|
                it_behaves_like 'successful sudo'
 | 
						|
              end
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          context 'when user does not exist' do
 | 
						|
            before do
 | 
						|
              set_param(API::Helpers::SUDO_PARAM, 'nonexistent')
 | 
						|
            end
 | 
						|
 | 
						|
            it 'raises an error' do
 | 
						|
              expect { current_user }.to raise_error /User with ID or username 'nonexistent' Not Found/
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context 'when token does not have sudo scope' do
 | 
						|
          before do
 | 
						|
            token.scopes = %w[api]
 | 
						|
            token.save!
 | 
						|
 | 
						|
            set_param(API::Helpers::SUDO_PARAM, user.id.to_s)
 | 
						|
          end
 | 
						|
 | 
						|
          it 'raises an error' do
 | 
						|
            expect { current_user }.to raise_error Gitlab::Auth::InsufficientScopeError
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when not admin' do
 | 
						|
        before do
 | 
						|
          token.user = user
 | 
						|
          token.save!
 | 
						|
 | 
						|
          set_param(API::Helpers::SUDO_PARAM, user.id.to_s)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'raises an error' do
 | 
						|
          expect { current_user }.to raise_error /Must be admin to use sudo/
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'using an OAuth token' do
 | 
						|
      let(:token) { create(:oauth_access_token) }
 | 
						|
 | 
						|
      before do
 | 
						|
        env['HTTP_AUTHORIZATION'] = "Bearer #{token.plaintext_token}"
 | 
						|
      end
 | 
						|
 | 
						|
      it_behaves_like 'sudo'
 | 
						|
    end
 | 
						|
 | 
						|
    context 'using a personal access token' do
 | 
						|
      let(:token) { create(:personal_access_token) }
 | 
						|
 | 
						|
      context 'passed as param' do
 | 
						|
        before do
 | 
						|
          set_param(Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_PARAM, token.token)
 | 
						|
        end
 | 
						|
 | 
						|
        it_behaves_like 'sudo'
 | 
						|
      end
 | 
						|
 | 
						|
      context 'passed as header' do
 | 
						|
        before do
 | 
						|
          env[Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER] = token.token
 | 
						|
        end
 | 
						|
 | 
						|
        it_behaves_like 'sudo'
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'using warden authentication' do
 | 
						|
      before do
 | 
						|
        warden_authenticate_returns admin
 | 
						|
        env[API::Helpers::SUDO_HEADER] = user.username
 | 
						|
      end
 | 
						|
 | 
						|
      it 'raises an error' do
 | 
						|
        expect { current_user }.to raise_error /Must be authenticated using an OAuth or Personal Access Token to use sudo/
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |