Added #17494: Advanced-search and predefined filters
Added #17494: Advanced-search and predefined filters
New functionality
Advanced search:
- Added new advanced-search which allows filtering on backend
- Added functionality to manage private and public filters. The provided new permissions for new functionality
- Create new settings-page to manage filters
API:
- Added API to manage the predefined filters
Database:
- Added tables for predefined filters and predefined filter permissions
Testing:
- Added plenty of unit- and feature tests for the advanced search and predefined filters
- Added tests for the "old" advanced search
Screenshots
Advanced search:
Predefined filter create modal:
Predefined filter settings page
:warning: We detected 1 security issue in this pull request:
Insecure Use of Dangerous Function (1)
| Severity | Details | Docs |
|---|---|---|
| Medium | Title: Dynamic evaluation of untrusted input (Frontend) https://github.com/grokability/snipe-it/blob/a89f75b108dbba270d9b6c45ad8a65c8d5aa2037/public/js/dist/advanced-search.js#L1 |
:books: |
More info on how to fix Insecure Use of Dangerous Function in JavaScript.
👉 Go to the dashboard for detailed results.
📥 Happy? Share your feedback with us.
Hi there and thank you for you PR.
It looks like a lot of work went into this but that also means there are a lot of changed files which makes reviewing this difficult 😅.
In order for the team to start reviewing this can you please make the following changes:
- [x] It looks like a formatter was run for a lot of lines that aren't relevant to the feature. Please remove the formatting changes that are not on lines added or changed while building the feature this PR focuses on.
- This is helpful for the reviewers before the code is merged and also in the future when we want to track the changes to a file. Formatting for the sake of formatting makes tracking down relevant changes to a file more difficult in the future.
- [x] Please remove files/changes that seem to be relevant to your local dev environment like the references to Codacy.
- [ ] Please remove the build assets.
- Those changes should not be included in PRs since they make reviewing a lot more difficult. If needed we build them locally when testing.
- [x] Please remove the translations except for our source of truth,
en-US. - [ ] Please remove the
.gitignorefiles in the storage directories.- I don't think they are necessary?
- [ ] It looks like this PR includes changes that aren't relevant to advanced search and pre-defined filters (like changes to alerts/notifications). Please move those changes to another PR so both features/changes can be reviewed individually.
- [x] Please provide details about the technical implementation in the PR description.
- The screenshots are really appreciated so we can get an overview of the new functionality but a walkthrough of the actual code added and changed will go a long way in making the PR review more manageable.
It may seem like a lot but these changes are needed before the team can dive in and start reviewing. We need to get the 21k changed lines down to something manageable for our devs.
Again, thank you for your contribution!
Sorry, maybe I should have been more specific but the goal is not completely remove the build like done in a261b85 (#18264), but to remove the changes to those files in comparison to what is on develop. In other words, the PR diff should show no changes for the frontend assets that are built.
When I talked about removing irrelevant code-formatting changes I meant reverting these types of changes:
The relevant lines for this PR are 165/166 but there are 6 other lines touched that should not be included.
In general, having 285 files changed with thousands of lines touched is un-reviewable:
Here is an overview of all relevant files changed:
Backend
Controllers
-
app/Http/Controllers/Api/AssetsController.php: Added new filtering using the FilterService. -
app/Http/Controllers/Api/GroupsController.php: Added selectlist for the group-select dropdown. -
app/Http/Controllers/Api/PredefinedFilterController.php: Controller for managing predefined filters. -
app/Http/Controllers/Api/PredefinedFilterPermissionController.php:Controller to manage permissions for predefined filters. -
app/Http/Controllers/AssetsController.php: Added logic to apply predefined filters using the predefinedFilterID parameter in the URL. -
app/Http/Controllers/PredefinedFilterController.php: Controller for the predefined filter page in settings.
Models
-
app/Models/Asset.php: Integrated FilterService for advanced filtering. -
app/Models/PredefinedFilter.php: Model for predefined filters. -
app/Models/PredefinedFilterPermission.php: Model for predefined filter permissions.
Policies & Providers
-
app/Policies/PredefinedFilterPolicy.php: Policy for predefined filters. -
app/Providers/AuthServiceProvider.php: Registered permissions for predefined filters.
Services
-
app/Services/FilterService/FilterService.php: New service containing filtering logic. -
app/Services/PredefinedFilterService.php: Service for CRUD operations on predefined filters.
Transformers
-
app/Http/Transformers/PredefinedFiltersTransformer.php: Transformer for predefined filters.
Migrations
-
database/migrations/2025_08_29_120952_create_predefined_filters_table.php: Create predefined filters table. -
database/migrations/2025_09_05_054824_create_predefined_filters_permissions.php: Create predefined filter permissions table. -
database/migrations/2025_09_25_120708_make_predefined_filter_permissions_unique.php: Enforce unique combination of predefinedFilterId and permissionGroupId (We could have moved this into the 2025_08_29_120952_create_predefined_filters_table migration, but we noticed during development that it was a good idea to make this unique, and we thought that creating another migration would be the cleaner solution.).
Frontend
CSS
-
resources/assets/css/components/advancedSearch/advanced-search-index.css: Styles for the advanced search index page. -
resources/assets/css/components/advancedSearch/advanced-search.css: Styles for the advanced search drawer. -
resources/assets/css/components/advancedSearch/floating-buttons.css: Styles for floating buttons in the filter drawer.
JavaScript
-
resources/assets/js/advancedSearch/advanced-search-index.js: Logic for opening/closing the advanced search drawer. -
resources/assets/js/advancedSearch/advanced-search.js: Main JS file for advanced search. -
resources/assets/js/advancedSearch/apiService.js: Backend communication for fetching predefined filters. -
resources/assets/js/advancedSearch/filterFormManager.js: Manages filter inputs. -
resources/assets/js/advancedSearch/filterInputs.js: Implements filter input classes. -
resources/assets/js/advancedSearch/filterUiController.js: Handles loading/updating/saving predefined filters. -
resources/assets/js/advancedSearch/floating-buttons.js: Logic for floating buttons in the filter drawer. -
resources/assets/js/advancedSearch/search-inputs.js: Expands select2 fields on focus. -
resources/assets/js/simpleDIContainer.js: A simple implementation of a DI-Container that we implemented ourselves because we didn't want to add external dependencies.
Views
-
resources/views/hardware/index.blade.php: Restructured to embed advanced search. -
resources/views/livewire/partials/advancedsearch/modal.blade.php: Modal for managing predefined filters. -
resources/views/predefined-filters/index.blade.php: Page to manage predefined filters.
Partials
-
resources/views/partials/advanced-search/advanced-search-translations.blade.php: Sets translations for advanced search. -
resources/views/partials/advanced-search/advanced-search.blade.php: Main advanced search component. -
resources/views/partials/advanced-search/search-inputs.blade.php: Search input components. -
resources/views/partials/forms/edit/*: Moved dropdowns to components for advanced search. -
resources/views/partials/select/dropdowns/*: Dropdown components for forms/edit.
Tests
Feature Tests
-
tests/Feature/AssetQuery/*: Tests for different asset filters. -
tests/Feature/AssetQuery/Api/*: API tests for asset filters. -
tests/Feature/PredefinedFilter/Api/PredefinedFilterControllerTest.php: Tests for PredefinedFilterController. -
tests/Feature/PredefinedFilter/UI/PredefinedFilterModalTest.php: Tests for the predefined filter modal UI.
Unit Tests
-
tests/Unit/Models/AssetUnitTest.php: Unit tests for the Asset model.
Database
We've added two tables to store the predefined filters:
-
predefined_filters to storethe predefined filters. The actual filter-data is stored as a json-string -
predefined_filter_permissionsto store which user has which permissions to create/edit/view/delete a predefined filter
Hi there,
we have made the necessary changes you mentioned earlier.
Summary:
- reverted the formatting stuff
- removed files related to our development environment
- removed all build assets we did not use
- removed Translations except en-US
- removed .gitignore
- moved notifications to a separate PR (#18290)
- Provided technical details (https://github.com/grokability/snipe-it/pull/18264#issuecomment-3625866640)
Predefined Filter Feature
In addition to the previous explanation, this section covers the new predefined filter functionality.
Summary This part adds a feature to save the current filter configuration, allowing users to quickly reapply it later.
Database Structure
We added two new tables:
- predefined_filters
This table stores each predefined filter and its associated metadata.
| Field | Type | Null | Key | Default | Extra | Explanation |
|---|---|---|---|---|---|---|
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment | Primary key |
| name | varchar(191) | NO | NULL | Name of the filter | ||
| created_by | int(10) unsigned | NO | NULL | Creator user ID | ||
| created_at | timestamp | YES | current_timestamp() | Creation time | ||
| updated_at | timestamp | YES | current_timestamp() | on update current_timestamp() | Last update time | |
| deleted_at | timestamp | YES | NULL | Soft delete time | ||
| filter_data | longtext | NO | NULL | Actual filter data (JSON) | ||
| is_public | tinyint(1) | NO | 0 | Whether the filter is public | ||
| object_type | varchar(191) | YES | asset | Defaults to asset (placeholder for future use) |
Filter Examples
Standard fields (e.g. company, asset_tag)
[
{
"field": "company",
"value": [8, "com"],
"operator": "contains",
"logic": "AND"
}
]
Explanation:
- 8 → exact company ID
- "com" → substring used in the contains search
Custom fields
[
{
"field": "_snipeit_ram_3",
"value": "32",
"operator": "equals",
"logic": "AND"
}
]
Explanation:
- Custom fields use the same structure as standard fields
- Prefix snipeit
_ follows the pattern in the assets table
Checked-out-to (assigned_to)
[
{
"field": "assigned_to",
"value": {
"type": "App\\Models\\Asset",
"value": "Demo"
},
"operator": "equals",
"logic": "AND"
}
]
Explanation:
- Handles relationships to other objects (e.g., assets or users)
- "type" specifies the related model
- "value" specifies the related entity
Date range filters
[
{
"field": "purchase_date",
"value": {
"startDate": "2024-03-14",
"endDate": "2025-12-14"
},
"operator": "equals",
"logic": "AND"
}
]
Explanation:
- Supports filtering by date ranges
- "startDate" and "endDate" define the range
- predefined_filter_permissions
The predefined_filter_permissions table is a many-to-many mapping between predefined filters and permission groups. It defines which groups have access to which filters.
| Field | Type | Null | Key | Default | Extra | Explanation |
|---|---|---|---|---|---|---|
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment | Primary key |
| predefined_filter_id | bigint(20) unsigned | NO | MUL | NULL | Linked predefined filter ID | |
| permission_group_id | bigint(20) unsigned | NO | NULL | Linked permission group ID | ||
| created_by | int(10) unsigned | NO | NULL | Creator user ID | ||
| created_at | timestamp | YES | NULL | Creation time | ||
| updated_at | timestamp | YES | NULL | Last update time |
Permission System
We added four new permissions for predefined filters:
- create
- view
- edit
- delete
How it works:
- A user can perform an action on a predefined filter if they belong to a permission group linked to that filter and the group has the corresponding permission.
- Superusers bypass all restrictions and can perform any action.
Thank you for addressing the changes requested (I know it was a lot). This is a big PR (understandably) so our team is going to need some time to review and consider it.