112 lines
4.2 KiB
Plaintext
112 lines
4.2 KiB
Plaintext
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1><%= @project.name %> - Events</h1>
|
|
<div>
|
|
<%= link_to "← Back to Project", @project, class: "btn btn-secondary" %>
|
|
<%= link_to "Analytics", analytics_project_path(@project), class: "btn btn-info" %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5>Filters</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<%= form_with url: project_events_path(@project), method: :get, local: true, class: "row g-3" do |form| %>
|
|
<div class="col-md-3">
|
|
<%= form.label :ip, "IP Address", class: "form-label" %>
|
|
<%= form.text_field :ip, value: params[:ip], class: "form-control", placeholder: "Filter by IP" %>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<%= form.label :waf_action, "Action", class: "form-label" %>
|
|
<%= form.select :waf_action,
|
|
options_for_select([['All', ''], ['Allow', 'allow'], ['Block', 'block'], ['Challenge', 'challenge']], params[:waf_action]),
|
|
{}, { class: "form-select" } %>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<%= form.label :country, "Country", class: "form-label" %>
|
|
<%= form.text_field :country, value: params[:country], class: "form-control", placeholder: "Country code (e.g. US)" %>
|
|
</div>
|
|
<div class="col-md-3 d-flex align-items-end">
|
|
<%= form.submit "Apply Filters", class: "btn btn-primary me-2" %>
|
|
<%= link_to "Clear", project_events_path(@project), class: "btn btn-outline-secondary" %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Events Table -->
|
|
<div class="card">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h5>Events (<%= @events.count %>)</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<% if @events.any? %>
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>IP Address</th>
|
|
<th>Action</th>
|
|
<th>Path</th>
|
|
<th>Method</th>
|
|
<th>Status</th>
|
|
<th>Country</th>
|
|
<th>User Agent</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% @events.each do |event| %>
|
|
<tr>
|
|
<td><%= event.timestamp.strftime("%Y-%m-%d %H:%M:%S") %></td>
|
|
<td><code><%= event.ip_address %></code></td>
|
|
<td>
|
|
<span class="badge bg-<%= event.blocked? ? 'danger' : event.allowed? ? 'success' : 'warning' %>">
|
|
<%= event.waf_action %>
|
|
</span>
|
|
</td>
|
|
<td><code><%= event.request_path %></code></td>
|
|
<td><%= event.request_method %></td>
|
|
<td><%= event.response_status %></td>
|
|
<td>
|
|
<% if event.country_code.present? %>
|
|
<span class="badge bg-light text-dark"><%= event.country_code %></span>
|
|
<% else %>
|
|
<span class="text-muted">-</span>
|
|
<% end %>
|
|
</td>
|
|
<td class="text-truncate" style="max-width: 200px;" title="<%= event.user_agent %>">
|
|
<%= event.user_agent&.truncate(30) || '-' %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
<% if @pagy.pages > 1 %>
|
|
<div class="d-flex justify-content-center mt-4">
|
|
<%== pagy_nav(@pagy) %>
|
|
</div>
|
|
<div class="text-center text-muted mt-2">
|
|
Showing <%= @pagy.from %> to <%= @pagy.to %> of <%= @pagy.count %> events
|
|
</div>
|
|
<% end %>
|
|
<% else %>
|
|
<div class="text-center py-5">
|
|
<p class="text-muted mb-3">
|
|
<% if params[:ip].present? || params[:waf_action].present? || params[:country].present? %>
|
|
No events found matching your filters.
|
|
<% else %>
|
|
No events have been received yet.
|
|
<% end %>
|
|
</p>
|
|
<% if params[:ip].present? || params[:waf_action].present? || params[:country].present? %>
|
|
<%= link_to "Clear Filters", project_events_path(@project), class: "btn btn-outline-primary" %>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div> |