Commit 35f1dd93 authored by Nikola Milojevic's avatar Nikola Milojevic

Merge branch 'incubation-5mp-tracking' into 'master'

Track `Projects::GoogleCloud` events with Snowplow

See merge request gitlab-org/gitlab!81890
parents d3e7bd2f 6c99dd3a
...@@ -10,18 +10,25 @@ class Projects::GoogleCloud::BaseController < Projects::ApplicationController ...@@ -10,18 +10,25 @@ class Projects::GoogleCloud::BaseController < Projects::ApplicationController
private private
def admin_project_google_cloud! def admin_project_google_cloud!
access_denied! unless can?(current_user, :admin_project_google_cloud, project) unless can?(current_user, :admin_project_google_cloud, project)
track_event('admin_project_google_cloud!', 'access_denied', 'invalid_user')
access_denied!
end
end end
def google_oauth2_enabled! def google_oauth2_enabled!
config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2') config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2')
if config.app_id.blank? || config.app_secret.blank? if config.app_id.blank? || config.app_secret.blank?
track_event('google_oauth2_enabled!', 'access_denied', { reason: 'google_oauth2_not_configured', config: config })
access_denied! 'This GitLab instance not configured for Google Oauth2.' access_denied! 'This GitLab instance not configured for Google Oauth2.'
end end
end end
def feature_flag_enabled! def feature_flag_enabled!
access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud, project) unless Feature.enabled?(:incubation_5mp_google_cloud, project)
track_event('feature_flag_enabled!', 'access_denied', 'feature_flag_not_enabled')
access_denied!
end
end end
def validate_gcp_token! def validate_gcp_token!
...@@ -53,9 +60,21 @@ class Projects::GoogleCloud::BaseController < Projects::ApplicationController ...@@ -53,9 +60,21 @@ class Projects::GoogleCloud::BaseController < Projects::ApplicationController
session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
end end
def handle_gcp_error(error, project) def handle_gcp_error(action, error)
Gitlab::ErrorTracking.track_exception(error, project_id: project.id) track_event(action, 'gcp_error', error)
@js_data = { screen: 'gcp_error', error: error.to_s }.to_json @js_data = { screen: 'gcp_error', error: error.to_s }.to_json
render status: :unauthorized, template: 'projects/google_cloud/errors/gcp_error' render status: :unauthorized, template: 'projects/google_cloud/errors/gcp_error'
end end
def track_event(action, label, property)
options = { label: label, project: project, user: current_user }
if property.is_a?(String)
options[:property] = property
else
options[:extra] = property
end
Gitlab::Tracking.event('Projects::GoogleCloud', action, **options)
end
end end
...@@ -9,6 +9,7 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base ...@@ -9,6 +9,7 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base
.new(project, current_user, params).execute .new(project, current_user, params).execute
if enable_cloud_run_response[:status] == :error if enable_cloud_run_response[:status] == :error
track_event('deployments#cloud_run', 'enable_cloud_run_error', enable_cloud_run_response)
flash[:error] = enable_cloud_run_response[:message] flash[:error] = enable_cloud_run_response[:message]
redirect_to project_google_cloud_index_path(project) redirect_to project_google_cloud_index_path(project)
else else
...@@ -17,15 +18,17 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base ...@@ -17,15 +18,17 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base
.new(project, current_user, params).execute .new(project, current_user, params).execute
if generate_pipeline_response[:status] == :error if generate_pipeline_response[:status] == :error
track_event('deployments#cloud_run', 'generate_pipeline_error', generate_pipeline_response)
flash[:error] = 'Failed to generate pipeline' flash[:error] = 'Failed to generate pipeline'
redirect_to project_google_cloud_index_path(project) redirect_to project_google_cloud_index_path(project)
else else
cloud_run_mr_params = cloud_run_mr_params(generate_pipeline_response[:branch_name]) cloud_run_mr_params = cloud_run_mr_params(generate_pipeline_response[:branch_name])
track_event('deployments#cloud_run', 'cloud_run_success', cloud_run_mr_params)
redirect_to project_new_merge_request_path(project, merge_request: cloud_run_mr_params) redirect_to project_new_merge_request_path(project, merge_request: cloud_run_mr_params)
end end
end end
rescue Google::Apis::ClientError => error rescue Google::Apis::ClientError => error
handle_gcp_error(error, project) handle_gcp_error('deployments#cloud_run', error)
end end
def cloud_storage def cloud_storage
......
...@@ -18,13 +18,13 @@ class Projects::GoogleCloud::GcpRegionsController < Projects::GoogleCloud::BaseC ...@@ -18,13 +18,13 @@ class Projects::GoogleCloud::GcpRegionsController < Projects::GoogleCloud::BaseC
refs: refs, refs: refs,
cancelPath: project_google_cloud_index_path(project) cancelPath: project_google_cloud_index_path(project)
}.to_json }.to_json
track_event('gcp_regions#index', 'form_render', @js_data)
end end
def create def create
permitted_params = params.permit(:ref, :gcp_region) permitted_params = params.permit(:ref, :gcp_region)
response = GoogleCloud::GcpRegionAddOrReplaceService.new(project).execute(permitted_params[:ref], permitted_params[:gcp_region])
GoogleCloud::GcpRegionAddOrReplaceService.new(project).execute(permitted_params[:ref], permitted_params[:gcp_region]) track_event('gcp_regions#create', 'form_submit', response)
redirect_to project_google_cloud_index_path(project), notice: _('GCP region configured') redirect_to project_google_cloud_index_path(project), notice: _('GCP region configured')
end end
end end
...@@ -10,6 +10,7 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: ...@@ -10,6 +10,7 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::
if gcp_projects.empty? if gcp_projects.empty?
@js_data = { screen: 'no_gcp_projects' }.to_json @js_data = { screen: 'no_gcp_projects' }.to_json
track_event('service_accounts#index', 'form_error', 'no_gcp_projects')
render status: :unauthorized, template: 'projects/google_cloud/errors/no_gcp_projects' render status: :unauthorized, template: 'projects/google_cloud/errors/no_gcp_projects'
else else
params = { per_page: 50 } params = { per_page: 50 }
...@@ -22,9 +23,11 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: ...@@ -22,9 +23,11 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::
refs: refs, refs: refs,
cancelPath: project_google_cloud_index_path(project) cancelPath: project_google_cloud_index_path(project)
}.to_json }.to_json
track_event('service_accounts#index', 'form_success', @js_data)
end end
rescue Google::Apis::ClientError => error rescue Google::Apis::ClientError => error
handle_gcp_error(error, project) handle_gcp_error('service_accounts#index', error)
end end
def create def create
...@@ -38,8 +41,9 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: ...@@ -38,8 +41,9 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::
environment_name: permitted_params[:ref] environment_name: permitted_params[:ref]
).execute ).execute
track_event('service_accounts#create', 'form_submit', response)
redirect_to project_google_cloud_index_path(project), notice: response.message redirect_to project_google_cloud_index_path(project), notice: response.message
rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error
handle_gcp_error(error, project) handle_gcp_error('service_accounts#create', error)
end end
end end
...@@ -14,6 +14,7 @@ class Projects::GoogleCloudController < Projects::GoogleCloud::BaseController ...@@ -14,6 +14,7 @@ class Projects::GoogleCloudController < Projects::GoogleCloud::BaseController
configureGcpRegionsUrl: project_google_cloud_gcp_regions_path(project), configureGcpRegionsUrl: project_google_cloud_gcp_regions_path(project),
gcpRegions: gcp_regions gcpRegions: gcp_regions
}.to_json }.to_json
track_event('google_cloud#index', 'index', @js_data)
end end
private private
......
...@@ -22,13 +22,21 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do ...@@ -22,13 +22,21 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
project.add_maintainer(user_maintainer) project.add_maintainer(user_maintainer)
end end
describe "Routes must be restricted behind Google OAuth2" do describe "Routes must be restricted behind Google OAuth2", :snowplow do
context 'when a public request is made' do context 'when a public request is made' do
it 'returns not found on GET request' do it 'returns not found on GET request' do
urls_list.each do |url| urls_list.each do |url|
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: nil
)
end end
end end
end end
...@@ -40,6 +48,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do ...@@ -40,6 +48,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: nil
)
end end
end end
end end
...@@ -60,7 +76,7 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do ...@@ -60,7 +76,7 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
end end
end end
describe 'Authorized GET project/-/google_cloud/deployments/cloud_run' do describe 'Authorized GET project/-/google_cloud/deployments/cloud_run', :snowplow do
let_it_be(:url) { "#{project_google_cloud_deployments_cloud_run_path(project)}" } let_it_be(:url) { "#{project_google_cloud_deployments_cloud_run_path(project)}" }
before do before do
...@@ -72,25 +88,39 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do ...@@ -72,25 +88,39 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
end end
it 'redirects to google_cloud home on enable service error' do it 'redirects to google_cloud home on enable service error' do
# since GPC_PROJECT_ID is not set, enable cloud run service should return an error
get url get url
expect(response).to redirect_to(project_google_cloud_index_path(project)) expect(response).to redirect_to(project_google_cloud_index_path(project))
# since GPC_PROJECT_ID is not set, enable cloud run service should return an error
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'deployments#cloud_run',
label: 'enable_cloud_run_error',
extra: { message: 'No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.',
status: :error },
project: project,
user: user_maintainer
)
end end
it 'tracks error and redirects to gcp_error' do it 'redirects to gcp_error' do
mock_google_error = Google::Apis::ClientError.new('some_error') mock_gcp_error = Google::Apis::ClientError.new('some_error')
allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service| allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service|
allow(service).to receive(:execute).and_raise(mock_google_error) allow(service).to receive(:execute).and_raise(mock_gcp_error)
end end
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(mock_google_error, { project_id: project.id })
get url get url
expect(response).to render_template(:gcp_error) expect(response).to render_template(:gcp_error)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'deployments#cloud_run',
label: 'gcp_error',
extra: mock_gcp_error,
project: project,
user: user_maintainer
)
end end
context 'GCP_PROJECT_IDs are defined' do context 'GCP_PROJECT_IDs are defined' do
...@@ -106,6 +136,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do ...@@ -106,6 +136,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
get url get url
expect(response).to redirect_to(project_google_cloud_index_path(project)) expect(response).to redirect_to(project_google_cloud_index_path(project))
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'deployments#cloud_run',
label: 'generate_pipeline_error',
extra: { status: :error },
project: project,
user: user_maintainer
)
end end
it 'redirects to create merge request form' do it 'redirects to create merge request form' do
...@@ -121,11 +159,24 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do ...@@ -121,11 +159,24 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
expect(response).to have_gitlab_http_status(:found) expect(response).to have_gitlab_http_status(:found)
expect(response.location).to include(project_new_merge_request_path(project)) expect(response.location).to include(project_new_merge_request_path(project))
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'deployments#cloud_run',
label: 'cloud_run_success',
extra: { "title": "Enable deployments to Cloud Run",
"description": "This merge request includes a Cloud Run deployment job in the pipeline definition (.gitlab-ci.yml).\n\nThe `deploy-to-cloud-run` job:\n* Requires the following environment variables\n * `GCP_PROJECT_ID`\n * `GCP_SERVICE_ACCOUNT_KEY`\n* Job definition can be found at: https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library\n\nThis pipeline definition has been committed to the branch ``.\nYou may modify the pipeline definition further or accept the changes as-is if suitable.\n",
"source_project_id": project.id,
"target_project_id": project.id,
"source_branch": nil,
"target_branch": project.default_branch },
project: project,
user: user_maintainer
)
end end
end end
end end
describe 'Authorized GET project/-/google_cloud/deployments/cloud_storage' do describe 'Authorized GET project/-/google_cloud/deployments/cloud_storage', :snowplow do
let_it_be(:url) { "#{project_google_cloud_deployments_cloud_storage_path(project)}" } let_it_be(:url) { "#{project_google_cloud_deployments_cloud_storage_path(project)}" }
before do before do
......
...@@ -6,6 +6,65 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do ...@@ -6,6 +6,65 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do
let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:repository) { project.repository } let_it_be(:repository) { project.repository }
let(:user_guest) { create(:user) }
let(:user_maintainer) { create(:user) }
RSpec.shared_examples "should track not_found event" do
it "tracks event" do
is_expected.to be(404)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: nil
)
end
end
RSpec.shared_examples "should track access_denied event" do
it "tracks event" do
is_expected.to be(404)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: nil
)
end
end
RSpec.shared_examples "should track feature_flag_disabled event" do |user|
it "tracks event" do
is_expected.to be(404)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'feature_flag_enabled!',
label: 'access_denied',
property: 'feature_flag_not_enabled',
project: project,
user: user_maintainer
)
end
end
RSpec.shared_examples "should track gcp_error event" do |config|
it "tracks event" do
is_expected.to be(403)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'google_oauth2_enabled!',
label: 'access_denied',
extra: { reason: 'google_oauth2_not_configured', config: config },
project: project,
user: user_maintainer
)
end
end
RSpec.shared_examples "should be not found" do RSpec.shared_examples "should be not found" do
it 'returns not found' do it 'returns not found' do
is_expected.to be(404) is_expected.to be(404)
...@@ -20,27 +79,25 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do ...@@ -20,27 +79,25 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do
RSpec.shared_examples "public request should 404" do RSpec.shared_examples "public request should 404" do
it_behaves_like "should be not found" it_behaves_like "should be not found"
it_behaves_like "should track not_found event"
end end
RSpec.shared_examples "unauthorized access should 404" do RSpec.shared_examples "unauthorized access should 404" do
let(:user_guest) { create(:user) }
before do before do
project.add_guest(user_guest) project.add_guest(user_guest)
end end
it_behaves_like "should be not found" it_behaves_like "should be not found"
it_behaves_like "should track access_denied event"
end end
describe 'GET #index' do describe 'GET #index', :snowplow do
subject { get project_google_cloud_gcp_regions_path(project) } subject { get project_google_cloud_gcp_regions_path(project) }
it_behaves_like "public request should 404" it_behaves_like "public request should 404"
it_behaves_like "unauthorized access should 404" it_behaves_like "unauthorized access should 404"
context 'when authorized members make requests' do context 'when authorized members make requests' do
let(:user_maintainer) { create(:user) }
before do before do
project.add_maintainer(user_maintainer) project.add_maintainer(user_maintainer)
sign_in(user_maintainer) sign_in(user_maintainer)
...@@ -51,15 +108,17 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do ...@@ -51,15 +108,17 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do
end end
context 'but gitlab instance is not configured for google oauth2' do context 'but gitlab instance is not configured for google oauth2' do
unconfigured_google_oauth2 = Struct.new(:app_id, :app_secret)
.new('', '')
before do before do
unconfigured_google_oauth2 = Struct.new(:app_id, :app_secret)
.new('', '')
allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for) allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
.with('google_oauth2') .with('google_oauth2')
.and_return(unconfigured_google_oauth2) .and_return(unconfigured_google_oauth2)
end end
it_behaves_like "should be forbidden" it_behaves_like "should be forbidden"
it_behaves_like "should track gcp_error event", unconfigured_google_oauth2
end end
context 'but feature flag is disabled' do context 'but feature flag is disabled' do
...@@ -68,19 +127,18 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do ...@@ -68,19 +127,18 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do
end end
it_behaves_like "should be not found" it_behaves_like "should be not found"
it_behaves_like "should track feature_flag_disabled event"
end end
end end
end end
describe 'POST #index' do describe 'POST #index', :snowplow do
subject { post project_google_cloud_gcp_regions_path(project), params: { gcp_region: 'region1', environment: 'env1' } } subject { post project_google_cloud_gcp_regions_path(project), params: { gcp_region: 'region1', environment: 'env1' } }
it_behaves_like "public request should 404" it_behaves_like "public request should 404"
it_behaves_like "unauthorized access should 404" it_behaves_like "unauthorized access should 404"
context 'when authorized members make requests' do context 'when authorized members make requests' do
let(:user_maintainer) { create(:user) }
before do before do
project.add_maintainer(user_maintainer) project.add_maintainer(user_maintainer)
sign_in(user_maintainer) sign_in(user_maintainer)
......
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::GoogleCloud::ServiceAccountsController do RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
let_it_be(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }
describe 'GET index' do describe 'GET index', :snowplow do
let_it_be(:url) { "#{project_google_cloud_service_accounts_path(project)}" } let_it_be(:url) { "#{project_google_cloud_service_accounts_path(project)}" }
let(:user_guest) { create(:user) } let(:user_guest) { create(:user) }
...@@ -27,6 +27,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do ...@@ -27,6 +27,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: nil
)
end end
it 'returns not found on POST request' do it 'returns not found on POST request' do
...@@ -42,6 +50,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do ...@@ -42,6 +50,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
sign_in(unauthorized_member) sign_in(unauthorized_member)
get url get url
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: unauthorized_member
)
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
...@@ -52,6 +68,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do ...@@ -52,6 +68,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
sign_in(unauthorized_member) sign_in(unauthorized_member)
post url post url
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: unauthorized_member
)
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
...@@ -80,42 +104,75 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do ...@@ -80,42 +104,75 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
end end
context 'and user has successfully completed the google oauth2 flow' do context 'and user has successfully completed the google oauth2 flow' do
before do context 'but the user does not have gcp projects' do
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client| before do
mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l') allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
allow(client).to receive(:validate_token).and_return(true) mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l')
allow(client).to receive(:list_projects).and_return([{}, {}, {}]) allow(client).to receive(:list_projects).and_return([])
allow(client).to receive(:create_service_account).and_return(mock_service_account) allow(client).to receive(:validate_token).and_return(true)
allow(client).to receive(:create_service_account_key).and_return({}) allow(client).to receive(:create_service_account).and_return(mock_service_account)
allow(client).to receive(:grant_service_account_roles) allow(client).to receive(:create_service_account_key).and_return({})
allow(client).to receive(:grant_service_account_roles)
end
end end
end
it 'returns success on GET' do it 'renders no_gcp_projects' do
authorized_members.each do |authorized_member| authorized_members.each do |authorized_member|
allow_next_instance_of(BranchesFinder) do |branches_finder| allow_next_instance_of(BranchesFinder) do |branches_finder|
allow(branches_finder).to receive(:execute).and_return([]) allow(branches_finder).to receive(:execute).and_return([])
end
allow_next_instance_of(TagsFinder) do |branches_finder|
allow(branches_finder).to receive(:execute).and_return([])
end
sign_in(authorized_member)
get url
expect(response).to render_template('projects/google_cloud/errors/no_gcp_projects')
end end
end
end
allow_next_instance_of(TagsFinder) do |branches_finder| context 'user has three gcp_projects' do
allow(branches_finder).to receive(:execute).and_return([]) before do
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l')
allow(client).to receive(:list_projects).and_return([{}, {}, {}])
allow(client).to receive(:validate_token).and_return(true)
allow(client).to receive(:create_service_account).and_return(mock_service_account)
allow(client).to receive(:create_service_account_key).and_return({})
allow(client).to receive(:grant_service_account_roles)
end end
end
sign_in(authorized_member) it 'returns success on GET' do
authorized_members.each do |authorized_member|
allow_next_instance_of(BranchesFinder) do |branches_finder|
allow(branches_finder).to receive(:execute).and_return([])
end
get url allow_next_instance_of(TagsFinder) do |branches_finder|
allow(branches_finder).to receive(:execute).and_return([])
end
sign_in(authorized_member)
get url
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end
end end
end
it 'returns success on POST' do it 'returns success on POST' do
authorized_members.each do |authorized_member| authorized_members.each do |authorized_member|
sign_in(authorized_member) sign_in(authorized_member)
post url, params: { gcp_project: 'prj1', ref: 'env1' } post url, params: { gcp_project: 'prj1', ref: 'env1' }
expect(response).to redirect_to(project_google_cloud_index_path(project)) expect(response).to redirect_to(project_google_cloud_index_path(project))
end
end end
end end
end end
......
...@@ -8,7 +8,7 @@ MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret) ...@@ -8,7 +8,7 @@ MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret)
RSpec.describe Projects::GoogleCloudController do RSpec.describe Projects::GoogleCloudController do
let_it_be(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }
describe 'GET index' do describe 'GET index', :snowplow do
let_it_be(:url) { "#{project_google_cloud_index_path(project)}" } let_it_be(:url) { "#{project_google_cloud_index_path(project)}" }
context 'when a public request is made' do context 'when a public request is made' do
...@@ -16,6 +16,13 @@ RSpec.describe Projects::GoogleCloudController do ...@@ -16,6 +16,13 @@ RSpec.describe Projects::GoogleCloudController do
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: nil)
end end
end end
...@@ -29,6 +36,14 @@ RSpec.describe Projects::GoogleCloudController do ...@@ -29,6 +36,14 @@ RSpec.describe Projects::GoogleCloudController do
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: user
)
end end
end end
...@@ -42,6 +57,14 @@ RSpec.describe Projects::GoogleCloudController do ...@@ -42,6 +57,14 @@ RSpec.describe Projects::GoogleCloudController do
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'admin_project_google_cloud!',
label: 'access_denied',
property: 'invalid_user',
project: project,
user: user
)
end end
end end
...@@ -74,19 +97,26 @@ RSpec.describe Projects::GoogleCloudController do ...@@ -74,19 +97,26 @@ RSpec.describe Projects::GoogleCloudController do
let(:user) { project.creator } let(:user) { project.creator }
context 'but gitlab instance is not configured for google oauth2' do context 'but gitlab instance is not configured for google oauth2' do
before do it 'returns forbidden' do
unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '') unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '')
allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for) allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
.with('google_oauth2') .with('google_oauth2')
.and_return(unconfigured_google_oauth2) .and_return(unconfigured_google_oauth2)
end
it 'returns forbidden' do
sign_in(user) sign_in(user)
get url get url
expect(response).to have_gitlab_http_status(:forbidden) expect(response).to have_gitlab_http_status(:forbidden)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'google_oauth2_enabled!',
label: 'access_denied',
extra: { reason: 'google_oauth2_not_configured',
config: unconfigured_google_oauth2 },
project: project,
user: user
)
end end
end end
...@@ -101,6 +131,14 @@ RSpec.describe Projects::GoogleCloudController do ...@@ -101,6 +131,14 @@ RSpec.describe Projects::GoogleCloudController do
get url get url
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
expect_snowplow_event(
category: 'Projects::GoogleCloud',
action: 'feature_flag_enabled!',
label: 'access_denied',
property: 'feature_flag_not_enabled',
project: project,
user: user
)
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