Commit fe229670 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'filter-for-project-and-group-audit-events' into 'master'

Date filter for project and group audit events

Closes #37270

See merge request gitlab-org/gitlab!20641
parents e5ca52a7 51724ce6
---
title: Add created_before/after filter to group/project audit events
merge_request: 20641
author:
type: added
# frozen_string_literal: true # frozen_string_literal: true
class Admin::AuditLogsController < Admin::ApplicationController class Admin::AuditLogsController < Admin::ApplicationController
include AuditEvents::EnforcesValidDateParams
include AuditEvents::AuditLogsParams
before_action :check_license_admin_audit_log_available! before_action :check_license_admin_audit_log_available!
before_action :validate_date_params
PER_PAGE = 25 PER_PAGE = 25
...@@ -22,21 +24,7 @@ class Admin::AuditLogsController < Admin::ApplicationController ...@@ -22,21 +24,7 @@ class Admin::AuditLogsController < Admin::ApplicationController
private private
def audit_logs_params
params.permit(:entity_type, :entity_id, :created_before, :created_after)
end
def check_license_admin_audit_log_available! def check_license_admin_audit_log_available!
render_404 unless License.feature_available?(:admin_audit_log) render_404 unless License.feature_available?(:admin_audit_log)
end end
def validate_date_params
unless valid_utc_date?(params[:created_before]) && valid_utc_date?(params[:created_after])
flash[:alert] = _('Invalid date format. Please use UTC format as YYYY-MM-DD')
end
end
def valid_utc_date?(date)
date.blank? || date =~ Gitlab::Regex.utc_date_regex
end
end end
# frozen_string_literal: true
module AuditEvents
module AuditLogsParams
def audit_logs_params
params.permit(:entity_type, :entity_id, :created_before, :created_after)
end
end
end
# frozen_string_literal: true
module AuditEvents
module EnforcesValidDateParams
extend ActiveSupport::Concern
included do
before_action :validate_date_params, only: [:index]
end
private
def validate_date_params
unless valid_utc_date?(params[:created_before]) && valid_utc_date?(params[:created_after])
flash[:alert] = _('Invalid date format. Please use UTC format as YYYY-MM-DD')
end
end
def valid_utc_date?(date)
date.blank? || date =~ Gitlab::Regex.utc_date_regex
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
class Groups::AuditEventsController < Groups::ApplicationController class Groups::AuditEventsController < Groups::ApplicationController
include AuditEvents::EnforcesValidDateParams
include AuditEvents::AuditLogsParams
before_action :authorize_admin_group! before_action :authorize_admin_group!
before_action :check_audit_events_available! before_action :check_audit_events_available!
layout 'group_settings' layout 'group_settings'
def index def index
@events = AuditLogFinder.new(entity_type: group.class.name, entity_id: group.id).execute.page(params[:page]) @events = AuditLogFinder.new(audit_logs_params).execute.page(params[:page])
end
private
def audit_logs_params
super.merge(
entity_type: group.class.name,
entity_id: group.id
)
end end
end end
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
class Projects::AuditEventsController < Projects::ApplicationController class Projects::AuditEventsController < Projects::ApplicationController
include LicenseHelper include LicenseHelper
include AuditEvents::EnforcesValidDateParams
include AuditEvents::AuditLogsParams
before_action :authorize_admin_project! before_action :authorize_admin_project!
before_action :check_audit_events_available! before_action :check_audit_events_available!
...@@ -9,7 +11,16 @@ class Projects::AuditEventsController < Projects::ApplicationController ...@@ -9,7 +11,16 @@ class Projects::AuditEventsController < Projects::ApplicationController
layout 'project_settings' layout 'project_settings'
def index def index
@events = AuditLogFinder.new(entity_type: project.class.name, entity_id: project.id).execute.page(params[:page]) @events = AuditLogFinder.new(audit_logs_params).execute.page(params[:page])
end
private
def audit_logs_params
super.merge(
entity_type: project.class.name,
entity_id: project.id
)
end end
def check_audit_events_available! def check_audit_events_available!
......
...@@ -3,4 +3,5 @@ ...@@ -3,4 +3,5 @@
%h3.page-title Group Audit Events %h3.page-title Group Audit Events
%p.light Events in #{@group.name} %p.light Events in #{@group.name}
= render 'shared/audit_events/event_filter', path: group_audit_events_path(@group)
= render 'shared/audit_events/event_table', events: @events = render 'shared/audit_events/event_table', events: @events
...@@ -8,4 +8,5 @@ ...@@ -8,4 +8,5 @@
%p.light Events in #{@project.full_path} %p.light Events in #{@project.full_path}
- if feature_available - if feature_available
= render 'shared/audit_events/event_filter', path: project_audit_events_path(@project)
= render 'shared/audit_events/event_table', events: @events = render 'shared/audit_events/event_table', events: @events
.row-content-block.second-block
= form_tag path, method: :get, class: 'filter-form' do
.prepend-top-10
.form-group
= label_tag :created_after, _('Created after'), class: 'label-bold'
= date_field_tag :created_after, params[:created_after],
class: 'form-control', placeholder: 'YYYY-MM-DD'
.form-group
= label_tag :created_before, _('Created before'), class: 'label-bold'
= date_field_tag :created_before, params[:created_before],
class: 'form-control', placeholder: 'YYYY-MM-DD'
= submit_tag _('Search'), class: 'btn'
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
= s_('AuditEvents|Target') = s_('AuditEvents|Target')
.table-section.section-20{ role: 'rowheader' } .table-section.section-20{ role: 'rowheader' }
= s_('AuditEvents|At') = s_('AuditEvents|At')
- events.each do |event| - events.map(&:present).each do |event|
.gl-responsive-table-row .gl-responsive-table-row
.table-section.section-15 .table-section.section-15
.table-mobile-header{ role: 'rowheader' } .table-mobile-header{ role: 'rowheader' }
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
.table-section.section-50.section-wrap.audit-action.js-audit-action .table-section.section-50.section-wrap.audit-action.js-audit-action
%span= sanitize(human_text(event.details), tags: %w(strong)) %span= sanitize(human_text(event.details), tags: %w(strong))
.table-section.section-15.section-wrap .table-section.section-15.section-wrap
= event.details[:target_details] = event.target
.table-section.section-20 .table-section.section-20
= event.created_at = event.date
= paginate events, theme: "gitlab" = paginate events, theme: "gitlab"
...@@ -19,12 +19,14 @@ describe Groups::AuditEventsController do ...@@ -19,12 +19,14 @@ describe Groups::AuditEventsController do
end end
context 'when audit_events feature is available' do context 'when audit_events feature is available' do
let(:audit_logs_params) { ActionController::Parameters.new(entity_type: ::Group.name, entity_id: group.id).permit! }
before do before do
stub_licensed_features(audit_events: true) stub_licensed_features(audit_events: true)
end end
it 'renders index with 200 status code' do it 'renders index with 200 status code' do
expect(AuditLogFinder).to receive(:new).with(entity_type: ::Group.name, entity_id: group.id).and_call_original expect(AuditLogFinder).to receive(:new).with(audit_logs_params).and_call_original
request request
......
...@@ -19,12 +19,14 @@ describe Projects::AuditEventsController do ...@@ -19,12 +19,14 @@ describe Projects::AuditEventsController do
end end
context 'when audit_events feature is available' do context 'when audit_events feature is available' do
let(:audit_logs_params) { ActionController::Parameters.new(entity_type: ::Project.name, entity_id: project.id).permit! }
before do before do
stub_licensed_features(audit_events: true) stub_licensed_features(audit_events: true)
end end
it 'renders index with 200 status code' do it 'renders index with 200 status code' do
expect(AuditLogFinder).to receive(:new).with(entity_type: ::Project.name, entity_id: project.id).and_call_original expect(AuditLogFinder).to receive(:new).with(audit_logs_params).and_call_original
request request
......
...@@ -116,37 +116,7 @@ describe 'Admin::AuditLogs', :js do ...@@ -116,37 +116,7 @@ describe 'Admin::AuditLogs', :js do
visit admin_audit_logs_path visit admin_audit_logs_path
end end
it 'shows only 2 days old events' do it_behaves_like 'audit events filter'
page.within '.content' do
fill_in 'Created after', with: 4.days.ago
fill_in 'Created before', with: 2.days.ago
click_button 'Search'
end
expect(page).to have_content(audit_event_2.author_name)
expect(page).not_to have_content(audit_event_1.author_name)
expect(page).not_to have_content(audit_event_3.author_name)
end
it 'shows only yesterday events' do
page.within '.content' do
fill_in 'Created after', with: 2.days.ago
click_button 'Search'
end
expect(page).to have_content(audit_event_3.author_name)
expect(page).not_to have_content(audit_event_1.author_name)
expect(page).not_to have_content(audit_event_2.author_name)
end
it 'shows a message if provided date is invalid' do
page.within '.content' do
fill_in 'Created after', with: '12-345-6789'
click_button 'Search'
end
expect(page).to have_content('Invalid date format. Please use UTC format as YYYY-MM-DD')
end
end end
end end
......
...@@ -61,4 +61,16 @@ describe 'Groups > Audit Events', :js do ...@@ -61,4 +61,16 @@ describe 'Groups > Audit Events', :js do
end end
end end
end end
describe 'filter by date', js: false do
let!(:audit_event_1) { create(:group_audit_event, entity_type: 'Group', entity_id: group.id, created_at: 5.days.ago) }
let!(:audit_event_2) { create(:group_audit_event, entity_type: 'Group', entity_id: group.id, created_at: 3.days.ago) }
let!(:audit_event_3) { create(:group_audit_event, entity_type: 'Group', entity_id: group.id, created_at: 1.day.ago) }
before do
visit group_audit_events_path(group)
end
it_behaves_like 'audit events filter'
end
end end
...@@ -120,4 +120,16 @@ describe 'Projects > Audit Events', :js do ...@@ -120,4 +120,16 @@ describe 'Projects > Audit Events', :js do
it_behaves_like 'audit event contains custom message' do it_behaves_like 'audit event contains custom message' do
let(:audit_events_url) { project_audit_events_path(project) } let(:audit_events_url) { project_audit_events_path(project) }
end end
describe 'filter by date', js: false do
let!(:audit_event_1) { create(:project_audit_event, entity_type: 'Project', entity_id: project.id, created_at: 5.days.ago) }
let!(:audit_event_2) { create(:project_audit_event, entity_type: 'Project', entity_id: project.id, created_at: 3.days.ago) }
let!(:audit_event_3) { create(:project_audit_event, entity_type: 'Project', entity_id: project.id, created_at: 1.day.ago) }
before do
visit project_audit_events_path(project)
end
it_behaves_like 'audit events filter'
end
end end
# frozen_string_literal: true
shared_examples_for 'audit events filter' do
it 'shows only 2 days old events' do
page.within '.content' do
fill_in 'Created after', with: 4.days.ago
fill_in 'Created before', with: 2.days.ago
click_button 'Search'
end
expect(page).to have_content(audit_event_2.present.date)
expect(page).not_to have_content(audit_event_1.present.date)
expect(page).not_to have_content(audit_event_3.present.date)
end
it 'shows only yesterday events' do
page.within '.content' do
fill_in 'Created after', with: 2.days.ago
click_button 'Search'
end
expect(page).to have_content(audit_event_3.present.date)
expect(page).not_to have_content(audit_event_1.present.date)
expect(page).not_to have_content(audit_event_2.present.date)
end
it 'shows a message if provided date is invalid' do
page.within '.content' do
fill_in 'Created after', with: '12-345-6789'
click_button 'Search'
end
expect(page).to have_content('Invalid date format. Please use UTC format as YYYY-MM-DD')
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