Commit 6172b14a authored by Max Woolf's avatar Max Woolf

Merge branch '351602-auditor-group-level-events' into 'master'

Ensures audit events are visible to auditor at Group level

See merge request gitlab-org/gitlab!81267
parents 458ec608 662a01dc
...@@ -44,6 +44,8 @@ class Groups::AuditEventsController < Groups::ApplicationController ...@@ -44,6 +44,8 @@ class Groups::AuditEventsController < Groups::ApplicationController
end end
def filter_by_author(params) def filter_by_author(params)
can?(current_user, :admin_group, group) ? params : params.merge(author_id: current_user.id) return params if can?(current_user, :admin_group, group) || current_user.auditor?
params.merge(author_id: current_user.id)
end end
end end
...@@ -270,6 +270,7 @@ module EE ...@@ -270,6 +270,7 @@ module EE
rule { auditor }.policy do rule { auditor }.policy do
enable :read_group enable :read_group
enable :read_group_security_dashboard enable :read_group_security_dashboard
enable :read_group_audit_events
end end
rule { group_saml_config_enabled & group_saml_available & (admin | owner) }.enable :admin_group_saml rule { group_saml_config_enabled & group_saml_available & (admin | owner) }.enable :admin_group_saml
......
...@@ -7,6 +7,7 @@ RSpec.describe Groups::AuditEventsController do ...@@ -7,6 +7,7 @@ RSpec.describe Groups::AuditEventsController do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:owner) { create(:user) } let_it_be(:owner) { create(:user) }
let_it_be(:auditor) { create(:user, auditor: true) }
let_it_be(:group) { create(:group, :private) } let_it_be(:group) { create(:group, :private) }
let_it_be(:events) { create_list(:group_audit_event, 5, entity_id: group.id) } let_it_be(:events) { create_list(:group_audit_event, 5, entity_id: group.id) }
...@@ -15,152 +16,177 @@ RSpec.describe Groups::AuditEventsController do ...@@ -15,152 +16,177 @@ RSpec.describe Groups::AuditEventsController do
let(:entity_type) { nil } let(:entity_type) { nil }
let(:entity_id) { nil } let(:entity_id) { nil }
context 'authorized' do shared_context 'when audit_events feature is available' do
let(:level) { Gitlab::Audit::Levels::Group.new(group: group) }
let(:audit_logs_params) { ActionController::Parameters.new(sort: '', entity_type: '', entity_id: '', created_after: Date.current.beginning_of_month, created_before: Date.current.end_of_day).permit! }
before do before do
group.add_owner(owner) stub_licensed_features(audit_events: true)
sign_in(owner)
allow(Gitlab::Audit::Levels::Group).to receive(:new).and_return(level)
allow(AuditLogFinder).to receive(:new).and_call_original
end end
context do shared_examples 'AuditLogFinder params' do
let(:request) do it 'has the correct params' do
get :index, params: { group_id: group.to_param, sort: sort, entity_type: entity_type, entity_id: entity_id } request
expect(AuditLogFinder).to have_received(:new).with(
level: level, params: audit_logs_params
)
end end
end
context 'when audit_events feature is available' do it 'renders index with 200 status code' do
let(:level) { Gitlab::Audit::Levels::Group.new(group: group) } request
let(:audit_logs_params) { ActionController::Parameters.new(sort: '', entity_type: '', entity_id: '', created_after: Date.current.beginning_of_month, created_before: Date.current.end_of_day).permit! }
before do expect(response).to have_gitlab_http_status(:ok)
stub_licensed_features(audit_events: true) expect(response).to render_template(:index)
end
allow(Gitlab::Audit::Levels::Group).to receive(:new).and_return(level) context 'invokes AuditLogFinder with correct arguments' do
allow(AuditLogFinder).to receive(:new).and_call_original it_behaves_like 'AuditLogFinder params'
end end
shared_examples 'AuditLogFinder params' do context 'author' do
it 'has the correct params' do context 'when no author entity type is specified' do
request it_behaves_like 'AuditLogFinder params'
end
expect(AuditLogFinder).to have_received(:new).with( context 'when the author entity type is specified' do
level: level, params: audit_logs_params let(:entity_type) { 'Author' }
) let(:entity_id) { 1 }
end let(:audit_logs_params) { ActionController::Parameters.new(sort: '', author_id: '1', created_after: Date.current.beginning_of_month, created_before: Date.current.end_of_day).permit! }
end
it 'renders index with 200 status code' do it_behaves_like 'AuditLogFinder params'
end
end
context 'ordering' do
shared_examples 'orders by id descending' do
it 'orders by id descending' do
request request
expect(response).to have_gitlab_http_status(:ok) actual_event_ids = assigns(:events).map { |event| event[:id] }
expect(response).to render_template(:index) expected_event_ids = events.map(&:id).reverse
end
context 'invokes AuditLogFinder with correct arguments' do expect(actual_event_ids).to eq(expected_event_ids)
it_behaves_like 'AuditLogFinder params'
end end
end
context 'when no sort order is specified' do
it_behaves_like 'orders by id descending'
end
context 'when sorting by latest events first' do
let(:sort) { 'created_desc' }
context 'author' do it_behaves_like 'orders by id descending'
context 'when no author entity type is specified' do end
it_behaves_like 'AuditLogFinder params'
end context 'when sorting by oldest events first' do
let(:sort) { 'created_asc' }
it 'orders by id ascending' do
request
context 'when the author entity type is specified' do actual_event_ids = assigns(:events).map { |event| event[:id] }
let(:entity_type) { 'Author' } expected_event_ids = events.map(&:id)
let(:entity_id) { 1 }
let(:audit_logs_params) { ActionController::Parameters.new(sort: '', author_id: '1', created_after: Date.current.beginning_of_month, created_before: Date.current.end_of_day).permit! }
it_behaves_like 'AuditLogFinder params' expect(actual_event_ids).to eq(expected_event_ids)
end
end end
end
context 'ordering' do context 'when sorting by an unsupported sort order' do
shared_examples 'orders by id descending' do let(:sort) { 'FOO' }
it 'orders by id descending' do
request
actual_event_ids = assigns(:events).map { |event| event[:id] } it_behaves_like 'orders by id descending'
expected_event_ids = events.map(&:id).reverse end
end
expect(actual_event_ids).to eq(expected_event_ids) context 'pagination' do
end it 'sets instance variables' do
end request
context 'when no sort order is specified' do expect(assigns(:is_last_page)).to be(true)
it_behaves_like 'orders by id descending' end
end
context 'when sorting by latest events first' do it 'paginates audit events, without casting a count query' do
let(:sort) { 'created_desc' } serializer = instance_spy(AuditEventSerializer)
allow(AuditEventSerializer).to receive(:new).and_return(serializer)
it_behaves_like 'orders by id descending' request
end
context 'when sorting by oldest events first' do expect(serializer).to have_received(:represent).with(kind_of(Kaminari::PaginatableWithoutCount))
let(:sort) { 'created_asc' } end
end
it 'orders by id ascending' do it 'tracks search event', :snowplow do
request request
actual_event_ids = assigns(:events).map { |event| event[:id] } expect_snowplow_event(
expected_event_ids = events.map(&:id) category: 'Groups::AuditEventsController',
action: 'search_audit_event',
user: client,
namespace: group
)
end
expect(actual_event_ids).to eq(expected_event_ids) context 'when invalid date' do
end where(:created_before, :created_after) do
end 'invalid-date' | nil
nil | true
'2021-13-10' | nil
nil | '2021-02-31'
'2021-03-31' | '2021-02-31'
end
context 'when sorting by an unsupported sort order' do with_them do
let(:sort) { 'FOO' } it 'returns an error' do
get :index, params: { group_id: group.to_param, 'created_before': created_before, 'created_after': created_after }
it_behaves_like 'orders by id descending' expect(response).to have_gitlab_http_status(:bad_request)
end expect(flash[:alert]).to eq 'Invalid date format. Please use UTC format as YYYY-MM-DD'
end end
end
end
end
context 'pagination' do context 'when authorized owner' do
it 'sets instance variables' do before do
request group.add_owner(owner)
sign_in(owner)
end
expect(assigns(:is_last_page)).to be(true) let(:client) { owner }
end
it 'paginates audit events, without casting a count query' do context do
serializer = instance_spy(AuditEventSerializer) let(:request) do
allow(AuditEventSerializer).to receive(:new).and_return(serializer) get :index, params: { group_id: group.to_param, sort: sort, entity_type: entity_type, entity_id: entity_id }
end
request it_behaves_like 'when audit_events feature is available'
end
expect(serializer).to have_received(:represent).with(kind_of(Kaminari::PaginatableWithoutCount)) it_behaves_like 'tracking unique visits', :index do
end let(:request_params) { { group_id: group.to_param, sort: sort, entity_type: entity_type, entity_id: entity_id } }
end let(:target_id) { 'g_compliance_audit_events' }
end
end
it 'tracks search event', :snowplow do context 'when authorized auditor' do
request before do
sign_in(auditor)
end
expect_snowplow_event( let(:client) { auditor }
category: 'Groups::AuditEventsController',
action: 'search_audit_event',
user: owner,
namespace: group
)
end
context 'when invalid date' do context do
where(:created_before, :created_after) do let(:request) do
'invalid-date' | nil get :index, params: { group_id: group.to_param, sort: sort, entity_type: entity_type, entity_id: entity_id }
nil | true
'2021-13-10' | nil
nil | '2021-02-31'
'2021-03-31' | '2021-02-31'
end
with_them do
it 'returns an error' do
get :index, params: { group_id: group.to_param, 'created_before': created_before, 'created_after': created_after }
expect(response).to have_gitlab_http_status(:bad_request)
expect(flash[:alert]).to eq 'Invalid date format. Please use UTC format as YYYY-MM-DD'
end
end
end
end end
it_behaves_like 'when audit_events feature is available'
end end
it_behaves_like 'tracking unique visits', :index do it_behaves_like 'tracking unique visits', :index do
......
...@@ -610,6 +610,7 @@ RSpec.describe GroupPolicy do ...@@ -610,6 +610,7 @@ RSpec.describe GroupPolicy do
it { is_expected.to be_allowed(:read_group) } it { is_expected.to be_allowed(:read_group) }
it { is_expected.to be_allowed(:read_milestone) } it { is_expected.to be_allowed(:read_milestone) }
it { is_expected.to be_allowed(:read_group_audit_events) }
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