Conversation
- Add search_text scope to Webhook model with SQL injection protection - Add filter_by_search method to WebhooksController - Update index view with search input field alongside date filters - Add comprehensive test coverage for search functionality - Update CHANGELOG with feature entry Supports case-insensitive searching of both headers and payload content.
There was a problem hiding this comment.
Pull request overview
This PR implements case-insensitive text search functionality for the webhooks admin interface, allowing administrators to filter webhooks by searching within header or payload content.
Changes:
- Added
search_textscope to the Webhook model for filtering by headers and payload content using SQL LIKE queries - Added
filter_by_searchcontroller method to apply search filtering in the webhooks index action - Updated the view to include a search input field with responsive layout and updated clear button logic
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| app/models/webhook.rb | Added search_text scope using SQLite json_quote() and LIKE queries for searching headers and payload |
| app/controllers/admin/webhooks_controller.rb | Added filter_by_search method and integrated it into the index action's filter chain |
| app/views/admin/webhooks/index.html.erb | Added search input field with responsive flex-wrap layout and updated clear button condition |
| spec/requests/admin/webhooks_spec.rb | Added 8 comprehensive test cases covering payload search, header search, case-insensitivity, combined filters, and special characters |
| CHANGELOG.md | Added feature entry for the text search functionality |
Comments suppressed due to low confidence (2)
spec/requests/admin/webhooks_spec.rb:46
- This assignment to old_webhook is useless, since its value is never read.
old_webhook = create(:webhook, received_at: 10.days.ago)
spec/requests/admin/webhooks_spec.rb:47
- This assignment to new_webhook is useless, since its value is never read.
new_webhook = create(:webhook, received_at: 1.day.ago)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| it "handles special characters safely" do | ||
| webhook = create(:webhook, payload: '{"data":"test%value"}') | ||
|
|
||
| get "/admin/webhooks", params: { q: "test%" }, headers: auth_headers | ||
|
|
||
| expect(response).to have_http_status(:ok) | ||
| end |
There was a problem hiding this comment.
The test only verifies that the request doesn't crash when searching for special characters, but doesn't verify that the webhook is actually found. Consider adding an assertion like expect(response.body).to include(webhook.id.to_s) to ensure the special character search works correctly and finds the matching webhook.
| where( | ||
| "json_quote(headers) LIKE ? OR payload LIKE ?", | ||
| "%#{sanitize_sql_like(term)}%", | ||
| "%#{sanitize_sql_like(term)}%" | ||
| ) |
There was a problem hiding this comment.
The LIKE queries on headers and payload columns will perform full table scans since they use leading wildcards (%term%). This could become a performance bottleneck as the number of webhooks grows. Consider adding documentation about this limitation, or if this becomes an issue in production, consider implementing full-text search using SQLite's FTS5 extension or adding a separate searchable text column with an index.
| return all if term.blank? | ||
|
|
||
| where( | ||
| "json_quote(headers) LIKE ? OR payload LIKE ?", |
There was a problem hiding this comment.
The use of json_quote(headers) may not be necessary and could cause unexpected behavior. In SQLite, the json column type stores data as TEXT, so you can search it directly with LIKE similar to the payload column.
Consider simplifying to: "headers LIKE ? OR payload LIKE ?"
The json_quote() function converts a value to a JSON string literal, which adds extra quoting that may not be needed since the headers are already stored as JSON text in SQLite. While the current implementation may work, direct LIKE matching would be simpler and more predictable.
| "json_quote(headers) LIKE ? OR payload LIKE ?", | |
| "headers LIKE ? OR payload LIKE ?", |
| end | ||
|
|
||
| it "handles special characters safely" do | ||
| webhook = create(:webhook, payload: '{"data":"test%value"}') |
Summary
Implements case-insensitive text search for the webhooks index, allowing filtering by headers or payload content.
Changes
search_textscope to Webhook model using SQLitejson_quote()for headers and direct LIKE for payloadfilter_by_searchmethod and integrated it into the index actionSecurity
sanitize_sql_likefor user inputTest Coverage
Verification